Hiroh Satoh / keyboard Featured

Dependencies:   BLE_API mbed-dev nRF51822

Committer:
cho45
Date:
Mon Jul 18 09:23:15 2016 +0900
Revision:
2:c2e3f240640c
Parent:
0:be89b5fdea09
Child:
3:266dfa9f8709
pretty

Who changed what in which revision?

UserRevisionLine numberNew contents of line
cho45 0:be89b5fdea09 1 /* mbed Microcontroller Library
cho45 0:be89b5fdea09 2 * Copyright (c) 2015 ARM Limited
cho45 0:be89b5fdea09 3 *
cho45 0:be89b5fdea09 4 * Licensed under the Apache License, Version 2.0 (the "License");
cho45 0:be89b5fdea09 5 * you may not use this file except in compliance with the License.
cho45 0:be89b5fdea09 6 * You may obtain a copy of the License at
cho45 0:be89b5fdea09 7 *
cho45 0:be89b5fdea09 8 * http://www.apache.org/licenses/LICENSE-2.0
cho45 0:be89b5fdea09 9 *
cho45 0:be89b5fdea09 10 * Unless required by applicable law or agreed to in writing, software
cho45 0:be89b5fdea09 11 * distributed under the License is distributed on an "AS IS" BASIS,
cho45 0:be89b5fdea09 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
cho45 0:be89b5fdea09 13 * See the License for the specific language governing permissions and
cho45 0:be89b5fdea09 14 * limitations under the License.
cho45 0:be89b5fdea09 15 */
cho45 0:be89b5fdea09 16
cho45 0:be89b5fdea09 17 #include "mbed.h"
cho45 0:be89b5fdea09 18 #include "BLE.h"
cho45 0:be89b5fdea09 19 #include "KeyboardService.h"
cho45 0:be89b5fdea09 20 #include "BatteryService.h"
cho45 0:be89b5fdea09 21 #include "DeviceInformationService.h"
cho45 0:be89b5fdea09 22
cho45 0:be89b5fdea09 23 static const char MODEL_NAME[] = "keyboard";
cho45 0:be89b5fdea09 24 static const char SERIAL_NUMBER[] = "X00000";
cho45 0:be89b5fdea09 25 static const char HARDWARE_REVISION[] = "0.1";
cho45 0:be89b5fdea09 26 static const char FIRMWARE_REVISION[] = "0.1";
cho45 0:be89b5fdea09 27 static const char SOFTWARE_REVISION[] = "0.0";
cho45 0:be89b5fdea09 28
cho45 0:be89b5fdea09 29 static const uint8_t DEVICE_NAME[] = "my keyboard";
cho45 0:be89b5fdea09 30 static const uint8_t SHORT_DEVICE_NAME[] = "kbd1";
cho45 0:be89b5fdea09 31
cho45 2:c2e3f240640c 32 static const bool ENABLE_BONDING = true;
cho45 2:c2e3f240640c 33 static const bool REQUIRE_MITM = true;
cho45 2:c2e3f240640c 34 static const uint8_t PASSKEY[6] = {'1','2','3','4','5','6'}; // must be 6-digits number
cho45 2:c2e3f240640c 35
cho45 0:be89b5fdea09 36 InterruptIn button1(D2);
cho45 0:be89b5fdea09 37
cho45 0:be89b5fdea09 38 static const uint16_t uuid16_list[] = {
cho45 2:c2e3f240640c 39 GattService::UUID_HUMAN_INTERFACE_DEVICE_SERVICE,
cho45 2:c2e3f240640c 40 GattService::UUID_DEVICE_INFORMATION_SERVICE,
cho45 2:c2e3f240640c 41 GattService::UUID_BATTERY_SERVICE
cho45 0:be89b5fdea09 42 };
cho45 0:be89b5fdea09 43
cho45 0:be89b5fdea09 44 KeyboardService* keyboardService;
cho45 0:be89b5fdea09 45 BatteryService* batteryService;
cho45 0:be89b5fdea09 46 DeviceInformationService* deviceInformationService;
cho45 0:be89b5fdea09 47
cho45 0:be89b5fdea09 48 // I2C i2c(D2, D3);
cho45 2:c2e3f240640c 49 AnalogIn batteryInput(A4);
cho45 0:be89b5fdea09 50
cho45 0:be89b5fdea09 51 static void onConnect(const Gap::ConnectionCallbackParams_t *params) {
cho45 2:c2e3f240640c 52 printf("onConnect\r\n");
cho45 0:be89b5fdea09 53 }
cho45 0:be89b5fdea09 54
cho45 2:c2e3f240640c 55 static void onDisconnect(const Gap::DisconnectionCallbackParams_t *params) {
cho45 2:c2e3f240640c 56 printf("onDisconnect\r\n");
cho45 2:c2e3f240640c 57 BLE::Instance(BLE::DEFAULT_INSTANCE).gap().startAdvertising();
cho45 2:c2e3f240640c 58 }
cho45 2:c2e3f240640c 59
cho45 2:c2e3f240640c 60 static void onTimeout(const Gap::TimeoutSource_t source) {
cho45 2:c2e3f240640c 61 printf("onTimeout\r\n");
cho45 2:c2e3f240640c 62 BLE::Instance(BLE::DEFAULT_INSTANCE).gap().startAdvertising();
cho45 2:c2e3f240640c 63 }
cho45 0:be89b5fdea09 64
cho45 0:be89b5fdea09 65 static void passkeyDisplayCallback(Gap::Handle_t handle, const SecurityManager::Passkey_t passkey) {
cho45 2:c2e3f240640c 66 printf("Input passKey: ");
cho45 2:c2e3f240640c 67 for (unsigned i = 0; i < Gap::ADDR_LEN; i++) {
cho45 2:c2e3f240640c 68 printf("%c", passkey[i]);
cho45 2:c2e3f240640c 69 }
cho45 2:c2e3f240640c 70 printf("\r\n");
cho45 2:c2e3f240640c 71 }
cho45 2:c2e3f240640c 72
cho45 2:c2e3f240640c 73 static void securitySetupCompletedCallback(Gap::Handle_t handle, SecurityManager::SecurityCompletionStatus_t status) {
cho45 2:c2e3f240640c 74 if (status == SecurityManager::SEC_STATUS_SUCCESS) {
cho45 2:c2e3f240640c 75 printf("Security success %d\r\n", status);
cho45 2:c2e3f240640c 76 } else {
cho45 2:c2e3f240640c 77 printf("Security failed %d\r\n", status);
cho45 2:c2e3f240640c 78 }
cho45 2:c2e3f240640c 79 }
cho45 2:c2e3f240640c 80
cho45 2:c2e3f240640c 81 static void securitySetupInitiatedCallback(Gap::Handle_t, bool allowBonding, bool requireMITM, SecurityManager::SecurityIOCapabilities_t iocaps) {
cho45 2:c2e3f240640c 82 printf("Security setup initiated\r\n");
cho45 0:be89b5fdea09 83 }
cho45 0:be89b5fdea09 84
cho45 2:c2e3f240640c 85 static void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) {
cho45 2:c2e3f240640c 86 // https://developer.mbed.org/compiler/#nav:/keyboard/BLE_API/ble/blecommon.h;
cho45 2:c2e3f240640c 87 ble_error_t error;
cho45 2:c2e3f240640c 88 BLE &ble = params->ble;
cho45 2:c2e3f240640c 89
cho45 2:c2e3f240640c 90 error = params->error;
cho45 2:c2e3f240640c 91 if (error != BLE_ERROR_NONE) {
cho45 2:c2e3f240640c 92 printf("error on ble.init() \r\n");
cho45 2:c2e3f240640c 93 goto return_error;
cho45 2:c2e3f240640c 94 }
cho45 2:c2e3f240640c 95
cho45 2:c2e3f240640c 96 ble.gap().onDisconnection(onDisconnect);
cho45 2:c2e3f240640c 97 ble.gap().onConnection(onConnect);
cho45 2:c2e3f240640c 98 ble.gap().onTimeout(onTimeout);
cho45 2:c2e3f240640c 99
cho45 2:c2e3f240640c 100 printf("setup ble security manager\r\n");
cho45 2:c2e3f240640c 101 ble.securityManager().onSecuritySetupInitiated(securitySetupInitiatedCallback);
cho45 2:c2e3f240640c 102 ble.securityManager().onPasskeyDisplay(passkeyDisplayCallback);
cho45 2:c2e3f240640c 103 ble.securityManager().onSecuritySetupCompleted(securitySetupCompletedCallback);
cho45 2:c2e3f240640c 104 // bonding with hard-coded passkey.
cho45 2:c2e3f240640c 105 error = ble.securityManager().init(ENABLE_BONDING, REQUIRE_MITM, SecurityManager::IO_CAPS_DISPLAY_ONLY, PASSKEY);
cho45 2:c2e3f240640c 106 if (error != BLE_ERROR_NONE) {
cho45 2:c2e3f240640c 107 printf("error on ble.securityManager().init()");
cho45 2:c2e3f240640c 108 goto return_error;
cho45 2:c2e3f240640c 109 }
cho45 2:c2e3f240640c 110
cho45 2:c2e3f240640c 111 keyboardService = new KeyboardService(ble);
cho45 2:c2e3f240640c 112 deviceInformationService = new DeviceInformationService(ble, "lowreal.net", MODEL_NAME, SERIAL_NUMBER, HARDWARE_REVISION, FIRMWARE_REVISION, SOFTWARE_REVISION);
cho45 2:c2e3f240640c 113 batteryService = new BatteryService(ble, 10);
cho45 0:be89b5fdea09 114
cho45 2:c2e3f240640c 115 printf("general setup\r\n");
cho45 2:c2e3f240640c 116 error = ble.gap().accumulateAdvertisingPayload(
cho45 2:c2e3f240640c 117 GapAdvertisingData::BREDR_NOT_SUPPORTED |
cho45 2:c2e3f240640c 118 GapAdvertisingData::LE_GENERAL_DISCOVERABLE
cho45 2:c2e3f240640c 119 );
cho45 2:c2e3f240640c 120 if (error != BLE_ERROR_NONE) goto return_error;
cho45 2:c2e3f240640c 121
cho45 2:c2e3f240640c 122 printf("set COMPLETE_LIST_16BIT_SERVICE_IDS\r\n");
cho45 2:c2e3f240640c 123 error = ble.gap().accumulateAdvertisingPayload(
cho45 2:c2e3f240640c 124 GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS,
cho45 2:c2e3f240640c 125 (uint8_t*)uuid16_list, sizeof(uuid16_list)
cho45 2:c2e3f240640c 126 );
cho45 2:c2e3f240640c 127 if (error != BLE_ERROR_NONE) goto return_error;
cho45 2:c2e3f240640c 128
cho45 2:c2e3f240640c 129 printf("set advertising\r\n");
cho45 2:c2e3f240640c 130 // see 5.1.2: HID over GATT Specification (pg. 25)
cho45 2:c2e3f240640c 131 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
cho45 0:be89b5fdea09 132
cho45 2:c2e3f240640c 133 printf("set advertising interval\r\n");
cho45 2:c2e3f240640c 134 ble.gap().setAdvertisingInterval(50);
cho45 2:c2e3f240640c 135 // XXX
cho45 2:c2e3f240640c 136 // ble.gap().setAdvertisingTimeout(0);
cho45 2:c2e3f240640c 137
cho45 2:c2e3f240640c 138 printf("set keyboard\r\n");
cho45 2:c2e3f240640c 139 error = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::KEYBOARD);
cho45 2:c2e3f240640c 140 if (error != BLE_ERROR_NONE) goto return_error;
cho45 2:c2e3f240640c 141
cho45 2:c2e3f240640c 142 printf("set complete local name\r\n");
cho45 2:c2e3f240640c 143 error = ble.gap().accumulateAdvertisingPayload(
cho45 2:c2e3f240640c 144 GapAdvertisingData::COMPLETE_LOCAL_NAME,
cho45 2:c2e3f240640c 145 DEVICE_NAME, sizeof(DEVICE_NAME)
cho45 2:c2e3f240640c 146 );
cho45 2:c2e3f240640c 147 if (error != BLE_ERROR_NONE) goto return_error;
cho45 2:c2e3f240640c 148
cho45 2:c2e3f240640c 149 printf("set device name\r\n");
cho45 2:c2e3f240640c 150 error = ble.gap().setDeviceName(DEVICE_NAME);
cho45 2:c2e3f240640c 151 if (error != BLE_ERROR_NONE) goto return_error;
cho45 2:c2e3f240640c 152 // ble.gap().setTxPower(-12);
cho45 0:be89b5fdea09 153
cho45 0:be89b5fdea09 154
cho45 2:c2e3f240640c 155 printf("advertising\r\n");
cho45 2:c2e3f240640c 156 error = ble.gap().startAdvertising();
cho45 2:c2e3f240640c 157 if (error != BLE_ERROR_NONE) goto return_error;
cho45 2:c2e3f240640c 158 return;
cho45 0:be89b5fdea09 159
cho45 2:c2e3f240640c 160 return_error:
cho45 2:c2e3f240640c 161 printf("error with %d\r\n", error);
cho45 2:c2e3f240640c 162 return;
cho45 0:be89b5fdea09 163 }
cho45 0:be89b5fdea09 164
cho45 0:be89b5fdea09 165 void send_string(const char * c) {
cho45 2:c2e3f240640c 166 if (!keyboardService) return;
cho45 2:c2e3f240640c 167
cho45 2:c2e3f240640c 168 if (!keyboardService->isConnected()) {
cho45 2:c2e3f240640c 169 printf("we haven't connected yet...");
cho45 2:c2e3f240640c 170 } else {
cho45 2:c2e3f240640c 171 int len = strlen(c);
cho45 2:c2e3f240640c 172 keyboardService->printf(c);
cho45 2:c2e3f240640c 173 printf("sending %d chars\r\n", len);
cho45 2:c2e3f240640c 174 }
cho45 0:be89b5fdea09 175 }
cho45 2:c2e3f240640c 176
cho45 0:be89b5fdea09 177 void send_stuff() {
cho45 2:c2e3f240640c 178 send_string("hello world!\n");
cho45 2:c2e3f240640c 179 }
cho45 2:c2e3f240640c 180
cho45 2:c2e3f240640c 181 void updateBatteryLevel() {
cho45 2:c2e3f240640c 182 if (!batteryService) return;
cho45 2:c2e3f240640c 183 static const float BATTERY_MAX = 2.4;
cho45 2:c2e3f240640c 184
cho45 2:c2e3f240640c 185 float batteryVoltage = batteryInput.read() * 1.2 * 3;
cho45 2:c2e3f240640c 186 float percentage = (batteryVoltage / BATTERY_MAX) * 100;
cho45 2:c2e3f240640c 187 if (percentage > 100) {
cho45 2:c2e3f240640c 188 percentage = 100;
cho45 2:c2e3f240640c 189 }
cho45 2:c2e3f240640c 190 batteryService->updateBatteryLevel(static_cast<uint8_t>(percentage));
cho45 0:be89b5fdea09 191 }
cho45 0:be89b5fdea09 192
cho45 0:be89b5fdea09 193 int main(void) {
cho45 2:c2e3f240640c 194 // Use internal 1.2V reference for batteryInput
cho45 2:c2e3f240640c 195 // 1/3 pre-scaled input and 1.2V internal band gap reference
cho45 2:c2e3f240640c 196 // (mbed uses vdd for reference but i want use band gap)
cho45 2:c2e3f240640c 197 // ref. mbed-src/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/analogin_api.c
cho45 2:c2e3f240640c 198 NRF_ADC->CONFIG =
cho45 2:c2e3f240640c 199 (ADC_CONFIG_RES_10bit << ADC_CONFIG_RES_Pos) |
cho45 2:c2e3f240640c 200 (ADC_CONFIG_INPSEL_AnalogInputOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) |
cho45 2:c2e3f240640c 201 (ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) |
cho45 2:c2e3f240640c 202 (ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos);
cho45 0:be89b5fdea09 203
cho45 0:be89b5fdea09 204
cho45 2:c2e3f240640c 205 // https://github.com/jpbrucker/BLE_HID/blob/master/examples/examples_common.cpp
cho45 0:be89b5fdea09 206
cho45 2:c2e3f240640c 207 printf("ble.init\r\n");
cho45 2:c2e3f240640c 208 BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
cho45 2:c2e3f240640c 209 ble.init(bleInitComplete);
cho45 0:be89b5fdea09 210
cho45 2:c2e3f240640c 211 button1.rise(send_stuff);
cho45 0:be89b5fdea09 212
cho45 2:c2e3f240640c 213 while (!ble.hasInitialized()) { }
cho45 0:be89b5fdea09 214
cho45 2:c2e3f240640c 215 printf("ble.hasIntialized\r\n");
cho45 0:be89b5fdea09 216
cho45 2:c2e3f240640c 217 while (1) {
cho45 2:c2e3f240640c 218 ble.waitForEvent();
cho45 2:c2e3f240640c 219 }
cho45 2:c2e3f240640c 220 }