Qi Yao / LinkNode---test123

Dependencies:   mbed

Fork of LinkNode-Test by Qi Yao

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