Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of LinkNode-Test 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 "nRF5xGap.h" 00018 #include "mbed.h" 00019 00020 #include "common/common.h" 00021 #include "ble_advdata.h " 00022 #include "ble_hci.h" 00023 00024 nRF5xGap &nRF5xGap::getInstance() { 00025 static nRF5xGap m_instance; 00026 return m_instance; 00027 } 00028 00029 void radioNotificationStaticCallback(bool param) { 00030 nRF5xGap::getInstance().processRadioNotificationEvent(param); 00031 } 00032 00033 /**************************************************************************/ 00034 /*! 00035 @brief Sets the advertising parameters and payload for the device 00036 00037 @param[in] params 00038 Basic advertising details, including the advertising 00039 delay, timeout and how the device should be advertised 00040 @params[in] advData 00041 The primary advertising data payload 00042 @params[in] scanResponse 00043 The optional Scan Response payload if the advertising 00044 type is set to \ref GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED 00045 in \ref GapAdveritinngParams 00046 00047 @returns \ref ble_error_t 00048 00049 @retval BLE_ERROR_NONE 00050 Everything executed properly 00051 00052 @retval BLE_ERROR_BUFFER_OVERFLOW 00053 The proposed action would cause a buffer overflow. All 00054 advertising payloads must be <= 31 bytes, for example. 00055 00056 @retval BLE_ERROR_NOT_IMPLEMENTED 00057 A feature was requested that is not yet supported in the 00058 nRF51 firmware or hardware. 00059 00060 @retval BLE_ERROR_PARAM_OUT_OF_RANGE 00061 One of the proposed values is outside the valid range. 00062 00063 @section EXAMPLE 00064 00065 @code 00066 00067 @endcode 00068 */ 00069 /**************************************************************************/ 00070 ble_error_t nRF5xGap::setAdvertisingData(const GapAdvertisingData &advData, const GapAdvertisingData &scanResponse) 00071 { 00072 /* Make sure we don't exceed the advertising payload length */ 00073 if (advData.getPayloadLen() > GAP_ADVERTISING_DATA_MAX_PAYLOAD) { 00074 return BLE_ERROR_BUFFER_OVERFLOW; 00075 } 00076 00077 /* Make sure we have a payload! */ 00078 if (advData.getPayloadLen() == 0) { 00079 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00080 } 00081 00082 /* Check the scan response payload limits */ 00083 //if ((params.getAdvertisingType() == GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED)) 00084 //{ 00085 // /* Check if we're within the upper limit */ 00086 // if (advData.getPayloadLen() > GAP_ADVERTISING_DATA_MAX_PAYLOAD) 00087 // { 00088 // return BLE_ERROR_BUFFER_OVERFLOW; 00089 // } 00090 // /* Make sure we have a payload! */ 00091 // if (advData.getPayloadLen() == 0) 00092 // { 00093 // return BLE_ERROR_PARAM_OUT_OF_RANGE; 00094 // } 00095 //} 00096 00097 /* Send advertising data! */ 00098 ASSERT(ERROR_NONE == 00099 sd_ble_gap_adv_data_set(advData.getPayload(), 00100 advData.getPayloadLen(), 00101 scanResponse.getPayload(), 00102 scanResponse.getPayloadLen()), 00103 BLE_ERROR_PARAM_OUT_OF_RANGE); 00104 00105 /* Make sure the GAP Service appearance value is aligned with the 00106 *appearance from GapAdvertisingData */ 00107 ASSERT(ERROR_NONE == sd_ble_gap_appearance_set(advData.getAppearance()), 00108 BLE_ERROR_PARAM_OUT_OF_RANGE); 00109 00110 /* ToDo: Perform some checks on the payload, for example the Scan Response can't */ 00111 /* contains a flags AD type, etc. */ 00112 00113 return BLE_ERROR_NONE; 00114 } 00115 00116 /**************************************************************************/ 00117 /*! 00118 @brief Starts the BLE HW, initialising any services that were 00119 added before this function was called. 00120 00121 @note All services must be added before calling this function! 00122 00123 @returns ble_error_t 00124 00125 @retval BLE_ERROR_NONE 00126 Everything executed properly 00127 00128 @section EXAMPLE 00129 00130 @code 00131 00132 @endcode 00133 */ 00134 /**************************************************************************/ 00135 ble_error_t nRF5xGap::startAdvertising(const GapAdvertisingParams ¶ms) 00136 { 00137 /* Make sure we support the advertising type */ 00138 if (params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) { 00139 /* ToDo: This requires a propery security implementation, etc. */ 00140 return BLE_ERROR_NOT_IMPLEMENTED; 00141 } 00142 00143 /* Check interval range */ 00144 if (params.getAdvertisingType() == GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED) { 00145 /* Min delay is slightly longer for unconnectable devices */ 00146 if ((params.getIntervalInADVUnits () < GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN_NONCON) || 00147 (params.getIntervalInADVUnits () > GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX)) { 00148 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00149 } 00150 } else { 00151 if ((params.getIntervalInADVUnits () < GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN) || 00152 (params.getIntervalInADVUnits () > GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX)) { 00153 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00154 } 00155 } 00156 00157 /* Check timeout is zero for Connectable Directed */ 00158 if ((params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) && (params.getTimeout() != 0)) { 00159 /* Timeout must be 0 with this type, although we'll never get here */ 00160 /* since this isn't implemented yet anyway */ 00161 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00162 } 00163 00164 /* Check timeout for other advertising types */ 00165 if ((params.getAdvertisingType() != GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) && 00166 (params.getTimeout() > GapAdvertisingParams::GAP_ADV_PARAMS_TIMEOUT_MAX)) { 00167 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00168 } 00169 00170 /* Start Advertising */ 00171 ble_gap_adv_params_t adv_para = {0}; 00172 00173 adv_para.type = params.getAdvertisingType(); 00174 adv_para.p_peer_addr = NULL; // Undirected advertisement 00175 adv_para.fp = BLE_GAP_ADV_FP_ANY; 00176 adv_para.p_whitelist = NULL; 00177 adv_para.interval = params.getIntervalInADVUnits (); // advertising interval (in units of 0.625 ms) 00178 adv_para.timeout = params.getTimeout(); 00179 00180 ASSERT(ERROR_NONE == sd_ble_gap_adv_start(&adv_para), BLE_ERROR_PARAM_OUT_OF_RANGE); 00181 00182 state.advertising = 1; 00183 00184 return BLE_ERROR_NONE; 00185 } 00186 00187 /**************************************************************************/ 00188 /*! 00189 @brief Stops the BLE HW and disconnects from any devices 00190 00191 @returns ble_error_t 00192 00193 @retval BLE_ERROR_NONE 00194 Everything executed properly 00195 00196 @section EXAMPLE 00197 00198 @code 00199 00200 @endcode 00201 */ 00202 /**************************************************************************/ 00203 ble_error_t nRF5xGap::stopAdvertising(void) 00204 { 00205 /* Stop Advertising */ 00206 ASSERT(ERROR_NONE == sd_ble_gap_adv_stop(), BLE_ERROR_PARAM_OUT_OF_RANGE); 00207 00208 state.advertising = 0; 00209 00210 return BLE_ERROR_NONE; 00211 } 00212 00213 ble_error_t nRF5xGap::connect(const Address_t peerAddr, 00214 Gap::AddressType_t peerAddrType, 00215 const ConnectionParams_t *connectionParams, 00216 const GapScanningParams *scanParamsIn) 00217 { 00218 ble_gap_addr_t addr; 00219 addr.addr_type = peerAddrType; 00220 memcpy(addr.addr, peerAddr, Gap::ADDR_LEN); 00221 00222 ble_gap_conn_params_t connParams; 00223 if (connectionParams != NULL) { 00224 connParams.min_conn_interval = connectionParams->minConnectionInterval; 00225 connParams.max_conn_interval = connectionParams->maxConnectionInterval; 00226 connParams.slave_latency = connectionParams->slaveLatency; 00227 connParams.conn_sup_timeout = connectionParams->connectionSupervisionTimeout; 00228 } else { 00229 connParams.min_conn_interval = 50; 00230 connParams.max_conn_interval = 100; 00231 connParams.slave_latency = 0; 00232 connParams.conn_sup_timeout = 600; 00233 } 00234 00235 ble_gap_scan_params_t scanParams; 00236 scanParams.selective = 0; /**< If 1, ignore unknown devices (non whitelisted). */ 00237 scanParams.p_whitelist = NULL; /**< Pointer to whitelist, NULL if none is given. */ 00238 if (scanParamsIn != NULL) { 00239 scanParams.active = scanParamsIn->getActiveScanning(); /**< If 1, perform active scanning (scan requests). */ 00240 scanParams.interval = scanParamsIn->getInterval(); /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ 00241 scanParams.window = scanParamsIn->getWindow(); /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ 00242 scanParams.timeout = scanParamsIn->getTimeout(); /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ 00243 } else { 00244 scanParams.active = _scanningParams.getActiveScanning(); /**< If 1, perform active scanning (scan requests). */ 00245 scanParams.interval = _scanningParams.getInterval(); /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ 00246 scanParams.window = _scanningParams.getWindow(); /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ 00247 scanParams.timeout = _scanningParams.getTimeout(); /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ 00248 } 00249 00250 uint32_t rc = sd_ble_gap_connect(&addr, &scanParams, &connParams); 00251 if (rc == NRF_SUCCESS) { 00252 return BLE_ERROR_NONE; 00253 } 00254 switch (rc) { 00255 case NRF_ERROR_INVALID_ADDR: 00256 return BLE_ERROR_INVALID_PARAM; 00257 case NRF_ERROR_INVALID_PARAM: 00258 return BLE_ERROR_INVALID_PARAM; 00259 case NRF_ERROR_INVALID_STATE: 00260 return BLE_ERROR_INVALID_STATE; 00261 case BLE_ERROR_GAP_INVALID_BLE_ADDR: 00262 return BLE_ERROR_INVALID_PARAM; 00263 case NRF_ERROR_NO_MEM: 00264 return BLE_ERROR_NO_MEM; 00265 case NRF_ERROR_BUSY: 00266 return BLE_STACK_BUSY; 00267 default: 00268 case BLE_ERROR_GAP_WHITELIST_IN_USE: 00269 return BLE_ERROR_UNSPECIFIED; 00270 } 00271 } 00272 00273 ble_error_t nRF5xGap::disconnect(Handle_t connectionHandle, DisconnectionReason_t reason) 00274 { 00275 state.advertising = 0; 00276 state.connected = 0; 00277 00278 uint8_t code = BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION; 00279 switch (reason) { 00280 case REMOTE_USER_TERMINATED_CONNECTION: 00281 code = BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION; 00282 break; 00283 case CONN_INTERVAL_UNACCEPTABLE: 00284 code = BLE_HCI_CONN_INTERVAL_UNACCEPTABLE; 00285 break; 00286 default: 00287 break; 00288 } 00289 00290 /* Disconnect if we are connected to a central device */ 00291 ASSERT_INT(ERROR_NONE, sd_ble_gap_disconnect(connectionHandle, code), BLE_ERROR_PARAM_OUT_OF_RANGE); 00292 00293 return BLE_ERROR_NONE; 00294 } 00295 00296 /*! 00297 @brief Disconnects if we are connected to a central device 00298 00299 @returns ble_error_t 00300 00301 @retval BLE_ERROR_NONE 00302 Everything executed properly 00303 */ 00304 ble_error_t nRF5xGap::disconnect(DisconnectionReason_t reason) 00305 { 00306 return disconnect(m_connectionHandle, reason); 00307 } 00308 00309 ble_error_t nRF5xGap::getPreferredConnectionParams(ConnectionParams_t *params) 00310 { 00311 ASSERT_INT(NRF_SUCCESS, 00312 sd_ble_gap_ppcp_get(reinterpret_cast<ble_gap_conn_params_t *>(params)), 00313 BLE_ERROR_PARAM_OUT_OF_RANGE); 00314 00315 return BLE_ERROR_NONE; 00316 } 00317 00318 ble_error_t nRF5xGap::setPreferredConnectionParams(const ConnectionParams_t *params) 00319 { 00320 ASSERT_INT(NRF_SUCCESS, 00321 sd_ble_gap_ppcp_set(reinterpret_cast<const ble_gap_conn_params_t *>(params)), 00322 BLE_ERROR_PARAM_OUT_OF_RANGE); 00323 00324 return BLE_ERROR_NONE; 00325 } 00326 00327 ble_error_t nRF5xGap::updateConnectionParams(Handle_t handle, const ConnectionParams_t *newParams) 00328 { 00329 uint32_t rc; 00330 00331 rc = sd_ble_gap_conn_param_update(handle, reinterpret_cast<ble_gap_conn_params_t *>(const_cast<ConnectionParams_t*>(newParams))); 00332 if (rc == NRF_SUCCESS) { 00333 return BLE_ERROR_NONE; 00334 } else { 00335 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00336 } 00337 } 00338 00339 /**************************************************************************/ 00340 /*! 00341 @brief Sets the 16-bit connection handle 00342 */ 00343 /**************************************************************************/ 00344 void nRF5xGap::setConnectionHandle(uint16_t con_handle) 00345 { 00346 m_connectionHandle = con_handle; 00347 } 00348 00349 /**************************************************************************/ 00350 /*! 00351 @brief Gets the 16-bit connection handle 00352 */ 00353 /**************************************************************************/ 00354 uint16_t nRF5xGap::getConnectionHandle(void) 00355 { 00356 return m_connectionHandle; 00357 } 00358 00359 /**************************************************************************/ 00360 /*! 00361 @brief Sets the BLE device address 00362 00363 @returns ble_error_t 00364 00365 @section EXAMPLE 00366 00367 @code 00368 00369 uint8_t device_address[6] = { 0xca, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0 }; 00370 nrf.getGap().setAddress(Gap::ADDR_TYPE_RANDOM_STATIC, device_address); 00371 00372 @endcode 00373 */ 00374 /**************************************************************************/ 00375 ble_error_t nRF5xGap::setAddress(AddressType_t type, const Address_t address) 00376 { 00377 uint8_t cycle_mode; 00378 ble_gap_addr_t dev_addr; 00379 00380 /* When using Public or Static addresses, the cycle mode must be None. 00381 When using Random Private addresses, the cycle mode must be Auto. 00382 In auto mode, the given address is ignored. 00383 */ 00384 if ((type == ADDR_TYPE_PUBLIC) || (type == ADDR_TYPE_RANDOM_STATIC)) 00385 { 00386 cycle_mode = BLE_GAP_ADDR_CYCLE_MODE_NONE; 00387 memcpy(dev_addr.addr, address, ADDR_LEN); 00388 } 00389 else if ((type == ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE) || (type == ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE)) 00390 { 00391 cycle_mode = BLE_GAP_ADDR_CYCLE_MODE_AUTO; 00392 // address is ignored when in auto mode 00393 } 00394 else 00395 { 00396 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00397 } 00398 00399 dev_addr.addr_type = type; 00400 ASSERT_INT(ERROR_NONE, sd_ble_gap_address_set(cycle_mode, &dev_addr), BLE_ERROR_PARAM_OUT_OF_RANGE); 00401 00402 return BLE_ERROR_NONE; 00403 } 00404 00405 ble_error_t nRF5xGap::getAddress(AddressType_t *typeP, Address_t address) 00406 { 00407 ble_gap_addr_t dev_addr; 00408 if (sd_ble_gap_address_get(&dev_addr) != NRF_SUCCESS) { 00409 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00410 } 00411 00412 if (typeP != NULL) { 00413 *typeP = static_cast<AddressType_t>(dev_addr.addr_type); 00414 } 00415 if (address != NULL) { 00416 memcpy(address, dev_addr.addr, ADDR_LEN); 00417 } 00418 return BLE_ERROR_NONE; 00419 } 00420 00421 ble_error_t nRF5xGap::setDeviceName(const uint8_t *deviceName) 00422 { 00423 ble_gap_conn_sec_mode_t sec_mode; 00424 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); // no security is needed 00425 00426 if (sd_ble_gap_device_name_set(&sec_mode, deviceName, strlen((const char *)deviceName)) == NRF_SUCCESS) { 00427 return BLE_ERROR_NONE; 00428 } else { 00429 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00430 } 00431 } 00432 00433 ble_error_t nRF5xGap::getDeviceName(uint8_t *deviceName, unsigned *lengthP) 00434 { 00435 if (sd_ble_gap_device_name_get(deviceName, (uint16_t *)lengthP) == NRF_SUCCESS) { 00436 return BLE_ERROR_NONE; 00437 } else { 00438 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00439 } 00440 } 00441 00442 ble_error_t nRF5xGap::setAppearance(GapAdvertisingData::Appearance appearance) 00443 { 00444 if (sd_ble_gap_appearance_set(appearance) == NRF_SUCCESS) { 00445 return BLE_ERROR_NONE; 00446 } else { 00447 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00448 } 00449 } 00450 00451 ble_error_t nRF5xGap::getAppearance(GapAdvertisingData::Appearance *appearanceP) 00452 { 00453 if ((sd_ble_gap_appearance_get(reinterpret_cast<uint16_t *>(appearanceP)) == NRF_SUCCESS)) { 00454 return BLE_ERROR_NONE; 00455 } else { 00456 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00457 } 00458 } 00459 00460 /* (Valid values are -40, -20, -16, -12, -8, -4, 0, 4) */ 00461 ble_error_t nRF5xGap::setTxPower(int8_t txPower) 00462 { 00463 unsigned rc; 00464 if ((rc = sd_ble_gap_tx_power_set(txPower)) != NRF_SUCCESS) { 00465 switch (rc) { 00466 case NRF_ERROR_BUSY: 00467 return BLE_STACK_BUSY; 00468 case NRF_ERROR_INVALID_PARAM: 00469 default: 00470 return BLE_ERROR_PARAM_OUT_OF_RANGE; 00471 } 00472 } 00473 00474 return BLE_ERROR_NONE; 00475 } 00476 00477 void nRF5xGap::getPermittedTxPowerValues(const int8_t **valueArrayPP, size_t *countP) 00478 { 00479 static const int8_t permittedTxValues[] = { 00480 -40, -30, -20, -16, -12, -8, -4, 0, 4 00481 }; 00482 00483 *valueArrayPP = permittedTxValues; 00484 *countP = sizeof(permittedTxValues) / sizeof(int8_t); 00485 }
Generated on Tue Jul 12 2022 16:00:20 by
