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 Nordic Semiconductor

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers nRF5xGap.cpp Source File

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 &params)
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 }