ble nano hid over gatt

Dependencies:   BLE_API mbed-dev nRF51822

Committer:
cho45
Date:
Fri Aug 26 15:39:03 2016 +0000
Revision:
39:b7889285c9ef
Parent:
38:115875b8cb6c
Child:
40:364deaa190fe
timeout ?????HID over GATT??????????

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 6:f1c3ea8bc850 3 #include "KeyboardService.h"
cho45 6:f1c3ea8bc850 4 #include "BatteryService.h"
cho45 6:f1c3ea8bc850 5 #include "DeviceInformationService.h"
cho45 15:70bf079d3ee1 6 #include "DFUService.h"
cho45 6:f1c3ea8bc850 7 #include "HIDController_BLE.h"
cho45 6:f1c3ea8bc850 8
cho45 6:f1c3ea8bc850 9 static const char MODEL_NAME[] = "keyboard";
cho45 6:f1c3ea8bc850 10 static const char SERIAL_NUMBER[] = "X00000";
cho45 6:f1c3ea8bc850 11 static const char HARDWARE_REVISION[] = "0.1";
cho45 6:f1c3ea8bc850 12 static const char FIRMWARE_REVISION[] = "0.1";
cho45 6:f1c3ea8bc850 13 static const char SOFTWARE_REVISION[] = "0.0";
cho45 6:f1c3ea8bc850 14
cho45 6:f1c3ea8bc850 15 static const uint8_t DEVICE_NAME[] = "my keyboard";
cho45 6:f1c3ea8bc850 16 static const uint8_t SHORT_DEVICE_NAME[] = "kbd1";
cho45 6:f1c3ea8bc850 17
cho45 6:f1c3ea8bc850 18 static const bool ENABLE_BONDING = true;
cho45 6:f1c3ea8bc850 19 static const bool REQUIRE_MITM = true;
cho45 6:f1c3ea8bc850 20 static const uint8_t PASSKEY[6] = {'1','2','3','4','5','6'}; // must be 6-digits number
cho45 6:f1c3ea8bc850 21
cho45 6:f1c3ea8bc850 22 static const uint16_t uuid16_list[] = {
cho45 6:f1c3ea8bc850 23 GattService::UUID_HUMAN_INTERFACE_DEVICE_SERVICE,
cho45 6:f1c3ea8bc850 24 GattService::UUID_DEVICE_INFORMATION_SERVICE,
cho45 6:f1c3ea8bc850 25 GattService::UUID_BATTERY_SERVICE
cho45 6:f1c3ea8bc850 26 };
cho45 6:f1c3ea8bc850 27
cho45 6:f1c3ea8bc850 28 static KeyboardService* keyboardService;
cho45 6:f1c3ea8bc850 29 static BatteryService* batteryService;
cho45 6:f1c3ea8bc850 30 static DeviceInformationService* deviceInformationService;
cho45 15:70bf079d3ee1 31 static DFUService* dfuService;
cho45 6:f1c3ea8bc850 32
cho45 13:b0ffdf2012b9 33 static BLEProtocol::Address_t peerAddress;
cho45 27:7370b8994603 34
cho45 27:7370b8994603 35 static volatile Status_t controllerStatus;
cho45 13:b0ffdf2012b9 36
cho45 6:f1c3ea8bc850 37 static void onConnect(const Gap::ConnectionCallbackParams_t *params) {
cho45 13:b0ffdf2012b9 38 peerAddress.type = params->peerAddrType;
cho45 13:b0ffdf2012b9 39 memcpy(peerAddress.address, params->peerAddr, Gap::ADDR_LEN);
cho45 34:7da766a8aa96 40 // TODO whitelist に peerAddr が含まれていない場合 securitySetupCompletedCallback を待ってから CONNECTED にすべき
cho45 29:ec548c473d50 41 controllerStatus = CONNECTED;
cho45 6:f1c3ea8bc850 42 }
cho45 6:f1c3ea8bc850 43
cho45 6:f1c3ea8bc850 44 static void onDisconnect(const Gap::DisconnectionCallbackParams_t *params) {
cho45 27:7370b8994603 45 controllerStatus = DISCONNECTED;
cho45 39:b7889285c9ef 46 BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
cho45 39:b7889285c9ef 47 ble.gap().setAdvertisingInterval(20);
cho45 39:b7889285c9ef 48 // printf("set advertising timeout\r\n");
cho45 39:b7889285c9ef 49 ble.gap().setAdvertisingTimeout(30);
cho45 39:b7889285c9ef 50 ble.gap().startAdvertising();
cho45 6:f1c3ea8bc850 51 }
cho45 6:f1c3ea8bc850 52
cho45 6:f1c3ea8bc850 53 static void onTimeout(const Gap::TimeoutSource_t source) {
cho45 32:6c0f43fda460 54 controllerStatus = TIMEOUT;
cho45 39:b7889285c9ef 55 BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
cho45 39:b7889285c9ef 56 ble.gap().setAdvertisingInterval(1000);
cho45 39:b7889285c9ef 57 // printf("set advertising timeout\r\n");
cho45 39:b7889285c9ef 58 ble.gap().setAdvertisingTimeout(0);
cho45 39:b7889285c9ef 59 ble.gap().startAdvertising();
cho45 6:f1c3ea8bc850 60 }
cho45 6:f1c3ea8bc850 61
cho45 6:f1c3ea8bc850 62 static void passkeyDisplayCallback(Gap::Handle_t handle, const SecurityManager::Passkey_t passkey) {
cho45 29:ec548c473d50 63 /*
cho45 6:f1c3ea8bc850 64 printf("Input passKey: ");
cho45 6:f1c3ea8bc850 65 for (unsigned i = 0; i < Gap::ADDR_LEN; i++) {
cho45 6:f1c3ea8bc850 66 printf("%c", passkey[i]);
cho45 6:f1c3ea8bc850 67 }
cho45 6:f1c3ea8bc850 68 printf("\r\n");
cho45 29:ec548c473d50 69 */
cho45 6:f1c3ea8bc850 70 }
cho45 6:f1c3ea8bc850 71
cho45 6:f1c3ea8bc850 72 static void securitySetupCompletedCallback(Gap::Handle_t handle, SecurityManager::SecurityCompletionStatus_t status) {
cho45 6:f1c3ea8bc850 73 if (status == SecurityManager::SEC_STATUS_SUCCESS) {
cho45 29:ec548c473d50 74 /*
cho45 6:f1c3ea8bc850 75 printf("Security success %d\r\n", status);
cho45 13:b0ffdf2012b9 76 printf("Set whitelist\r\n");
cho45 29:ec548c473d50 77 */
cho45 13:b0ffdf2012b9 78 Gap::Whitelist_t whitelist;
cho45 13:b0ffdf2012b9 79 whitelist.size = 1;
cho45 13:b0ffdf2012b9 80 whitelist.capacity = 1;
cho45 13:b0ffdf2012b9 81 whitelist.addresses = &peerAddress;
cho45 13:b0ffdf2012b9 82
cho45 13:b0ffdf2012b9 83 BLE::Instance(BLE::DEFAULT_INSTANCE).gap().setWhitelist(whitelist);
cho45 29:ec548c473d50 84 //printf("Set Advertising Policy Mode\r\n");
cho45 13:b0ffdf2012b9 85 // BLE::Instance(BLE::DEFAULT_INSTANCE).gap().setAdvertisingPolicyMode(Gap::ADV_POLICY_FILTER_SCAN_REQS);
cho45 13:b0ffdf2012b9 86 // BLE::Instance(BLE::DEFAULT_INSTANCE).gap().setAdvertisingPolicyMode(Gap::ADV_POLICY_FILTER_CONN_REQS);
cho45 13:b0ffdf2012b9 87 BLE::Instance(BLE::DEFAULT_INSTANCE).gap().setAdvertisingPolicyMode(Gap::ADV_POLICY_FILTER_ALL_REQS);
cho45 6:f1c3ea8bc850 88 } else {
cho45 29:ec548c473d50 89 //printf("Security failed %d\r\n", status);
cho45 6:f1c3ea8bc850 90 }
cho45 6:f1c3ea8bc850 91 }
cho45 6:f1c3ea8bc850 92
cho45 6:f1c3ea8bc850 93 static void securitySetupInitiatedCallback(Gap::Handle_t, bool allowBonding, bool requireMITM, SecurityManager::SecurityIOCapabilities_t iocaps) {
cho45 29:ec548c473d50 94 // printf("Security setup initiated\r\n");
cho45 6:f1c3ea8bc850 95 }
cho45 6:f1c3ea8bc850 96
cho45 6:f1c3ea8bc850 97 static void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) {
cho45 6:f1c3ea8bc850 98 // https://developer.mbed.org/compiler/#nav:/keyboard/BLE_API/ble/blecommon.h;
cho45 6:f1c3ea8bc850 99 ble_error_t error;
cho45 6:f1c3ea8bc850 100 BLE &ble = params->ble;
cho45 23:b31957ce64e9 101
cho45 27:7370b8994603 102 controllerStatus = DISCONNECTED;
cho45 16:345eebc4f259 103
cho45 16:345eebc4f259 104 /**< Minimum Connection Interval in 1.25 ms units, see BLE_GAP_CP_LIMITS.*/
cho45 29:ec548c473d50 105 uint16_t minConnectionInterval = Gap::MSEC_TO_GAP_DURATION_UNITS(20);
cho45 16:345eebc4f259 106 /**< Maximum Connection Interval in 1.25 ms units, see BLE_GAP_CP_LIMITS.*/
cho45 29:ec548c473d50 107 uint16_t maxConnectionInterval = Gap::MSEC_TO_GAP_DURATION_UNITS(40);
cho45 16:345eebc4f259 108 /**< Slave Latency in number of connection events, see BLE_GAP_CP_LIMITS.*/
cho45 29:ec548c473d50 109 uint16_t slaveLatency = 4;
cho45 16:345eebc4f259 110 /**< Connection Supervision Timeout in 10 ms units, see BLE_GAP_CP_LIMITS.*/
cho45 16:345eebc4f259 111 uint16_t connectionSupervisionTimeout = 32 * 100;
cho45 16:345eebc4f259 112 Gap::ConnectionParams_t connectionParams = {
cho45 16:345eebc4f259 113 minConnectionInterval,
cho45 16:345eebc4f259 114 maxConnectionInterval,
cho45 16:345eebc4f259 115 slaveLatency,
cho45 16:345eebc4f259 116 connectionSupervisionTimeout
cho45 16:345eebc4f259 117 };
cho45 16:345eebc4f259 118
cho45 6:f1c3ea8bc850 119 error = params->error;
cho45 6:f1c3ea8bc850 120 if (error != BLE_ERROR_NONE) {
cho45 6:f1c3ea8bc850 121 printf("error on ble.init() \r\n");
cho45 6:f1c3ea8bc850 122 goto return_error;
cho45 6:f1c3ea8bc850 123 }
cho45 6:f1c3ea8bc850 124
cho45 6:f1c3ea8bc850 125 ble.gap().onDisconnection(onDisconnect);
cho45 6:f1c3ea8bc850 126 ble.gap().onConnection(onConnect);
cho45 6:f1c3ea8bc850 127 ble.gap().onTimeout(onTimeout);
cho45 6:f1c3ea8bc850 128
cho45 17:3233ee19f716 129 // printf("setup ble security manager\r\n");
cho45 6:f1c3ea8bc850 130 ble.securityManager().onSecuritySetupInitiated(securitySetupInitiatedCallback);
cho45 6:f1c3ea8bc850 131 ble.securityManager().onPasskeyDisplay(passkeyDisplayCallback);
cho45 6:f1c3ea8bc850 132 ble.securityManager().onSecuritySetupCompleted(securitySetupCompletedCallback);
cho45 6:f1c3ea8bc850 133 // bonding with hard-coded passkey.
cho45 6:f1c3ea8bc850 134 error = ble.securityManager().init(ENABLE_BONDING, REQUIRE_MITM, SecurityManager::IO_CAPS_DISPLAY_ONLY, PASSKEY);
cho45 6:f1c3ea8bc850 135 if (error != BLE_ERROR_NONE) {
cho45 6:f1c3ea8bc850 136 printf("error on ble.securityManager().init()");
cho45 6:f1c3ea8bc850 137 goto return_error;
cho45 6:f1c3ea8bc850 138 }
cho45 16:345eebc4f259 139
cho45 6:f1c3ea8bc850 140
cho45 17:3233ee19f716 141 // printf("new KeyboardService\r\n");
cho45 6:f1c3ea8bc850 142 keyboardService = new KeyboardService(ble);
cho45 17:3233ee19f716 143 // printf("new DeviceInformationService\r\n");
cho45 6:f1c3ea8bc850 144 deviceInformationService = new DeviceInformationService(ble, "lowreal.net", MODEL_NAME, SERIAL_NUMBER, HARDWARE_REVISION, FIRMWARE_REVISION, SOFTWARE_REVISION);
cho45 17:3233ee19f716 145 // printf("new BatteryService\r\n");
cho45 6:f1c3ea8bc850 146 batteryService = new BatteryService(ble, 100);
cho45 37:4ce71fa47fc3 147 /** TODO
cho45 16:345eebc4f259 148 printf("new DFUService\r\n");
cho45 16:345eebc4f259 149 dfuService = new DFUService(ble);
cho45 16:345eebc4f259 150 */
cho45 16:345eebc4f259 151
cho45 17:3233ee19f716 152 //printf("setup connection params\r\n");
cho45 16:345eebc4f259 153
cho45 16:345eebc4f259 154 ble.gap().setPreferredConnectionParams(&connectionParams);
cho45 6:f1c3ea8bc850 155
cho45 17:3233ee19f716 156 // printf("general setup\r\n");
cho45 6:f1c3ea8bc850 157 error = ble.gap().accumulateAdvertisingPayload(
cho45 6:f1c3ea8bc850 158 GapAdvertisingData::BREDR_NOT_SUPPORTED |
cho45 6:f1c3ea8bc850 159 GapAdvertisingData::LE_GENERAL_DISCOVERABLE
cho45 6:f1c3ea8bc850 160 );
cho45 9:d1daefbf1fbd 161 // shoud be LE_LIMITED_DISCOVERABLE
cho45 9:d1daefbf1fbd 162 // error = ble.gap().accumulateAdvertisingPayload(
cho45 9:d1daefbf1fbd 163 // GapAdvertisingData::BREDR_NOT_SUPPORTED |
cho45 9:d1daefbf1fbd 164 // GapAdvertisingData::LE_LIMITED_DISCOVERABLE
cho45 9:d1daefbf1fbd 165 // );
cho45 6:f1c3ea8bc850 166 if (error != BLE_ERROR_NONE) goto return_error;
cho45 6:f1c3ea8bc850 167
cho45 17:3233ee19f716 168 // printf("set COMPLETE_LIST_16BIT_SERVICE_IDS\r\n");
cho45 6:f1c3ea8bc850 169 error = ble.gap().accumulateAdvertisingPayload(
cho45 6:f1c3ea8bc850 170 GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS,
cho45 6:f1c3ea8bc850 171 (uint8_t*)uuid16_list, sizeof(uuid16_list)
cho45 6:f1c3ea8bc850 172 );
cho45 6:f1c3ea8bc850 173 if (error != BLE_ERROR_NONE) goto return_error;
cho45 6:f1c3ea8bc850 174
cho45 17:3233ee19f716 175 // printf("set advertising\r\n");
cho45 6:f1c3ea8bc850 176 // see 5.1.2: HID over GATT Specification (pg. 25)
cho45 6:f1c3ea8bc850 177 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
cho45 6:f1c3ea8bc850 178
cho45 17:3233ee19f716 179 // printf("set advertising interval\r\n");
cho45 28:1f843a3daab0 180 ble.gap().setAdvertisingInterval(20);
cho45 17:3233ee19f716 181 // printf("set advertising timeout\r\n");
cho45 38:115875b8cb6c 182 ble.gap().setAdvertisingTimeout(30);
cho45 28:1f843a3daab0 183
cho45 28:1f843a3daab0 184 /*
cho45 28:1f843a3daab0 185 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED);
cho45 28:1f843a3daab0 186 ble.gap().setAdvertisingTimeout(1.28);
cho45 28:1f843a3daab0 187 */
cho45 6:f1c3ea8bc850 188
cho45 17:3233ee19f716 189 // printf("set keyboard\r\n");
cho45 6:f1c3ea8bc850 190 error = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::KEYBOARD);
cho45 6:f1c3ea8bc850 191 if (error != BLE_ERROR_NONE) goto return_error;
cho45 6:f1c3ea8bc850 192
cho45 17:3233ee19f716 193 // printf("set complete local name\r\n");
cho45 6:f1c3ea8bc850 194 error = ble.gap().accumulateAdvertisingPayload(
cho45 6:f1c3ea8bc850 195 GapAdvertisingData::COMPLETE_LOCAL_NAME,
cho45 6:f1c3ea8bc850 196 DEVICE_NAME, sizeof(DEVICE_NAME)
cho45 6:f1c3ea8bc850 197 );
cho45 6:f1c3ea8bc850 198 if (error != BLE_ERROR_NONE) goto return_error;
cho45 6:f1c3ea8bc850 199
cho45 17:3233ee19f716 200 // printf("set device name\r\n");
cho45 6:f1c3ea8bc850 201 error = ble.gap().setDeviceName(DEVICE_NAME);
cho45 6:f1c3ea8bc850 202 if (error != BLE_ERROR_NONE) goto return_error;
cho45 22:a78f0a91280a 203 /* (Valid values are -40, -20, -16, -12, -8, -4, 0, 4) */
cho45 19:cd7f2fe05ae4 204 ble.gap().setTxPower(0);
cho45 6:f1c3ea8bc850 205
cho45 32:6c0f43fda460 206 ble.gap().setAdvertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST);
cho45 23:b31957ce64e9 207
cho45 32:6c0f43fda460 208 // printf("advertising\r\n");
cho45 6:f1c3ea8bc850 209 error = ble.gap().startAdvertising();
cho45 6:f1c3ea8bc850 210 if (error != BLE_ERROR_NONE) goto return_error;
cho45 32:6c0f43fda460 211 controllerStatus = ADVERTISING;
cho45 6:f1c3ea8bc850 212 return;
cho45 6:f1c3ea8bc850 213
cho45 6:f1c3ea8bc850 214 return_error:
cho45 6:f1c3ea8bc850 215 printf("error with %d\r\n", error);
cho45 6:f1c3ea8bc850 216 return;
cho45 6:f1c3ea8bc850 217 }
cho45 6:f1c3ea8bc850 218
cho45 20:d8840ac38434 219 bool HIDController::connected() {
cho45 27:7370b8994603 220 return controllerStatus == CONNECTED;
cho45 27:7370b8994603 221 }
cho45 27:7370b8994603 222
cho45 27:7370b8994603 223 Status_t HIDController::status() {
cho45 27:7370b8994603 224 return controllerStatus;
cho45 20:d8840ac38434 225 }
cho45 20:d8840ac38434 226
cho45 32:6c0f43fda460 227 const char* HIDController::statusString() {
cho45 32:6c0f43fda460 228 static const char* disconnected = "disconnected";
cho45 32:6c0f43fda460 229 static const char* connecting = "connecting";
cho45 32:6c0f43fda460 230 static const char* connected = "connected";
cho45 32:6c0f43fda460 231 static const char* timeout = "timeout";
cho45 32:6c0f43fda460 232 static const char* advertising = "advertising";
cho45 32:6c0f43fda460 233 static const char* unknown = "unknown";
cho45 32:6c0f43fda460 234
cho45 32:6c0f43fda460 235 return controllerStatus == DISCONNECTED ? disconnected:
cho45 32:6c0f43fda460 236 controllerStatus == CONNECTING ? connecting:
cho45 32:6c0f43fda460 237 controllerStatus == CONNECTED ? connected:
cho45 32:6c0f43fda460 238 controllerStatus == TIMEOUT ? timeout:
cho45 32:6c0f43fda460 239 controllerStatus == ADVERTISING ? advertising:
cho45 32:6c0f43fda460 240 unknown;
cho45 32:6c0f43fda460 241 }
cho45 32:6c0f43fda460 242
cho45 6:f1c3ea8bc850 243 void HIDController::init() {
cho45 6:f1c3ea8bc850 244 // https://github.com/jpbrucker/BLE_HID/blob/master/examples/examples_common.cpp
cho45 6:f1c3ea8bc850 245 printf("ble.init\r\n");
cho45 6:f1c3ea8bc850 246
cho45 6:f1c3ea8bc850 247 BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
cho45 6:f1c3ea8bc850 248 ble.init(bleInitComplete);
cho45 6:f1c3ea8bc850 249
cho45 6:f1c3ea8bc850 250 while (!ble.hasInitialized()) { }
cho45 6:f1c3ea8bc850 251 printf("ble.hasIntialized\r\n");
cho45 6:f1c3ea8bc850 252 }
cho45 6:f1c3ea8bc850 253
cho45 22:a78f0a91280a 254
cho45 10:1aed2481a743 255 void HIDController::waitForEvent() {
cho45 6:f1c3ea8bc850 256 BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
cho45 21:d801c32231b0 257 keyboardService->stopReportTicker();
cho45 6:f1c3ea8bc850 258 ble.waitForEvent();
cho45 6:f1c3ea8bc850 259 }
cho45 6:f1c3ea8bc850 260
cho45 6:f1c3ea8bc850 261 void HIDController::appendReportData(uint8_t key) {
cho45 6:f1c3ea8bc850 262 if (keyboardService) {
cho45 6:f1c3ea8bc850 263 keyboardService->appendReportData(key);
cho45 6:f1c3ea8bc850 264 }
cho45 6:f1c3ea8bc850 265 }
cho45 6:f1c3ea8bc850 266
cho45 6:f1c3ea8bc850 267 void HIDController::deleteReportData(uint8_t key) {
cho45 6:f1c3ea8bc850 268 if (keyboardService) {
cho45 6:f1c3ea8bc850 269 keyboardService->deleteReportData(key);
cho45 6:f1c3ea8bc850 270 }
cho45 6:f1c3ea8bc850 271 }
cho45 9:d1daefbf1fbd 272
cho45 9:d1daefbf1fbd 273 void HIDController::queueCurrentReportData() {
cho45 29:ec548c473d50 274 if (!connected()) return;
cho45 9:d1daefbf1fbd 275 if (keyboardService) {
cho45 30:f9ebc769118d 276 printf("Q\r\n");
cho45 9:d1daefbf1fbd 277 keyboardService->queueCurrentReportData();
cho45 9:d1daefbf1fbd 278 }
cho45 9:d1daefbf1fbd 279 }
cho45 37:4ce71fa47fc3 280
cho45 37:4ce71fa47fc3 281 void HIDController::updateBatteryLevel(uint8_t percentage) {
cho45 37:4ce71fa47fc3 282 if (!batteryService) return;
cho45 37:4ce71fa47fc3 283 batteryService->updateBatteryLevel(percentage);
cho45 37:4ce71fa47fc3 284 }
cho45 37:4ce71fa47fc3 285
cho45 38:115875b8cb6c 286 void HIDController::initializeConnection() {
cho45 38:115875b8cb6c 287 ble_error_t error;
cho45 38:115875b8cb6c 288 BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
cho45 39:b7889285c9ef 289 ble.gap().setAdvertisingInterval(20);
cho45 39:b7889285c9ef 290 ble.gap().setAdvertisingTimeout(30);
cho45 38:115875b8cb6c 291 ble.gap().setAdvertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST);
cho45 38:115875b8cb6c 292
cho45 38:115875b8cb6c 293 // printf("advertising\r\n");
cho45 38:115875b8cb6c 294 error = ble.gap().startAdvertising();
cho45 38:115875b8cb6c 295 if (error != BLE_ERROR_NONE) goto return_error;
cho45 38:115875b8cb6c 296 controllerStatus = ADVERTISING;
cho45 38:115875b8cb6c 297 return;
cho45 38:115875b8cb6c 298
cho45 38:115875b8cb6c 299 return_error:
cho45 38:115875b8cb6c 300 printf("error with %d\r\n", error);
cho45 38:115875b8cb6c 301 return;
cho45 38:115875b8cb6c 302 }
cho45 38:115875b8cb6c 303