Nordic stack and drivers for the mbed BLE API. Version to work around build bug.
Dependents: microbit_rubber_ducky microbit_mouse_BLE microbit_mouse_BLE_daybreak_version microbit_presenter
Fork of nRF51822 by
nRF5xGap.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "nRF5xn.h" 00018 #ifdef YOTTA_CFG_MBED_OS 00019 #include "mbed-drivers/mbed.h" 00020 #else 00021 #include "mbed.h" 00022 #endif 00023 #include "ble/BLE.h" 00024 00025 #include "common/common.h" 00026 #include "ble_advdata.h " 00027 #include "ble_hci.h" 00028 00029 void radioNotificationStaticCallback(bool param) { 00030 nRF5xGap &gap = (nRF5xGap &) nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getGap(); 00031 gap.processRadioNotificationEvent(param); 00032 } 00033 00034 /**************************************************************************/ 00035 /*! 00036 @brief Sets the advertising parameters and payload for the device 00037 00038 @param[in] params 00039 Basic advertising details, including the advertising 00040 delay, timeout and how the device should be advertised 00041 @params[in] advData 00042 The primary advertising data payload 00043 @params[in] scanResponse 00044 The optional Scan Response payload if the advertising 00045 type is set to \ref GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED 00046 in \ref GapAdveritinngParams 00047 00048 @returns \ref ble_error_t 00049 00050 @retval BLE_ERROR_NONE 00051 Everything executed properly 00052 00053 @retval BLE_ERROR_BUFFER_OVERFLOW 00054 The proposed action would cause a buffer overflow. All 00055 advertising payloads must be <= 31 bytes, for example. 00056 00057 @retval BLE_ERROR_NOT_IMPLEMENTED 00058 A feature was requested that is not yet supported in the 00059 nRF51 firmware or hardware. 00060 00061 @retval BLE_ERROR_PARAM_OUT_OF_RANGE 00062 One of the proposed values is outside the valid range. 00063 00064 @section EXAMPLE 00065 00066 @code 00067 00068 @endcode 00069 */ 00070 /**************************************************************************/ 00071 ble_error_t nRF5xGap::setAdvertisingData(const GapAdvertisingData &advData, const GapAdvertisingData &scanResponse) 00072 { 00073 /* Make sure we don't exceed the advertising payload length */ 00074 if (advData.getPayloadLen() > GAP_ADVERTISING_DATA_MAX_PAYLOAD) { 00075 return BLE_ERROR_BUFFER_OVERFLOW; 00076 } 00077 00078 /* Make sure we have a payload! */ 00079 if (advData.getPayloadLen() == 0) { 00080 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00081 } 00082 00083 /* Check the scan response payload limits */ 00084 //if ((params.getAdvertisingType() == GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED)) 00085 //{ 00086 // /* Check if we're within the upper limit */ 00087 // if (advData.getPayloadLen() > GAP_ADVERTISING_DATA_MAX_PAYLOAD) 00088 // { 00089 // return BLE_ERROR_BUFFER_OVERFLOW; 00090 // } 00091 // /* Make sure we have a payload! */ 00092 // if (advData.getPayloadLen() == 0) 00093 // { 00094 // return BLE_ERROR_PARAM_OUT_OF_RANGE; 00095 // } 00096 //} 00097 00098 /* Send advertising data! */ 00099 ASSERT(ERROR_NONE == 00100 sd_ble_gap_adv_data_set(advData.getPayload(), 00101 advData.getPayloadLen(), 00102 scanResponse.getPayload(), 00103 scanResponse.getPayloadLen()), 00104 BLE_ERROR_PARAM_OUT_OF_RANGE); 00105 00106 /* Make sure the GAP Service appearance value is aligned with the 00107 *appearance from GapAdvertisingData */ 00108 ASSERT(ERROR_NONE == sd_ble_gap_appearance_set(advData.getAppearance()), 00109 BLE_ERROR_PARAM_OUT_OF_RANGE); 00110 00111 /* ToDo: Perform some checks on the payload, for example the Scan Response can't */ 00112 /* contains a flags AD type, etc. */ 00113 00114 return BLE_ERROR_NONE; 00115 } 00116 00117 /**************************************************************************/ 00118 /*! 00119 @brief Starts the BLE HW, initialising any services that were 00120 added before this function was called. 00121 00122 @note All services must be added before calling this function! 00123 00124 @returns ble_error_t 00125 00126 @retval BLE_ERROR_NONE 00127 Everything executed properly 00128 00129 @section EXAMPLE 00130 00131 @code 00132 00133 @endcode 00134 */ 00135 /**************************************************************************/ 00136 ble_error_t nRF5xGap::startAdvertising(const GapAdvertisingParams ¶ms) 00137 { 00138 /* Make sure we support the advertising type */ 00139 if (params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) { 00140 /* ToDo: This requires a propery security implementation, etc. */ 00141 return BLE_ERROR_NOT_IMPLEMENTED; 00142 } 00143 00144 /* Check interval range */ 00145 if (params.getAdvertisingType() == GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED) { 00146 /* Min delay is slightly longer for unconnectable devices */ 00147 if ((params.getIntervalInADVUnits() < GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN_NONCON) || 00148 (params.getIntervalInADVUnits() > GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX)) { 00149 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00150 } 00151 } else { 00152 if ((params.getIntervalInADVUnits() < GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN) || 00153 (params.getIntervalInADVUnits() > GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX)) { 00154 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00155 } 00156 } 00157 00158 /* Check timeout is zero for Connectable Directed */ 00159 if ((params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) && (params.getTimeout() != 0)) { 00160 /* Timeout must be 0 with this type, although we'll never get here */ 00161 /* since this isn't implemented yet anyway */ 00162 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00163 } 00164 00165 /* Check timeout for other advertising types */ 00166 if ((params.getAdvertisingType() != GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) && 00167 (params.getTimeout() > GapAdvertisingParams::GAP_ADV_PARAMS_TIMEOUT_MAX)) { 00168 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00169 } 00170 00171 /* Allocate the stack's whitelist statically */ 00172 ble_gap_whitelist_t whitelist; 00173 ble_gap_addr_t *whitelistAddressPtrs[YOTTA_CFG_WHITELIST_MAX_SIZE]; 00174 ble_gap_irk_t *whitelistIrkPtrs[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; 00175 /* Initialize the whitelist */ 00176 whitelist.pp_addrs = whitelistAddressPtrs; 00177 whitelist.pp_irks = whitelistIrkPtrs; 00178 whitelist.addr_count = 0; 00179 whitelist.irk_count = 0; 00180 00181 /* Add missing IRKs to whitelist from the bond table held by the SoftDevice */ 00182 if (advertisingPolicyMode != Gap::ADV_POLICY_IGNORE_WHITELIST) { 00183 ble_error_t error = generateStackWhitelist(whitelist); 00184 if (error != BLE_ERROR_NONE) { 00185 return error; 00186 } 00187 } 00188 00189 /* Start Advertising */ 00190 ble_gap_adv_params_t adv_para = {0}; 00191 00192 adv_para.type = params.getAdvertisingType(); 00193 adv_para.p_peer_addr = NULL; // Undirected advertisement 00194 adv_para.fp = advertisingPolicyMode; 00195 adv_para.p_whitelist = &whitelist; 00196 adv_para.interval = params.getIntervalInADVUnits(); // advertising interval (in units of 0.625 ms) 00197 adv_para.timeout = params.getTimeout(); 00198 00199 ASSERT(ERROR_NONE == sd_ble_gap_adv_start(&adv_para), BLE_ERROR_PARAM_OUT_OF_RANGE); 00200 00201 state.advertising = 1; 00202 00203 return BLE_ERROR_NONE; 00204 } 00205 00206 /* Observer role is not supported by S110, return BLE_ERROR_NOT_IMPLEMENTED */ 00207 #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) 00208 ble_error_t nRF5xGap::startRadioScan(const GapScanningParams &scanningParams) 00209 { 00210 /* Allocate the stack's whitelist statically */ 00211 ble_gap_whitelist_t whitelist; 00212 ble_gap_addr_t *whitelistAddressPtrs[YOTTA_CFG_WHITELIST_MAX_SIZE]; 00213 ble_gap_irk_t *whitelistIrkPtrs[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; 00214 /* Initialize the whitelist */ 00215 whitelist.pp_addrs = whitelistAddressPtrs; 00216 whitelist.pp_irks = whitelistIrkPtrs; 00217 whitelist.addr_count = 0; 00218 whitelist.irk_count = 0; 00219 00220 /* Add missing IRKs to whitelist from the bond table held by the SoftDevice */ 00221 if (scanningPolicyMode != Gap::SCAN_POLICY_IGNORE_WHITELIST) { 00222 ble_error_t error = generateStackWhitelist(whitelist); 00223 if (error != BLE_ERROR_NONE) { 00224 return error; 00225 } 00226 } 00227 00228 ble_gap_scan_params_t scanParams = { 00229 .active = scanningParams.getActiveScanning(), /**< If 1, perform active scanning (scan requests). */ 00230 .selective = scanningPolicyMode, /**< If 1, ignore unknown devices (non whitelisted). */ 00231 .p_whitelist = &whitelist, /**< Pointer to whitelist, NULL if none is given. */ 00232 .interval = scanningParams.getInterval(), /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ 00233 .window = scanningParams.getWindow(), /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ 00234 .timeout = scanningParams.getTimeout(), /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ 00235 }; 00236 00237 if (sd_ble_gap_scan_start(&scanParams) != NRF_SUCCESS) { 00238 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00239 } 00240 00241 return BLE_ERROR_NONE; 00242 } 00243 00244 ble_error_t nRF5xGap::stopScan(void) { 00245 if (sd_ble_gap_scan_stop() == NRF_SUCCESS) { 00246 return BLE_ERROR_NONE; 00247 } 00248 00249 return BLE_STACK_BUSY; 00250 } 00251 #endif 00252 00253 /**************************************************************************/ 00254 /*! 00255 @brief Stops the BLE HW and disconnects from any devices 00256 00257 @returns ble_error_t 00258 00259 @retval BLE_ERROR_NONE 00260 Everything executed properly 00261 00262 @section EXAMPLE 00263 00264 @code 00265 00266 @endcode 00267 */ 00268 /**************************************************************************/ 00269 ble_error_t nRF5xGap::stopAdvertising(void) 00270 { 00271 /* Stop Advertising */ 00272 ASSERT(ERROR_NONE == sd_ble_gap_adv_stop(), BLE_ERROR_PARAM_OUT_OF_RANGE); 00273 00274 state.advertising = 0; 00275 00276 return BLE_ERROR_NONE; 00277 } 00278 00279 ble_error_t nRF5xGap::connect(const Address_t peerAddr, 00280 BLEProtocol::AddressType_t peerAddrType, 00281 const ConnectionParams_t *connectionParams, 00282 const GapScanningParams *scanParamsIn) 00283 { 00284 ble_gap_addr_t addr; 00285 addr.addr_type = peerAddrType; 00286 memcpy(addr.addr, peerAddr, Gap::ADDR_LEN); 00287 00288 ble_gap_conn_params_t connParams; 00289 if (connectionParams != NULL) { 00290 connParams.min_conn_interval = connectionParams->minConnectionInterval; 00291 connParams.max_conn_interval = connectionParams->maxConnectionInterval; 00292 connParams.slave_latency = connectionParams->slaveLatency; 00293 connParams.conn_sup_timeout = connectionParams->connectionSupervisionTimeout; 00294 } else { 00295 connParams.min_conn_interval = 50; 00296 connParams.max_conn_interval = 100; 00297 connParams.slave_latency = 0; 00298 connParams.conn_sup_timeout = 600; 00299 } 00300 00301 /* Allocate the stack's whitelist statically */ 00302 ble_gap_whitelist_t whitelist; 00303 ble_gap_addr_t *whitelistAddressPtrs[YOTTA_CFG_WHITELIST_MAX_SIZE]; 00304 ble_gap_irk_t *whitelistIrkPtrs[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; 00305 /* Initialize the whitelist */ 00306 whitelist.pp_addrs = whitelistAddressPtrs; 00307 whitelist.pp_irks = whitelistIrkPtrs; 00308 whitelist.addr_count = 0; 00309 whitelist.irk_count = 0; 00310 00311 /* Add missing IRKs to whitelist from the bond table held by the SoftDevice */ 00312 if (scanningPolicyMode != Gap::SCAN_POLICY_IGNORE_WHITELIST) { 00313 ble_error_t error = generateStackWhitelist(whitelist); 00314 if (error != BLE_ERROR_NONE) { 00315 return error; 00316 } 00317 } 00318 00319 ble_gap_scan_params_t scanParams; 00320 scanParams.selective = scanningPolicyMode; /**< If 1, ignore unknown devices (non whitelisted). */ 00321 scanParams.p_whitelist = &whitelist; /**< Pointer to whitelist, NULL if none is given. */ 00322 if (scanParamsIn != NULL) { 00323 scanParams.active = scanParamsIn->getActiveScanning(); /**< If 1, perform active scanning (scan requests). */ 00324 scanParams.interval = scanParamsIn->getInterval(); /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ 00325 scanParams.window = scanParamsIn->getWindow(); /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ 00326 scanParams.timeout = scanParamsIn->getTimeout(); /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ 00327 } else { 00328 scanParams.active = _scanningParams.getActiveScanning(); /**< If 1, perform active scanning (scan requests). */ 00329 scanParams.interval = _scanningParams.getInterval(); /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ 00330 scanParams.window = _scanningParams.getWindow(); /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ 00331 scanParams.timeout = _scanningParams.getTimeout(); /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ 00332 } 00333 00334 uint32_t rc = sd_ble_gap_connect(&addr, &scanParams, &connParams); 00335 if (rc == NRF_SUCCESS) { 00336 return BLE_ERROR_NONE; 00337 } 00338 switch (rc) { 00339 case NRF_ERROR_INVALID_ADDR: 00340 return BLE_ERROR_INVALID_PARAM; 00341 case NRF_ERROR_INVALID_PARAM: 00342 return BLE_ERROR_INVALID_PARAM; 00343 case NRF_ERROR_INVALID_STATE: 00344 return BLE_ERROR_INVALID_STATE; 00345 case BLE_ERROR_GAP_INVALID_BLE_ADDR: 00346 return BLE_ERROR_INVALID_PARAM; 00347 case NRF_ERROR_NO_MEM: 00348 return BLE_ERROR_NO_MEM; 00349 case NRF_ERROR_BUSY: 00350 return BLE_STACK_BUSY; 00351 default: 00352 case BLE_ERROR_GAP_WHITELIST_IN_USE: 00353 return BLE_ERROR_UNSPECIFIED; 00354 } 00355 } 00356 00357 ble_error_t nRF5xGap::disconnect(Handle_t connectionHandle, DisconnectionReason_t reason) 00358 { 00359 state.advertising = 0; 00360 state.connected = 0; 00361 00362 uint8_t code = BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION; 00363 switch (reason) { 00364 case REMOTE_USER_TERMINATED_CONNECTION: 00365 code = BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION; 00366 break; 00367 case CONN_INTERVAL_UNACCEPTABLE: 00368 code = BLE_HCI_CONN_INTERVAL_UNACCEPTABLE; 00369 break; 00370 default: 00371 break; 00372 } 00373 00374 /* Disconnect if we are connected to a central device */ 00375 ASSERT_INT(ERROR_NONE, sd_ble_gap_disconnect(connectionHandle, code), BLE_ERROR_PARAM_OUT_OF_RANGE); 00376 00377 return BLE_ERROR_NONE; 00378 } 00379 00380 /*! 00381 @brief Disconnects if we are connected to a central device 00382 00383 @returns ble_error_t 00384 00385 @retval BLE_ERROR_NONE 00386 Everything executed properly 00387 */ 00388 ble_error_t nRF5xGap::disconnect(DisconnectionReason_t reason) 00389 { 00390 return disconnect(m_connectionHandle, reason); 00391 } 00392 00393 ble_error_t nRF5xGap::getPreferredConnectionParams(ConnectionParams_t *params) 00394 { 00395 ASSERT_INT(NRF_SUCCESS, 00396 sd_ble_gap_ppcp_get(reinterpret_cast<ble_gap_conn_params_t *>(params)), 00397 BLE_ERROR_PARAM_OUT_OF_RANGE); 00398 00399 return BLE_ERROR_NONE; 00400 } 00401 00402 ble_error_t nRF5xGap::setPreferredConnectionParams(const ConnectionParams_t *params) 00403 { 00404 ASSERT_INT(NRF_SUCCESS, 00405 sd_ble_gap_ppcp_set(reinterpret_cast<const ble_gap_conn_params_t *>(params)), 00406 BLE_ERROR_PARAM_OUT_OF_RANGE); 00407 00408 return BLE_ERROR_NONE; 00409 } 00410 00411 ble_error_t nRF5xGap::updateConnectionParams(Handle_t handle, const ConnectionParams_t *newParams) 00412 { 00413 uint32_t rc; 00414 00415 rc = sd_ble_gap_conn_param_update(handle, reinterpret_cast<ble_gap_conn_params_t *>(const_cast<ConnectionParams_t*>(newParams))); 00416 if (rc == NRF_SUCCESS) { 00417 return BLE_ERROR_NONE; 00418 } else { 00419 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00420 } 00421 } 00422 00423 /**************************************************************************/ 00424 /*! 00425 @brief Clear nRF5xGap's state. 00426 00427 @returns ble_error_t 00428 00429 @retval BLE_ERROR_NONE 00430 Everything executed properly 00431 */ 00432 /**************************************************************************/ 00433 ble_error_t nRF5xGap::reset(void) 00434 { 00435 /* Clear all state that is from the parent, including private members */ 00436 if (Gap::reset() != BLE_ERROR_NONE) { 00437 return BLE_ERROR_INVALID_STATE; 00438 } 00439 00440 /* Clear derived class members */ 00441 m_connectionHandle = BLE_CONN_HANDLE_INVALID; 00442 00443 /* Set the whitelist policy filter modes to IGNORE_WHITELIST */ 00444 advertisingPolicyMode = Gap::ADV_POLICY_IGNORE_WHITELIST; 00445 scanningPolicyMode = Gap::SCAN_POLICY_IGNORE_WHITELIST; 00446 00447 /* Clear the internal whitelist */ 00448 whitelistAddressesSize = 0; 00449 00450 return BLE_ERROR_NONE; 00451 } 00452 00453 /**************************************************************************/ 00454 /*! 00455 @brief Sets the 16-bit connection handle 00456 */ 00457 /**************************************************************************/ 00458 void nRF5xGap::setConnectionHandle(uint16_t con_handle) 00459 { 00460 m_connectionHandle = con_handle; 00461 } 00462 00463 /**************************************************************************/ 00464 /*! 00465 @brief Gets the 16-bit connection handle 00466 */ 00467 /**************************************************************************/ 00468 uint16_t nRF5xGap::getConnectionHandle(void) 00469 { 00470 return m_connectionHandle; 00471 } 00472 00473 /**************************************************************************/ 00474 /*! 00475 @brief Sets the BLE device address 00476 00477 @returns ble_error_t 00478 00479 @section EXAMPLE 00480 00481 @code 00482 00483 uint8_t device_address[6] = { 0xca, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0 }; 00484 nrf.getGap().setAddress(Gap::BLEProtocol::AddressType::RANDOM_STATIC, device_address); 00485 00486 @endcode 00487 */ 00488 /**************************************************************************/ 00489 ble_error_t nRF5xGap::setAddress(AddressType_t type, const Address_t address) 00490 { 00491 uint8_t cycle_mode; 00492 ble_gap_addr_t dev_addr; 00493 00494 /* When using Public or Static addresses, the cycle mode must be None. 00495 When using Random Private addresses, the cycle mode must be Auto. 00496 In auto mode, the given address is ignored. 00497 */ 00498 if ((type == BLEProtocol::AddressType::PUBLIC) || (type == BLEProtocol::AddressType::RANDOM_STATIC)) 00499 { 00500 cycle_mode = BLE_GAP_ADDR_CYCLE_MODE_NONE; 00501 memcpy(dev_addr.addr, address, ADDR_LEN); 00502 } 00503 else if ((type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) || (type == BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE)) 00504 { 00505 cycle_mode = BLE_GAP_ADDR_CYCLE_MODE_AUTO; 00506 // address is ignored when in auto mode 00507 } 00508 else 00509 { 00510 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00511 } 00512 00513 dev_addr.addr_type = type; 00514 ASSERT_INT(ERROR_NONE, sd_ble_gap_address_set(cycle_mode, &dev_addr), BLE_ERROR_PARAM_OUT_OF_RANGE); 00515 00516 return BLE_ERROR_NONE; 00517 } 00518 00519 ble_error_t nRF5xGap::getAddress(AddressType_t *typeP, Address_t address) 00520 { 00521 ble_gap_addr_t dev_addr; 00522 if (sd_ble_gap_address_get(&dev_addr) != NRF_SUCCESS) { 00523 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00524 } 00525 00526 if (typeP != NULL) { 00527 *typeP = static_cast<AddressType_t>(dev_addr.addr_type); 00528 } 00529 if (address != NULL) { 00530 memcpy(address, dev_addr.addr, ADDR_LEN); 00531 } 00532 return BLE_ERROR_NONE; 00533 } 00534 00535 ble_error_t nRF5xGap::setDeviceName(const uint8_t *deviceName) 00536 { 00537 ble_gap_conn_sec_mode_t sec_mode; 00538 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); // no security is needed 00539 00540 if (sd_ble_gap_device_name_set(&sec_mode, deviceName, strlen((const char *)deviceName)) == NRF_SUCCESS) { 00541 return BLE_ERROR_NONE; 00542 } else { 00543 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00544 } 00545 } 00546 00547 ble_error_t nRF5xGap::getDeviceName(uint8_t *deviceName, unsigned *lengthP) 00548 { 00549 if (sd_ble_gap_device_name_get(deviceName, (uint16_t *)lengthP) == NRF_SUCCESS) { 00550 return BLE_ERROR_NONE; 00551 } else { 00552 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00553 } 00554 } 00555 00556 ble_error_t nRF5xGap::setAppearance(GapAdvertisingData::Appearance appearance) 00557 { 00558 if (sd_ble_gap_appearance_set(appearance) == NRF_SUCCESS) { 00559 return BLE_ERROR_NONE; 00560 } else { 00561 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00562 } 00563 } 00564 00565 ble_error_t nRF5xGap::getAppearance(GapAdvertisingData::Appearance *appearanceP) 00566 { 00567 if ((sd_ble_gap_appearance_get(reinterpret_cast<uint16_t *>(appearanceP)) == NRF_SUCCESS)) { 00568 return BLE_ERROR_NONE; 00569 } else { 00570 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00571 } 00572 } 00573 00574 /* (Valid values are -40, -20, -16, -12, -8, -4, 0, 4) */ 00575 ble_error_t nRF5xGap::setTxPower(int8_t txPower) 00576 { 00577 unsigned rc; 00578 if ((rc = sd_ble_gap_tx_power_set(txPower)) != NRF_SUCCESS) { 00579 switch (rc) { 00580 case NRF_ERROR_BUSY: 00581 return BLE_STACK_BUSY; 00582 case NRF_ERROR_INVALID_PARAM: 00583 default: 00584 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00585 } 00586 } 00587 00588 return BLE_ERROR_NONE; 00589 } 00590 00591 void nRF5xGap::getPermittedTxPowerValues(const int8_t **valueArrayPP, size_t *countP) 00592 { 00593 static const int8_t permittedTxValues[] = { 00594 -40, -30, -20, -16, -12, -8, -4, 0, 4 00595 }; 00596 00597 *valueArrayPP = permittedTxValues; 00598 *countP = sizeof(permittedTxValues) / sizeof(int8_t); 00599 } 00600 00601 /**************************************************************************/ 00602 /*! 00603 @brief Get the capacity of the internal whitelist maintained by this 00604 implementation. 00605 00606 @returns The capacity of the internal whitelist. 00607 00608 @section EXAMPLE 00609 00610 @code 00611 00612 @endcode 00613 */ 00614 /**************************************************************************/ 00615 uint8_t nRF5xGap::getMaxWhitelistSize(void) const 00616 { 00617 return YOTTA_CFG_WHITELIST_MAX_SIZE; 00618 } 00619 00620 /**************************************************************************/ 00621 /*! 00622 @brief Get a copy of the implementation's internal whitelist. 00623 00624 @param[out] whitelistOut 00625 A \ref Gap::Whitelist_t structure containing a copy of the 00626 addresses in the implemenetation's internal whitelist. 00627 00628 @returns \ref ble_errror_t 00629 00630 @retval BLE_ERROR_NONE 00631 Everything executed properly. 00632 00633 @section EXAMPLE 00634 00635 @code 00636 00637 @endcode 00638 */ 00639 /**************************************************************************/ 00640 ble_error_t nRF5xGap::getWhitelist(Gap::Whitelist_t &whitelistOut) const 00641 { 00642 uint8_t i; 00643 for (i = 0; i < whitelistAddressesSize && i < whitelistOut.capacity; ++i) { 00644 memcpy(&whitelistOut.addresses[i], &whitelistAddresses[i], sizeof(BLEProtocol::Address_t)); 00645 } 00646 whitelistOut.size = i; 00647 00648 return BLE_ERROR_NONE; 00649 } 00650 00651 /**************************************************************************/ 00652 /*! 00653 @brief Set the whitelist that will be used in the next call to 00654 startAdvertising(). 00655 00656 @param[in] whitelistIn 00657 A reference to a \ref Gap::Whitelist_t structure 00658 representing a whitelist containing all the white listed 00659 BLE addresses. 00660 00661 @returns \ref ble_errror_t 00662 00663 @retval BLE_ERROR_NONE 00664 Everything executed properly. 00665 00666 BLE_ERROR_INVALID_PARAM 00667 The supplied whitelist contains a private non-resolvable 00668 address 00669 00670 BLE_ERROR_PARAM_OUT_OF_RANGE 00671 The size of the supplied whitelist exceeds the maximum 00672 capacity of the implementation's internal whitelist. 00673 00674 @section EXAMPLE 00675 00676 @code 00677 00678 @endcode 00679 */ 00680 /**************************************************************************/ 00681 ble_error_t nRF5xGap::setWhitelist(const Gap::Whitelist_t &whitelistIn) 00682 { 00683 if (whitelistIn.size > getMaxWhitelistSize()) { 00684 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00685 } 00686 00687 /* Test for invalid parameters before we change the internal state */ 00688 for (uint8_t i = 0; i < whitelistIn.size; ++i) { 00689 if (whitelistIn.addresses[i].type == BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE) { 00690 /* This is not allowed because it is completely meaningless */ 00691 return BLE_ERROR_INVALID_PARAM; 00692 } 00693 } 00694 00695 whitelistAddressesSize = 0; 00696 for (uint8_t i = 0; i < whitelistIn.size; ++i) { 00697 memcpy(&whitelistAddresses[whitelistAddressesSize], &whitelistIn.addresses[i], sizeof(BLEProtocol::Address_t)); 00698 whitelistAddressesSize++; 00699 } 00700 00701 return BLE_ERROR_NONE; 00702 } 00703 00704 /**************************************************************************/ 00705 /*! 00706 @brief Set the advertising policy filter mode that will be used in 00707 the next call to startAdvertising(). 00708 00709 @returns \ref ble_errror_t 00710 00711 @retval BLE_ERROR_NONE 00712 Everything executed properly. 00713 00714 BLE_ERROR_NOT_IMPLEMENTED 00715 This feature is currently note implemented. 00716 00717 @section EXAMPLE 00718 00719 @code 00720 00721 @endcode 00722 */ 00723 /**************************************************************************/ 00724 ble_error_t nRF5xGap::setAdvertisingPolicyMode(Gap::AdvertisingPolicyMode_t mode) 00725 { 00726 advertisingPolicyMode = mode; 00727 00728 return BLE_ERROR_NONE; 00729 } 00730 00731 /**************************************************************************/ 00732 /*! 00733 @brief Set the scanning policy filter mode that will be used in 00734 the next call to startAdvertising(). 00735 00736 @returns \ref ble_errror_t 00737 00738 @retval BLE_ERROR_NONE 00739 Everything executed properly. 00740 00741 BLE_ERROR_NOT_IMPLEMENTED 00742 This feature is currently note implemented. 00743 00744 @section EXAMPLE 00745 00746 @code 00747 00748 @endcode 00749 */ 00750 /**************************************************************************/ 00751 ble_error_t nRF5xGap::setScanningPolicyMode(Gap::ScanningPolicyMode_t mode) 00752 { 00753 scanningPolicyMode = mode; 00754 00755 return BLE_ERROR_NONE; 00756 } 00757 00758 /**************************************************************************/ 00759 /*! 00760 @brief Set the initiator policy filter mode that will be used in 00761 the next call to startAdvertising() 00762 00763 @returns \ref ble_errror_t 00764 00765 @retval BLE_ERROR_NONE 00766 Everything executed properly. 00767 00768 BLE_ERROR_NOT_IMPLEMENTED 00769 This feature is currently note implemented. 00770 00771 @section EXAMPLE 00772 00773 @code 00774 00775 @endcode 00776 */ 00777 /**************************************************************************/ 00778 ble_error_t nRF5xGap::setInitiatorPolicyMode(Gap::InitiatorPolicyMode_t mode) 00779 { 00780 return BLE_ERROR_NOT_IMPLEMENTED; 00781 } 00782 00783 /**************************************************************************/ 00784 /*! 00785 @brief Get the current advertising policy filter mode. 00786 00787 @returns The advertising policy filter mode. 00788 00789 @section EXAMPLE 00790 00791 @code 00792 00793 @endcode 00794 */ 00795 /**************************************************************************/ 00796 Gap::AdvertisingPolicyMode_t nRF5xGap::getAdvertisingPolicyMode(void) const 00797 { 00798 return advertisingPolicyMode; 00799 } 00800 00801 /**************************************************************************/ 00802 /*! 00803 @brief Get the current scanning policy filter mode. 00804 00805 @returns The scanning policy filter mode. 00806 00807 @section EXAMPLE 00808 00809 @code 00810 00811 @endcode 00812 */ 00813 /**************************************************************************/ 00814 Gap::ScanningPolicyMode_t nRF5xGap::getScanningPolicyMode(void) const 00815 { 00816 return scanningPolicyMode; 00817 } 00818 00819 /**************************************************************************/ 00820 /*! 00821 @brief Get the current initiator policy filter mode. 00822 00823 @returns The initiator policy filter mode. 00824 00825 @note Currently initiator filtering using the whitelist is not 00826 implemented in this module. 00827 00828 @section EXAMPLE 00829 00830 @code 00831 00832 @endcode 00833 */ 00834 /**************************************************************************/ 00835 Gap::InitiatorPolicyMode_t nRF5xGap::getInitiatorPolicyMode(void) const 00836 { 00837 return Gap::INIT_POLICY_IGNORE_WHITELIST; 00838 } 00839 00840 /**************************************************************************/ 00841 /*! 00842 @brief Helper function used to populate the ble_gap_whitelist_t that 00843 will be used by the SoftDevice for filtering requests. 00844 00845 @returns \ref ble_error_t 00846 00847 @retval BLE_ERROR_NONE 00848 Everything executed properly 00849 00850 @retval BLE_ERROR_INVALID_STATE 00851 The internal stack was not initialized correctly. 00852 00853 @note Both the SecurityManager and Gap must initialize correctly for 00854 this function to succeed. 00855 00856 @note This function is needed because for the BLE API the whitelist 00857 is just a collection of keys, but for the stack it also includes 00858 the IRK table. 00859 00860 @section EXAMPLE 00861 00862 @code 00863 00864 @endcode 00865 */ 00866 /**************************************************************************/ 00867 ble_error_t nRF5xGap::generateStackWhitelist(ble_gap_whitelist_t &whitelist) 00868 { 00869 ble_gap_whitelist_t whitelistFromBondTable; 00870 ble_gap_addr_t *addressPtr[1]; 00871 ble_gap_irk_t *irkPtr[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; 00872 00873 nRF5xSecurityManager& securityManager = (nRF5xSecurityManager&) nRF5xn::Instance(0).getSecurityManager(); 00874 00875 if (securityManager.hasInitialized()) { 00876 /* We do not care about the addresses, set the count to 0 */ 00877 whitelistFromBondTable.addr_count = 0; 00878 /* The Nordic SDK will return a failure if we set pp_addr to NULL */ 00879 whitelistFromBondTable.pp_addrs = addressPtr; 00880 /* We want all the IRKs we can get because we do not know which ones match the addresses */ 00881 whitelistFromBondTable.irk_count = YOTTA_CFG_IRK_TABLE_MAX_SIZE; 00882 whitelistFromBondTable.pp_irks = irkPtr; 00883 00884 /* Use the security manager to get the IRKs from the bond table */ 00885 ble_error_t error = securityManager.createWhitelistFromBondTable(whitelistFromBondTable); 00886 if (error != BLE_ERROR_NONE) { 00887 return error; 00888 } 00889 } else { 00890 /** 00891 * If there is no security manager then we cannot access the bond table, 00892 * so disable IRK matching 00893 */ 00894 whitelistFromBondTable.addr_count = 0; 00895 whitelistFromBondTable.irk_count = 0; 00896 } 00897 00898 /** 00899 * For every private resolvable address in the local whitelist check if 00900 * there is an IRK for said address in the bond table and add it to the 00901 * local IRK list. 00902 */ 00903 whitelist.irk_count = 0; 00904 whitelist.addr_count = 0; 00905 for (uint8_t i = 0; i < whitelistAddressesSize; ++i) { 00906 if (whitelistAddresses[i].addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) { 00907 /* Test if there is a matching IRK for this private resolvable address */ 00908 for (uint8_t j = 0; j < whitelistFromBondTable.irk_count; ++j) { 00909 if (securityManager.matchAddressAndIrk(&whitelistAddresses[i], whitelistFromBondTable.pp_irks[j])) { 00910 /* Found the corresponding IRK, add it to our local whitelist */ 00911 whitelist.pp_irks[whitelist.irk_count] = whitelistFromBondTable.pp_irks[j]; 00912 whitelist.irk_count++; 00913 /* Make sure we do not look at this IRK again */ 00914 if (j != whitelistFromBondTable.irk_count - 1) { 00915 /** 00916 * This is not the last IRK, so replace the pointer 00917 * with the last pointer in the array 00918 */ 00919 whitelistFromBondTable.pp_irks[j] = 00920 whitelistFromBondTable.pp_irks[whitelistFromBondTable.irk_count - 1]; 00921 } 00922 /** 00923 * If the IRK is the last pointer in the array simply 00924 * decrement the total IRK count 00925 */ 00926 whitelistFromBondTable.irk_count--; 00927 break; 00928 } 00929 } 00930 } else { 00931 /* Include the address into the whitelist */ 00932 whitelist.pp_addrs[whitelist.addr_count] = &whitelistAddresses[i]; 00933 whitelist.addr_count++; 00934 } 00935 } 00936 00937 return BLE_ERROR_NONE; 00938 }
Generated on Tue Jul 12 2022 19:52:03 by 1.7.2