library for BLE_GAP_backpack

Dependencies:   nrf51-sdk

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     return BLE_ERROR_NONE;
00202 }
00203 
00204 /* Observer role is not supported by S110, return BLE_ERROR_NOT_IMPLEMENTED */
00205 #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
00206 ble_error_t nRF5xGap::startRadioScan(const GapScanningParams &scanningParams)
00207 {
00208     /* Allocate the stack's whitelist statically */
00209     ble_gap_whitelist_t  whitelist;
00210     ble_gap_addr_t      *whitelistAddressPtrs[YOTTA_CFG_WHITELIST_MAX_SIZE];
00211     ble_gap_irk_t       *whitelistIrkPtrs[YOTTA_CFG_IRK_TABLE_MAX_SIZE];
00212     /* Initialize the whitelist */
00213     whitelist.pp_addrs   = whitelistAddressPtrs;
00214     whitelist.pp_irks    = whitelistIrkPtrs;
00215     whitelist.addr_count = 0;
00216     whitelist.irk_count  = 0;
00217 
00218     /* Add missing IRKs to whitelist from the bond table held by the SoftDevice */
00219     if (scanningPolicyMode != Gap::SCAN_POLICY_IGNORE_WHITELIST) {
00220         ble_error_t error = generateStackWhitelist(whitelist);
00221         if (error != BLE_ERROR_NONE) {
00222             return error;
00223         }
00224     }
00225 
00226     ble_gap_scan_params_t scanParams = {
00227         .active      = scanningParams.getActiveScanning(), /**< If 1, perform active scanning (scan requests). */
00228         .selective   = scanningPolicyMode,    /**< If 1, ignore unknown devices (non whitelisted). */
00229         .p_whitelist = &whitelist, /**< Pointer to whitelist, NULL if none is given. */
00230         .interval    = scanningParams.getInterval(),  /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */
00231         .window      = scanningParams.getWindow(),    /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */
00232         .timeout     = scanningParams.getTimeout(),   /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */
00233     };
00234 
00235     if (sd_ble_gap_scan_start(&scanParams) != NRF_SUCCESS) {
00236         return BLE_ERROR_PARAM_OUT_OF_RANGE;
00237     }
00238 
00239     return BLE_ERROR_NONE;
00240 }
00241 
00242 ble_error_t nRF5xGap::stopScan(void) {
00243     if (sd_ble_gap_scan_stop() == NRF_SUCCESS) {
00244         return BLE_ERROR_NONE;
00245     }
00246 
00247     return BLE_STACK_BUSY;
00248 }
00249 #endif
00250 
00251 /**************************************************************************/
00252 /*!
00253     @brief  Stops the BLE HW and disconnects from any devices
00254 
00255     @returns    ble_error_t
00256 
00257     @retval     BLE_ERROR_NONE
00258                 Everything executed properly
00259 
00260     @section EXAMPLE
00261 
00262     @code
00263 
00264     @endcode
00265 */
00266 /**************************************************************************/
00267 ble_error_t nRF5xGap::stopAdvertising(void)
00268 {
00269     /* Stop Advertising */
00270     ASSERT(ERROR_NONE == sd_ble_gap_adv_stop(), BLE_ERROR_PARAM_OUT_OF_RANGE);
00271 
00272     state.advertising = 0;
00273 
00274     return BLE_ERROR_NONE;
00275 }
00276 
00277 ble_error_t nRF5xGap::connect(const Address_t             peerAddr,
00278                               BLEProtocol::AddressType_t  peerAddrType,
00279                               const ConnectionParams_t   *connectionParams,
00280                               const GapScanningParams    *scanParamsIn)
00281 {
00282     ble_gap_addr_t addr;
00283     addr.addr_type = peerAddrType;
00284     memcpy(addr.addr, peerAddr, Gap::ADDR_LEN);
00285 
00286     ble_gap_conn_params_t connParams;
00287     if (connectionParams != NULL) {
00288         connParams.min_conn_interval = connectionParams->minConnectionInterval;
00289         connParams.max_conn_interval = connectionParams->maxConnectionInterval;
00290         connParams.slave_latency     = connectionParams->slaveLatency;
00291         connParams.conn_sup_timeout  = connectionParams->connectionSupervisionTimeout;
00292     } else {
00293         connParams.min_conn_interval = 50;
00294         connParams.max_conn_interval = 100;
00295         connParams.slave_latency     = 0;
00296         connParams.conn_sup_timeout  = 600;
00297     }
00298 
00299     /* Allocate the stack's whitelist statically */
00300     ble_gap_whitelist_t  whitelist;
00301     ble_gap_addr_t      *whitelistAddressPtrs[YOTTA_CFG_WHITELIST_MAX_SIZE];
00302     ble_gap_irk_t       *whitelistIrkPtrs[YOTTA_CFG_IRK_TABLE_MAX_SIZE];
00303     /* Initialize the whitelist */
00304     whitelist.pp_addrs   = whitelistAddressPtrs;
00305     whitelist.pp_irks    = whitelistIrkPtrs;
00306     whitelist.addr_count = 0;
00307     whitelist.irk_count  = 0;
00308 
00309     /* Add missing IRKs to whitelist from the bond table held by the SoftDevice */
00310     if (scanningPolicyMode != Gap::SCAN_POLICY_IGNORE_WHITELIST) {
00311         ble_error_t error = generateStackWhitelist(whitelist);
00312         if (error != BLE_ERROR_NONE) {
00313             return error;
00314         }
00315     }
00316 
00317     ble_gap_scan_params_t scanParams;
00318     scanParams.selective   = scanningPolicyMode;    /**< If 1, ignore unknown devices (non whitelisted). */
00319     scanParams.p_whitelist = &whitelist; /**< Pointer to whitelist, NULL if none is given. */
00320     if (scanParamsIn != NULL) {
00321         scanParams.active      = scanParamsIn->getActiveScanning();   /**< If 1, perform active scanning (scan requests). */
00322         scanParams.interval    = scanParamsIn->getInterval();         /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */
00323         scanParams.window      = scanParamsIn->getWindow();           /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */
00324         scanParams.timeout     = scanParamsIn->getTimeout();          /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */
00325     } else {
00326         scanParams.active      = _scanningParams.getActiveScanning(); /**< If 1, perform active scanning (scan requests). */
00327         scanParams.interval    = _scanningParams.getInterval();       /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */
00328         scanParams.window      = _scanningParams.getWindow();         /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */
00329         scanParams.timeout     = _scanningParams.getTimeout();        /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */
00330     }
00331 
00332     uint32_t rc = sd_ble_gap_connect(&addr, &scanParams, &connParams);
00333     if (rc == NRF_SUCCESS) {
00334         return BLE_ERROR_NONE;
00335     }
00336     switch (rc) {
00337         case NRF_ERROR_INVALID_ADDR:
00338             return BLE_ERROR_INVALID_PARAM;
00339         case NRF_ERROR_INVALID_PARAM:
00340             return BLE_ERROR_INVALID_PARAM;
00341         case NRF_ERROR_INVALID_STATE:
00342             return BLE_ERROR_INVALID_STATE;
00343         case BLE_ERROR_GAP_INVALID_BLE_ADDR:
00344             return BLE_ERROR_INVALID_PARAM;
00345         case NRF_ERROR_NO_MEM:
00346             return BLE_ERROR_NO_MEM;
00347         case NRF_ERROR_BUSY:
00348             return BLE_STACK_BUSY;
00349         default:
00350         case BLE_ERROR_GAP_WHITELIST_IN_USE:
00351             return BLE_ERROR_UNSPECIFIED;
00352     }
00353 }
00354 
00355 ble_error_t nRF5xGap::disconnect(Handle_t connectionHandle, DisconnectionReason_t reason)
00356 {
00357     uint8_t code = BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION;
00358     switch (reason) {
00359         case REMOTE_USER_TERMINATED_CONNECTION:
00360             code = BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION;
00361             break;
00362         case CONN_INTERVAL_UNACCEPTABLE:
00363             code = BLE_HCI_CONN_INTERVAL_UNACCEPTABLE;
00364             break;
00365         default:
00366             break;
00367     }
00368 
00369     /* Disconnect if we are connected to a central device */
00370     ASSERT_INT(ERROR_NONE, sd_ble_gap_disconnect(connectionHandle, code), BLE_ERROR_PARAM_OUT_OF_RANGE);
00371 
00372     return BLE_ERROR_NONE;
00373 }
00374 
00375 /*!
00376     @brief  Disconnects if we are connected to a central device
00377 
00378     @returns    ble_error_t
00379 
00380     @retval     BLE_ERROR_NONE
00381                 Everything executed properly
00382 */
00383 ble_error_t nRF5xGap::disconnect(DisconnectionReason_t reason)
00384 {
00385     return disconnect(m_connectionHandle, reason);
00386 }
00387 
00388 ble_error_t nRF5xGap::getPreferredConnectionParams(ConnectionParams_t *params)
00389 {
00390     ASSERT_INT(NRF_SUCCESS,
00391         sd_ble_gap_ppcp_get(reinterpret_cast<ble_gap_conn_params_t *>(params)),
00392         BLE_ERROR_PARAM_OUT_OF_RANGE);
00393 
00394     return BLE_ERROR_NONE;
00395 }
00396 
00397 ble_error_t nRF5xGap::setPreferredConnectionParams(const ConnectionParams_t *params)
00398 {
00399     ASSERT_INT(NRF_SUCCESS,
00400         sd_ble_gap_ppcp_set(reinterpret_cast<const ble_gap_conn_params_t *>(params)),
00401         BLE_ERROR_PARAM_OUT_OF_RANGE);
00402 
00403     return BLE_ERROR_NONE;
00404 }
00405 
00406 ble_error_t nRF5xGap::updateConnectionParams(Handle_t handle, const ConnectionParams_t *newParams)
00407 {
00408     uint32_t rc;
00409 
00410     rc = sd_ble_gap_conn_param_update(handle, reinterpret_cast<ble_gap_conn_params_t *>(const_cast<ConnectionParams_t*>(newParams)));
00411     if (rc == NRF_SUCCESS) {
00412         return BLE_ERROR_NONE;
00413     } else {
00414         return BLE_ERROR_PARAM_OUT_OF_RANGE;
00415     }
00416 }
00417 
00418 /**************************************************************************/
00419 /*!
00420     @brief  Clear nRF5xGap's state.
00421 
00422     @returns    ble_error_t
00423 
00424     @retval     BLE_ERROR_NONE
00425                 Everything executed properly
00426 */
00427 /**************************************************************************/
00428 ble_error_t nRF5xGap::reset(void)
00429 {
00430     /* Clear all state that is from the parent, including private members */
00431     if (Gap::reset() != BLE_ERROR_NONE) {
00432         return BLE_ERROR_INVALID_STATE;
00433     }
00434 
00435     /* Clear derived class members */
00436     m_connectionHandle = BLE_CONN_HANDLE_INVALID;
00437 
00438     /* Set the whitelist policy filter modes to IGNORE_WHITELIST */
00439     advertisingPolicyMode = Gap::ADV_POLICY_IGNORE_WHITELIST;
00440     scanningPolicyMode    = Gap::SCAN_POLICY_IGNORE_WHITELIST;
00441 
00442     /* Clear the internal whitelist */
00443     whitelistAddressesSize = 0;
00444 
00445     return BLE_ERROR_NONE;
00446 }
00447 
00448 /**************************************************************************/
00449 /*!
00450     @brief  Sets the 16-bit connection handle
00451 */
00452 /**************************************************************************/
00453 void nRF5xGap::setConnectionHandle(uint16_t con_handle)
00454 {
00455     m_connectionHandle = con_handle;
00456 }
00457 
00458 /**************************************************************************/
00459 /*!
00460     @brief  Gets the 16-bit connection handle
00461 */
00462 /**************************************************************************/
00463 uint16_t nRF5xGap::getConnectionHandle(void)
00464 {
00465     return m_connectionHandle;
00466 }
00467 
00468 /**************************************************************************/
00469 /*!
00470     @brief      Sets the BLE device address
00471 
00472     @returns    ble_error_t
00473 
00474     @section EXAMPLE
00475 
00476     @code
00477 
00478     uint8_t device_address[6] = { 0xca, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0 };
00479     nrf.getGap().setAddress(Gap::BLEProtocol::AddressType::RANDOM_STATIC, device_address);
00480 
00481     @endcode
00482 */
00483 /**************************************************************************/
00484 ble_error_t nRF5xGap::setAddress(AddressType_t type, const Address_t address)
00485 {
00486     uint8_t cycle_mode;
00487     ble_gap_addr_t dev_addr;
00488 
00489     /* When using Public or Static addresses, the cycle mode must be None.
00490        When using Random Private addresses, the cycle mode must be Auto.
00491        In auto mode, the given address is ignored.
00492     */
00493     if ((type == BLEProtocol::AddressType::PUBLIC) || (type == BLEProtocol::AddressType::RANDOM_STATIC))
00494     {
00495         cycle_mode = BLE_GAP_ADDR_CYCLE_MODE_NONE;
00496         memcpy(dev_addr.addr, address, ADDR_LEN);
00497     }
00498     else if ((type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) || (type == BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE))
00499     {
00500         cycle_mode = BLE_GAP_ADDR_CYCLE_MODE_AUTO;
00501         // address is ignored when in auto mode
00502     }
00503     else
00504     {
00505         return BLE_ERROR_PARAM_OUT_OF_RANGE;
00506     }
00507 
00508     dev_addr.addr_type = type;
00509     ASSERT_INT(ERROR_NONE, sd_ble_gap_address_set(cycle_mode, &dev_addr), BLE_ERROR_PARAM_OUT_OF_RANGE);
00510 
00511     return BLE_ERROR_NONE;
00512 }
00513 
00514 ble_error_t nRF5xGap::getAddress(AddressType_t *typeP, Address_t address)
00515 {
00516     ble_gap_addr_t dev_addr;
00517     if (sd_ble_gap_address_get(&dev_addr) != NRF_SUCCESS) {
00518         return BLE_ERROR_PARAM_OUT_OF_RANGE;
00519     }
00520 
00521     if (typeP != NULL) {
00522         *typeP = static_cast<AddressType_t>(dev_addr.addr_type);
00523     }
00524     if (address != NULL) {
00525         memcpy(address, dev_addr.addr, ADDR_LEN);
00526     }
00527     return BLE_ERROR_NONE;
00528 }
00529 
00530 ble_error_t nRF5xGap::setDeviceName(const uint8_t *deviceName)
00531 {
00532     ble_gap_conn_sec_mode_t sec_mode;
00533     BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); // no security is needed
00534 
00535     if (sd_ble_gap_device_name_set(&sec_mode, deviceName, strlen((const char *)deviceName)) == NRF_SUCCESS) {
00536         return BLE_ERROR_NONE;
00537     } else {
00538         return BLE_ERROR_PARAM_OUT_OF_RANGE;
00539     }
00540 }
00541 
00542 ble_error_t nRF5xGap::getDeviceName(uint8_t *deviceName, unsigned *lengthP)
00543 {
00544     if (sd_ble_gap_device_name_get(deviceName, (uint16_t *)lengthP) == NRF_SUCCESS) {
00545         return BLE_ERROR_NONE;
00546     } else {
00547         return BLE_ERROR_PARAM_OUT_OF_RANGE;
00548     }
00549 }
00550 
00551 ble_error_t nRF5xGap::setAppearance(GapAdvertisingData::Appearance appearance)
00552 {
00553     if (sd_ble_gap_appearance_set(appearance) == NRF_SUCCESS) {
00554         return BLE_ERROR_NONE;
00555     } else {
00556         return BLE_ERROR_PARAM_OUT_OF_RANGE;
00557     }
00558 }
00559 
00560 ble_error_t nRF5xGap::getAppearance(GapAdvertisingData::Appearance *appearanceP)
00561 {
00562     if ((sd_ble_gap_appearance_get(reinterpret_cast<uint16_t *>(appearanceP)) == NRF_SUCCESS)) {
00563         return BLE_ERROR_NONE;
00564     } else {
00565         return BLE_ERROR_PARAM_OUT_OF_RANGE;
00566     }
00567 }
00568 
00569 /* (Valid values are -40, -20, -16, -12, -8, -4, 0, 4) */
00570 ble_error_t nRF5xGap::setTxPower(int8_t txPower)
00571 {
00572     unsigned rc;
00573     if ((rc = sd_ble_gap_tx_power_set(txPower)) != NRF_SUCCESS) {
00574         switch (rc) {
00575             case NRF_ERROR_BUSY:
00576                 return BLE_STACK_BUSY;
00577             case NRF_ERROR_INVALID_PARAM:
00578             default:
00579                 return BLE_ERROR_PARAM_OUT_OF_RANGE;
00580         }
00581     }
00582 
00583     return BLE_ERROR_NONE;
00584 }
00585 
00586 void nRF5xGap::getPermittedTxPowerValues(const int8_t **valueArrayPP, size_t *countP)
00587 {
00588     static const int8_t permittedTxValues[] = {
00589         -40, -30, -20, -16, -12, -8, -4, 0, 4
00590     };
00591 
00592     *valueArrayPP = permittedTxValues;
00593     *countP = sizeof(permittedTxValues) / sizeof(int8_t);
00594 }
00595 
00596 /**************************************************************************/
00597 /*!
00598     @brief  Get the capacity of the internal whitelist maintained by this
00599             implementation.
00600 
00601     @returns    The capacity of the internal whitelist.
00602 
00603     @section EXAMPLE
00604 
00605     @code
00606 
00607     @endcode
00608 */
00609 /**************************************************************************/
00610 uint8_t nRF5xGap::getMaxWhitelistSize(void) const
00611 {
00612     return YOTTA_CFG_WHITELIST_MAX_SIZE;
00613 }
00614 
00615 /**************************************************************************/
00616 /*!
00617     @brief  Get a copy of the implementation's internal whitelist.
00618 
00619     @param[out] whitelistOut
00620                 A \ref Gap::Whitelist_t structure containing a copy of the
00621                 addresses in the implemenetation's internal whitelist.
00622 
00623     @returns    \ref ble_errror_t
00624 
00625     @retval     BLE_ERROR_NONE
00626                 Everything executed properly.
00627 
00628     @section EXAMPLE
00629 
00630     @code
00631 
00632     @endcode
00633 */
00634 /**************************************************************************/
00635 ble_error_t nRF5xGap::getWhitelist(Gap::Whitelist_t &whitelistOut) const
00636 {
00637     uint8_t i;
00638     for (i = 0; i < whitelistAddressesSize && i < whitelistOut.capacity; ++i) {
00639         memcpy(&whitelistOut.addresses[i], &whitelistAddresses[i], sizeof(BLEProtocol::Address_t));
00640     }
00641     whitelistOut.size = i;
00642 
00643     return BLE_ERROR_NONE;
00644 }
00645 
00646 /**************************************************************************/
00647 /*!
00648     @brief  Set the whitelist that will be used in the next call to
00649             startAdvertising().
00650 
00651     @param[in]  whitelistIn
00652                 A reference to a \ref Gap::Whitelist_t structure
00653                 representing a whitelist containing all the white listed
00654                 BLE addresses.
00655 
00656     @returns    \ref ble_errror_t
00657 
00658     @retval     BLE_ERROR_NONE
00659                 Everything executed properly.
00660 
00661                 BLE_ERROR_INVALID_PARAM
00662                 The supplied whitelist contains a private non-resolvable
00663                 address
00664 
00665                 BLE_ERROR_PARAM_OUT_OF_RANGE
00666                 The size of the supplied whitelist exceeds the maximum
00667                 capacity of the implementation's internal whitelist.
00668 
00669     @section EXAMPLE
00670 
00671     @code
00672 
00673     @endcode
00674 */
00675 /**************************************************************************/
00676 ble_error_t nRF5xGap::setWhitelist(const Gap::Whitelist_t &whitelistIn)
00677 {
00678     if (whitelistIn.size > getMaxWhitelistSize()) {
00679         return BLE_ERROR_PARAM_OUT_OF_RANGE;
00680     }
00681 
00682     /* Test for invalid parameters before we change the internal state */
00683     for (uint8_t i = 0; i < whitelistIn.size; ++i) {
00684         if (whitelistIn.addresses[i].type == BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE) {
00685             /* This is not allowed because it is completely meaningless */
00686             return BLE_ERROR_INVALID_PARAM;
00687         }
00688     }
00689 
00690     whitelistAddressesSize = 0;
00691     for (uint8_t i = 0; i < whitelistIn.size; ++i) {
00692         memcpy(&whitelistAddresses[whitelistAddressesSize], &whitelistIn.addresses[i], sizeof(BLEProtocol::Address_t));
00693         whitelistAddressesSize++;
00694     }
00695 
00696     return BLE_ERROR_NONE;
00697 }
00698 
00699 /**************************************************************************/
00700 /*!
00701     @brief  Set the advertising policy filter mode that will be used in
00702             the next call to startAdvertising().
00703 
00704     @returns    \ref ble_errror_t
00705 
00706     @retval     BLE_ERROR_NONE
00707                 Everything executed properly.
00708 
00709                 BLE_ERROR_NOT_IMPLEMENTED
00710                 This feature is currently note implemented.
00711 
00712     @section EXAMPLE
00713 
00714     @code
00715 
00716     @endcode
00717 */
00718 /**************************************************************************/
00719 ble_error_t nRF5xGap::setAdvertisingPolicyMode(Gap::AdvertisingPolicyMode_t mode)
00720 {
00721     advertisingPolicyMode = mode;
00722 
00723     return BLE_ERROR_NONE;
00724 }
00725 
00726 /**************************************************************************/
00727 /*!
00728     @brief  Set the scanning policy filter mode that will be used in
00729             the next call to startAdvertising().
00730 
00731     @returns    \ref ble_errror_t
00732 
00733     @retval     BLE_ERROR_NONE
00734                 Everything executed properly.
00735 
00736                 BLE_ERROR_NOT_IMPLEMENTED
00737                 This feature is currently note implemented.
00738 
00739     @section EXAMPLE
00740 
00741     @code
00742 
00743     @endcode
00744 */
00745 /**************************************************************************/
00746 ble_error_t nRF5xGap::setScanningPolicyMode(Gap::ScanningPolicyMode_t mode)
00747 {
00748     scanningPolicyMode = mode;
00749 
00750     return BLE_ERROR_NONE;
00751 }
00752 
00753 /**************************************************************************/
00754 /*!
00755     @brief  Set the initiator policy filter mode that will be used in
00756             the next call to startAdvertising()
00757 
00758     @returns    \ref ble_errror_t
00759 
00760     @retval     BLE_ERROR_NONE
00761                 Everything executed properly.
00762 
00763                 BLE_ERROR_NOT_IMPLEMENTED
00764                 This feature is currently note implemented.
00765 
00766     @section EXAMPLE
00767 
00768     @code
00769 
00770     @endcode
00771 */
00772 /**************************************************************************/
00773 ble_error_t nRF5xGap::setInitiatorPolicyMode(Gap::InitiatorPolicyMode_t mode)
00774 {
00775     return BLE_ERROR_NOT_IMPLEMENTED;
00776 }
00777 
00778 /**************************************************************************/
00779 /*!
00780     @brief  Get the current advertising policy filter mode.
00781 
00782     @returns    The advertising policy filter mode.
00783 
00784     @section EXAMPLE
00785 
00786     @code
00787 
00788     @endcode
00789 */
00790 /**************************************************************************/
00791 Gap::AdvertisingPolicyMode_t nRF5xGap::getAdvertisingPolicyMode(void) const
00792 {
00793     return advertisingPolicyMode;
00794 }
00795 
00796 /**************************************************************************/
00797 /*!
00798     @brief  Get the current scanning policy filter mode.
00799 
00800     @returns    The scanning policy filter mode.
00801 
00802     @section EXAMPLE
00803 
00804     @code
00805 
00806     @endcode
00807 */
00808 /**************************************************************************/
00809 Gap::ScanningPolicyMode_t nRF5xGap::getScanningPolicyMode(void) const
00810 {
00811     return scanningPolicyMode;
00812 }
00813 
00814 /**************************************************************************/
00815 /*!
00816     @brief  Get the current initiator policy filter mode.
00817 
00818     @returns    The initiator policy filter mode.
00819 
00820     @note   Currently initiator filtering using the whitelist is not
00821             implemented in this module.
00822 
00823     @section EXAMPLE
00824 
00825     @code
00826 
00827     @endcode
00828 */
00829 /**************************************************************************/
00830 Gap::InitiatorPolicyMode_t nRF5xGap::getInitiatorPolicyMode(void) const
00831 {
00832     return Gap::INIT_POLICY_IGNORE_WHITELIST;
00833 }
00834 
00835 /**************************************************************************/
00836 /*!
00837     @brief  Helper function used to populate the ble_gap_whitelist_t that
00838             will be used by the SoftDevice for filtering requests.
00839 
00840     @returns    \ref ble_error_t
00841 
00842     @retval     BLE_ERROR_NONE
00843                 Everything executed properly
00844 
00845     @retval     BLE_ERROR_INVALID_STATE
00846                 The internal stack was not initialized correctly.
00847 
00848     @note  Both the SecurityManager and Gap must initialize correctly for
00849            this function to succeed.
00850 
00851     @note  This function is needed because for the BLE API the whitelist
00852            is just a collection of keys, but for the stack it also includes
00853            the IRK table.
00854 
00855     @section EXAMPLE
00856 
00857     @code
00858 
00859     @endcode
00860 */
00861 /**************************************************************************/
00862 ble_error_t nRF5xGap::generateStackWhitelist(ble_gap_whitelist_t &whitelist)
00863 {
00864     ble_gap_whitelist_t  whitelistFromBondTable;
00865     ble_gap_addr_t      *addressPtr[1];
00866     ble_gap_irk_t       *irkPtr[YOTTA_CFG_IRK_TABLE_MAX_SIZE];
00867 
00868     nRF5xSecurityManager& securityManager = (nRF5xSecurityManager&) nRF5xn::Instance(0).getSecurityManager();
00869 
00870     if (securityManager.hasInitialized()) {
00871         /* We do not care about the addresses, set the count to 0 */
00872         whitelistFromBondTable.addr_count = 0;
00873         /* The Nordic SDK will return a failure if we set pp_addr to NULL */
00874         whitelistFromBondTable.pp_addrs   = addressPtr;
00875         /* We want all the IRKs we can get because we do not know which ones match the addresses */
00876         whitelistFromBondTable.irk_count  = YOTTA_CFG_IRK_TABLE_MAX_SIZE;
00877         whitelistFromBondTable.pp_irks    = irkPtr;
00878 
00879         /* Use the security manager to get the IRKs from the bond table */
00880         ble_error_t error = securityManager.createWhitelistFromBondTable(whitelistFromBondTable);
00881         if (error != BLE_ERROR_NONE) {
00882             return error;
00883         }
00884     } else  {
00885         /**
00886          * If there is no security manager then we cannot access the bond table,
00887          * so disable IRK matching
00888          */
00889         whitelistFromBondTable.addr_count = 0;
00890         whitelistFromBondTable.irk_count  = 0;
00891     }
00892 
00893     /**
00894      * For every private resolvable address in the local whitelist check if
00895      * there is an IRK for said address in the bond table and add it to the
00896      * local IRK list.
00897      */
00898     whitelist.irk_count  = 0;
00899     whitelist.addr_count = 0;
00900     for (uint8_t i = 0; i < whitelistAddressesSize; ++i) {
00901         if (whitelistAddresses[i].addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) {
00902             /* Test if there is a matching IRK for this private resolvable address */
00903             for (uint8_t j = 0; j < whitelistFromBondTable.irk_count; ++j) {
00904                 if (securityManager.matchAddressAndIrk(&whitelistAddresses[i], whitelistFromBondTable.pp_irks[j])) {
00905                     /* Found the corresponding IRK, add it to our local whitelist */
00906                     whitelist.pp_irks[whitelist.irk_count] = whitelistFromBondTable.pp_irks[j];
00907                     whitelist.irk_count++;
00908                     /* Make sure we do not look at this IRK again */
00909                     if (j != whitelistFromBondTable.irk_count - 1) {
00910                         /**
00911                          * This is not the last IRK, so replace the pointer
00912                          * with the last pointer in the array
00913                          */
00914                         whitelistFromBondTable.pp_irks[j] =
00915                             whitelistFromBondTable.pp_irks[whitelistFromBondTable.irk_count - 1];
00916                     }
00917                     /**
00918                      * If the IRK is the last pointer in the array simply
00919                      * decrement the total IRK count
00920                      */
00921                     whitelistFromBondTable.irk_count--;
00922                     break;
00923                 }
00924             }
00925         } else {
00926             /* Include the address into the whitelist */
00927             whitelist.pp_addrs[whitelist.addr_count] = &whitelistAddresses[i];
00928             whitelist.addr_count++;
00929         }
00930     }
00931 
00932     return BLE_ERROR_NONE;
00933 }