PBL mbed final
Fork of nRF51822 by
Revision 391:8cc3528a1233, committed 2015-07-21
- Comitter:
- rgrover1
- Date:
- Tue Jul 21 13:23:45 2015 +0100
- Parent:
- 390:d9f7f0134e24
- Child:
- 392:b21c1373df4d
- Commit message:
- Synchronized with git rev 4ec44d75
Author: Andrew Fernandes
Change DiscoveredCharacteristic API to return long or short UUIDs.
Changed in this revision
--- a/source/btle/btle.cpp Tue Jul 21 13:23:45 2015 +0100 +++ b/source/btle/btle.cpp Tue Jul 21 13:23:45 2015 +0100 @@ -31,9 +31,9 @@ #include "pstorage.h" #include "ble/GapEvents.h" -#include "nRF5xGap.h" -#include "nRF5xGattServer.h" -#include "nRF5xSecurityManager.h" +#include "nRF51Gap.h" +#include "nRF51GattServer.h" +#include "nRF51SecurityManager.h" #include "device_manager.h" @@ -113,11 +113,11 @@ switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: { Gap::Handle_t handle = p_ble_evt->evt.gap_evt.conn_handle; - nRF5xGap::getInstance().setConnectionHandle(handle); + nRF51Gap::getInstance().setConnectionHandle(handle); const Gap::ConnectionParams_t *params = reinterpret_cast<Gap::ConnectionParams_t *>(&(p_ble_evt->evt.gap_evt.params.connected.conn_params)); const ble_gap_addr_t *peer = &p_ble_evt->evt.gap_evt.params.connected.peer_addr; const ble_gap_addr_t *own = &p_ble_evt->evt.gap_evt.params.connected.own_addr; - nRF5xGap::getInstance().processConnectionEvent(handle, + nRF51Gap::getInstance().processConnectionEvent(handle, static_cast<Gap::Role_t>(p_ble_evt->evt.gap_evt.params.connected.role), static_cast<Gap::AddressType_t>(peer->addr_type), peer->addr, static_cast<Gap::AddressType_t>(own->addr_type), own->addr, @@ -129,7 +129,7 @@ Gap::Handle_t handle = p_ble_evt->evt.gap_evt.conn_handle; // Since we are not in a connection and have not started advertising, // store bonds - nRF5xGap::getInstance().setConnectionHandle (BLE_CONN_HANDLE_INVALID); + nRF51Gap::getInstance().setConnectionHandle (BLE_CONN_HANDLE_INVALID); Gap::DisconnectionReason_t reason; switch (p_ble_evt->evt.gap_evt.params.disconnected.reason) { @@ -148,16 +148,16 @@ reason = static_cast<Gap::DisconnectionReason_t>(p_ble_evt->evt.gap_evt.params.disconnected.reason); break; } - nRF5xGap::getInstance().processDisconnectionEvent(handle, reason); + nRF51Gap::getInstance().processDisconnectionEvent(handle, reason); break; } case BLE_GAP_EVT_PASSKEY_DISPLAY: - nRF5xSecurityManager::getInstance().processPasskeyDisplayEvent(p_ble_evt->evt.gap_evt.conn_handle, p_ble_evt->evt.gap_evt.params.passkey_display.passkey); + nRF51SecurityManager::getInstance().processPasskeyDisplayEvent(p_ble_evt->evt.gap_evt.conn_handle, p_ble_evt->evt.gap_evt.params.passkey_display.passkey); break; case BLE_GAP_EVT_TIMEOUT: - nRF5xGap::getInstance().processTimeoutEvent(static_cast<Gap::TimeoutSource_t>(p_ble_evt->evt.gap_evt.params.timeout.src)); + nRF51Gap::getInstance().processTimeoutEvent(static_cast<Gap::TimeoutSource_t>(p_ble_evt->evt.gap_evt.params.timeout.src)); break; case BLE_GATTC_EVT_TIMEOUT: @@ -169,7 +169,7 @@ case BLE_GAP_EVT_ADV_REPORT: { const ble_gap_evt_adv_report_t *advReport = &p_ble_evt->evt.gap_evt.params.adv_report; - nRF5xGap::getInstance().processAdvertisementReport(advReport->peer_addr.addr, + nRF51Gap::getInstance().processAdvertisementReport(advReport->peer_addr.addr, advReport->rssi, advReport->scan_rsp, static_cast<GapAdvertisingParams::AdvertisingType_t>(advReport->type), @@ -182,7 +182,7 @@ break; } - nRF5xGattServer::getInstance().hwCallback(p_ble_evt); + nRF51GattServer::getInstance().hwCallback(p_ble_evt); } /*! @brief Callback when an error occurs inside the SoftDevice */
--- a/source/btle/btle_discovery.cpp Tue Jul 21 13:23:45 2015 +0100 +++ b/source/btle/btle_discovery.cpp Tue Jul 21 13:23:45 2015 +0100 @@ -14,12 +14,12 @@ * limitations under the License. */ -#include "nRF5xServiceDiscovery.h" -#include "nRF5xGattClient.h" +#include "nRF51ServiceDiscovery.h" +#include "nRF51GattClient.h" void bleGattcEventHandler(const ble_evt_t *p_ble_evt) { - nRF5xServiceDiscovery &sdSingleton = nRF5xGattClient::getInstance().discovery; + nRF51ServiceDiscovery &sdSingleton = nRF51GattClient::getInstance().discovery; switch (p_ble_evt->header.evt_id) { case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: @@ -61,7 +61,7 @@ .len = p_ble_evt->evt.gattc_evt.params.read_rsp.len, .data = p_ble_evt->evt.gattc_evt.params.read_rsp.data, }; - nRF5xGattClient::getInstance().processReadResponse(&response); + nRF51GattClient::getInstance().processReadResponse(&response); } break; @@ -73,7 +73,7 @@ .len = p_ble_evt->evt.gattc_evt.params.write_rsp.len, .data = p_ble_evt->evt.gattc_evt.params.write_rsp.data, }; - nRF5xGattClient::getInstance().processWriteResponse(&response); + nRF51GattClient::getInstance().processWriteResponse(&response); } break; @@ -84,7 +84,7 @@ params.len = p_ble_evt->evt.gattc_evt.params.hvx.len; params.data = p_ble_evt->evt.gattc_evt.params.hvx.data; - nRF5xGattClient::getInstance().processHVXEvent(¶ms); + nRF51GattClient::getInstance().processHVXEvent(¶ms); } break; }
--- a/source/btle/btle_security.cpp Tue Jul 21 13:23:45 2015 +0100 +++ b/source/btle/btle_security.cpp Tue Jul 21 13:23:45 2015 +0100 @@ -17,8 +17,8 @@ #include "btle.h" #include "pstorage.h" -#include "nRF5xGap.h" -#include "nRF5xSecurityManager.h" +#include "nRF51Gap.h" +#include "nRF51SecurityManager.h" #include "device_manager.h" #include "btle_security.h" @@ -154,14 +154,14 @@ switch (p_event->event_id) { case DM_EVT_SECURITY_SETUP: /* started */ { const ble_gap_sec_params_t *peerParams = &p_event->event_param.p_gap_param->params.sec_params_request.peer_params; - nRF5xSecurityManager::getInstance().processSecuritySetupInitiatedEvent(p_event->event_param.p_gap_param->conn_handle, + nRF51SecurityManager::getInstance().processSecuritySetupInitiatedEvent(p_event->event_param.p_gap_param->conn_handle, peerParams->bond, peerParams->mitm, (SecurityManager::SecurityIOCapabilities_t)peerParams->io_caps); break; } case DM_EVT_SECURITY_SETUP_COMPLETE: - nRF5xSecurityManager::getInstance(). + nRF51SecurityManager::getInstance(). processSecuritySetupCompletedEvent(p_event->event_param.p_gap_param->conn_handle, (SecurityManager::SecurityCompletionStatus_t)(p_event->event_param.p_gap_param->params.auth_status.auth_status)); break; @@ -195,11 +195,11 @@ break; } - nRF5xSecurityManager::getInstance().processLinkSecuredEvent(p_event->event_param.p_gap_param->conn_handle, resolvedSecurityMode); + nRF51SecurityManager::getInstance().processLinkSecuredEvent(p_event->event_param.p_gap_param->conn_handle, resolvedSecurityMode); break; } case DM_EVT_DEVICE_CONTEXT_STORED: - nRF5xSecurityManager::getInstance().processSecurityContextStoredEvent(p_event->event_param.p_gap_param->conn_handle); + nRF51SecurityManager::getInstance().processSecurityContextStoredEvent(p_event->event_param.p_gap_param->conn_handle); break; default: break;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/nRF51822n.cpp Tue Jul 21 13:23:45 2015 +0100 @@ -0,0 +1,91 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mbed.h" +#include "nRF51822n.h" +#include "nrf_soc.h" + +#include "btle/btle.h" +#include "nrf_delay.h" + +#include "softdevice_handler.h" + +/** + * The singleton which represents the nRF51822 transport for the BLE. + */ +static nRF51822n deviceInstance; + +/** + * BLE-API requires an implementation of the following function in order to + * obtain its transport handle. + */ +BLEInstanceBase * +createBLEInstance(void) +{ + return (&deviceInstance); +} + +nRF51822n::nRF51822n(void) +{ +} + +nRF51822n::~nRF51822n(void) +{ +} + +const char *nRF51822n::getVersion(void) +{ + static char versionString[32]; + static bool versionFetched = false; + + if (!versionFetched) { + ble_version_t version; + if ((sd_ble_version_get(&version) == NRF_SUCCESS) && (version.company_id == 0x0059)) { + switch (version.version_number) { + case 0x07: + snprintf(versionString, sizeof(versionString), "Nordic BLE4.1 fw:%04x", version.subversion_number); + break; + default: + snprintf(versionString, sizeof(versionString), "Nordic (spec unknown) fw:%04x", version.subversion_number); + break; + } + versionFetched = true; + } else { + strncpy(versionString, "unknown", sizeof(versionString)); + } + } + + return versionString; +} + +ble_error_t nRF51822n::init(void) +{ + /* ToDo: Clear memory contents, reset the SD, etc. */ + btle_init(); + + return BLE_ERROR_NONE; +} + +ble_error_t nRF51822n::shutdown(void) +{ + return (softdevice_handler_sd_disable() == NRF_SUCCESS) ? BLE_ERROR_NONE : BLE_STACK_BUSY; +} + +void +nRF51822n::waitForEvent(void) +{ + sd_app_evt_wait(); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/nRF51822n.h Tue Jul 21 13:23:45 2015 +0100 @@ -0,0 +1,63 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NRF51822_H__ +#define __NRF51822_H__ + +#include "mbed.h" +#include "ble/blecommon.h" +#include "ble/BLE.h" +#include "nRF51Gap.h" +#include "nRF51GattServer.h" +#include "nRF51GattClient.h" +#include "nRF51SecurityManager.h" +#include "btle.h" + +class nRF51822n : public BLEInstanceBase +{ +public: + nRF51822n(void); + virtual ~nRF51822n(void); + + virtual ble_error_t init(void); + virtual ble_error_t shutdown(void); + virtual const char *getVersion(void); + + virtual Gap &getGap() { + return nRF51Gap::getInstance(); + }; + virtual const Gap &getGap() const { + return nRF51Gap::getInstance(); + }; + virtual GattServer &getGattServer() { + return nRF51GattServer::getInstance(); + }; + virtual const GattServer &getGattServer() const { + return nRF51GattServer::getInstance(); + }; + virtual GattClient &getGattClient() { + return nRF51GattClient::getInstance(); + } + virtual const SecurityManager &getSecurityManager() const { + return nRF51SecurityManager::getInstance(); + } + virtual SecurityManager &getSecurityManager() { + return nRF51SecurityManager::getInstance(); + } + virtual void waitForEvent(void); +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/nRF51DiscoveredCharacteristic.cpp Tue Jul 21 13:23:45 2015 +0100 @@ -0,0 +1,63 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "nRF51DiscoveredCharacteristic.h" +#include "nRF51GattClient.h" +#include "ble_gatt.h" + +void +nRF51DiscoveredCharacteristic::setup(nRF51GattClient *gattcIn, + Gap::Handle_t connectionHandleIn, + ble_gatt_char_props_t propsIn, + GattAttribute::Handle_t declHandleIn, + GattAttribute::Handle_t valueHandleIn) +{ + gattc = gattcIn; + connHandle = connectionHandleIn; + declHandle = declHandleIn; + valueHandle = valueHandleIn; + + props._broadcast = propsIn.broadcast; + props._read = propsIn.read; + props._writeWoResp = propsIn.write_wo_resp; + props._write = propsIn.write; + props._notify = propsIn.notify; + props._indicate = propsIn.indicate; + props._authSignedWrite = propsIn.auth_signed_wr; +} + +void +nRF51DiscoveredCharacteristic::setup(nRF51GattClient *gattcIn, + Gap::Handle_t connectionHandleIn, + UUID::ShortUUIDBytes_t uuidIn, + ble_gatt_char_props_t propsIn, + GattAttribute::Handle_t declHandleIn, + GattAttribute::Handle_t valueHandleIn) +{ + gattc = gattcIn; + connHandle = connectionHandleIn; + uuid = uuidIn; + declHandle = declHandleIn; + valueHandle = valueHandleIn; + + props._broadcast = propsIn.broadcast; + props._read = propsIn.read; + props._writeWoResp = propsIn.write_wo_resp; + props._write = propsIn.write; + props._notify = propsIn.notify; + props._indicate = propsIn.indicate; + props._authSignedWrite = propsIn.auth_signed_wr; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/nRF51DiscoveredCharacteristic.h Tue Jul 21 13:23:45 2015 +0100 @@ -0,0 +1,41 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NRF_DISCOVERED_CHARACTERISTIC_H__ +#define __NRF_DISCOVERED_CHARACTERISTIC_H__ + +#include "ble/DiscoveredCharacteristic.h" +#include "ble_gatt.h" + +class nRF51GattClient; /* forward declaration */ + +class nRF51DiscoveredCharacteristic : public DiscoveredCharacteristic { +public: + void setup(nRF51GattClient *gattcIn, + Gap::Handle_t connectionHandleIn, + ble_gatt_char_props_t propsIn, + GattAttribute::Handle_t declHandleIn, + GattAttribute::Handle_t valueHandleIn); + + void setup(nRF51GattClient *gattcIn, + Gap::Handle_t connectionHandleIn, + UUID::ShortUUIDBytes_t uuidIn, + ble_gatt_char_props_t propsIn, + GattAttribute::Handle_t declHandleIn, + GattAttribute::Handle_t valueHandleIn); +}; + +#endif /* __NRF_DISCOVERED_CHARACTERISTIC_H__ */ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/nRF51Gap.cpp Tue Jul 21 13:23:45 2015 +0100 @@ -0,0 +1,465 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "nRF51Gap.h" +#include "mbed.h" + +#include "common/common.h" +#include "ble_advdata.h" +#include "ble_hci.h" + +nRF51Gap &nRF51Gap::getInstance() { + static nRF51Gap m_instance; + return m_instance; +} + +/**************************************************************************/ +/*! + @brief Sets the advertising parameters and payload for the device + + @param[in] params + Basic advertising details, including the advertising + delay, timeout and how the device should be advertised + @params[in] advData + The primary advertising data payload + @params[in] scanResponse + The optional Scan Response payload if the advertising + type is set to \ref GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED + in \ref GapAdveritinngParams + + @returns \ref ble_error_t + + @retval BLE_ERROR_NONE + Everything executed properly + + @retval BLE_ERROR_BUFFER_OVERFLOW + The proposed action would cause a buffer overflow. All + advertising payloads must be <= 31 bytes, for example. + + @retval BLE_ERROR_NOT_IMPLEMENTED + A feature was requested that is not yet supported in the + nRF51 firmware or hardware. + + @retval BLE_ERROR_PARAM_OUT_OF_RANGE + One of the proposed values is outside the valid range. + + @section EXAMPLE + + @code + + @endcode +*/ +/**************************************************************************/ +ble_error_t nRF51Gap::setAdvertisingData(const GapAdvertisingData &advData, const GapAdvertisingData &scanResponse) +{ + /* Make sure we don't exceed the advertising payload length */ + if (advData.getPayloadLen() > GAP_ADVERTISING_DATA_MAX_PAYLOAD) { + return BLE_ERROR_BUFFER_OVERFLOW; + } + + /* Make sure we have a payload! */ + if (advData.getPayloadLen() == 0) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + /* Check the scan response payload limits */ + //if ((params.getAdvertisingType() == GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED)) + //{ + // /* Check if we're within the upper limit */ + // if (advData.getPayloadLen() > GAP_ADVERTISING_DATA_MAX_PAYLOAD) + // { + // return BLE_ERROR_BUFFER_OVERFLOW; + // } + // /* Make sure we have a payload! */ + // if (advData.getPayloadLen() == 0) + // { + // return BLE_ERROR_PARAM_OUT_OF_RANGE; + // } + //} + + /* Send advertising data! */ + ASSERT(ERROR_NONE == + sd_ble_gap_adv_data_set(advData.getPayload(), + advData.getPayloadLen(), + scanResponse.getPayload(), + scanResponse.getPayloadLen()), + BLE_ERROR_PARAM_OUT_OF_RANGE); + + /* Make sure the GAP Service appearance value is aligned with the + *appearance from GapAdvertisingData */ + ASSERT(ERROR_NONE == sd_ble_gap_appearance_set(advData.getAppearance()), + BLE_ERROR_PARAM_OUT_OF_RANGE); + + /* ToDo: Perform some checks on the payload, for example the Scan Response can't */ + /* contains a flags AD type, etc. */ + + return BLE_ERROR_NONE; +} + +/**************************************************************************/ +/*! + @brief Starts the BLE HW, initialising any services that were + added before this function was called. + + @note All services must be added before calling this function! + + @returns ble_error_t + + @retval BLE_ERROR_NONE + Everything executed properly + + @section EXAMPLE + + @code + + @endcode +*/ +/**************************************************************************/ +ble_error_t nRF51Gap::startAdvertising(const GapAdvertisingParams ¶ms) +{ + /* Make sure we support the advertising type */ + if (params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) { + /* ToDo: This requires a propery security implementation, etc. */ + return BLE_ERROR_NOT_IMPLEMENTED; + } + + /* Check interval range */ + if (params.getAdvertisingType() == GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED) { + /* Min delay is slightly longer for unconnectable devices */ + if ((params.getInterval() < GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN_NONCON) || + (params.getInterval() > GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX)) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + } else { + if ((params.getInterval() < GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN) || + (params.getInterval() > GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX)) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + } + + /* Check timeout is zero for Connectable Directed */ + if ((params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) && (params.getTimeout() != 0)) { + /* Timeout must be 0 with this type, although we'll never get here */ + /* since this isn't implemented yet anyway */ + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + /* Check timeout for other advertising types */ + if ((params.getAdvertisingType() != GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) && + (params.getTimeout() > GapAdvertisingParams::GAP_ADV_PARAMS_TIMEOUT_MAX)) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + /* Start Advertising */ + ble_gap_adv_params_t adv_para = {0}; + + adv_para.type = params.getAdvertisingType(); + adv_para.p_peer_addr = NULL; // Undirected advertisement + adv_para.fp = BLE_GAP_ADV_FP_ANY; + adv_para.p_whitelist = NULL; + adv_para.interval = params.getInterval(); // advertising interval (in units of 0.625 ms) + adv_para.timeout = params.getTimeout(); + + ASSERT(ERROR_NONE == sd_ble_gap_adv_start(&adv_para), BLE_ERROR_PARAM_OUT_OF_RANGE); + + state.advertising = 1; + + return BLE_ERROR_NONE; +} + +/**************************************************************************/ +/*! + @brief Stops the BLE HW and disconnects from any devices + + @returns ble_error_t + + @retval BLE_ERROR_NONE + Everything executed properly + + @section EXAMPLE + + @code + + @endcode +*/ +/**************************************************************************/ +ble_error_t nRF51Gap::stopAdvertising(void) +{ + /* Stop Advertising */ + ASSERT(ERROR_NONE == sd_ble_gap_adv_stop(), BLE_ERROR_PARAM_OUT_OF_RANGE); + + state.advertising = 0; + + return BLE_ERROR_NONE; +} + +ble_error_t nRF51Gap::connect(const Address_t peerAddr, + Gap::AddressType_t peerAddrType, + const ConnectionParams_t *connectionParams, + const GapScanningParams *scanParamsIn) +{ + ble_gap_addr_t addr; + addr.addr_type = peerAddrType; + memcpy(addr.addr, peerAddr, Gap::ADDR_LEN); + + ble_gap_conn_params_t connParams; + if (connectionParams != NULL) { + connParams.min_conn_interval = connectionParams->minConnectionInterval; + connParams.max_conn_interval = connectionParams->maxConnectionInterval; + connParams.slave_latency = connectionParams->slaveLatency; + connParams.conn_sup_timeout = connectionParams->connectionSupervisionTimeout; + } else { + connParams.min_conn_interval = 50; + connParams.max_conn_interval = 100; + connParams.slave_latency = 0; + connParams.conn_sup_timeout = 600; + } + + ble_gap_scan_params_t scanParams; + scanParams.active = 0; /**< If 1, perform active scanning (scan requests). */ + scanParams.selective = 0; /**< If 1, ignore unknown devices (non whitelisted). */ + scanParams.p_whitelist = NULL; /**< Pointer to whitelist, NULL if none is given. */ + if (scanParamsIn != NULL) { + scanParams.interval = scanParamsIn->getInterval(); /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ + scanParams.window = scanParamsIn->getWindow(); /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ + scanParams.timeout = scanParamsIn->getTimeout(); /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ + } else { + scanParams.interval = 500; /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ + scanParams.window = 200; /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ + scanParams.timeout = 0; /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ + } + + uint32_t rc = sd_ble_gap_connect(&addr, &scanParams, &connParams); + if (rc == NRF_SUCCESS) { + return BLE_ERROR_NONE; + } + switch (rc) { + case NRF_ERROR_INVALID_ADDR: + return BLE_ERROR_INVALID_PARAM; + case NRF_ERROR_INVALID_PARAM: + return BLE_ERROR_INVALID_PARAM; + case NRF_ERROR_INVALID_STATE: + return BLE_ERROR_INVALID_STATE; + case BLE_ERROR_GAP_INVALID_BLE_ADDR: + return BLE_ERROR_INVALID_PARAM; + case NRF_ERROR_NO_MEM: + return BLE_ERROR_NO_MEM; + case NRF_ERROR_BUSY: + return BLE_STACK_BUSY; + default: + case BLE_ERROR_GAP_WHITELIST_IN_USE: + return BLE_ERROR_UNSPECIFIED; + } +} + +ble_error_t nRF51Gap::disconnect(Handle_t connectionHandle, DisconnectionReason_t reason) +{ + state.advertising = 0; + state.connected = 0; + + uint8_t code = BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION; + switch (reason) { + case REMOTE_USER_TERMINATED_CONNECTION: + code = BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION; + break; + case CONN_INTERVAL_UNACCEPTABLE: + code = BLE_HCI_CONN_INTERVAL_UNACCEPTABLE; + break; + default: + break; + } + + /* Disconnect if we are connected to a central device */ + ASSERT_INT(ERROR_NONE, sd_ble_gap_disconnect(connectionHandle, code), BLE_ERROR_PARAM_OUT_OF_RANGE); + + return BLE_ERROR_NONE; +} + +/*! + @brief Disconnects if we are connected to a central device + + @returns ble_error_t + + @retval BLE_ERROR_NONE + Everything executed properly +*/ +ble_error_t nRF51Gap::disconnect(DisconnectionReason_t reason) +{ + return disconnect(m_connectionHandle, reason); +} + +ble_error_t nRF51Gap::getPreferredConnectionParams(ConnectionParams_t *params) +{ + ASSERT_INT(NRF_SUCCESS, + sd_ble_gap_ppcp_get(reinterpret_cast<ble_gap_conn_params_t *>(params)), + BLE_ERROR_PARAM_OUT_OF_RANGE); + + return BLE_ERROR_NONE; +} + +ble_error_t nRF51Gap::setPreferredConnectionParams(const ConnectionParams_t *params) +{ + ASSERT_INT(NRF_SUCCESS, + sd_ble_gap_ppcp_set(reinterpret_cast<const ble_gap_conn_params_t *>(params)), + BLE_ERROR_PARAM_OUT_OF_RANGE); + + return BLE_ERROR_NONE; +} + +ble_error_t nRF51Gap::updateConnectionParams(Handle_t handle, const ConnectionParams_t *newParams) +{ + uint32_t rc; + + rc = sd_ble_gap_conn_param_update(handle, reinterpret_cast<ble_gap_conn_params_t *>(const_cast<ConnectionParams_t*>(newParams))); + if (rc == NRF_SUCCESS) { + return BLE_ERROR_NONE; + } else { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } +} + +/**************************************************************************/ +/*! + @brief Sets the 16-bit connection handle +*/ +/**************************************************************************/ +void nRF51Gap::setConnectionHandle(uint16_t con_handle) +{ + m_connectionHandle = con_handle; +} + +/**************************************************************************/ +/*! + @brief Gets the 16-bit connection handle +*/ +/**************************************************************************/ +uint16_t nRF51Gap::getConnectionHandle(void) +{ + return m_connectionHandle; +} + +/**************************************************************************/ +/*! + @brief Sets the BLE device address + + @returns ble_error_t + + @section EXAMPLE + + @code + + uint8_t device_address[6] = { 0xca, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0 }; + nrf.getGap().setAddress(Gap::ADDR_TYPE_RANDOM_STATIC, device_address); + + @endcode +*/ +/**************************************************************************/ +ble_error_t nRF51Gap::setAddress(AddressType_t type, const Address_t address) +{ + if (type > ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + ble_gap_addr_t dev_addr; + dev_addr.addr_type = type; + memcpy(dev_addr.addr, address, ADDR_LEN); + + ASSERT_INT(ERROR_NONE, sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &dev_addr), BLE_ERROR_PARAM_OUT_OF_RANGE); + + return BLE_ERROR_NONE; +} + +ble_error_t nRF51Gap::getAddress(AddressType_t *typeP, Address_t address) +{ + ble_gap_addr_t dev_addr; + if (sd_ble_gap_address_get(&dev_addr) != NRF_SUCCESS) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + if (typeP != NULL) { + *typeP = static_cast<AddressType_t>(dev_addr.addr_type); + } + if (address != NULL) { + memcpy(address, dev_addr.addr, ADDR_LEN); + } + return BLE_ERROR_NONE; +} + +ble_error_t nRF51Gap::setDeviceName(const uint8_t *deviceName) +{ + ble_gap_conn_sec_mode_t sec_mode; + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); // no security is needed + + if (sd_ble_gap_device_name_set(&sec_mode, deviceName, strlen((const char *)deviceName)) == NRF_SUCCESS) { + return BLE_ERROR_NONE; + } else { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } +} + +ble_error_t nRF51Gap::getDeviceName(uint8_t *deviceName, unsigned *lengthP) +{ + if (sd_ble_gap_device_name_get(deviceName, (uint16_t *)lengthP) == NRF_SUCCESS) { + return BLE_ERROR_NONE; + } else { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } +} + +ble_error_t nRF51Gap::setAppearance(GapAdvertisingData::Appearance appearance) +{ + if (sd_ble_gap_appearance_set(appearance) == NRF_SUCCESS) { + return BLE_ERROR_NONE; + } else { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } +} + +ble_error_t nRF51Gap::getAppearance(GapAdvertisingData::Appearance *appearanceP) +{ + if (sd_ble_gap_appearance_get(reinterpret_cast<uint16_t *>(appearanceP))) { + return BLE_ERROR_NONE; + } else { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } +} + +/* (Valid values are -40, -20, -16, -12, -8, -4, 0, 4) */ +ble_error_t nRF51Gap::setTxPower(int8_t txPower) +{ + unsigned rc; + if ((rc = sd_ble_gap_tx_power_set(txPower)) != NRF_SUCCESS) { + switch (rc) { + case NRF_ERROR_BUSY: + return BLE_STACK_BUSY; + case NRF_ERROR_INVALID_PARAM: + default: + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + } + + return BLE_ERROR_NONE; +} + +void nRF51Gap::getPermittedTxPowerValues(const int8_t **valueArrayPP, size_t *countP) +{ + static const int8_t permittedTxValues[] = { + -40, -30, -20, -16, -12, -8, -4, 0, 4 + }; + + *valueArrayPP = permittedTxValues; + *countP = sizeof(permittedTxValues) / sizeof(int8_t); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/nRF51Gap.h Tue Jul 21 13:23:45 2015 +0100 @@ -0,0 +1,113 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NRF51822_GAP_H__ +#define __NRF51822_GAP_H__ + +#include "mbed.h" +#include "ble/blecommon.h" +#include "ble.h" +#include "ble/GapAdvertisingParams.h" +#include "ble/GapAdvertisingData.h" +#include "ble/Gap.h" +#include "ble/GapScanningParams.h" + +#include "nrf_soc.h" +#include "ble_radio_notification.h" +#include "btle_security.h" + +/**************************************************************************/ +/*! + \brief + +*/ +/**************************************************************************/ +class nRF51Gap : public Gap +{ +public: + static nRF51Gap &getInstance(); + + /* Functions that must be implemented from Gap */ + virtual ble_error_t setAddress(AddressType_t type, const Address_t address); + virtual ble_error_t getAddress(AddressType_t *typeP, Address_t address); + virtual ble_error_t setAdvertisingData(const GapAdvertisingData &, const GapAdvertisingData &); + + virtual uint16_t getMinAdvertisingInterval(void) const {return ADVERTISEMENT_DURATION_UNITS_TO_MS(BLE_GAP_ADV_INTERVAL_MIN);} + virtual uint16_t getMinNonConnectableAdvertisingInterval(void) const {return ADVERTISEMENT_DURATION_UNITS_TO_MS(BLE_GAP_ADV_NONCON_INTERVAL_MIN);} + virtual uint16_t getMaxAdvertisingInterval(void) const {return ADVERTISEMENT_DURATION_UNITS_TO_MS(BLE_GAP_ADV_INTERVAL_MAX);} + + virtual ble_error_t startAdvertising(const GapAdvertisingParams &); + virtual ble_error_t stopAdvertising(void); + virtual ble_error_t connect(const Address_t, Gap::AddressType_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParams); + virtual ble_error_t disconnect(Handle_t connectionHandle, DisconnectionReason_t reason); + virtual ble_error_t disconnect(DisconnectionReason_t reason); + + virtual ble_error_t setDeviceName(const uint8_t *deviceName); + virtual ble_error_t getDeviceName(uint8_t *deviceName, unsigned *lengthP); + virtual ble_error_t setAppearance(GapAdvertisingData::Appearance appearance); + virtual ble_error_t getAppearance(GapAdvertisingData::Appearance *appearanceP); + + virtual ble_error_t setTxPower(int8_t txPower); + virtual void getPermittedTxPowerValues(const int8_t **valueArrayPP, size_t *countP); + + void setConnectionHandle(uint16_t con_handle); + uint16_t getConnectionHandle(void); + + virtual ble_error_t getPreferredConnectionParams(ConnectionParams_t *params); + virtual ble_error_t setPreferredConnectionParams(const ConnectionParams_t *params); + virtual ble_error_t updateConnectionParams(Handle_t handle, const ConnectionParams_t *params); + + virtual void onRadioNotification(RadioNotificationEventCallback_t callback) { + Gap::onRadioNotification(callback); + ble_radio_notification_init(NRF_APP_PRIORITY_HIGH, NRF_RADIO_NOTIFICATION_DISTANCE_800US, radioNotificationCallback); + } + + virtual ble_error_t startRadioScan(const GapScanningParams &scanningParams) { + ble_gap_scan_params_t scanParams = { + .active = scanningParams.getActiveScanning(), /**< If 1, perform active scanning (scan requests). */ + .selective = 0, /**< If 1, ignore unknown devices (non whitelisted). */ + .p_whitelist = NULL, /**< Pointer to whitelist, NULL if none is given. */ + .interval = scanningParams.getInterval(), /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ + .window = scanningParams.getWindow(), /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ + .timeout = scanningParams.getTimeout(), /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ + }; + + if (sd_ble_gap_scan_start(&scanParams) != NRF_SUCCESS) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + return BLE_ERROR_NONE; + } + + virtual ble_error_t stopScan(void) { + if (sd_ble_gap_scan_stop() == NRF_SUCCESS) { + return BLE_ERROR_NONE; + } + + return BLE_STACK_BUSY; + } + +private: + uint16_t m_connectionHandle; + nRF51Gap() { + m_connectionHandle = BLE_CONN_HANDLE_INVALID; + } + + nRF51Gap(nRF51Gap const &); + void operator=(nRF51Gap const &); +}; + +#endif // ifndef __NRF51822_GAP_H__ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/nRF51GattClient.cpp Tue Jul 21 13:23:45 2015 +0100 @@ -0,0 +1,34 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "nRF51GattClient.h" + +nRF51GattClient nRFGattClientSingleton; + +nRF51GattClient & +nRF51GattClient::getInstance(void) { + return nRFGattClientSingleton; +} + +ble_error_t +nRF51GattClient::launchServiceDiscovery(Gap::Handle_t connectionHandle, + ServiceDiscovery::ServiceCallback_t sc, + ServiceDiscovery::CharacteristicCallback_t cc, + const UUID &matchingServiceUUIDIn, + const UUID &matchingCharacteristicUUIDIn) +{ + return discovery.launch(connectionHandle, sc, cc, matchingServiceUUIDIn, matchingCharacteristicUUIDIn); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/nRF51GattClient.h Tue Jul 21 13:23:45 2015 +0100 @@ -0,0 +1,157 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NRF51822_GATT_CLIENT_H__ +#define __NRF51822_GATT_CLIENT_H__ + +#include "ble/GattClient.h" +#include "nRF51ServiceDiscovery.h" + +class nRF51GattClient : public GattClient +{ +public: + static nRF51GattClient &getInstance(); + + /** + * Launch service discovery. Once launched, service discovery will remain + * active with callbacks being issued back into the application for matching + * services/characteristics. isActive() can be used to determine status; and + * a termination callback (if setup) will be invoked at the end. Service + * discovery can be terminated prematurely if needed using terminate(). + * + * @param connectionHandle + * Handle for the connection with the peer. + * @param sc + * This is the application callback for matching service. Taken as + * NULL by default. Note: service discovery may still be active + * when this callback is issued; calling asynchronous BLE-stack + * APIs from within this application callback might cause the + * stack to abort service discovery. If this becomes an issue, it + * may be better to make local copy of the discoveredService and + * wait for service discovery to terminate before operating on the + * service. + * @param cc + * This is the application callback for matching characteristic. + * Taken as NULL by default. Note: service discovery may still be + * active when this callback is issued; calling asynchronous + * BLE-stack APIs from within this application callback might cause + * the stack to abort service discovery. If this becomes an issue, + * it may be better to make local copy of the discoveredCharacteristic + * and wait for service discovery to terminate before operating on the + * characteristic. + * @param matchingServiceUUID + * UUID based filter for specifying a service in which the application is + * interested. By default it is set as the wildcard UUID_UNKNOWN, + * in which case it matches all services. If characteristic-UUID + * filter (below) is set to the wildcard value, then a service + * callback will be invoked for the matching service (or for every + * service if the service filter is a wildcard). + * @param matchingCharacteristicUUIDIn + * UUID based filter for specifying characteristic in which the application + * is interested. By default it is set as the wildcard UUID_UKNOWN + * to match against any characteristic. If both service-UUID + * filter and characteristic-UUID filter are used with non- wildcard + * values, then only a single characteristic callback is + * invoked for the matching characteristic. + * + * @Note Using wildcard values for both service-UUID and characteristic- + * UUID will result in complete service discovery--callbacks being + * called for every service and characteristic. + * + * @return + * BLE_ERROR_NONE if service discovery is launched successfully; else an appropriate error. + */ + virtual ble_error_t launchServiceDiscovery(Gap::Handle_t connectionHandle, + ServiceDiscovery::ServiceCallback_t sc = NULL, + ServiceDiscovery::CharacteristicCallback_t cc = NULL, + const UUID &matchingServiceUUID = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN), + const UUID &matchingCharacteristicUUIDIn = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)); + + virtual void onServiceDiscoveryTermination(ServiceDiscovery::TerminationCallback_t callback) { + discovery.onTermination(callback); + } + + /** + * Is service-discovery currently active? + */ + virtual bool isServiceDiscoveryActive(void) const { + return discovery.isActive(); + } + + /** + * Terminate an ongoing service-discovery. This should result in an + * invocation of the TerminationCallback if service-discovery is active. + */ + virtual void terminateServiceDiscovery(void) { + discovery.terminate(); + } + + virtual ble_error_t read(Gap::Handle_t connHandle, GattAttribute::Handle_t attributeHandle, uint16_t offset) const { + uint32_t rc = sd_ble_gattc_read(connHandle, attributeHandle, offset); + if (rc == NRF_SUCCESS) { + return BLE_ERROR_NONE; + } + switch (rc) { + case NRF_ERROR_BUSY: + return BLE_STACK_BUSY; + case BLE_ERROR_INVALID_CONN_HANDLE: + case NRF_ERROR_INVALID_STATE: + case NRF_ERROR_INVALID_ADDR: + default: + return BLE_ERROR_INVALID_STATE; + } + } + + virtual ble_error_t write(GattClient::WriteOp_t cmd, Gap::Handle_t connHandle, GattAttribute::Handle_t attributeHandle, size_t length, const uint8_t *value) const { + ble_gattc_write_params_t writeParams = { }; + writeParams.write_op = cmd; + writeParams.handle = attributeHandle; + writeParams.len = length; + writeParams.p_value = const_cast<uint8_t *>(value); + + uint32_t rc = sd_ble_gattc_write(connHandle, &writeParams); + if (rc == NRF_SUCCESS) { + return BLE_ERROR_NONE; + } + switch (rc) { + case NRF_ERROR_BUSY: + return BLE_STACK_BUSY; + case BLE_ERROR_NO_TX_BUFFERS: + return BLE_ERROR_NO_MEM; + case BLE_ERROR_INVALID_CONN_HANDLE: + case NRF_ERROR_INVALID_STATE: + case NRF_ERROR_INVALID_ADDR: + default: + return BLE_ERROR_INVALID_STATE; + } + } + +public: + nRF51GattClient() : discovery(this) { + /* empty */ + } + + friend void bleGattcEventHandler(const ble_evt_t *p_ble_evt); + +private: + nRF51GattClient(const nRF51GattClient &); + const nRF51GattClient& operator=(const nRF51GattClient &); + +private: + nRF51ServiceDiscovery discovery; +}; + +#endif // ifndef __NRF51822_GATT_CLIENT_H__ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/nRF51GattServer.cpp Tue Jul 21 13:23:45 2015 +0100 @@ -0,0 +1,457 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "nRF51GattServer.h" +#include "mbed.h" + +#include "common/common.h" +#include "btle/custom/custom_helper.h" + +#include "nRF51Gap.h" + +nRF51GattServer &nRF51GattServer::getInstance(void) { + static nRF51GattServer m_instance; + return m_instance; +} + +/**************************************************************************/ +/*! + @brief Adds a new service to the GATT table on the peripheral + + @returns ble_error_t + + @retval BLE_ERROR_NONE + Everything executed properly + + @section EXAMPLE + + @code + + @endcode +*/ +/**************************************************************************/ +ble_error_t nRF51GattServer::addService(GattService &service) +{ + /* ToDo: Make sure we don't overflow the array, etc. */ + /* ToDo: Make sure this service UUID doesn't already exist (?) */ + /* ToDo: Basic validation */ + + /* Add the service to the nRF51 */ + ble_uuid_t nordicUUID; + nordicUUID = custom_convert_to_nordic_uuid(service.getUUID()); + + uint16_t serviceHandle; + ASSERT( ERROR_NONE == + sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, + &nordicUUID, + &serviceHandle), + BLE_ERROR_PARAM_OUT_OF_RANGE ); + service.setHandle(serviceHandle); + + /* Add characteristics to the service */ + for (uint8_t i = 0; i < service.getCharacteristicCount(); i++) { + GattCharacteristic *p_char = service.getCharacteristic(i); + + /* Skip any incompletely defined, read-only characteristics. */ + if ((p_char->getValueAttribute().getValuePtr() == NULL) && + (p_char->getValueAttribute().getInitialLength() == 0) && + (p_char->getProperties() == GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ)) { + continue; + } + + nordicUUID = custom_convert_to_nordic_uuid(p_char->getValueAttribute().getUUID()); + + /* The user-description descriptor is a special case which needs to be + * handled at the time of adding the characteristic. The following block + * is meant to discover its presence. */ + const uint8_t *userDescriptionDescriptorValuePtr = NULL; + uint16_t userDescriptionDescriptorValueLen = 0; + for (uint8_t j = 0; j < p_char->getDescriptorCount(); j++) { + GattAttribute *p_desc = p_char->getDescriptor(j); + if (p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_USER_DESC) { + userDescriptionDescriptorValuePtr = p_desc->getValuePtr(); + userDescriptionDescriptorValueLen = p_desc->getLength(); + } + } + + ASSERT ( ERROR_NONE == + custom_add_in_characteristic(BLE_GATT_HANDLE_INVALID, + &nordicUUID, + p_char->getProperties(), + p_char->getRequiredSecurity(), + p_char->getValueAttribute().getValuePtr(), + p_char->getValueAttribute().getInitialLength(), + p_char->getValueAttribute().getMaxLength(), + userDescriptionDescriptorValuePtr, + userDescriptionDescriptorValueLen, + p_char->isReadAuthorizationEnabled(), + p_char->isWriteAuthorizationEnabled(), + &nrfCharacteristicHandles[characteristicCount]), + BLE_ERROR_PARAM_OUT_OF_RANGE ); + + /* Update the characteristic handle */ + p_characteristics[characteristicCount] = p_char; + p_char->getValueAttribute().setHandle(nrfCharacteristicHandles[characteristicCount].value_handle); + characteristicCount++; + + /* Add optional descriptors if any */ + /* ToDo: Make sure we don't overflow the array */ + for (uint8_t j = 0; j < p_char->getDescriptorCount(); j++) { + GattAttribute *p_desc = p_char->getDescriptor(j); + /* skip the user-description-descriptor here; this has already been handled when adding the characteristic (above). */ + if (p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_USER_DESC) { + continue; + } + + nordicUUID = custom_convert_to_nordic_uuid(p_desc->getUUID()); + + ASSERT(ERROR_NONE == + custom_add_in_descriptor(BLE_GATT_HANDLE_INVALID, + &nordicUUID, + p_desc->getValuePtr(), + p_desc->getInitialLength(), + p_desc->getMaxLength(), + &nrfDescriptorHandles[descriptorCount]), + BLE_ERROR_PARAM_OUT_OF_RANGE); + + p_descriptors[descriptorCount++] = p_desc; + p_desc->setHandle(nrfDescriptorHandles[descriptorCount]); + } + } + + serviceCount++; + + return BLE_ERROR_NONE; +} + +/**************************************************************************/ +/*! + @brief Reads the value of a characteristic, based on the service + and characteristic index fields + + @param[in] attributeHandle + The handle of the GattCharacteristic to read from + @param[in] buffer + Buffer to hold the the characteristic's value + (raw byte array in LSB format) + @param[in/out] len + input: Length in bytes to be read. + output: Total length of attribute value upon successful return. + + @returns ble_error_t + + @retval BLE_ERROR_NONE + Everything executed properly +*/ +/**************************************************************************/ +ble_error_t nRF51GattServer::read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) +{ + return read(BLE_CONN_HANDLE_INVALID, attributeHandle, buffer, lengthP); +} + +ble_error_t nRF51GattServer::read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) +{ + ble_gatts_value_t value = { + .len = *lengthP, + .offset = 0, + .p_value = buffer, + }; + + ASSERT( ERROR_NONE == + sd_ble_gatts_value_get(connectionHandle, attributeHandle, &value), + BLE_ERROR_PARAM_OUT_OF_RANGE); + *lengthP = value.len; + + return BLE_ERROR_NONE; +} + +/**************************************************************************/ +/*! + @brief Updates the value of a characteristic, based on the service + and characteristic index fields + + @param[in] charHandle + The handle of the GattCharacteristic to write to + @param[in] buffer + Data to use when updating the characteristic's value + (raw byte array in LSB format) + @param[in] len + The number of bytes in buffer + + @returns ble_error_t + + @retval BLE_ERROR_NONE + Everything executed properly +*/ +/**************************************************************************/ +ble_error_t nRF51GattServer::write(GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly) +{ + return write(BLE_CONN_HANDLE_INVALID, attributeHandle, buffer, len, localOnly); +} + +ble_error_t nRF51GattServer::write(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly) +{ + uint16_t gapConnectionHandle = nRF51Gap::getInstance().getConnectionHandle(); + ble_error_t returnValue = BLE_ERROR_NONE; + + ble_gatts_value_t value = { + .len = len, + .offset = 0, + .p_value = const_cast<uint8_t *>(buffer), + }; + + if (localOnly) { + /* Only update locally regardless of notify/indicate */ + ASSERT_INT( ERROR_NONE, + sd_ble_gatts_value_set(connectionHandle, attributeHandle, &value), + BLE_ERROR_PARAM_OUT_OF_RANGE ); + return BLE_ERROR_NONE; + } + + int characteristicIndex = resolveValueHandleToCharIndex(attributeHandle); + if ((characteristicIndex != -1) && + (p_characteristics[characteristicIndex]->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)) && + (gapConnectionHandle != connectionHandle)) { + /* HVX update for the characteristic value */ + ble_gatts_hvx_params_t hvx_params; + + hvx_params.handle = attributeHandle; + hvx_params.type = + (p_characteristics[characteristicIndex]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) ? BLE_GATT_HVX_NOTIFICATION : BLE_GATT_HVX_INDICATION; + hvx_params.offset = 0; + hvx_params.p_data = const_cast<uint8_t *>(buffer); + hvx_params.p_len = &len; + + error_t error = (error_t) sd_ble_gatts_hvx(gapConnectionHandle, &hvx_params); + + /* ERROR_INVALID_STATE, ERROR_BUSY, ERROR_GATTS_SYS_ATTR_MISSING and ERROR_NO_TX_BUFFERS the ATT table has been updated. */ + if ((error != ERROR_NONE) && (error != ERROR_INVALID_STATE) && (error != ERROR_BLE_NO_TX_BUFFERS) && (error != ERROR_BUSY) && (error != ERROR_BLEGATTS_SYS_ATTR_MISSING)) { + ASSERT_INT( ERROR_NONE, + sd_ble_gatts_value_set(connectionHandle, attributeHandle, &value), + BLE_ERROR_PARAM_OUT_OF_RANGE ); + } + + /* Notifications consume application buffers. The return value can + be used for resending notifications. + */ + if (error != ERROR_NONE) { + returnValue = BLE_STACK_BUSY; + } + } else { + ASSERT_INT( ERROR_NONE, + sd_ble_gatts_value_set(connectionHandle, attributeHandle, &value), + BLE_ERROR_PARAM_OUT_OF_RANGE ); + } + + return returnValue; +} + +ble_error_t nRF51GattServer::areUpdatesEnabled(const GattCharacteristic &characteristic, bool *enabledP) +{ + /* Forward the call with the default connection handle. */ + return areUpdatesEnabled(nRF51Gap::getInstance().getConnectionHandle(), characteristic, enabledP); +} + +ble_error_t nRF51GattServer::areUpdatesEnabled(Gap::Handle_t connectionHandle, const GattCharacteristic &characteristic, bool *enabledP) +{ + int characteristicIndex = resolveValueHandleToCharIndex(characteristic.getValueHandle()); + if (characteristicIndex == -1) { + return BLE_ERROR_INVALID_PARAM; + } + + /* Read the cccd value from the GATT server. */ + GattAttribute::Handle_t cccdHandle = nrfCharacteristicHandles[characteristicIndex].cccd_handle; + uint16_t cccdValue; + uint16_t length = sizeof(cccdValue); + ble_error_t rc = read(connectionHandle, cccdHandle, reinterpret_cast<uint8_t *>(&cccdValue), &length); + if (rc != BLE_ERROR_NONE) { + return rc; + } + if (length != sizeof(cccdValue)) { + return BLE_ERROR_INVALID_STATE; + } + + /* Check for NOTFICATION or INDICATION in CCCD. */ + if ((cccdValue & BLE_GATT_HVX_NOTIFICATION) || (cccdValue & BLE_GATT_HVX_INDICATION)) { + *enabledP = true; + } + + return BLE_ERROR_NONE; +} + +/**************************************************************************/ +/*! + @brief Callback handler for events getting pushed up from the SD +*/ +/**************************************************************************/ +void nRF51GattServer::hwCallback(ble_evt_t *p_ble_evt) +{ + GattAttribute::Handle_t handle_value; + GattServerEvents::gattEvent_t eventType; + const ble_gatts_evt_t *gattsEventP = &p_ble_evt->evt.gatts_evt; + + switch (p_ble_evt->header.evt_id) { + case BLE_GATTS_EVT_WRITE: { + /* There are 2 use case here: Values being updated & CCCD (indicate/notify) enabled */ + + /* 1.) Handle CCCD changes */ + handle_value = gattsEventP->params.write.handle; + int characteristicIndex = resolveCCCDHandleToCharIndex(handle_value); + if ((characteristicIndex != -1) && + (p_characteristics[characteristicIndex]->getProperties() & + (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY))) { + + uint16_t cccd_value = (gattsEventP->params.write.data[1] << 8) | gattsEventP->params.write.data[0]; /* Little Endian but M0 may be mis-aligned */ + + if (((p_characteristics[characteristicIndex]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) && (cccd_value & BLE_GATT_HVX_INDICATION)) || + ((p_characteristics[characteristicIndex]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) && (cccd_value & BLE_GATT_HVX_NOTIFICATION))) { + eventType = GattServerEvents::GATT_EVENT_UPDATES_ENABLED; + } else { + eventType = GattServerEvents::GATT_EVENT_UPDATES_DISABLED; + } + + handleEvent(eventType, p_characteristics[characteristicIndex]->getValueHandle()); + return; + } + + /* 2.) Changes to the characteristic value will be handled with other events below */ + eventType = GattServerEvents::GATT_EVENT_DATA_WRITTEN; + } + break; + + case BLE_GATTS_EVT_HVC: + /* Indication confirmation received */ + eventType = GattServerEvents::GATT_EVENT_CONFIRMATION_RECEIVED; + handle_value = gattsEventP->params.hvc.handle; + break; + + case BLE_EVT_TX_COMPLETE: { + handleDataSentEvent(p_ble_evt->evt.common_evt.params.tx_complete.count); + return; + } + + case BLE_GATTS_EVT_SYS_ATTR_MISSING: + sd_ble_gatts_sys_attr_set(gattsEventP->conn_handle, NULL, 0, 0); + return; + + case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: + switch (gattsEventP->params.authorize_request.type) { + case BLE_GATTS_AUTHORIZE_TYPE_READ: + eventType = GattServerEvents::GATT_EVENT_READ_AUTHORIZATION_REQ; + handle_value = gattsEventP->params.authorize_request.request.read.handle; + break; + case BLE_GATTS_AUTHORIZE_TYPE_WRITE: + eventType = GattServerEvents::GATT_EVENT_WRITE_AUTHORIZATION_REQ; + handle_value = gattsEventP->params.authorize_request.request.write.handle; + break; + default: + return; + } + break; + + default: + return; + } + + int characteristicIndex = resolveValueHandleToCharIndex(handle_value); + if (characteristicIndex == -1) { + return; + } + + /* Find index (charHandle) in the pool */ + switch (eventType) { + case GattServerEvents::GATT_EVENT_DATA_WRITTEN: { + GattWriteCallbackParams cbParams = { + .handle = handle_value, + .writeOp = static_cast<GattWriteCallbackParams::WriteOp_t>(gattsEventP->params.write.op), + .offset = gattsEventP->params.write.offset, + .len = gattsEventP->params.write.len, + .data = gattsEventP->params.write.data + }; + handleDataWrittenEvent(&cbParams); + break; + } + case GattServerEvents::GATT_EVENT_WRITE_AUTHORIZATION_REQ: { + GattWriteAuthCallbackParams cbParams = { + .handle = handle_value, + .offset = gattsEventP->params.authorize_request.request.write.offset, + .len = gattsEventP->params.authorize_request.request.write.len, + .data = gattsEventP->params.authorize_request.request.write.data, + }; + ble_gatts_rw_authorize_reply_params_t reply = { + .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, + .params = { + .write = { + .gatt_status = p_characteristics[characteristicIndex]->authorizeWrite(&cbParams) + } + } + }; + sd_ble_gatts_rw_authorize_reply(gattsEventP->conn_handle, &reply); + + /* + * If write-authorization is enabled for a characteristic, + * AUTHORIZATION_REQ event (if replied with true) is *not* + * followed by another DATA_WRITTEN event; so we still need + * to invoke handleDataWritten(), much the same as we would + * have done if write-authorization had not been enabled. + */ + if (reply.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS) { + GattWriteCallbackParams cbParams = { + .handle = handle_value, + .writeOp = static_cast<GattWriteCallbackParams::WriteOp_t>(gattsEventP->params.authorize_request.request.write.op), + .offset = gattsEventP->params.authorize_request.request.write.offset, + .len = gattsEventP->params.authorize_request.request.write.len, + .data = gattsEventP->params.authorize_request.request.write.data, + }; + handleDataWrittenEvent(&cbParams); + } + break; + } + case GattServerEvents::GATT_EVENT_READ_AUTHORIZATION_REQ: { + GattReadAuthCallbackParams cbParams = { + .handle = handle_value, + .offset = gattsEventP->params.authorize_request.request.read.offset, + .len = 0, + .data = NULL + }; + + ble_gatts_rw_authorize_reply_params_t reply = { + .type = BLE_GATTS_AUTHORIZE_TYPE_READ, + .params = { + .read = { + .gatt_status = p_characteristics[characteristicIndex]->authorizeRead(&cbParams) + } + } + }; + + if (cbParams.authorizationReply == BLE_GATT_STATUS_SUCCESS) { + if (cbParams.data != NULL) { + reply.params.read.update = 1; + reply.params.read.offset = cbParams.offset; + reply.params.read.len = cbParams.len; + reply.params.read.p_data = cbParams.data; + } + } + + sd_ble_gatts_rw_authorize_reply(gattsEventP->conn_handle, &reply); + break; + } + + default: + handleEvent(eventType, handle_value); + break; + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/nRF51GattServer.h Tue Jul 21 13:23:45 2015 +0100 @@ -0,0 +1,98 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NRF51822_GATT_SERVER_H__ +#define __NRF51822_GATT_SERVER_H__ + +#include <stddef.h> + +#include "ble/blecommon.h" +#include "ble.h" /* nordic ble */ +#include "ble/Gap.h" +#include "ble/GattServer.h" + +class nRF51GattServer : public GattServer +{ +public: + static nRF51GattServer &getInstance(); + + /* Functions that must be implemented from GattServer */ + virtual ble_error_t addService(GattService &); + virtual ble_error_t read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP); + virtual ble_error_t read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP); + virtual ble_error_t write(GattAttribute::Handle_t, const uint8_t[], uint16_t, bool localOnly = false); + virtual ble_error_t write(Gap::Handle_t connectionHandle, GattAttribute::Handle_t, const uint8_t[], uint16_t, bool localOnly = false); + virtual ble_error_t areUpdatesEnabled(const GattCharacteristic &characteristic, bool *enabledP); + virtual ble_error_t areUpdatesEnabled(Gap::Handle_t connectionHandle, const GattCharacteristic &characteristic, bool *enabledP); + + /* nRF51 Functions */ + void eventCallback(void); + void hwCallback(ble_evt_t *p_ble_evt); + +private: + const static unsigned BLE_TOTAL_CHARACTERISTICS = 20; + const static unsigned BLE_TOTAL_DESCRIPTORS = 8; + +private: + /** + * resolve a value attribute to its owning characteristic. + * @param valueHandle the value handle to be resolved. + * @return characteristic index if a resolution is found, else -1. + */ + int resolveValueHandleToCharIndex(GattAttribute::Handle_t valueHandle) const { + unsigned charIndex; + for (charIndex = 0; charIndex < characteristicCount; charIndex++) { + if (nrfCharacteristicHandles[charIndex].value_handle == valueHandle) { + return charIndex; + } + } + + return -1; + } + + /** + * resolve a CCCD attribute handle to its owning characteristic. + * @param cccdHandle the CCCD handle to be resolved. + * @return characteristic index if a resolution is found, else -1. + */ + int resolveCCCDHandleToCharIndex(GattAttribute::Handle_t cccdHandle) const { + unsigned charIndex; + for (charIndex = 0; charIndex < characteristicCount; charIndex++) { + if (nrfCharacteristicHandles[charIndex].cccd_handle == cccdHandle) { + return charIndex; + } + } + + return -1; + } + +private: + GattCharacteristic *p_characteristics[BLE_TOTAL_CHARACTERISTICS]; + ble_gatts_char_handles_t nrfCharacteristicHandles[BLE_TOTAL_CHARACTERISTICS]; + GattAttribute *p_descriptors[BLE_TOTAL_DESCRIPTORS]; + uint8_t descriptorCount; + uint16_t nrfDescriptorHandles[BLE_TOTAL_DESCRIPTORS]; + + nRF51GattServer() : GattServer(), p_characteristics(), nrfCharacteristicHandles(), p_descriptors(), descriptorCount(0), nrfDescriptorHandles() { + /* empty */ + } + +private: + nRF51GattServer(const nRF51GattServer &); + const nRF51GattServer& operator=(const nRF51GattServer &); +}; + +#endif // ifndef __NRF51822_GATT_SERVER_H__ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/nRF51SecurityManager.cpp Tue Jul 21 13:23:45 2015 +0100 @@ -0,0 +1,22 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "nRF51SecurityManager.h" + +nRF51SecurityManager &nRF51SecurityManager::getInstance(void) { + static nRF51SecurityManager m_instance; + return m_instance; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/nRF51SecurityManager.h Tue Jul 21 13:23:45 2015 +0100 @@ -0,0 +1,56 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NRF51822_SECURITY_MANAGER_H__ +#define __NRF51822_SECURITY_MANAGER_H__ + +#include <stddef.h> + +#include "ble/SecurityManager.h" +#include "btle_security.h" + +class nRF51SecurityManager : public SecurityManager +{ +public: + static nRF51SecurityManager &getInstance(); + + /* Functions that must be implemented from SecurityManager */ + virtual ble_error_t init(bool enableBonding, + bool requireMITM, + SecurityIOCapabilities_t iocaps, + const Passkey_t passkey) { + return btle_initializeSecurity(enableBonding, requireMITM, iocaps, passkey); + } + + virtual ble_error_t getLinkSecurity(Gap::Handle_t connectionHandle, LinkSecurityStatus_t *securityStatusP) { + return btle_getLinkSecurity(connectionHandle, securityStatusP); + } + + virtual ble_error_t purgeAllBondingState(void) { + return btle_purgeAllBondingState(); + } + +public: + nRF51SecurityManager() { + /* empty */ + } + +private: + nRF51SecurityManager(const nRF51SecurityManager &); + const nRF51SecurityManager& operator=(const nRF51SecurityManager &); +}; + +#endif // ifndef __NRF51822_SECURITY_MANAGER_H__ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/nRF51ServiceDiscovery.cpp Tue Jul 21 13:23:45 2015 +0100 @@ -0,0 +1,282 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "nRF51ServiceDiscovery.h" + +ble_error_t +nRF51ServiceDiscovery::launchCharacteristicDiscovery(Gap::Handle_t connectionHandle, + Gap::Handle_t startHandle, + Gap::Handle_t endHandle) +{ + characteristicDiscoveryStarted(connectionHandle); + + ble_gattc_handle_range_t handleRange = { + .start_handle = startHandle, + .end_handle = endHandle + }; + uint32_t rc; + if ((rc = sd_ble_gattc_characteristics_discover(connectionHandle, &handleRange)) != NRF_SUCCESS) { + terminateCharacteristicDiscovery(); + switch (rc) { + case BLE_ERROR_INVALID_CONN_HANDLE: + case NRF_ERROR_INVALID_ADDR: + return BLE_ERROR_INVALID_PARAM; + case NRF_ERROR_BUSY: + return BLE_STACK_BUSY; + default: + case NRF_ERROR_INVALID_STATE: + return BLE_ERROR_INVALID_STATE; + } + } + + return BLE_ERROR_NONE; +} + +void +nRF51ServiceDiscovery::setupDiscoveredServices(const ble_gattc_evt_prim_srvc_disc_rsp_t *response) +{ + serviceIndex = 0; + numServices = response->count; + + /* Account for the limitation on the number of discovered services we can handle at a time. */ + if (numServices > BLE_DB_DISCOVERY_MAX_SRV) { + numServices = BLE_DB_DISCOVERY_MAX_SRV; + } + + serviceUUIDDiscoveryQueue.reset(); + for (unsigned serviceIndex = 0; serviceIndex < numServices; serviceIndex++) { + if (response->services[serviceIndex].uuid.type == BLE_UUID_TYPE_UNKNOWN) { + serviceUUIDDiscoveryQueue.enqueue(serviceIndex); + services[serviceIndex].setup(response->services[serviceIndex].handle_range.start_handle, + response->services[serviceIndex].handle_range.end_handle); + } else { + services[serviceIndex].setup(response->services[serviceIndex].uuid.uuid, + response->services[serviceIndex].handle_range.start_handle, + response->services[serviceIndex].handle_range.end_handle); + } + } + + /* Trigger discovery of service UUID if necessary. */ + if (serviceUUIDDiscoveryQueue.getCount()) { + serviceUUIDDiscoveryQueue.triggerFirst(); + } +} + +void +nRF51ServiceDiscovery::setupDiscoveredCharacteristics(const ble_gattc_evt_char_disc_rsp_t *response) +{ + characteristicIndex = 0; + numCharacteristics = response->count; + + /* Account for the limitation on the number of discovered characteristics we can handle at a time. */ + if (numCharacteristics > BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV) { + numCharacteristics = BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV; + } + + charUUIDDiscoveryQueue.reset(); + for (unsigned charIndex = 0; charIndex < numCharacteristics; charIndex++) { + if (response->chars[charIndex].uuid.type == BLE_UUID_TYPE_UNKNOWN) { + charUUIDDiscoveryQueue.enqueue(charIndex); + characteristics[charIndex].setup(gattc, + connHandle, + response->chars[charIndex].char_props, + response->chars[charIndex].handle_decl, + response->chars[charIndex].handle_value); + } else { + characteristics[charIndex].setup(gattc, + connHandle, + response->chars[charIndex].uuid.uuid, + response->chars[charIndex].char_props, + response->chars[charIndex].handle_decl, + response->chars[charIndex].handle_value); + } + } + + /* Trigger discovery of char UUID if necessary. */ + if (charUUIDDiscoveryQueue.getCount()) { + charUUIDDiscoveryQueue.triggerFirst(); + } +} + +void +nRF51ServiceDiscovery::progressCharacteristicDiscovery(void) +{ + /* Iterate through the previously discovered characteristics cached in characteristics[]. */ + while ((state == CHARACTERISTIC_DISCOVERY_ACTIVE) && (characteristicIndex < numCharacteristics)) { + if ((matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) || + ((matchingCharacteristicUUID == characteristics[characteristicIndex].getUUID()) && + (matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) { + if (characteristicCallback) { + characteristicCallback(&characteristics[characteristicIndex]); + } + } + + characteristicIndex++; + } + + /* Relaunch discovery of new characteristics beyond the last entry cached in characteristics[]. */ + if (state == CHARACTERISTIC_DISCOVERY_ACTIVE) { + /* Determine the ending handle of the last cached characteristic. */ + Gap::Handle_t startHandle = characteristics[characteristicIndex - 1].getValueHandle() + 1; + Gap::Handle_t endHandle = services[serviceIndex].getEndHandle(); + resetDiscoveredCharacteristics(); /* Note: resetDiscoveredCharacteristics() must come after fetching start and end Handles. */ + + if (startHandle < endHandle) { + ble_gattc_handle_range_t handleRange = { + .start_handle = startHandle, + .end_handle = endHandle + }; + if (sd_ble_gattc_characteristics_discover(connHandle, &handleRange) != NRF_SUCCESS) { + terminateCharacteristicDiscovery(); + } + } else { + terminateCharacteristicDiscovery(); + } + } +} + +void +nRF51ServiceDiscovery::progressServiceDiscovery(void) +{ + /* Iterate through the previously discovered services cached in services[]. */ + while ((state == SERVICE_DISCOVERY_ACTIVE) && (serviceIndex < numServices)) { + if ((matchingServiceUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) || + (matchingServiceUUID == services[serviceIndex].getUUID().getShortUUID())) { + + if (serviceCallback && (matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN))) { + serviceCallback(&services[serviceIndex]); + } + + if ((state == SERVICE_DISCOVERY_ACTIVE) && characteristicCallback) { + launchCharacteristicDiscovery(connHandle, services[serviceIndex].getStartHandle(), services[serviceIndex].getEndHandle()); + } else { + serviceIndex++; + } + } else { + serviceIndex++; + } + } + + /* Relaunch discovery of new services beyond the last entry cached in services[]. */ + if ((state == SERVICE_DISCOVERY_ACTIVE) && (numServices > 0) && (serviceIndex > 0)) { + /* Determine the ending handle of the last cached service. */ + Gap::Handle_t endHandle = services[serviceIndex - 1].getEndHandle(); + resetDiscoveredServices(); /* Note: resetDiscoveredServices() must come after fetching endHandle. */ + + if (endHandle == SRV_DISC_END_HANDLE) { + terminateServiceDiscovery(); + } else { + if (sd_ble_gattc_primary_services_discover(connHandle, endHandle, NULL) != NRF_SUCCESS) { + terminateServiceDiscovery(); + } + } + } +} + +void +nRF51ServiceDiscovery::ServiceUUIDDiscoveryQueue::triggerFirst(void) +{ + while (numIndices) { /* loop until a call to char_value_by_uuid_read() succeeds or we run out of pending indices. */ + parentDiscoveryObject->state = DISCOVER_SERVICE_UUIDS; + + unsigned serviceIndex = getFirst(); + ble_uuid_t uuid = { + .uuid = BLE_UUID_SERVICE_PRIMARY, + .type = BLE_UUID_TYPE_BLE, + }; + ble_gattc_handle_range_t handleRange = { + .start_handle = parentDiscoveryObject->services[serviceIndex].getStartHandle(), + .end_handle = parentDiscoveryObject->services[serviceIndex].getEndHandle(), + }; + if (sd_ble_gattc_char_value_by_uuid_read(parentDiscoveryObject->connHandle, &uuid, &handleRange) == NRF_SUCCESS) { + return; + } + + /* Skip this service if we fail to launch a read for its service-declaration + * attribute. Its UUID will remain INVALID, and it may not match any filters. */ + dequeue(); + } + + /* Switch back to service discovery upon exhausting the service-indices pending UUID discovery. */ + if (parentDiscoveryObject->state == DISCOVER_SERVICE_UUIDS) { + parentDiscoveryObject->state = SERVICE_DISCOVERY_ACTIVE; + } +} + +void +nRF51ServiceDiscovery::CharUUIDDiscoveryQueue::triggerFirst(void) +{ + while (numIndices) { /* loop until a call to char_value_by_uuid_read() succeeds or we run out of pending indices. */ + parentDiscoveryObject->state = DISCOVER_CHARACTERISTIC_UUIDS; + + unsigned charIndex = getFirst(); + ble_uuid_t uuid = { + .uuid = BLE_UUID_CHARACTERISTIC, + .type = BLE_UUID_TYPE_BLE, + }; + ble_gattc_handle_range_t handleRange = { }; + handleRange.start_handle = parentDiscoveryObject->characteristics[charIndex].getDeclHandle(); + handleRange.end_handle = parentDiscoveryObject->characteristics[charIndex].getDeclHandle() + 1; + if (sd_ble_gattc_char_value_by_uuid_read(parentDiscoveryObject->connHandle, &uuid, &handleRange) == NRF_SUCCESS) { + return; + } + + /* Skip this service if we fail to launch a read for its service-declaration + * attribute. Its UUID will remain INVALID, and it may not match any filters. */ + dequeue(); + } + + /* Switch back to service discovery upon exhausting the service-indices pending UUID discovery. */ + if (parentDiscoveryObject->state == DISCOVER_CHARACTERISTIC_UUIDS) { + parentDiscoveryObject->state = CHARACTERISTIC_DISCOVERY_ACTIVE; + } +} + +void +nRF51ServiceDiscovery::processDiscoverUUIDResponse(const ble_gattc_evt_char_val_by_uuid_read_rsp_t *response) +{ + if (state == DISCOVER_SERVICE_UUIDS) { + if ((response->count == 1) && (response->value_len == UUID::LENGTH_OF_LONG_UUID)) { + UUID::LongUUIDBytes_t uuid; + /* Switch longUUID bytes to MSB */ + for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) { + uuid[i] = response->handle_value[0].p_value[UUID::LENGTH_OF_LONG_UUID - 1 - i]; + } + + unsigned serviceIndex = serviceUUIDDiscoveryQueue.dequeue(); + services[serviceIndex].setupLongUUID(uuid); + + serviceUUIDDiscoveryQueue.triggerFirst(); + } else { + serviceUUIDDiscoveryQueue.dequeue(); + } + } else if (state == DISCOVER_CHARACTERISTIC_UUIDS) { + if ((response->count == 1) && (response->value_len == UUID::LENGTH_OF_LONG_UUID + 1 /* props */ + 2 /* value handle */)) { + UUID::LongUUIDBytes_t uuid; + /* Switch longUUID bytes to MSB */ + for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) { + uuid[i] = response->handle_value[0].p_value[3 + UUID::LENGTH_OF_LONG_UUID - 1 - i]; + } + + unsigned charIndex = charUUIDDiscoveryQueue.dequeue(); + characteristics[charIndex].setupLongUUID(uuid); + + charUUIDDiscoveryQueue.triggerFirst(); + } else { + charUUIDDiscoveryQueue.dequeue(); + } + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/nRF51ServiceDiscovery.h Tue Jul 21 13:23:45 2015 +0100 @@ -0,0 +1,305 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NRF_SERVICE_DISCOVERY_H__ +#define __NRF_SERVICE_DISCOVERY_H__ + +#include "ble/ServiceDiscovery.h" +#include "ble/DiscoveredService.h" +#include "nRF51DiscoveredCharacteristic.h" + +#include "ble.h" +#include "ble_gattc.h" + +class nRF51GattClient; /* forward declaration */ + +class nRF51ServiceDiscovery : public ServiceDiscovery +{ +public: + static const uint16_t SRV_DISC_START_HANDLE = 0x0001; /**< The start handle value used during service discovery. */ + static const uint16_t SRV_DISC_END_HANDLE = 0xFFFF; /**< The end handle value used during service discovery. */ + +public: + static const unsigned BLE_DB_DISCOVERY_MAX_SRV = 4; /**< Maximum number of services we can retain information for after a single discovery. */ + static const unsigned BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV = 4; /**< Maximum number of characteristics per service we can retain information for. */ + +public: + nRF51ServiceDiscovery(nRF51GattClient *gattcIn) : + gattc(gattcIn), + serviceIndex(0), + numServices(0), + characteristicIndex(0), + numCharacteristics(0), + state(INACTIVE), + services(), + characteristics(), + serviceUUIDDiscoveryQueue(this), + charUUIDDiscoveryQueue(this), + onTerminationCallback(NULL) { + /* empty */ + } + + virtual ble_error_t launch(Gap::Handle_t connectionHandle, + ServiceDiscovery::ServiceCallback_t sc, + ServiceDiscovery::CharacteristicCallback_t cc, + const UUID &matchingServiceUUIDIn, + const UUID &matchingCharacteristicUUIDIn) + { + if (isActive()) { + return BLE_ERROR_INVALID_STATE; + } + + serviceCallback = sc; + characteristicCallback = cc; + matchingServiceUUID = matchingServiceUUIDIn; + matchingCharacteristicUUID = matchingCharacteristicUUIDIn; + + serviceDiscoveryStarted(connectionHandle); + + uint32_t rc; + if ((rc = sd_ble_gattc_primary_services_discover(connectionHandle, SRV_DISC_START_HANDLE, NULL)) != NRF_SUCCESS) { + terminate(); + switch (rc) { + case NRF_ERROR_INVALID_PARAM: + case BLE_ERROR_INVALID_CONN_HANDLE: + return BLE_ERROR_INVALID_PARAM; + case NRF_ERROR_BUSY: + return BLE_STACK_BUSY; + default: + case NRF_ERROR_INVALID_STATE: + return BLE_ERROR_INVALID_STATE; + } + } + + return BLE_ERROR_NONE; + } + + virtual bool isActive(void) const { + return state != INACTIVE; + } + + virtual void terminate(void) { + terminateServiceDiscovery(); + } + + virtual void onTermination(ServiceDiscovery::TerminationCallback_t callback) { + onTerminationCallback = callback; + } + +private: + ble_error_t launchCharacteristicDiscovery(Gap::Handle_t connectionHandle, Gap::Handle_t startHandle, Gap::Handle_t endHandle); + +private: + void setupDiscoveredServices(const ble_gattc_evt_prim_srvc_disc_rsp_t *response); + void setupDiscoveredCharacteristics(const ble_gattc_evt_char_disc_rsp_t *response); + + void triggerServiceUUIDDiscovery(void); + void processDiscoverUUIDResponse(const ble_gattc_evt_char_val_by_uuid_read_rsp_t *response); + void removeFirstServiceNeedingUUIDDiscovery(void); + + void terminateServiceDiscovery(void) { + bool wasActive = isActive(); + state = INACTIVE; + + if (wasActive && onTerminationCallback) { + onTerminationCallback(connHandle); + } + } + + void terminateCharacteristicDiscovery(void) { + if (state == CHARACTERISTIC_DISCOVERY_ACTIVE) { + state = SERVICE_DISCOVERY_ACTIVE; + } + serviceIndex++; /* Progress service index to keep discovery alive. */ + } + +private: + void resetDiscoveredServices(void) { + numServices = 0; + serviceIndex = 0; + } + + void resetDiscoveredCharacteristics(void) { + numCharacteristics = 0; + characteristicIndex = 0; + } + +private: + void serviceDiscoveryStarted(Gap::Handle_t connectionHandle) { + connHandle = connectionHandle; + resetDiscoveredServices(); + state = SERVICE_DISCOVERY_ACTIVE; + } + +private: + void characteristicDiscoveryStarted(Gap::Handle_t connectionHandle) { + connHandle = connectionHandle; + resetDiscoveredCharacteristics(); + state = CHARACTERISTIC_DISCOVERY_ACTIVE; + } + +private: + /** + * A datatype to contain service-indices for which long UUIDs need to be + * discovered using read_val_by_uuid(). + */ + class ServiceUUIDDiscoveryQueue { + public: + ServiceUUIDDiscoveryQueue(nRF51ServiceDiscovery *parent) : + numIndices(0), + serviceIndices(), + parentDiscoveryObject(parent) { + /* empty */ + } + + public: + void reset(void) { + numIndices = 0; + for (unsigned i = 0; i < BLE_DB_DISCOVERY_MAX_SRV; i++) { + serviceIndices[i] = INVALID_INDEX; + } + } + void enqueue(int serviceIndex) { + serviceIndices[numIndices++] = serviceIndex; + } + int dequeue(void) { + if (numIndices == 0) { + return INVALID_INDEX; + } + + unsigned valueToReturn = serviceIndices[0]; + numIndices--; + for (unsigned i = 0; i < numIndices; i++) { + serviceIndices[i] = serviceIndices[i + 1]; + } + + return valueToReturn; + } + unsigned getFirst(void) const { + return serviceIndices[0]; + } + size_t getCount(void) const { + return numIndices; + } + + /** + * Trigger UUID discovery for the first of the enqueued ServiceIndices. + */ + void triggerFirst(void); + + private: + static const int INVALID_INDEX = -1; + + private: + size_t numIndices; + int serviceIndices[BLE_DB_DISCOVERY_MAX_SRV]; + + nRF51ServiceDiscovery *parentDiscoveryObject; + }; + friend class ServiceUUIDDiscoveryQueue; + + /** + * A datatype to contain characteristic-indices for which long UUIDs need to + * be discovered using read_val_by_uuid(). + */ + class CharUUIDDiscoveryQueue { + public: + CharUUIDDiscoveryQueue(nRF51ServiceDiscovery *parent) : + numIndices(0), + charIndices(), + parentDiscoveryObject(parent) { + /* empty */ + } + + public: + void reset(void) { + numIndices = 0; + for (unsigned i = 0; i < BLE_DB_DISCOVERY_MAX_SRV; i++) { + charIndices[i] = INVALID_INDEX; + } + } + void enqueue(int serviceIndex) { + charIndices[numIndices++] = serviceIndex; + } + int dequeue(void) { + if (numIndices == 0) { + return INVALID_INDEX; + } + + unsigned valueToReturn = charIndices[0]; + numIndices--; + for (unsigned i = 0; i < numIndices; i++) { + charIndices[i] = charIndices[i + 1]; + } + + return valueToReturn; + } + unsigned getFirst(void) const { + return charIndices[0]; + } + size_t getCount(void) const { + return numIndices; + } + + /** + * Trigger UUID discovery for the first of the enqueued charIndices. + */ + void triggerFirst(void); + + private: + static const int INVALID_INDEX = -1; + + private: + size_t numIndices; + int charIndices[BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV]; + + nRF51ServiceDiscovery *parentDiscoveryObject; + }; + friend class CharUUIDDiscoveryQueue; + +private: + friend void bleGattcEventHandler(const ble_evt_t *p_ble_evt); + void progressCharacteristicDiscovery(void); + void progressServiceDiscovery(void); + +private: + nRF51GattClient *gattc; + +private: + uint8_t serviceIndex; /**< Index of the current service being discovered. This is intended for internal use during service discovery.*/ + uint8_t numServices; /**< Number of services at the peers GATT database.*/ + uint8_t characteristicIndex; /**< Index of the current characteristic being discovered. This is intended for internal use during service discovery.*/ + uint8_t numCharacteristics; /**< Number of characteristics within the service.*/ + + enum State_t { + INACTIVE, + SERVICE_DISCOVERY_ACTIVE, + CHARACTERISTIC_DISCOVERY_ACTIVE, + DISCOVER_SERVICE_UUIDS, + DISCOVER_CHARACTERISTIC_UUIDS, + } state; + + DiscoveredService services[BLE_DB_DISCOVERY_MAX_SRV]; /**< Information related to the current service being discovered. + * This is intended for internal use during service discovery. */ + nRF51DiscoveredCharacteristic characteristics[BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV]; + + ServiceUUIDDiscoveryQueue serviceUUIDDiscoveryQueue; + CharUUIDDiscoveryQueue charUUIDDiscoveryQueue; + + TerminationCallback_t onTerminationCallback; +}; + +#endif /*__NRF_SERVICE_DISCOVERY_H__*/ \ No newline at end of file
--- a/source/nRF5xDiscoveredCharacteristic.cpp Tue Jul 21 13:23:45 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "nRF5xDiscoveredCharacteristic.h" -#include "nRF5xGattClient.h" -#include "ble_gatt.h" - -void -nRF5xDiscoveredCharacteristic::setup(nRF5xGattClient *gattcIn, - Gap::Handle_t connectionHandleIn, - ble_gatt_char_props_t propsIn, - GattAttribute::Handle_t declHandleIn, - GattAttribute::Handle_t valueHandleIn) -{ - gattc = gattcIn; - connHandle = connectionHandleIn; - declHandle = declHandleIn; - valueHandle = valueHandleIn; - - props._broadcast = propsIn.broadcast; - props._read = propsIn.read; - props._writeWoResp = propsIn.write_wo_resp; - props._write = propsIn.write; - props._notify = propsIn.notify; - props._indicate = propsIn.indicate; - props._authSignedWrite = propsIn.auth_signed_wr; -} - -void -nRF5xDiscoveredCharacteristic::setup(nRF5xGattClient *gattcIn, - Gap::Handle_t connectionHandleIn, - UUID::ShortUUIDBytes_t uuidIn, - ble_gatt_char_props_t propsIn, - GattAttribute::Handle_t declHandleIn, - GattAttribute::Handle_t valueHandleIn) -{ - gattc = gattcIn; - connHandle = connectionHandleIn; - uuid = uuidIn; - declHandle = declHandleIn; - valueHandle = valueHandleIn; - - props._broadcast = propsIn.broadcast; - props._read = propsIn.read; - props._writeWoResp = propsIn.write_wo_resp; - props._write = propsIn.write; - props._notify = propsIn.notify; - props._indicate = propsIn.indicate; - props._authSignedWrite = propsIn.auth_signed_wr; -} \ No newline at end of file
--- a/source/nRF5xDiscoveredCharacteristic.h Tue Jul 21 13:23:45 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __NRF_DISCOVERED_CHARACTERISTIC_H__ -#define __NRF_DISCOVERED_CHARACTERISTIC_H__ - -#include "ble/DiscoveredCharacteristic.h" -#include "ble_gatt.h" - -class nRF5xGattClient; /* forward declaration */ - -class nRF5xDiscoveredCharacteristic : public DiscoveredCharacteristic { -public: - void setup(nRF5xGattClient *gattcIn, - Gap::Handle_t connectionHandleIn, - ble_gatt_char_props_t propsIn, - GattAttribute::Handle_t declHandleIn, - GattAttribute::Handle_t valueHandleIn); - - void setup(nRF5xGattClient *gattcIn, - Gap::Handle_t connectionHandleIn, - UUID::ShortUUIDBytes_t uuidIn, - ble_gatt_char_props_t propsIn, - GattAttribute::Handle_t declHandleIn, - GattAttribute::Handle_t valueHandleIn); -}; - -#endif /* __NRF_DISCOVERED_CHARACTERISTIC_H__ */ \ No newline at end of file
--- a/source/nRF5xGap.cpp Tue Jul 21 13:23:45 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,465 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "nRF5xGap.h" -#include "mbed.h" - -#include "common/common.h" -#include "ble_advdata.h" -#include "ble_hci.h" - -nRF5xGap &nRF5xGap::getInstance() { - static nRF5xGap m_instance; - return m_instance; -} - -/**************************************************************************/ -/*! - @brief Sets the advertising parameters and payload for the device - - @param[in] params - Basic advertising details, including the advertising - delay, timeout and how the device should be advertised - @params[in] advData - The primary advertising data payload - @params[in] scanResponse - The optional Scan Response payload if the advertising - type is set to \ref GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED - in \ref GapAdveritinngParams - - @returns \ref ble_error_t - - @retval BLE_ERROR_NONE - Everything executed properly - - @retval BLE_ERROR_BUFFER_OVERFLOW - The proposed action would cause a buffer overflow. All - advertising payloads must be <= 31 bytes, for example. - - @retval BLE_ERROR_NOT_IMPLEMENTED - A feature was requested that is not yet supported in the - nRF51 firmware or hardware. - - @retval BLE_ERROR_PARAM_OUT_OF_RANGE - One of the proposed values is outside the valid range. - - @section EXAMPLE - - @code - - @endcode -*/ -/**************************************************************************/ -ble_error_t nRF5xGap::setAdvertisingData(const GapAdvertisingData &advData, const GapAdvertisingData &scanResponse) -{ - /* Make sure we don't exceed the advertising payload length */ - if (advData.getPayloadLen() > GAP_ADVERTISING_DATA_MAX_PAYLOAD) { - return BLE_ERROR_BUFFER_OVERFLOW; - } - - /* Make sure we have a payload! */ - if (advData.getPayloadLen() == 0) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - - /* Check the scan response payload limits */ - //if ((params.getAdvertisingType() == GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED)) - //{ - // /* Check if we're within the upper limit */ - // if (advData.getPayloadLen() > GAP_ADVERTISING_DATA_MAX_PAYLOAD) - // { - // return BLE_ERROR_BUFFER_OVERFLOW; - // } - // /* Make sure we have a payload! */ - // if (advData.getPayloadLen() == 0) - // { - // return BLE_ERROR_PARAM_OUT_OF_RANGE; - // } - //} - - /* Send advertising data! */ - ASSERT(ERROR_NONE == - sd_ble_gap_adv_data_set(advData.getPayload(), - advData.getPayloadLen(), - scanResponse.getPayload(), - scanResponse.getPayloadLen()), - BLE_ERROR_PARAM_OUT_OF_RANGE); - - /* Make sure the GAP Service appearance value is aligned with the - *appearance from GapAdvertisingData */ - ASSERT(ERROR_NONE == sd_ble_gap_appearance_set(advData.getAppearance()), - BLE_ERROR_PARAM_OUT_OF_RANGE); - - /* ToDo: Perform some checks on the payload, for example the Scan Response can't */ - /* contains a flags AD type, etc. */ - - return BLE_ERROR_NONE; -} - -/**************************************************************************/ -/*! - @brief Starts the BLE HW, initialising any services that were - added before this function was called. - - @note All services must be added before calling this function! - - @returns ble_error_t - - @retval BLE_ERROR_NONE - Everything executed properly - - @section EXAMPLE - - @code - - @endcode -*/ -/**************************************************************************/ -ble_error_t nRF5xGap::startAdvertising(const GapAdvertisingParams ¶ms) -{ - /* Make sure we support the advertising type */ - if (params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) { - /* ToDo: This requires a propery security implementation, etc. */ - return BLE_ERROR_NOT_IMPLEMENTED; - } - - /* Check interval range */ - if (params.getAdvertisingType() == GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED) { - /* Min delay is slightly longer for unconnectable devices */ - if ((params.getInterval() < GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN_NONCON) || - (params.getInterval() > GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX)) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - } else { - if ((params.getInterval() < GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN) || - (params.getInterval() > GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX)) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - } - - /* Check timeout is zero for Connectable Directed */ - if ((params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) && (params.getTimeout() != 0)) { - /* Timeout must be 0 with this type, although we'll never get here */ - /* since this isn't implemented yet anyway */ - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - - /* Check timeout for other advertising types */ - if ((params.getAdvertisingType() != GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) && - (params.getTimeout() > GapAdvertisingParams::GAP_ADV_PARAMS_TIMEOUT_MAX)) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - - /* Start Advertising */ - ble_gap_adv_params_t adv_para = {0}; - - adv_para.type = params.getAdvertisingType(); - adv_para.p_peer_addr = NULL; // Undirected advertisement - adv_para.fp = BLE_GAP_ADV_FP_ANY; - adv_para.p_whitelist = NULL; - adv_para.interval = params.getInterval(); // advertising interval (in units of 0.625 ms) - adv_para.timeout = params.getTimeout(); - - ASSERT(ERROR_NONE == sd_ble_gap_adv_start(&adv_para), BLE_ERROR_PARAM_OUT_OF_RANGE); - - state.advertising = 1; - - return BLE_ERROR_NONE; -} - -/**************************************************************************/ -/*! - @brief Stops the BLE HW and disconnects from any devices - - @returns ble_error_t - - @retval BLE_ERROR_NONE - Everything executed properly - - @section EXAMPLE - - @code - - @endcode -*/ -/**************************************************************************/ -ble_error_t nRF5xGap::stopAdvertising(void) -{ - /* Stop Advertising */ - ASSERT(ERROR_NONE == sd_ble_gap_adv_stop(), BLE_ERROR_PARAM_OUT_OF_RANGE); - - state.advertising = 0; - - return BLE_ERROR_NONE; -} - -ble_error_t nRF5xGap::connect(const Address_t peerAddr, - Gap::AddressType_t peerAddrType, - const ConnectionParams_t *connectionParams, - const GapScanningParams *scanParamsIn) -{ - ble_gap_addr_t addr; - addr.addr_type = peerAddrType; - memcpy(addr.addr, peerAddr, Gap::ADDR_LEN); - - ble_gap_conn_params_t connParams; - if (connectionParams != NULL) { - connParams.min_conn_interval = connectionParams->minConnectionInterval; - connParams.max_conn_interval = connectionParams->maxConnectionInterval; - connParams.slave_latency = connectionParams->slaveLatency; - connParams.conn_sup_timeout = connectionParams->connectionSupervisionTimeout; - } else { - connParams.min_conn_interval = 50; - connParams.max_conn_interval = 100; - connParams.slave_latency = 0; - connParams.conn_sup_timeout = 600; - } - - ble_gap_scan_params_t scanParams; - scanParams.active = 0; /**< If 1, perform active scanning (scan requests). */ - scanParams.selective = 0; /**< If 1, ignore unknown devices (non whitelisted). */ - scanParams.p_whitelist = NULL; /**< Pointer to whitelist, NULL if none is given. */ - if (scanParamsIn != NULL) { - scanParams.interval = scanParamsIn->getInterval(); /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ - scanParams.window = scanParamsIn->getWindow(); /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ - scanParams.timeout = scanParamsIn->getTimeout(); /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ - } else { - scanParams.interval = 500; /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ - scanParams.window = 200; /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ - scanParams.timeout = 0; /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ - } - - uint32_t rc = sd_ble_gap_connect(&addr, &scanParams, &connParams); - if (rc == NRF_SUCCESS) { - return BLE_ERROR_NONE; - } - switch (rc) { - case NRF_ERROR_INVALID_ADDR: - return BLE_ERROR_INVALID_PARAM; - case NRF_ERROR_INVALID_PARAM: - return BLE_ERROR_INVALID_PARAM; - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - case BLE_ERROR_GAP_INVALID_BLE_ADDR: - return BLE_ERROR_INVALID_PARAM; - case NRF_ERROR_NO_MEM: - return BLE_ERROR_NO_MEM; - case NRF_ERROR_BUSY: - return BLE_STACK_BUSY; - default: - case BLE_ERROR_GAP_WHITELIST_IN_USE: - return BLE_ERROR_UNSPECIFIED; - } -} - -ble_error_t nRF5xGap::disconnect(Handle_t connectionHandle, DisconnectionReason_t reason) -{ - state.advertising = 0; - state.connected = 0; - - uint8_t code = BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION; - switch (reason) { - case REMOTE_USER_TERMINATED_CONNECTION: - code = BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION; - break; - case CONN_INTERVAL_UNACCEPTABLE: - code = BLE_HCI_CONN_INTERVAL_UNACCEPTABLE; - break; - default: - break; - } - - /* Disconnect if we are connected to a central device */ - ASSERT_INT(ERROR_NONE, sd_ble_gap_disconnect(connectionHandle, code), BLE_ERROR_PARAM_OUT_OF_RANGE); - - return BLE_ERROR_NONE; -} - -/*! - @brief Disconnects if we are connected to a central device - - @returns ble_error_t - - @retval BLE_ERROR_NONE - Everything executed properly -*/ -ble_error_t nRF5xGap::disconnect(DisconnectionReason_t reason) -{ - return disconnect(m_connectionHandle, reason); -} - -ble_error_t nRF5xGap::getPreferredConnectionParams(ConnectionParams_t *params) -{ - ASSERT_INT(NRF_SUCCESS, - sd_ble_gap_ppcp_get(reinterpret_cast<ble_gap_conn_params_t *>(params)), - BLE_ERROR_PARAM_OUT_OF_RANGE); - - return BLE_ERROR_NONE; -} - -ble_error_t nRF5xGap::setPreferredConnectionParams(const ConnectionParams_t *params) -{ - ASSERT_INT(NRF_SUCCESS, - sd_ble_gap_ppcp_set(reinterpret_cast<const ble_gap_conn_params_t *>(params)), - BLE_ERROR_PARAM_OUT_OF_RANGE); - - return BLE_ERROR_NONE; -} - -ble_error_t nRF5xGap::updateConnectionParams(Handle_t handle, const ConnectionParams_t *newParams) -{ - uint32_t rc; - - rc = sd_ble_gap_conn_param_update(handle, reinterpret_cast<ble_gap_conn_params_t *>(const_cast<ConnectionParams_t*>(newParams))); - if (rc == NRF_SUCCESS) { - return BLE_ERROR_NONE; - } else { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } -} - -/**************************************************************************/ -/*! - @brief Sets the 16-bit connection handle -*/ -/**************************************************************************/ -void nRF5xGap::setConnectionHandle(uint16_t con_handle) -{ - m_connectionHandle = con_handle; -} - -/**************************************************************************/ -/*! - @brief Gets the 16-bit connection handle -*/ -/**************************************************************************/ -uint16_t nRF5xGap::getConnectionHandle(void) -{ - return m_connectionHandle; -} - -/**************************************************************************/ -/*! - @brief Sets the BLE device address - - @returns ble_error_t - - @section EXAMPLE - - @code - - uint8_t device_address[6] = { 0xca, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0 }; - nrf.getGap().setAddress(Gap::ADDR_TYPE_RANDOM_STATIC, device_address); - - @endcode -*/ -/**************************************************************************/ -ble_error_t nRF5xGap::setAddress(AddressType_t type, const Address_t address) -{ - if (type > ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - - ble_gap_addr_t dev_addr; - dev_addr.addr_type = type; - memcpy(dev_addr.addr, address, ADDR_LEN); - - ASSERT_INT(ERROR_NONE, sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &dev_addr), BLE_ERROR_PARAM_OUT_OF_RANGE); - - return BLE_ERROR_NONE; -} - -ble_error_t nRF5xGap::getAddress(AddressType_t *typeP, Address_t address) -{ - ble_gap_addr_t dev_addr; - if (sd_ble_gap_address_get(&dev_addr) != NRF_SUCCESS) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - - if (typeP != NULL) { - *typeP = static_cast<AddressType_t>(dev_addr.addr_type); - } - if (address != NULL) { - memcpy(address, dev_addr.addr, ADDR_LEN); - } - return BLE_ERROR_NONE; -} - -ble_error_t nRF5xGap::setDeviceName(const uint8_t *deviceName) -{ - ble_gap_conn_sec_mode_t sec_mode; - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); // no security is needed - - if (sd_ble_gap_device_name_set(&sec_mode, deviceName, strlen((const char *)deviceName)) == NRF_SUCCESS) { - return BLE_ERROR_NONE; - } else { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } -} - -ble_error_t nRF5xGap::getDeviceName(uint8_t *deviceName, unsigned *lengthP) -{ - if (sd_ble_gap_device_name_get(deviceName, (uint16_t *)lengthP) == NRF_SUCCESS) { - return BLE_ERROR_NONE; - } else { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } -} - -ble_error_t nRF5xGap::setAppearance(GapAdvertisingData::Appearance appearance) -{ - if (sd_ble_gap_appearance_set(appearance) == NRF_SUCCESS) { - return BLE_ERROR_NONE; - } else { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } -} - -ble_error_t nRF5xGap::getAppearance(GapAdvertisingData::Appearance *appearanceP) -{ - if (sd_ble_gap_appearance_get(reinterpret_cast<uint16_t *>(appearanceP))) { - return BLE_ERROR_NONE; - } else { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } -} - -/* (Valid values are -40, -20, -16, -12, -8, -4, 0, 4) */ -ble_error_t nRF5xGap::setTxPower(int8_t txPower) -{ - unsigned rc; - if ((rc = sd_ble_gap_tx_power_set(txPower)) != NRF_SUCCESS) { - switch (rc) { - case NRF_ERROR_BUSY: - return BLE_STACK_BUSY; - case NRF_ERROR_INVALID_PARAM: - default: - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - } - - return BLE_ERROR_NONE; -} - -void nRF5xGap::getPermittedTxPowerValues(const int8_t **valueArrayPP, size_t *countP) -{ - static const int8_t permittedTxValues[] = { - -40, -30, -20, -16, -12, -8, -4, 0, 4 - }; - - *valueArrayPP = permittedTxValues; - *countP = sizeof(permittedTxValues) / sizeof(int8_t); -} \ No newline at end of file
--- a/source/nRF5xGap.h Tue Jul 21 13:23:45 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __NRF5x_GAP_H__ -#define __NRF5x_GAP_H__ - -#include "mbed.h" -#include "ble/blecommon.h" -#include "ble.h" -#include "ble/GapAdvertisingParams.h" -#include "ble/GapAdvertisingData.h" -#include "ble/Gap.h" -#include "ble/GapScanningParams.h" - -#include "nrf_soc.h" -#include "ble_radio_notification.h" -#include "btle_security.h" - -/**************************************************************************/ -/*! - \brief - -*/ -/**************************************************************************/ -class nRF5xGap : public Gap -{ -public: - static nRF5xGap &getInstance(); - - /* Functions that must be implemented from Gap */ - virtual ble_error_t setAddress(AddressType_t type, const Address_t address); - virtual ble_error_t getAddress(AddressType_t *typeP, Address_t address); - virtual ble_error_t setAdvertisingData(const GapAdvertisingData &, const GapAdvertisingData &); - - virtual uint16_t getMinAdvertisingInterval(void) const {return ADVERTISEMENT_DURATION_UNITS_TO_MS(BLE_GAP_ADV_INTERVAL_MIN);} - virtual uint16_t getMinNonConnectableAdvertisingInterval(void) const {return ADVERTISEMENT_DURATION_UNITS_TO_MS(BLE_GAP_ADV_NONCON_INTERVAL_MIN);} - virtual uint16_t getMaxAdvertisingInterval(void) const {return ADVERTISEMENT_DURATION_UNITS_TO_MS(BLE_GAP_ADV_INTERVAL_MAX);} - - virtual ble_error_t startAdvertising(const GapAdvertisingParams &); - virtual ble_error_t stopAdvertising(void); - virtual ble_error_t connect(const Address_t, Gap::AddressType_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParams); - virtual ble_error_t disconnect(Handle_t connectionHandle, DisconnectionReason_t reason); - virtual ble_error_t disconnect(DisconnectionReason_t reason); - - virtual ble_error_t setDeviceName(const uint8_t *deviceName); - virtual ble_error_t getDeviceName(uint8_t *deviceName, unsigned *lengthP); - virtual ble_error_t setAppearance(GapAdvertisingData::Appearance appearance); - virtual ble_error_t getAppearance(GapAdvertisingData::Appearance *appearanceP); - - virtual ble_error_t setTxPower(int8_t txPower); - virtual void getPermittedTxPowerValues(const int8_t **valueArrayPP, size_t *countP); - - void setConnectionHandle(uint16_t con_handle); - uint16_t getConnectionHandle(void); - - virtual ble_error_t getPreferredConnectionParams(ConnectionParams_t *params); - virtual ble_error_t setPreferredConnectionParams(const ConnectionParams_t *params); - virtual ble_error_t updateConnectionParams(Handle_t handle, const ConnectionParams_t *params); - - virtual void onRadioNotification(RadioNotificationEventCallback_t callback) { - Gap::onRadioNotification(callback); - ble_radio_notification_init(NRF_APP_PRIORITY_HIGH, NRF_RADIO_NOTIFICATION_DISTANCE_800US, radioNotificationCallback); - } - - virtual ble_error_t startRadioScan(const GapScanningParams &scanningParams) { - ble_gap_scan_params_t scanParams = { - .active = scanningParams.getActiveScanning(), /**< If 1, perform active scanning (scan requests). */ - .selective = 0, /**< If 1, ignore unknown devices (non whitelisted). */ - .p_whitelist = NULL, /**< Pointer to whitelist, NULL if none is given. */ - .interval = scanningParams.getInterval(), /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ - .window = scanningParams.getWindow(), /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ - .timeout = scanningParams.getTimeout(), /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ - }; - - if (sd_ble_gap_scan_start(&scanParams) != NRF_SUCCESS) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - - return BLE_ERROR_NONE; - } - - virtual ble_error_t stopScan(void) { - if (sd_ble_gap_scan_stop() == NRF_SUCCESS) { - return BLE_ERROR_NONE; - } - - return BLE_STACK_BUSY; - } - -private: - uint16_t m_connectionHandle; - nRF5xGap() { - m_connectionHandle = BLE_CONN_HANDLE_INVALID; - } - - nRF5xGap(nRF5xGap const &); - void operator=(nRF5xGap const &); -}; - -#endif // ifndef __NRF5x_GAP_H__ \ No newline at end of file
--- a/source/nRF5xGattClient.cpp Tue Jul 21 13:23:45 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "nRF5xGattClient.h" - -nRF5xGattClient nRFGattClientSingleton; - -nRF5xGattClient & -nRF5xGattClient::getInstance(void) { - return nRFGattClientSingleton; -} - -ble_error_t -nRF5xGattClient::launchServiceDiscovery(Gap::Handle_t connectionHandle, - ServiceDiscovery::ServiceCallback_t sc, - ServiceDiscovery::CharacteristicCallback_t cc, - const UUID &matchingServiceUUIDIn, - const UUID &matchingCharacteristicUUIDIn) -{ - return discovery.launch(connectionHandle, sc, cc, matchingServiceUUIDIn, matchingCharacteristicUUIDIn); -} \ No newline at end of file
--- a/source/nRF5xGattClient.h Tue Jul 21 13:23:45 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,157 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __NRF51822_GATT_CLIENT_H__ -#define __NRF51822_GATT_CLIENT_H__ - -#include "ble/GattClient.h" -#include "nRF5xServiceDiscovery.h" - -class nRF5xGattClient : public GattClient -{ -public: - static nRF5xGattClient &getInstance(); - - /** - * Launch service discovery. Once launched, service discovery will remain - * active with callbacks being issued back into the application for matching - * services/characteristics. isActive() can be used to determine status; and - * a termination callback (if setup) will be invoked at the end. Service - * discovery can be terminated prematurely if needed using terminate(). - * - * @param connectionHandle - * Handle for the connection with the peer. - * @param sc - * This is the application callback for matching service. Taken as - * NULL by default. Note: service discovery may still be active - * when this callback is issued; calling asynchronous BLE-stack - * APIs from within this application callback might cause the - * stack to abort service discovery. If this becomes an issue, it - * may be better to make local copy of the discoveredService and - * wait for service discovery to terminate before operating on the - * service. - * @param cc - * This is the application callback for matching characteristic. - * Taken as NULL by default. Note: service discovery may still be - * active when this callback is issued; calling asynchronous - * BLE-stack APIs from within this application callback might cause - * the stack to abort service discovery. If this becomes an issue, - * it may be better to make local copy of the discoveredCharacteristic - * and wait for service discovery to terminate before operating on the - * characteristic. - * @param matchingServiceUUID - * UUID based filter for specifying a service in which the application is - * interested. By default it is set as the wildcard UUID_UNKNOWN, - * in which case it matches all services. If characteristic-UUID - * filter (below) is set to the wildcard value, then a service - * callback will be invoked for the matching service (or for every - * service if the service filter is a wildcard). - * @param matchingCharacteristicUUIDIn - * UUID based filter for specifying characteristic in which the application - * is interested. By default it is set as the wildcard UUID_UKNOWN - * to match against any characteristic. If both service-UUID - * filter and characteristic-UUID filter are used with non- wildcard - * values, then only a single characteristic callback is - * invoked for the matching characteristic. - * - * @Note Using wildcard values for both service-UUID and characteristic- - * UUID will result in complete service discovery--callbacks being - * called for every service and characteristic. - * - * @return - * BLE_ERROR_NONE if service discovery is launched successfully; else an appropriate error. - */ - virtual ble_error_t launchServiceDiscovery(Gap::Handle_t connectionHandle, - ServiceDiscovery::ServiceCallback_t sc = NULL, - ServiceDiscovery::CharacteristicCallback_t cc = NULL, - const UUID &matchingServiceUUID = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN), - const UUID &matchingCharacteristicUUIDIn = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)); - - virtual void onServiceDiscoveryTermination(ServiceDiscovery::TerminationCallback_t callback) { - discovery.onTermination(callback); - } - - /** - * Is service-discovery currently active? - */ - virtual bool isServiceDiscoveryActive(void) const { - return discovery.isActive(); - } - - /** - * Terminate an ongoing service-discovery. This should result in an - * invocation of the TerminationCallback if service-discovery is active. - */ - virtual void terminateServiceDiscovery(void) { - discovery.terminate(); - } - - virtual ble_error_t read(Gap::Handle_t connHandle, GattAttribute::Handle_t attributeHandle, uint16_t offset) const { - uint32_t rc = sd_ble_gattc_read(connHandle, attributeHandle, offset); - if (rc == NRF_SUCCESS) { - return BLE_ERROR_NONE; - } - switch (rc) { - case NRF_ERROR_BUSY: - return BLE_STACK_BUSY; - case BLE_ERROR_INVALID_CONN_HANDLE: - case NRF_ERROR_INVALID_STATE: - case NRF_ERROR_INVALID_ADDR: - default: - return BLE_ERROR_INVALID_STATE; - } - } - - virtual ble_error_t write(GattClient::WriteOp_t cmd, Gap::Handle_t connHandle, GattAttribute::Handle_t attributeHandle, size_t length, const uint8_t *value) const { - ble_gattc_write_params_t writeParams = { }; - writeParams.write_op = cmd; - writeParams.handle = attributeHandle; - writeParams.len = length; - writeParams.p_value = const_cast<uint8_t *>(value); - - uint32_t rc = sd_ble_gattc_write(connHandle, &writeParams); - if (rc == NRF_SUCCESS) { - return BLE_ERROR_NONE; - } - switch (rc) { - case NRF_ERROR_BUSY: - return BLE_STACK_BUSY; - case BLE_ERROR_NO_TX_BUFFERS: - return BLE_ERROR_NO_MEM; - case BLE_ERROR_INVALID_CONN_HANDLE: - case NRF_ERROR_INVALID_STATE: - case NRF_ERROR_INVALID_ADDR: - default: - return BLE_ERROR_INVALID_STATE; - } - } - -public: - nRF5xGattClient() : discovery(this) { - /* empty */ - } - - friend void bleGattcEventHandler(const ble_evt_t *p_ble_evt); - -private: - nRF5xGattClient(const nRF5xGattClient &); - const nRF5xGattClient& operator=(const nRF5xGattClient &); - -private: - nRF5xServiceDiscovery discovery; -}; - -#endif // ifndef __NRF51822_GATT_CLIENT_H__ \ No newline at end of file
--- a/source/nRF5xGattServer.cpp Tue Jul 21 13:23:45 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,457 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "nRF5xGattServer.h" -#include "mbed.h" - -#include "common/common.h" -#include "btle/custom/custom_helper.h" - -#include "nRF5xGap.h" - -nRF5xGattServer &nRF5xGattServer::getInstance(void) { - static nRF5xGattServer m_instance; - return m_instance; -} - -/**************************************************************************/ -/*! - @brief Adds a new service to the GATT table on the peripheral - - @returns ble_error_t - - @retval BLE_ERROR_NONE - Everything executed properly - - @section EXAMPLE - - @code - - @endcode -*/ -/**************************************************************************/ -ble_error_t nRF5xGattServer::addService(GattService &service) -{ - /* ToDo: Make sure we don't overflow the array, etc. */ - /* ToDo: Make sure this service UUID doesn't already exist (?) */ - /* ToDo: Basic validation */ - - /* Add the service to the nRF51 */ - ble_uuid_t nordicUUID; - nordicUUID = custom_convert_to_nordic_uuid(service.getUUID()); - - uint16_t serviceHandle; - ASSERT( ERROR_NONE == - sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, - &nordicUUID, - &serviceHandle), - BLE_ERROR_PARAM_OUT_OF_RANGE ); - service.setHandle(serviceHandle); - - /* Add characteristics to the service */ - for (uint8_t i = 0; i < service.getCharacteristicCount(); i++) { - GattCharacteristic *p_char = service.getCharacteristic(i); - - /* Skip any incompletely defined, read-only characteristics. */ - if ((p_char->getValueAttribute().getValuePtr() == NULL) && - (p_char->getValueAttribute().getInitialLength() == 0) && - (p_char->getProperties() == GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ)) { - continue; - } - - nordicUUID = custom_convert_to_nordic_uuid(p_char->getValueAttribute().getUUID()); - - /* The user-description descriptor is a special case which needs to be - * handled at the time of adding the characteristic. The following block - * is meant to discover its presence. */ - const uint8_t *userDescriptionDescriptorValuePtr = NULL; - uint16_t userDescriptionDescriptorValueLen = 0; - for (uint8_t j = 0; j < p_char->getDescriptorCount(); j++) { - GattAttribute *p_desc = p_char->getDescriptor(j); - if (p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_USER_DESC) { - userDescriptionDescriptorValuePtr = p_desc->getValuePtr(); - userDescriptionDescriptorValueLen = p_desc->getLength(); - } - } - - ASSERT ( ERROR_NONE == - custom_add_in_characteristic(BLE_GATT_HANDLE_INVALID, - &nordicUUID, - p_char->getProperties(), - p_char->getRequiredSecurity(), - p_char->getValueAttribute().getValuePtr(), - p_char->getValueAttribute().getInitialLength(), - p_char->getValueAttribute().getMaxLength(), - userDescriptionDescriptorValuePtr, - userDescriptionDescriptorValueLen, - p_char->isReadAuthorizationEnabled(), - p_char->isWriteAuthorizationEnabled(), - &nrfCharacteristicHandles[characteristicCount]), - BLE_ERROR_PARAM_OUT_OF_RANGE ); - - /* Update the characteristic handle */ - p_characteristics[characteristicCount] = p_char; - p_char->getValueAttribute().setHandle(nrfCharacteristicHandles[characteristicCount].value_handle); - characteristicCount++; - - /* Add optional descriptors if any */ - /* ToDo: Make sure we don't overflow the array */ - for (uint8_t j = 0; j < p_char->getDescriptorCount(); j++) { - GattAttribute *p_desc = p_char->getDescriptor(j); - /* skip the user-description-descriptor here; this has already been handled when adding the characteristic (above). */ - if (p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_USER_DESC) { - continue; - } - - nordicUUID = custom_convert_to_nordic_uuid(p_desc->getUUID()); - - ASSERT(ERROR_NONE == - custom_add_in_descriptor(BLE_GATT_HANDLE_INVALID, - &nordicUUID, - p_desc->getValuePtr(), - p_desc->getInitialLength(), - p_desc->getMaxLength(), - &nrfDescriptorHandles[descriptorCount]), - BLE_ERROR_PARAM_OUT_OF_RANGE); - - p_descriptors[descriptorCount++] = p_desc; - p_desc->setHandle(nrfDescriptorHandles[descriptorCount]); - } - } - - serviceCount++; - - return BLE_ERROR_NONE; -} - -/**************************************************************************/ -/*! - @brief Reads the value of a characteristic, based on the service - and characteristic index fields - - @param[in] attributeHandle - The handle of the GattCharacteristic to read from - @param[in] buffer - Buffer to hold the the characteristic's value - (raw byte array in LSB format) - @param[in/out] len - input: Length in bytes to be read. - output: Total length of attribute value upon successful return. - - @returns ble_error_t - - @retval BLE_ERROR_NONE - Everything executed properly -*/ -/**************************************************************************/ -ble_error_t nRF5xGattServer::read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) -{ - return read(BLE_CONN_HANDLE_INVALID, attributeHandle, buffer, lengthP); -} - -ble_error_t nRF5xGattServer::read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) -{ - ble_gatts_value_t value = { - .len = *lengthP, - .offset = 0, - .p_value = buffer, - }; - - ASSERT( ERROR_NONE == - sd_ble_gatts_value_get(connectionHandle, attributeHandle, &value), - BLE_ERROR_PARAM_OUT_OF_RANGE); - *lengthP = value.len; - - return BLE_ERROR_NONE; -} - -/**************************************************************************/ -/*! - @brief Updates the value of a characteristic, based on the service - and characteristic index fields - - @param[in] charHandle - The handle of the GattCharacteristic to write to - @param[in] buffer - Data to use when updating the characteristic's value - (raw byte array in LSB format) - @param[in] len - The number of bytes in buffer - - @returns ble_error_t - - @retval BLE_ERROR_NONE - Everything executed properly -*/ -/**************************************************************************/ -ble_error_t nRF5xGattServer::write(GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly) -{ - return write(BLE_CONN_HANDLE_INVALID, attributeHandle, buffer, len, localOnly); -} - -ble_error_t nRF5xGattServer::write(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly) -{ - uint16_t gapConnectionHandle = nRF5xGap::getInstance().getConnectionHandle(); - ble_error_t returnValue = BLE_ERROR_NONE; - - ble_gatts_value_t value = { - .len = len, - .offset = 0, - .p_value = const_cast<uint8_t *>(buffer), - }; - - if (localOnly) { - /* Only update locally regardless of notify/indicate */ - ASSERT_INT( ERROR_NONE, - sd_ble_gatts_value_set(connectionHandle, attributeHandle, &value), - BLE_ERROR_PARAM_OUT_OF_RANGE ); - return BLE_ERROR_NONE; - } - - int characteristicIndex = resolveValueHandleToCharIndex(attributeHandle); - if ((characteristicIndex != -1) && - (p_characteristics[characteristicIndex]->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)) && - (gapConnectionHandle != connectionHandle)) { - /* HVX update for the characteristic value */ - ble_gatts_hvx_params_t hvx_params; - - hvx_params.handle = attributeHandle; - hvx_params.type = - (p_characteristics[characteristicIndex]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) ? BLE_GATT_HVX_NOTIFICATION : BLE_GATT_HVX_INDICATION; - hvx_params.offset = 0; - hvx_params.p_data = const_cast<uint8_t *>(buffer); - hvx_params.p_len = &len; - - error_t error = (error_t) sd_ble_gatts_hvx(gapConnectionHandle, &hvx_params); - - /* ERROR_INVALID_STATE, ERROR_BUSY, ERROR_GATTS_SYS_ATTR_MISSING and ERROR_NO_TX_BUFFERS the ATT table has been updated. */ - if ((error != ERROR_NONE) && (error != ERROR_INVALID_STATE) && (error != ERROR_BLE_NO_TX_BUFFERS) && (error != ERROR_BUSY) && (error != ERROR_BLEGATTS_SYS_ATTR_MISSING)) { - ASSERT_INT( ERROR_NONE, - sd_ble_gatts_value_set(connectionHandle, attributeHandle, &value), - BLE_ERROR_PARAM_OUT_OF_RANGE ); - } - - /* Notifications consume application buffers. The return value can - be used for resending notifications. - */ - if (error != ERROR_NONE) { - returnValue = BLE_STACK_BUSY; - } - } else { - ASSERT_INT( ERROR_NONE, - sd_ble_gatts_value_set(connectionHandle, attributeHandle, &value), - BLE_ERROR_PARAM_OUT_OF_RANGE ); - } - - return returnValue; -} - -ble_error_t nRF5xGattServer::areUpdatesEnabled(const GattCharacteristic &characteristic, bool *enabledP) -{ - /* Forward the call with the default connection handle. */ - return areUpdatesEnabled(nRF5xGap::getInstance().getConnectionHandle(), characteristic, enabledP); -} - -ble_error_t nRF5xGattServer::areUpdatesEnabled(Gap::Handle_t connectionHandle, const GattCharacteristic &characteristic, bool *enabledP) -{ - int characteristicIndex = resolveValueHandleToCharIndex(characteristic.getValueHandle()); - if (characteristicIndex == -1) { - return BLE_ERROR_INVALID_PARAM; - } - - /* Read the cccd value from the GATT server. */ - GattAttribute::Handle_t cccdHandle = nrfCharacteristicHandles[characteristicIndex].cccd_handle; - uint16_t cccdValue; - uint16_t length = sizeof(cccdValue); - ble_error_t rc = read(connectionHandle, cccdHandle, reinterpret_cast<uint8_t *>(&cccdValue), &length); - if (rc != BLE_ERROR_NONE) { - return rc; - } - if (length != sizeof(cccdValue)) { - return BLE_ERROR_INVALID_STATE; - } - - /* Check for NOTFICATION or INDICATION in CCCD. */ - if ((cccdValue & BLE_GATT_HVX_NOTIFICATION) || (cccdValue & BLE_GATT_HVX_INDICATION)) { - *enabledP = true; - } - - return BLE_ERROR_NONE; -} - -/**************************************************************************/ -/*! - @brief Callback handler for events getting pushed up from the SD -*/ -/**************************************************************************/ -void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) -{ - GattAttribute::Handle_t handle_value; - GattServerEvents::gattEvent_t eventType; - const ble_gatts_evt_t *gattsEventP = &p_ble_evt->evt.gatts_evt; - - switch (p_ble_evt->header.evt_id) { - case BLE_GATTS_EVT_WRITE: { - /* There are 2 use case here: Values being updated & CCCD (indicate/notify) enabled */ - - /* 1.) Handle CCCD changes */ - handle_value = gattsEventP->params.write.handle; - int characteristicIndex = resolveCCCDHandleToCharIndex(handle_value); - if ((characteristicIndex != -1) && - (p_characteristics[characteristicIndex]->getProperties() & - (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY))) { - - uint16_t cccd_value = (gattsEventP->params.write.data[1] << 8) | gattsEventP->params.write.data[0]; /* Little Endian but M0 may be mis-aligned */ - - if (((p_characteristics[characteristicIndex]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) && (cccd_value & BLE_GATT_HVX_INDICATION)) || - ((p_characteristics[characteristicIndex]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) && (cccd_value & BLE_GATT_HVX_NOTIFICATION))) { - eventType = GattServerEvents::GATT_EVENT_UPDATES_ENABLED; - } else { - eventType = GattServerEvents::GATT_EVENT_UPDATES_DISABLED; - } - - handleEvent(eventType, p_characteristics[characteristicIndex]->getValueHandle()); - return; - } - - /* 2.) Changes to the characteristic value will be handled with other events below */ - eventType = GattServerEvents::GATT_EVENT_DATA_WRITTEN; - } - break; - - case BLE_GATTS_EVT_HVC: - /* Indication confirmation received */ - eventType = GattServerEvents::GATT_EVENT_CONFIRMATION_RECEIVED; - handle_value = gattsEventP->params.hvc.handle; - break; - - case BLE_EVT_TX_COMPLETE: { - handleDataSentEvent(p_ble_evt->evt.common_evt.params.tx_complete.count); - return; - } - - case BLE_GATTS_EVT_SYS_ATTR_MISSING: - sd_ble_gatts_sys_attr_set(gattsEventP->conn_handle, NULL, 0, 0); - return; - - case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: - switch (gattsEventP->params.authorize_request.type) { - case BLE_GATTS_AUTHORIZE_TYPE_READ: - eventType = GattServerEvents::GATT_EVENT_READ_AUTHORIZATION_REQ; - handle_value = gattsEventP->params.authorize_request.request.read.handle; - break; - case BLE_GATTS_AUTHORIZE_TYPE_WRITE: - eventType = GattServerEvents::GATT_EVENT_WRITE_AUTHORIZATION_REQ; - handle_value = gattsEventP->params.authorize_request.request.write.handle; - break; - default: - return; - } - break; - - default: - return; - } - - int characteristicIndex = resolveValueHandleToCharIndex(handle_value); - if (characteristicIndex == -1) { - return; - } - - /* Find index (charHandle) in the pool */ - switch (eventType) { - case GattServerEvents::GATT_EVENT_DATA_WRITTEN: { - GattWriteCallbackParams cbParams = { - .handle = handle_value, - .writeOp = static_cast<GattWriteCallbackParams::WriteOp_t>(gattsEventP->params.write.op), - .offset = gattsEventP->params.write.offset, - .len = gattsEventP->params.write.len, - .data = gattsEventP->params.write.data - }; - handleDataWrittenEvent(&cbParams); - break; - } - case GattServerEvents::GATT_EVENT_WRITE_AUTHORIZATION_REQ: { - GattWriteAuthCallbackParams cbParams = { - .handle = handle_value, - .offset = gattsEventP->params.authorize_request.request.write.offset, - .len = gattsEventP->params.authorize_request.request.write.len, - .data = gattsEventP->params.authorize_request.request.write.data, - }; - ble_gatts_rw_authorize_reply_params_t reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = p_characteristics[characteristicIndex]->authorizeWrite(&cbParams) - } - } - }; - sd_ble_gatts_rw_authorize_reply(gattsEventP->conn_handle, &reply); - - /* - * If write-authorization is enabled for a characteristic, - * AUTHORIZATION_REQ event (if replied with true) is *not* - * followed by another DATA_WRITTEN event; so we still need - * to invoke handleDataWritten(), much the same as we would - * have done if write-authorization had not been enabled. - */ - if (reply.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS) { - GattWriteCallbackParams cbParams = { - .handle = handle_value, - .writeOp = static_cast<GattWriteCallbackParams::WriteOp_t>(gattsEventP->params.authorize_request.request.write.op), - .offset = gattsEventP->params.authorize_request.request.write.offset, - .len = gattsEventP->params.authorize_request.request.write.len, - .data = gattsEventP->params.authorize_request.request.write.data, - }; - handleDataWrittenEvent(&cbParams); - } - break; - } - case GattServerEvents::GATT_EVENT_READ_AUTHORIZATION_REQ: { - GattReadAuthCallbackParams cbParams = { - .handle = handle_value, - .offset = gattsEventP->params.authorize_request.request.read.offset, - .len = 0, - .data = NULL - }; - - ble_gatts_rw_authorize_reply_params_t reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_READ, - .params = { - .read = { - .gatt_status = p_characteristics[characteristicIndex]->authorizeRead(&cbParams) - } - } - }; - - if (cbParams.authorizationReply == BLE_GATT_STATUS_SUCCESS) { - if (cbParams.data != NULL) { - reply.params.read.update = 1; - reply.params.read.offset = cbParams.offset; - reply.params.read.len = cbParams.len; - reply.params.read.p_data = cbParams.data; - } - } - - sd_ble_gatts_rw_authorize_reply(gattsEventP->conn_handle, &reply); - break; - } - - default: - handleEvent(eventType, handle_value); - break; - } -} \ No newline at end of file
--- a/source/nRF5xGattServer.h Tue Jul 21 13:23:45 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __NRF51822_GATT_SERVER_H__ -#define __NRF51822_GATT_SERVER_H__ - -#include <stddef.h> - -#include "ble/blecommon.h" -#include "ble.h" /* nordic ble */ -#include "ble/Gap.h" -#include "ble/GattServer.h" - -class nRF5xGattServer : public GattServer -{ -public: - static nRF5xGattServer &getInstance(); - - /* Functions that must be implemented from GattServer */ - virtual ble_error_t addService(GattService &); - virtual ble_error_t read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP); - virtual ble_error_t read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP); - virtual ble_error_t write(GattAttribute::Handle_t, const uint8_t[], uint16_t, bool localOnly = false); - virtual ble_error_t write(Gap::Handle_t connectionHandle, GattAttribute::Handle_t, const uint8_t[], uint16_t, bool localOnly = false); - virtual ble_error_t areUpdatesEnabled(const GattCharacteristic &characteristic, bool *enabledP); - virtual ble_error_t areUpdatesEnabled(Gap::Handle_t connectionHandle, const GattCharacteristic &characteristic, bool *enabledP); - - /* nRF51 Functions */ - void eventCallback(void); - void hwCallback(ble_evt_t *p_ble_evt); - -private: - const static unsigned BLE_TOTAL_CHARACTERISTICS = 20; - const static unsigned BLE_TOTAL_DESCRIPTORS = 8; - -private: - /** - * resolve a value attribute to its owning characteristic. - * @param valueHandle the value handle to be resolved. - * @return characteristic index if a resolution is found, else -1. - */ - int resolveValueHandleToCharIndex(GattAttribute::Handle_t valueHandle) const { - unsigned charIndex; - for (charIndex = 0; charIndex < characteristicCount; charIndex++) { - if (nrfCharacteristicHandles[charIndex].value_handle == valueHandle) { - return charIndex; - } - } - - return -1; - } - - /** - * resolve a CCCD attribute handle to its owning characteristic. - * @param cccdHandle the CCCD handle to be resolved. - * @return characteristic index if a resolution is found, else -1. - */ - int resolveCCCDHandleToCharIndex(GattAttribute::Handle_t cccdHandle) const { - unsigned charIndex; - for (charIndex = 0; charIndex < characteristicCount; charIndex++) { - if (nrfCharacteristicHandles[charIndex].cccd_handle == cccdHandle) { - return charIndex; - } - } - - return -1; - } - -private: - GattCharacteristic *p_characteristics[BLE_TOTAL_CHARACTERISTICS]; - ble_gatts_char_handles_t nrfCharacteristicHandles[BLE_TOTAL_CHARACTERISTICS]; - GattAttribute *p_descriptors[BLE_TOTAL_DESCRIPTORS]; - uint8_t descriptorCount; - uint16_t nrfDescriptorHandles[BLE_TOTAL_DESCRIPTORS]; - - nRF5xGattServer() : GattServer(), p_characteristics(), nrfCharacteristicHandles(), p_descriptors(), descriptorCount(0), nrfDescriptorHandles() { - /* empty */ - } - -private: - nRF5xGattServer(const nRF5xGattServer &); - const nRF5xGattServer& operator=(const nRF5xGattServer &); -}; - -#endif // ifndef __NRF51822_GATT_SERVER_H__ \ No newline at end of file
--- a/source/nRF5xSecurityManager.cpp Tue Jul 21 13:23:45 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "nRF5xSecurityManager.h" - -nRF5xSecurityManager &nRF5xSecurityManager::getInstance(void) { - static nRF5xSecurityManager m_instance; - return m_instance; -} \ No newline at end of file
--- a/source/nRF5xSecurityManager.h Tue Jul 21 13:23:45 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __NRF51822_SECURITY_MANAGER_H__ -#define __NRF51822_SECURITY_MANAGER_H__ - -#include <stddef.h> - -#include "ble/SecurityManager.h" -#include "btle_security.h" - -class nRF5xSecurityManager : public SecurityManager -{ -public: - static nRF5xSecurityManager &getInstance(); - - /* Functions that must be implemented from SecurityManager */ - virtual ble_error_t init(bool enableBonding, - bool requireMITM, - SecurityIOCapabilities_t iocaps, - const Passkey_t passkey) { - return btle_initializeSecurity(enableBonding, requireMITM, iocaps, passkey); - } - - virtual ble_error_t getLinkSecurity(Gap::Handle_t connectionHandle, LinkSecurityStatus_t *securityStatusP) { - return btle_getLinkSecurity(connectionHandle, securityStatusP); - } - - virtual ble_error_t purgeAllBondingState(void) { - return btle_purgeAllBondingState(); - } - -public: - nRF5xSecurityManager() { - /* empty */ - } - -private: - nRF5xSecurityManager(const nRF5xSecurityManager &); - const nRF5xSecurityManager& operator=(const nRF5xSecurityManager &); -}; - -#endif // ifndef __NRF51822_SECURITY_MANAGER_H__ \ No newline at end of file
--- a/source/nRF5xServiceDiscovery.cpp Tue Jul 21 13:23:45 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,282 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "nRF5xServiceDiscovery.h" - -ble_error_t -nRF5xServiceDiscovery::launchCharacteristicDiscovery(Gap::Handle_t connectionHandle, - Gap::Handle_t startHandle, - Gap::Handle_t endHandle) -{ - characteristicDiscoveryStarted(connectionHandle); - - ble_gattc_handle_range_t handleRange = { - .start_handle = startHandle, - .end_handle = endHandle - }; - uint32_t rc; - if ((rc = sd_ble_gattc_characteristics_discover(connectionHandle, &handleRange)) != NRF_SUCCESS) { - terminateCharacteristicDiscovery(); - switch (rc) { - case BLE_ERROR_INVALID_CONN_HANDLE: - case NRF_ERROR_INVALID_ADDR: - return BLE_ERROR_INVALID_PARAM; - case NRF_ERROR_BUSY: - return BLE_STACK_BUSY; - default: - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - } - } - - return BLE_ERROR_NONE; -} - -void -nRF5xServiceDiscovery::setupDiscoveredServices(const ble_gattc_evt_prim_srvc_disc_rsp_t *response) -{ - serviceIndex = 0; - numServices = response->count; - - /* Account for the limitation on the number of discovered services we can handle at a time. */ - if (numServices > BLE_DB_DISCOVERY_MAX_SRV) { - numServices = BLE_DB_DISCOVERY_MAX_SRV; - } - - serviceUUIDDiscoveryQueue.reset(); - for (unsigned serviceIndex = 0; serviceIndex < numServices; serviceIndex++) { - if (response->services[serviceIndex].uuid.type == BLE_UUID_TYPE_UNKNOWN) { - serviceUUIDDiscoveryQueue.enqueue(serviceIndex); - services[serviceIndex].setup(response->services[serviceIndex].handle_range.start_handle, - response->services[serviceIndex].handle_range.end_handle); - } else { - services[serviceIndex].setup(response->services[serviceIndex].uuid.uuid, - response->services[serviceIndex].handle_range.start_handle, - response->services[serviceIndex].handle_range.end_handle); - } - } - - /* Trigger discovery of service UUID if necessary. */ - if (serviceUUIDDiscoveryQueue.getCount()) { - serviceUUIDDiscoveryQueue.triggerFirst(); - } -} - -void -nRF5xServiceDiscovery::setupDiscoveredCharacteristics(const ble_gattc_evt_char_disc_rsp_t *response) -{ - characteristicIndex = 0; - numCharacteristics = response->count; - - /* Account for the limitation on the number of discovered characteristics we can handle at a time. */ - if (numCharacteristics > BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV) { - numCharacteristics = BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV; - } - - charUUIDDiscoveryQueue.reset(); - for (unsigned charIndex = 0; charIndex < numCharacteristics; charIndex++) { - if (response->chars[charIndex].uuid.type == BLE_UUID_TYPE_UNKNOWN) { - charUUIDDiscoveryQueue.enqueue(charIndex); - characteristics[charIndex].setup(gattc, - connHandle, - response->chars[charIndex].char_props, - response->chars[charIndex].handle_decl, - response->chars[charIndex].handle_value); - } else { - characteristics[charIndex].setup(gattc, - connHandle, - response->chars[charIndex].uuid.uuid, - response->chars[charIndex].char_props, - response->chars[charIndex].handle_decl, - response->chars[charIndex].handle_value); - } - } - - /* Trigger discovery of char UUID if necessary. */ - if (charUUIDDiscoveryQueue.getCount()) { - charUUIDDiscoveryQueue.triggerFirst(); - } -} - -void -nRF5xServiceDiscovery::progressCharacteristicDiscovery(void) -{ - /* Iterate through the previously discovered characteristics cached in characteristics[]. */ - while ((state == CHARACTERISTIC_DISCOVERY_ACTIVE) && (characteristicIndex < numCharacteristics)) { - if ((matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) || - ((matchingCharacteristicUUID == characteristics[characteristicIndex].getShortUUID()) && - (matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) { - if (characteristicCallback) { - characteristicCallback(&characteristics[characteristicIndex]); - } - } - - characteristicIndex++; - } - - /* Relaunch discovery of new characteristics beyond the last entry cached in characteristics[]. */ - if (state == CHARACTERISTIC_DISCOVERY_ACTIVE) { - /* Determine the ending handle of the last cached characteristic. */ - Gap::Handle_t startHandle = characteristics[characteristicIndex - 1].getValueHandle() + 1; - Gap::Handle_t endHandle = services[serviceIndex].getEndHandle(); - resetDiscoveredCharacteristics(); /* Note: resetDiscoveredCharacteristics() must come after fetching start and end Handles. */ - - if (startHandle < endHandle) { - ble_gattc_handle_range_t handleRange = { - .start_handle = startHandle, - .end_handle = endHandle - }; - if (sd_ble_gattc_characteristics_discover(connHandle, &handleRange) != NRF_SUCCESS) { - terminateCharacteristicDiscovery(); - } - } else { - terminateCharacteristicDiscovery(); - } - } -} - -void -nRF5xServiceDiscovery::progressServiceDiscovery(void) -{ - /* Iterate through the previously discovered services cached in services[]. */ - while ((state == SERVICE_DISCOVERY_ACTIVE) && (serviceIndex < numServices)) { - if ((matchingServiceUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) || - (matchingServiceUUID == services[serviceIndex].getUUID().getShortUUID())) { - - if (serviceCallback && (matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN))) { - serviceCallback(&services[serviceIndex]); - } - - if ((state == SERVICE_DISCOVERY_ACTIVE) && characteristicCallback) { - launchCharacteristicDiscovery(connHandle, services[serviceIndex].getStartHandle(), services[serviceIndex].getEndHandle()); - } else { - serviceIndex++; - } - } else { - serviceIndex++; - } - } - - /* Relaunch discovery of new services beyond the last entry cached in services[]. */ - if ((state == SERVICE_DISCOVERY_ACTIVE) && (numServices > 0) && (serviceIndex > 0)) { - /* Determine the ending handle of the last cached service. */ - Gap::Handle_t endHandle = services[serviceIndex - 1].getEndHandle(); - resetDiscoveredServices(); /* Note: resetDiscoveredServices() must come after fetching endHandle. */ - - if (endHandle == SRV_DISC_END_HANDLE) { - terminateServiceDiscovery(); - } else { - if (sd_ble_gattc_primary_services_discover(connHandle, endHandle, NULL) != NRF_SUCCESS) { - terminateServiceDiscovery(); - } - } - } -} - -void -nRF5xServiceDiscovery::ServiceUUIDDiscoveryQueue::triggerFirst(void) -{ - while (numIndices) { /* loop until a call to char_value_by_uuid_read() succeeds or we run out of pending indices. */ - parentDiscoveryObject->state = DISCOVER_SERVICE_UUIDS; - - unsigned serviceIndex = getFirst(); - ble_uuid_t uuid = { - .uuid = BLE_UUID_SERVICE_PRIMARY, - .type = BLE_UUID_TYPE_BLE, - }; - ble_gattc_handle_range_t handleRange = { - .start_handle = parentDiscoveryObject->services[serviceIndex].getStartHandle(), - .end_handle = parentDiscoveryObject->services[serviceIndex].getEndHandle(), - }; - if (sd_ble_gattc_char_value_by_uuid_read(parentDiscoveryObject->connHandle, &uuid, &handleRange) == NRF_SUCCESS) { - return; - } - - /* Skip this service if we fail to launch a read for its service-declaration - * attribute. Its UUID will remain INVALID, and it may not match any filters. */ - dequeue(); - } - - /* Switch back to service discovery upon exhausting the service-indices pending UUID discovery. */ - if (parentDiscoveryObject->state == DISCOVER_SERVICE_UUIDS) { - parentDiscoveryObject->state = SERVICE_DISCOVERY_ACTIVE; - } -} - -void -nRF5xServiceDiscovery::CharUUIDDiscoveryQueue::triggerFirst(void) -{ - while (numIndices) { /* loop until a call to char_value_by_uuid_read() succeeds or we run out of pending indices. */ - parentDiscoveryObject->state = DISCOVER_CHARACTERISTIC_UUIDS; - - unsigned charIndex = getFirst(); - ble_uuid_t uuid = { - .uuid = BLE_UUID_CHARACTERISTIC, - .type = BLE_UUID_TYPE_BLE, - }; - ble_gattc_handle_range_t handleRange = { }; - handleRange.start_handle = parentDiscoveryObject->characteristics[charIndex].getDeclHandle(); - handleRange.end_handle = parentDiscoveryObject->characteristics[charIndex].getDeclHandle() + 1; - if (sd_ble_gattc_char_value_by_uuid_read(parentDiscoveryObject->connHandle, &uuid, &handleRange) == NRF_SUCCESS) { - return; - } - - /* Skip this service if we fail to launch a read for its service-declaration - * attribute. Its UUID will remain INVALID, and it may not match any filters. */ - dequeue(); - } - - /* Switch back to service discovery upon exhausting the service-indices pending UUID discovery. */ - if (parentDiscoveryObject->state == DISCOVER_CHARACTERISTIC_UUIDS) { - parentDiscoveryObject->state = CHARACTERISTIC_DISCOVERY_ACTIVE; - } -} - -void -nRF5xServiceDiscovery::processDiscoverUUIDResponse(const ble_gattc_evt_char_val_by_uuid_read_rsp_t *response) -{ - if (state == DISCOVER_SERVICE_UUIDS) { - if ((response->count == 1) && (response->value_len == UUID::LENGTH_OF_LONG_UUID)) { - UUID::LongUUIDBytes_t uuid; - /* Switch longUUID bytes to MSB */ - for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) { - uuid[i] = response->handle_value[0].p_value[UUID::LENGTH_OF_LONG_UUID - 1 - i]; - } - - unsigned serviceIndex = serviceUUIDDiscoveryQueue.dequeue(); - services[serviceIndex].setupLongUUID(uuid); - - serviceUUIDDiscoveryQueue.triggerFirst(); - } else { - serviceUUIDDiscoveryQueue.dequeue(); - } - } else if (state == DISCOVER_CHARACTERISTIC_UUIDS) { - if ((response->count == 1) && (response->value_len == UUID::LENGTH_OF_LONG_UUID + 1 /* props */ + 2 /* value handle */)) { - UUID::LongUUIDBytes_t uuid; - /* Switch longUUID bytes to MSB */ - for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) { - uuid[i] = response->handle_value[0].p_value[3 + UUID::LENGTH_OF_LONG_UUID - 1 - i]; - } - - unsigned charIndex = charUUIDDiscoveryQueue.dequeue(); - characteristics[charIndex].setupLongUUID(uuid); - - charUUIDDiscoveryQueue.triggerFirst(); - } else { - charUUIDDiscoveryQueue.dequeue(); - } - } -} \ No newline at end of file
--- a/source/nRF5xServiceDiscovery.h Tue Jul 21 13:23:45 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,305 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __NRF_SERVICE_DISCOVERY_H__ -#define __NRF_SERVICE_DISCOVERY_H__ - -#include "ble/ServiceDiscovery.h" -#include "ble/DiscoveredService.h" -#include "nRF5xDiscoveredCharacteristic.h" - -#include "ble.h" -#include "ble_gattc.h" - -class nRF5xGattClient; /* forward declaration */ - -class nRF5xServiceDiscovery : public ServiceDiscovery -{ -public: - static const uint16_t SRV_DISC_START_HANDLE = 0x0001; /**< The start handle value used during service discovery. */ - static const uint16_t SRV_DISC_END_HANDLE = 0xFFFF; /**< The end handle value used during service discovery. */ - -public: - static const unsigned BLE_DB_DISCOVERY_MAX_SRV = 4; /**< Maximum number of services we can retain information for after a single discovery. */ - static const unsigned BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV = 4; /**< Maximum number of characteristics per service we can retain information for. */ - -public: - nRF5xServiceDiscovery(nRF5xGattClient *gattcIn) : - gattc(gattcIn), - serviceIndex(0), - numServices(0), - characteristicIndex(0), - numCharacteristics(0), - state(INACTIVE), - services(), - characteristics(), - serviceUUIDDiscoveryQueue(this), - charUUIDDiscoveryQueue(this), - onTerminationCallback(NULL) { - /* empty */ - } - - virtual ble_error_t launch(Gap::Handle_t connectionHandle, - ServiceDiscovery::ServiceCallback_t sc, - ServiceDiscovery::CharacteristicCallback_t cc, - const UUID &matchingServiceUUIDIn, - const UUID &matchingCharacteristicUUIDIn) - { - if (isActive()) { - return BLE_ERROR_INVALID_STATE; - } - - serviceCallback = sc; - characteristicCallback = cc; - matchingServiceUUID = matchingServiceUUIDIn; - matchingCharacteristicUUID = matchingCharacteristicUUIDIn; - - serviceDiscoveryStarted(connectionHandle); - - uint32_t rc; - if ((rc = sd_ble_gattc_primary_services_discover(connectionHandle, SRV_DISC_START_HANDLE, NULL)) != NRF_SUCCESS) { - terminate(); - switch (rc) { - case NRF_ERROR_INVALID_PARAM: - case BLE_ERROR_INVALID_CONN_HANDLE: - return BLE_ERROR_INVALID_PARAM; - case NRF_ERROR_BUSY: - return BLE_STACK_BUSY; - default: - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - } - } - - return BLE_ERROR_NONE; - } - - virtual bool isActive(void) const { - return state != INACTIVE; - } - - virtual void terminate(void) { - terminateServiceDiscovery(); - } - - virtual void onTermination(ServiceDiscovery::TerminationCallback_t callback) { - onTerminationCallback = callback; - } - -private: - ble_error_t launchCharacteristicDiscovery(Gap::Handle_t connectionHandle, Gap::Handle_t startHandle, Gap::Handle_t endHandle); - -private: - void setupDiscoveredServices(const ble_gattc_evt_prim_srvc_disc_rsp_t *response); - void setupDiscoveredCharacteristics(const ble_gattc_evt_char_disc_rsp_t *response); - - void triggerServiceUUIDDiscovery(void); - void processDiscoverUUIDResponse(const ble_gattc_evt_char_val_by_uuid_read_rsp_t *response); - void removeFirstServiceNeedingUUIDDiscovery(void); - - void terminateServiceDiscovery(void) { - bool wasActive = isActive(); - state = INACTIVE; - - if (wasActive && onTerminationCallback) { - onTerminationCallback(connHandle); - } - } - - void terminateCharacteristicDiscovery(void) { - if (state == CHARACTERISTIC_DISCOVERY_ACTIVE) { - state = SERVICE_DISCOVERY_ACTIVE; - } - serviceIndex++; /* Progress service index to keep discovery alive. */ - } - -private: - void resetDiscoveredServices(void) { - numServices = 0; - serviceIndex = 0; - } - - void resetDiscoveredCharacteristics(void) { - numCharacteristics = 0; - characteristicIndex = 0; - } - -private: - void serviceDiscoveryStarted(Gap::Handle_t connectionHandle) { - connHandle = connectionHandle; - resetDiscoveredServices(); - state = SERVICE_DISCOVERY_ACTIVE; - } - -private: - void characteristicDiscoveryStarted(Gap::Handle_t connectionHandle) { - connHandle = connectionHandle; - resetDiscoveredCharacteristics(); - state = CHARACTERISTIC_DISCOVERY_ACTIVE; - } - -private: - /** - * A datatype to contain service-indices for which long UUIDs need to be - * discovered using read_val_by_uuid(). - */ - class ServiceUUIDDiscoveryQueue { - public: - ServiceUUIDDiscoveryQueue(nRF5xServiceDiscovery *parent) : - numIndices(0), - serviceIndices(), - parentDiscoveryObject(parent) { - /* empty */ - } - - public: - void reset(void) { - numIndices = 0; - for (unsigned i = 0; i < BLE_DB_DISCOVERY_MAX_SRV; i++) { - serviceIndices[i] = INVALID_INDEX; - } - } - void enqueue(int serviceIndex) { - serviceIndices[numIndices++] = serviceIndex; - } - int dequeue(void) { - if (numIndices == 0) { - return INVALID_INDEX; - } - - unsigned valueToReturn = serviceIndices[0]; - numIndices--; - for (unsigned i = 0; i < numIndices; i++) { - serviceIndices[i] = serviceIndices[i + 1]; - } - - return valueToReturn; - } - unsigned getFirst(void) const { - return serviceIndices[0]; - } - size_t getCount(void) const { - return numIndices; - } - - /** - * Trigger UUID discovery for the first of the enqueued ServiceIndices. - */ - void triggerFirst(void); - - private: - static const int INVALID_INDEX = -1; - - private: - size_t numIndices; - int serviceIndices[BLE_DB_DISCOVERY_MAX_SRV]; - - nRF5xServiceDiscovery *parentDiscoveryObject; - }; - friend class ServiceUUIDDiscoveryQueue; - - /** - * A datatype to contain characteristic-indices for which long UUIDs need to - * be discovered using read_val_by_uuid(). - */ - class CharUUIDDiscoveryQueue { - public: - CharUUIDDiscoveryQueue(nRF5xServiceDiscovery *parent) : - numIndices(0), - charIndices(), - parentDiscoveryObject(parent) { - /* empty */ - } - - public: - void reset(void) { - numIndices = 0; - for (unsigned i = 0; i < BLE_DB_DISCOVERY_MAX_SRV; i++) { - charIndices[i] = INVALID_INDEX; - } - } - void enqueue(int serviceIndex) { - charIndices[numIndices++] = serviceIndex; - } - int dequeue(void) { - if (numIndices == 0) { - return INVALID_INDEX; - } - - unsigned valueToReturn = charIndices[0]; - numIndices--; - for (unsigned i = 0; i < numIndices; i++) { - charIndices[i] = charIndices[i + 1]; - } - - return valueToReturn; - } - unsigned getFirst(void) const { - return charIndices[0]; - } - size_t getCount(void) const { - return numIndices; - } - - /** - * Trigger UUID discovery for the first of the enqueued charIndices. - */ - void triggerFirst(void); - - private: - static const int INVALID_INDEX = -1; - - private: - size_t numIndices; - int charIndices[BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV]; - - nRF5xServiceDiscovery *parentDiscoveryObject; - }; - friend class CharUUIDDiscoveryQueue; - -private: - friend void bleGattcEventHandler(const ble_evt_t *p_ble_evt); - void progressCharacteristicDiscovery(void); - void progressServiceDiscovery(void); - -private: - nRF5xGattClient *gattc; - -private: - uint8_t serviceIndex; /**< Index of the current service being discovered. This is intended for internal use during service discovery.*/ - uint8_t numServices; /**< Number of services at the peers GATT database.*/ - uint8_t characteristicIndex; /**< Index of the current characteristic being discovered. This is intended for internal use during service discovery.*/ - uint8_t numCharacteristics; /**< Number of characteristics within the service.*/ - - enum State_t { - INACTIVE, - SERVICE_DISCOVERY_ACTIVE, - CHARACTERISTIC_DISCOVERY_ACTIVE, - DISCOVER_SERVICE_UUIDS, - DISCOVER_CHARACTERISTIC_UUIDS, - } state; - - DiscoveredService services[BLE_DB_DISCOVERY_MAX_SRV]; /**< Information related to the current service being discovered. - * This is intended for internal use during service discovery. */ - nRF5xDiscoveredCharacteristic characteristics[BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV]; - - ServiceUUIDDiscoveryQueue serviceUUIDDiscoveryQueue; - CharUUIDDiscoveryQueue charUUIDDiscoveryQueue; - - TerminationCallback_t onTerminationCallback; -}; - -#endif /*__NRF_SERVICE_DISCOVERY_H__*/ \ No newline at end of file
--- a/source/nRF5xn.cpp Tue Jul 21 13:23:45 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "mbed.h" -#include "nRF5xn.h" -#include "nrf_soc.h" - -#include "btle/btle.h" -#include "nrf_delay.h" - -#include "softdevice_handler.h" - -/** - * The singleton which represents the nRF51822 transport for the BLE. - */ -static nRF5xn deviceInstance; - -/** - * BLE-API requires an implementation of the following function in order to - * obtain its transport handle. - */ -BLEInstanceBase * -createBLEInstance(void) -{ - return (&deviceInstance); -} - -nRF5xn::nRF5xn(void) -{ -} - -nRF5xn::~nRF5xn(void) -{ -} - -const char *nRF5xn::getVersion(void) -{ - static char versionString[32]; - static bool versionFetched = false; - - if (!versionFetched) { - ble_version_t version; - if ((sd_ble_version_get(&version) == NRF_SUCCESS) && (version.company_id == 0x0059)) { - switch (version.version_number) { - case 0x07: - snprintf(versionString, sizeof(versionString), "Nordic BLE4.1 fw:%04x", version.subversion_number); - break; - default: - snprintf(versionString, sizeof(versionString), "Nordic (spec unknown) fw:%04x", version.subversion_number); - break; - } - versionFetched = true; - } else { - strncpy(versionString, "unknown", sizeof(versionString)); - } - } - - return versionString; -} - -ble_error_t nRF5xn::init(void) -{ - /* ToDo: Clear memory contents, reset the SD, etc. */ - btle_init(); - - return BLE_ERROR_NONE; -} - -ble_error_t nRF5xn::shutdown(void) -{ - return (softdevice_handler_sd_disable() == NRF_SUCCESS) ? BLE_ERROR_NONE : BLE_STACK_BUSY; -} - -void -nRF5xn::waitForEvent(void) -{ - sd_app_evt_wait(); -} \ No newline at end of file
--- a/source/nRF5xn.h Tue Jul 21 13:23:45 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __NRF51822_H__ -#define __NRF51822_H__ - -#include "mbed.h" -#include "ble/blecommon.h" -#include "ble/BLE.h" -#include "nRF5xGap.h" -#include "nRF5xGattServer.h" -#include "nRF5xGattClient.h" -#include "nRF5xSecurityManager.h" -#include "btle.h" - -class nRF5xn : public BLEInstanceBase -{ -public: - nRF5xn(void); - virtual ~nRF5xn(void); - - virtual ble_error_t init(void); - virtual ble_error_t shutdown(void); - virtual const char *getVersion(void); - - virtual Gap &getGap() { - return nRF5xGap::getInstance(); - }; - virtual const Gap &getGap() const { - return nRF5xGap::getInstance(); - }; - virtual GattServer &getGattServer() { - return nRF5xGattServer::getInstance(); - }; - virtual const GattServer &getGattServer() const { - return nRF5xGattServer::getInstance(); - }; - virtual GattClient &getGattClient() { - return nRF5xGattClient::getInstance(); - } - virtual const SecurityManager &getSecurityManager() const { - return nRF5xSecurityManager::getInstance(); - } - virtual SecurityManager &getSecurityManager() { - return nRF5xSecurityManager::getInstance(); - } - virtual void waitForEvent(void); -}; - -#endif \ No newline at end of file