ble nano hid over gatt

Dependencies:   BLE_API mbed-dev nRF51822

Committer:
cho45
Date:
Thu Sep 01 19:33:25 2016 +0000
Revision:
67:81a545a4963c
Parent:
66:a7c6fbe45cf5
Child:
68:13e2343452d5
WDT ?????????

Who changed what in which revision?

UserRevisionLine numberNew contents of line
cho45 6:f1c3ea8bc850 1 #include "mbed.h"
cho45 6:f1c3ea8bc850 2 #include "BLE.h"
cho45 42:2c3be8694896 3
cho45 42:2c3be8694896 4 #include "config.h"
cho45 67:81a545a4963c 5 #include "WatchDog.h"
cho45 6:f1c3ea8bc850 6 #include "KeyboardService.h"
cho45 6:f1c3ea8bc850 7 #include "BatteryService.h"
cho45 6:f1c3ea8bc850 8 #include "DeviceInformationService.h"
cho45 15:70bf079d3ee1 9 #include "DFUService.h"
cho45 6:f1c3ea8bc850 10 #include "HIDController_BLE.h"
cho45 6:f1c3ea8bc850 11
cho45 59:2d6c0bff2151 12 static const char MANUFACTURERERS_NAME[] = "lowreal.net";
cho45 47:5bf2ae8cc710 13 static const char MODEL_NAME[] = "keble";
cho45 6:f1c3ea8bc850 14 static const char SERIAL_NUMBER[] = "X00000";
cho45 6:f1c3ea8bc850 15 static const char HARDWARE_REVISION[] = "0.1";
cho45 6:f1c3ea8bc850 16 static const char FIRMWARE_REVISION[] = "0.1";
cho45 6:f1c3ea8bc850 17 static const char SOFTWARE_REVISION[] = "0.0";
cho45 6:f1c3ea8bc850 18
cho45 47:5bf2ae8cc710 19 static const uint8_t DEVICE_NAME[] = "Keble";
cho45 6:f1c3ea8bc850 20
cho45 6:f1c3ea8bc850 21 static const bool ENABLE_BONDING = true;
cho45 6:f1c3ea8bc850 22 static const bool REQUIRE_MITM = true;
cho45 6:f1c3ea8bc850 23 static const uint8_t PASSKEY[6] = {'1','2','3','4','5','6'}; // must be 6-digits number
cho45 6:f1c3ea8bc850 24
cho45 6:f1c3ea8bc850 25 static const uint16_t uuid16_list[] = {
cho45 6:f1c3ea8bc850 26 GattService::UUID_HUMAN_INTERFACE_DEVICE_SERVICE,
cho45 6:f1c3ea8bc850 27 GattService::UUID_DEVICE_INFORMATION_SERVICE,
cho45 6:f1c3ea8bc850 28 GattService::UUID_BATTERY_SERVICE
cho45 6:f1c3ea8bc850 29 };
cho45 6:f1c3ea8bc850 30
cho45 6:f1c3ea8bc850 31 static KeyboardService* keyboardService;
cho45 6:f1c3ea8bc850 32 static BatteryService* batteryService;
cho45 6:f1c3ea8bc850 33 static DeviceInformationService* deviceInformationService;
cho45 48:d6938de02f62 34 // static DFUService* dfuService;
cho45 6:f1c3ea8bc850 35
cho45 59:2d6c0bff2151 36
cho45 13:b0ffdf2012b9 37 static BLEProtocol::Address_t peerAddress;
cho45 27:7370b8994603 38
cho45 27:7370b8994603 39 static volatile Status_t controllerStatus;
cho45 13:b0ffdf2012b9 40
cho45 6:f1c3ea8bc850 41 static void onConnect(const Gap::ConnectionCallbackParams_t *params) {
cho45 42:2c3be8694896 42 peerAddress.type = params->peerAddrType;
cho45 42:2c3be8694896 43 memcpy(peerAddress.address, params->peerAddr, Gap::ADDR_LEN);
cho45 42:2c3be8694896 44 // TODO whitelist に peerAddr が含まれていない場合 securitySetupCompletedCallback を待ってから CONNECTED にすべき
cho45 29:ec548c473d50 45 controllerStatus = CONNECTED;
cho45 6:f1c3ea8bc850 46 }
cho45 6:f1c3ea8bc850 47
cho45 6:f1c3ea8bc850 48 static void onDisconnect(const Gap::DisconnectionCallbackParams_t *params) {
cho45 27:7370b8994603 49 controllerStatus = DISCONNECTED;
cho45 42:2c3be8694896 50 DEBUG_PRINTF_BLE_INTERRUPT("onDisconnect\r\n");
cho45 6:f1c3ea8bc850 51 }
cho45 6:f1c3ea8bc850 52
cho45 6:f1c3ea8bc850 53 static void onTimeout(const Gap::TimeoutSource_t source) {
cho45 61:17e9a3afc4f4 54 DEBUG_PRINTF_BLE_INTERRUPT("onTimeout %d\r\n", source);
cho45 61:17e9a3afc4f4 55 switch (source) {
cho45 61:17e9a3afc4f4 56 case Gap::TIMEOUT_SRC_ADVERTISING:
cho45 61:17e9a3afc4f4 57 controllerStatus = TIMEOUT;
cho45 61:17e9a3afc4f4 58 return;
cho45 61:17e9a3afc4f4 59
cho45 61:17e9a3afc4f4 60 // treat following timeout as DISCONNECT (retry advertising)
cho45 61:17e9a3afc4f4 61 case Gap::TIMEOUT_SRC_SECURITY_REQUEST:
cho45 61:17e9a3afc4f4 62 case Gap::TIMEOUT_SRC_SCAN:
cho45 61:17e9a3afc4f4 63 case Gap::TIMEOUT_SRC_CONN:
cho45 61:17e9a3afc4f4 64 controllerStatus = DISCONNECTED;
cho45 61:17e9a3afc4f4 65 return;
cho45 61:17e9a3afc4f4 66 }
cho45 6:f1c3ea8bc850 67 }
cho45 6:f1c3ea8bc850 68
cho45 6:f1c3ea8bc850 69 static void passkeyDisplayCallback(Gap::Handle_t handle, const SecurityManager::Passkey_t passkey) {
cho45 42:2c3be8694896 70 DEBUG_PRINTF_BLE_INTERRUPT("Input passKey: ");
cho45 6:f1c3ea8bc850 71 for (unsigned i = 0; i < Gap::ADDR_LEN; i++) {
cho45 42:2c3be8694896 72 DEBUG_PRINTF_BLE_INTERRUPT("%c", passkey[i]);
cho45 6:f1c3ea8bc850 73 }
cho45 42:2c3be8694896 74 DEBUG_PRINTF_BLE_INTERRUPT("\r\n");
cho45 6:f1c3ea8bc850 75 }
cho45 6:f1c3ea8bc850 76
cho45 6:f1c3ea8bc850 77 static void securitySetupCompletedCallback(Gap::Handle_t handle, SecurityManager::SecurityCompletionStatus_t status) {
cho45 6:f1c3ea8bc850 78 if (status == SecurityManager::SEC_STATUS_SUCCESS) {
cho45 42:2c3be8694896 79 DEBUG_PRINTF_BLE_INTERRUPT("Security success %d\r\n", status);
cho45 42:2c3be8694896 80 DEBUG_PRINTF_BLE_INTERRUPT("Set whitelist\r\n");
cho45 13:b0ffdf2012b9 81 Gap::Whitelist_t whitelist;
cho45 13:b0ffdf2012b9 82 whitelist.size = 1;
cho45 13:b0ffdf2012b9 83 whitelist.capacity = 1;
cho45 13:b0ffdf2012b9 84 whitelist.addresses = &peerAddress;
cho45 13:b0ffdf2012b9 85
cho45 13:b0ffdf2012b9 86 BLE::Instance(BLE::DEFAULT_INSTANCE).gap().setWhitelist(whitelist);
cho45 42:2c3be8694896 87 DEBUG_PRINTF_BLE_INTERRUPT("Set Advertising Policy Mode\r\n");
cho45 13:b0ffdf2012b9 88 // BLE::Instance(BLE::DEFAULT_INSTANCE).gap().setAdvertisingPolicyMode(Gap::ADV_POLICY_FILTER_SCAN_REQS);
cho45 13:b0ffdf2012b9 89 // BLE::Instance(BLE::DEFAULT_INSTANCE).gap().setAdvertisingPolicyMode(Gap::ADV_POLICY_FILTER_CONN_REQS);
cho45 13:b0ffdf2012b9 90 BLE::Instance(BLE::DEFAULT_INSTANCE).gap().setAdvertisingPolicyMode(Gap::ADV_POLICY_FILTER_ALL_REQS);
cho45 6:f1c3ea8bc850 91 } else {
cho45 42:2c3be8694896 92 DEBUG_PRINTF_BLE_INTERRUPT("Security failed %d\r\n", status);
cho45 6:f1c3ea8bc850 93 }
cho45 6:f1c3ea8bc850 94 }
cho45 6:f1c3ea8bc850 95
cho45 6:f1c3ea8bc850 96 static void securitySetupInitiatedCallback(Gap::Handle_t, bool allowBonding, bool requireMITM, SecurityManager::SecurityIOCapabilities_t iocaps) {
cho45 42:2c3be8694896 97 DEBUG_PRINTF_BLE_INTERRUPT("Security setup initiated\r\n");
cho45 6:f1c3ea8bc850 98 }
cho45 6:f1c3ea8bc850 99
cho45 6:f1c3ea8bc850 100 static void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) {
cho45 6:f1c3ea8bc850 101 // https://developer.mbed.org/compiler/#nav:/keyboard/BLE_API/ble/blecommon.h;
cho45 6:f1c3ea8bc850 102 ble_error_t error;
cho45 6:f1c3ea8bc850 103 BLE &ble = params->ble;
cho45 23:b31957ce64e9 104
cho45 27:7370b8994603 105 controllerStatus = DISCONNECTED;
cho45 16:345eebc4f259 106
cho45 16:345eebc4f259 107 /**< Minimum Connection Interval in 1.25 ms units, see BLE_GAP_CP_LIMITS.*/
cho45 66:a7c6fbe45cf5 108 uint16_t minConnectionInterval = Gap::MSEC_TO_GAP_DURATION_UNITS(15);
cho45 65:391ce51e37cc 109 /**< Maximum Connection Interval in 1.25 ms units, see BLE_GAP_CP_LIMITS.*/
cho45 66:a7c6fbe45cf5 110 uint16_t maxConnectionInterval = Gap::MSEC_TO_GAP_DURATION_UNITS(20);
cho45 65:391ce51e37cc 111 /**< Slave Latency in number of connection events, see BLE_GAP_CP_LIMITS.*/
cho45 65:391ce51e37cc 112 uint16_t slaveLatency = 4;
cho45 65:391ce51e37cc 113 /**< Connection Supervision Timeout in 10 ms units, see BLE_GAP_CP_LIMITS.*/
cho45 65:391ce51e37cc 114 uint16_t connectionSupervisionTimeout = 32 * 100;
cho45 65:391ce51e37cc 115 Gap::ConnectionParams_t connectionParams = {
cho45 65:391ce51e37cc 116 minConnectionInterval,
cho45 65:391ce51e37cc 117 maxConnectionInterval,
cho45 65:391ce51e37cc 118 slaveLatency,
cho45 65:391ce51e37cc 119 connectionSupervisionTimeout
cho45 65:391ce51e37cc 120 };
cho45 65:391ce51e37cc 121
cho45 6:f1c3ea8bc850 122 error = params->error;
cho45 6:f1c3ea8bc850 123 if (error != BLE_ERROR_NONE) {
cho45 42:2c3be8694896 124 DEBUG_PRINTF_BLE("error on ble.init() \r\n");
cho45 6:f1c3ea8bc850 125 goto return_error;
cho45 6:f1c3ea8bc850 126 }
cho45 6:f1c3ea8bc850 127
cho45 6:f1c3ea8bc850 128 ble.gap().onDisconnection(onDisconnect);
cho45 6:f1c3ea8bc850 129 ble.gap().onConnection(onConnect);
cho45 6:f1c3ea8bc850 130 ble.gap().onTimeout(onTimeout);
cho45 6:f1c3ea8bc850 131
cho45 42:2c3be8694896 132 // DEBUG_PRINTF_BLE("setup ble security manager\r\n");
cho45 6:f1c3ea8bc850 133 ble.securityManager().onSecuritySetupInitiated(securitySetupInitiatedCallback);
cho45 6:f1c3ea8bc850 134 ble.securityManager().onPasskeyDisplay(passkeyDisplayCallback);
cho45 6:f1c3ea8bc850 135 ble.securityManager().onSecuritySetupCompleted(securitySetupCompletedCallback);
cho45 6:f1c3ea8bc850 136 // bonding with hard-coded passkey.
cho45 57:ae521136842c 137 error = ble.securityManager().init(ENABLE_BONDING, REQUIRE_MITM, SecurityManager::IO_CAPS_DISPLAY_ONLY, PASSKEY);
cho45 6:f1c3ea8bc850 138 if (error != BLE_ERROR_NONE) {
cho45 42:2c3be8694896 139 DEBUG_PRINTF_BLE("error on ble.securityManager().init()");
cho45 6:f1c3ea8bc850 140 goto return_error;
cho45 6:f1c3ea8bc850 141 }
cho45 16:345eebc4f259 142
cho45 6:f1c3ea8bc850 143
cho45 42:2c3be8694896 144 // DEBUG_PRINTF_BLE("new KeyboardService\r\n");
cho45 6:f1c3ea8bc850 145 keyboardService = new KeyboardService(ble);
cho45 42:2c3be8694896 146 // DEBUG_PRINTF_BLE("new DeviceInformationService\r\n");
cho45 59:2d6c0bff2151 147 deviceInformationService = new DeviceInformationService(ble, MANUFACTURERERS_NAME, MODEL_NAME, SERIAL_NUMBER, HARDWARE_REVISION, FIRMWARE_REVISION, SOFTWARE_REVISION);
cho45 42:2c3be8694896 148 // DEBUG_PRINTF_BLE("new BatteryService\r\n");
cho45 6:f1c3ea8bc850 149 batteryService = new BatteryService(ble, 100);
cho45 37:4ce71fa47fc3 150 /** TODO
cho45 42:2c3be8694896 151 DEBUG_PRINTF_BLE("new DFUService\r\n");
cho45 16:345eebc4f259 152 dfuService = new DFUService(ble);
cho45 16:345eebc4f259 153 */
cho45 16:345eebc4f259 154
cho45 42:2c3be8694896 155 //DEBUG_PRINTF_BLE("setup connection params\r\n");
cho45 16:345eebc4f259 156
cho45 65:391ce51e37cc 157 ble.gap().setPreferredConnectionParams(&connectionParams);
cho45 6:f1c3ea8bc850 158
cho45 42:2c3be8694896 159 // DEBUG_PRINTF_BLE("general setup\r\n");
cho45 65:391ce51e37cc 160 // error = ble.gap().accumulateAdvertisingPayload(
cho45 65:391ce51e37cc 161 // GapAdvertisingData::BREDR_NOT_SUPPORTED |
cho45 65:391ce51e37cc 162 // GapAdvertisingData::LE_GENERAL_DISCOVERABLE
cho45 65:391ce51e37cc 163 // );
cho45 65:391ce51e37cc 164 // shoud be LE_LIMITED_DISCOVERABLE
cho45 6:f1c3ea8bc850 165 error = ble.gap().accumulateAdvertisingPayload(
cho45 6:f1c3ea8bc850 166 GapAdvertisingData::BREDR_NOT_SUPPORTED |
cho45 65:391ce51e37cc 167 GapAdvertisingData::LE_LIMITED_DISCOVERABLE
cho45 6:f1c3ea8bc850 168 );
cho45 6:f1c3ea8bc850 169 if (error != BLE_ERROR_NONE) goto return_error;
cho45 6:f1c3ea8bc850 170
cho45 42:2c3be8694896 171 // DEBUG_PRINTF_BLE("set COMPLETE_LIST_16BIT_SERVICE_IDS\r\n");
cho45 6:f1c3ea8bc850 172 error = ble.gap().accumulateAdvertisingPayload(
cho45 6:f1c3ea8bc850 173 GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS,
cho45 6:f1c3ea8bc850 174 (uint8_t*)uuid16_list, sizeof(uuid16_list)
cho45 6:f1c3ea8bc850 175 );
cho45 6:f1c3ea8bc850 176 if (error != BLE_ERROR_NONE) goto return_error;
cho45 6:f1c3ea8bc850 177
cho45 42:2c3be8694896 178 // DEBUG_PRINTF_BLE("set advertising\r\n");
cho45 6:f1c3ea8bc850 179 // see 5.1.2: HID over GATT Specification (pg. 25)
cho45 6:f1c3ea8bc850 180 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
cho45 6:f1c3ea8bc850 181
cho45 42:2c3be8694896 182 // DEBUG_PRINTF_BLE("set advertising interval\r\n");
cho45 28:1f843a3daab0 183 ble.gap().setAdvertisingInterval(20);
cho45 42:2c3be8694896 184 // DEBUG_PRINTF_BLE("set advertising timeout\r\n");
cho45 38:115875b8cb6c 185 ble.gap().setAdvertisingTimeout(30);
cho45 28:1f843a3daab0 186
cho45 28:1f843a3daab0 187 /*
cho45 28:1f843a3daab0 188 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED);
cho45 28:1f843a3daab0 189 ble.gap().setAdvertisingTimeout(1.28);
cho45 28:1f843a3daab0 190 */
cho45 6:f1c3ea8bc850 191
cho45 42:2c3be8694896 192 // DEBUG_PRINTF_BLE("set keyboard\r\n");
cho45 6:f1c3ea8bc850 193 error = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::KEYBOARD);
cho45 6:f1c3ea8bc850 194 if (error != BLE_ERROR_NONE) goto return_error;
cho45 6:f1c3ea8bc850 195
cho45 42:2c3be8694896 196 // DEBUG_PRINTF_BLE("set complete local name\r\n");
cho45 6:f1c3ea8bc850 197 error = ble.gap().accumulateAdvertisingPayload(
cho45 6:f1c3ea8bc850 198 GapAdvertisingData::COMPLETE_LOCAL_NAME,
cho45 6:f1c3ea8bc850 199 DEVICE_NAME, sizeof(DEVICE_NAME)
cho45 6:f1c3ea8bc850 200 );
cho45 6:f1c3ea8bc850 201 if (error != BLE_ERROR_NONE) goto return_error;
cho45 6:f1c3ea8bc850 202
cho45 42:2c3be8694896 203 // DEBUG_PRINTF_BLE("set device name\r\n");
cho45 6:f1c3ea8bc850 204 error = ble.gap().setDeviceName(DEVICE_NAME);
cho45 6:f1c3ea8bc850 205 if (error != BLE_ERROR_NONE) goto return_error;
cho45 22:a78f0a91280a 206 /* (Valid values are -40, -20, -16, -12, -8, -4, 0, 4) */
cho45 19:cd7f2fe05ae4 207 ble.gap().setTxPower(0);
cho45 6:f1c3ea8bc850 208
cho45 65:391ce51e37cc 209 // TODO
cho45 65:391ce51e37cc 210 // ちゃんと接続済みになったら ADV_POLICY_FILTER_ALL_REQS にしないといけないが
cho45 65:391ce51e37cc 211 // ペアリングできてるかどうか知るよしがなくてどうしよもない
cho45 32:6c0f43fda460 212 ble.gap().setAdvertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST);
cho45 23:b31957ce64e9 213
cho45 42:2c3be8694896 214 // DEBUG_PRINTF_BLE("advertising\r\n");
cho45 6:f1c3ea8bc850 215 error = ble.gap().startAdvertising();
cho45 6:f1c3ea8bc850 216 if (error != BLE_ERROR_NONE) goto return_error;
cho45 32:6c0f43fda460 217 controllerStatus = ADVERTISING;
cho45 6:f1c3ea8bc850 218 return;
cho45 6:f1c3ea8bc850 219
cho45 6:f1c3ea8bc850 220 return_error:
cho45 42:2c3be8694896 221 DEBUG_PRINTF_BLE("error with %d\r\n", error);
cho45 6:f1c3ea8bc850 222 return;
cho45 6:f1c3ea8bc850 223 }
cho45 6:f1c3ea8bc850 224
cho45 20:d8840ac38434 225 bool HIDController::connected() {
cho45 27:7370b8994603 226 return controllerStatus == CONNECTED;
cho45 27:7370b8994603 227 }
cho45 27:7370b8994603 228
cho45 27:7370b8994603 229 Status_t HIDController::status() {
cho45 27:7370b8994603 230 return controllerStatus;
cho45 20:d8840ac38434 231 }
cho45 20:d8840ac38434 232
cho45 32:6c0f43fda460 233 const char* HIDController::statusString() {
cho45 59:2d6c0bff2151 234 static const char* const disconnected = "disconnected";
cho45 59:2d6c0bff2151 235 static const char* const connecting = "connecting";
cho45 59:2d6c0bff2151 236 static const char* const connected = "connected";
cho45 59:2d6c0bff2151 237 static const char* const timeout = "timeout";
cho45 59:2d6c0bff2151 238 static const char* const advertising = "advertising";
cho45 59:2d6c0bff2151 239 static const char* const unknown = "unknown";
cho45 32:6c0f43fda460 240
cho45 32:6c0f43fda460 241 return controllerStatus == DISCONNECTED ? disconnected:
cho45 32:6c0f43fda460 242 controllerStatus == CONNECTING ? connecting:
cho45 32:6c0f43fda460 243 controllerStatus == CONNECTED ? connected:
cho45 32:6c0f43fda460 244 controllerStatus == TIMEOUT ? timeout:
cho45 32:6c0f43fda460 245 controllerStatus == ADVERTISING ? advertising:
cho45 32:6c0f43fda460 246 unknown;
cho45 32:6c0f43fda460 247 }
cho45 32:6c0f43fda460 248
cho45 6:f1c3ea8bc850 249 void HIDController::init() {
cho45 6:f1c3ea8bc850 250 // https://github.com/jpbrucker/BLE_HID/blob/master/examples/examples_common.cpp
cho45 42:2c3be8694896 251 DEBUG_PRINTF_BLE("ble.init\r\n");
cho45 6:f1c3ea8bc850 252
cho45 6:f1c3ea8bc850 253 BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
cho45 6:f1c3ea8bc850 254 ble.init(bleInitComplete);
cho45 46:b8f4c050739a 255
cho45 46:b8f4c050739a 256 // copied from https://github.com/lancaster-university/microbit-dal/commit/3c314794f07e5ac91331c9e9849475375708ec89
cho45 46:b8f4c050739a 257 // configure the stack to hold on to CPU during critical timing events.
cho45 46:b8f4c050739a 258 // mbed-classic performs __disabe_irq calls in its timers, which can cause MIC failures
cho45 46:b8f4c050739a 259 // on secure BLE channels.
cho45 65:391ce51e37cc 260 ble_common_opt_radio_cpu_mutex_t opt;
cho45 65:391ce51e37cc 261 opt.enable = 1;
cho45 65:391ce51e37cc 262 sd_ble_opt_set(BLE_COMMON_OPT_RADIO_CPU_MUTEX, (const ble_opt_t *)&opt);
cho45 46:b8f4c050739a 263
cho45 6:f1c3ea8bc850 264 while (!ble.hasInitialized()) { }
cho45 42:2c3be8694896 265 DEBUG_PRINTF_BLE("ble.hasIntialized\r\n");
cho45 6:f1c3ea8bc850 266 }
cho45 6:f1c3ea8bc850 267
cho45 22:a78f0a91280a 268
cho45 10:1aed2481a743 269 void HIDController::waitForEvent() {
cho45 6:f1c3ea8bc850 270 BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
cho45 45:f4be69c936f6 271 keyboardService->processSend();
cho45 67:81a545a4963c 272 // SoftDevice が waitForEvent 中でも起きて
cho45 67:81a545a4963c 273 // じわじわと WDT のカウンタがすすんでリセットされてしまう(きがする)
cho45 67:81a545a4963c 274 // ので、waitForEvent 前には止める
cho45 58:64df960619ce 275 if (DEBUG_BLE_INTERRUPT) {
cho45 67:81a545a4963c 276 WatchDog::disable();
cho45 58:64df960619ce 277 ble.waitForEvent();
cho45 67:81a545a4963c 278 WatchDog::enable();
cho45 58:64df960619ce 279 } else {
cho45 58:64df960619ce 280 // disable internal HFCLK RC Clock surely. It consume 1mA constantly
cho45 58:64df960619ce 281 // TWI / SPI / UART must be disabled and boot without debug mode
cho45 58:64df960619ce 282 while (NRF_UART0->EVENTS_TXDRDY != 1);
cho45 58:64df960619ce 283
cho45 58:64df960619ce 284 const uint32_t tx = NRF_UART0->PSELTXD;
cho45 58:64df960619ce 285
cho45 58:64df960619ce 286 NRF_UART0->TASKS_STOPTX = 1;
cho45 58:64df960619ce 287 NRF_UART0->ENABLE = (UART_ENABLE_ENABLE_Disabled << UART_ENABLE_ENABLE_Pos);
cho45 58:64df960619ce 288
cho45 67:81a545a4963c 289 WatchDog::disable();
cho45 58:64df960619ce 290 ble.waitForEvent();
cho45 67:81a545a4963c 291 WatchDog::enable();
cho45 58:64df960619ce 292
cho45 58:64df960619ce 293 NRF_UART0->ENABLE = (UART_ENABLE_ENABLE_Enabled << UART_ENABLE_ENABLE_Pos);
cho45 58:64df960619ce 294 NRF_UART0->TASKS_STARTTX = 1;
cho45 58:64df960619ce 295 // dummy send to wakeup...
cho45 58:64df960619ce 296 NRF_UART0->PSELTXD = 0xFFFFFFFF;
cho45 58:64df960619ce 297 NRF_UART0->EVENTS_TXDRDY = 0;
cho45 58:64df960619ce 298 NRF_UART0->TXD = 0;
cho45 58:64df960619ce 299 while (NRF_UART0->EVENTS_TXDRDY != 1);
cho45 58:64df960619ce 300 NRF_UART0->PSELTXD = tx;
cho45 58:64df960619ce 301 }
cho45 6:f1c3ea8bc850 302 }
cho45 6:f1c3ea8bc850 303
cho45 48:d6938de02f62 304 void HIDController::appendReportData(const uint8_t key) {
cho45 6:f1c3ea8bc850 305 if (keyboardService) {
cho45 6:f1c3ea8bc850 306 keyboardService->appendReportData(key);
cho45 6:f1c3ea8bc850 307 }
cho45 6:f1c3ea8bc850 308 }
cho45 6:f1c3ea8bc850 309
cho45 48:d6938de02f62 310 void HIDController::deleteReportData(const uint8_t key) {
cho45 6:f1c3ea8bc850 311 if (keyboardService) {
cho45 6:f1c3ea8bc850 312 keyboardService->deleteReportData(key);
cho45 6:f1c3ea8bc850 313 }
cho45 6:f1c3ea8bc850 314 }
cho45 9:d1daefbf1fbd 315
cho45 9:d1daefbf1fbd 316 void HIDController::queueCurrentReportData() {
cho45 29:ec548c473d50 317 if (!connected()) return;
cho45 9:d1daefbf1fbd 318 if (keyboardService) {
cho45 60:b899414e1d34 319 DEBUG_PRINTF_BLE("Q %d\r\n", keyboardService->bufferCount);
cho45 9:d1daefbf1fbd 320 keyboardService->queueCurrentReportData();
cho45 9:d1daefbf1fbd 321 }
cho45 9:d1daefbf1fbd 322 }
cho45 37:4ce71fa47fc3 323
cho45 58:64df960619ce 324 void HIDController::updateBatteryLevel(const uint8_t percentage, const uint16_t voltage) {
cho45 37:4ce71fa47fc3 325 if (!batteryService) return;
cho45 58:64df960619ce 326 batteryService->updateBatteryLevel(percentage, voltage);
cho45 37:4ce71fa47fc3 327 }
cho45 37:4ce71fa47fc3 328
cho45 48:d6938de02f62 329 void HIDController::initializeConnection(const bool ignoreWhiteList = false) {
cho45 38:115875b8cb6c 330 ble_error_t error;
cho45 38:115875b8cb6c 331 BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
cho45 39:b7889285c9ef 332 ble.gap().setAdvertisingInterval(20);
cho45 39:b7889285c9ef 333 ble.gap().setAdvertisingTimeout(30);
cho45 40:364deaa190fe 334 if (ignoreWhiteList) {
cho45 40:364deaa190fe 335 ble.gap().setAdvertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST);
cho45 40:364deaa190fe 336 }
cho45 38:115875b8cb6c 337
cho45 42:2c3be8694896 338 // DEBUG_PRINTF_BLE("advertising\r\n");
cho45 38:115875b8cb6c 339 error = ble.gap().startAdvertising();
cho45 38:115875b8cb6c 340 if (error != BLE_ERROR_NONE) goto return_error;
cho45 38:115875b8cb6c 341 controllerStatus = ADVERTISING;
cho45 38:115875b8cb6c 342 return;
cho45 38:115875b8cb6c 343
cho45 38:115875b8cb6c 344 return_error:
cho45 42:2c3be8694896 345 DEBUG_PRINTF_BLE("error with %d\r\n", error);
cho45 38:115875b8cb6c 346 return;
cho45 65:391ce51e37cc 347 }