config changes
Fork of nRF51822 by
Revision 567:e1800bd55a9e, committed 2016-01-11
- Comitter:
- vcoubard
- Date:
- Mon Jan 11 10:19:19 2016 +0000
- Parent:
- 566:e425ad9e5d6e
- Child:
- 568:13b23a4b1f58
- Commit message:
- Synchronized with git rev 59ced0b4
Author: Vincent Coubard
rename remainingCharacteristic member, now it is named
discoveredCharacteristic. Add doc to the discovery process and the
rationale behind discoveredCharacteristic member.
Changed in this revision
--- a/source/btle/btle.cpp Mon Jan 11 10:19:18 2016 +0000 +++ b/source/btle/btle.cpp Mon Jan 11 10:19:19 2016 +0000 @@ -41,6 +41,10 @@ #include "ble_hci.h" #include "btle_discovery.h" +#include "nRF5xGattClient.h" +#include "nRF5xServiceDiscovery.h" +#include "nRF5xCharacteristicDescriptorDiscoverer.h" + extern "C" void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name); void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t *p_file_name); @@ -154,8 +158,8 @@ const ble_gap_addr_t *own = &p_ble_evt->evt.gap_evt.params.connected.own_addr; nRF5xGap::getInstance().processConnectionEvent(handle, role, - static_cast<BLEProtocol::AddressType::Type>(peer->addr_type), peer->addr, - static_cast<BLEProtocol::AddressType::Type>(own->addr_type), own->addr, + static_cast<Gap::AddressType_t>(peer->addr_type), peer->addr, + static_cast<Gap::AddressType_t>(own->addr_type), own->addr, params); break; } @@ -183,6 +187,12 @@ reason = static_cast<Gap::DisconnectionReason_t>(p_ble_evt->evt.gap_evt.params.disconnected.reason); break; } + + // Close all pending discoveries for this connection + nRF5xGattClient& gattClient = nRF5xGattClient::getInstance(); + gattClient.characteristicDescriptorDiscoverer().terminate(handle, BLE_ERROR_INVALID_STATE); + gattClient.discovery().terminate(handle); + nRF5xGap::getInstance().processDisconnectionEvent(handle, reason); break; }
--- a/source/btle/btle_discovery.cpp Mon Jan 11 10:19:18 2016 +0000 +++ b/source/btle/btle_discovery.cpp Mon Jan 11 10:19:19 2016 +0000 @@ -15,12 +15,15 @@ */ #include "nRF5xServiceDiscovery.h" +#include "nRF5xCharacteristicDescriptorDiscoverer.h" #include "nRF5xGattClient.h" #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) void bleGattcEventHandler(const ble_evt_t *p_ble_evt) { - nRF5xServiceDiscovery &sdSingleton = nRF5xGattClient::getInstance().discovery; + nRF5xServiceDiscovery &sdSingleton = nRF5xGattClient::getInstance().discovery(); + nRF5xCharacteristicDescriptorDiscoverer &characteristicDescriptorDiscoverer = + nRF5xGattClient::getInstance().characteristicDescriptorDiscoverer(); switch (p_ble_evt->header.evt_id) { case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: @@ -44,7 +47,7 @@ case BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND: default: - sdSingleton.terminateCharacteristicDiscovery(); + sdSingleton.terminateCharacteristicDiscovery(BLE_ERROR_NONE); break; } break; @@ -91,6 +94,28 @@ nRF5xGattClient::getInstance().processHVXEvent(¶ms); } break; + + case BLE_GATTC_EVT_DESC_DISC_RSP: { + uint16_t conn_handle = p_ble_evt->evt.gattc_evt.conn_handle; + uint16_t status = p_ble_evt->evt.gattc_evt.gatt_status; + const ble_gattc_evt_desc_disc_rsp_t& discovered_descriptors = p_ble_evt->evt.gattc_evt.params.desc_disc_rsp; + + switch(status) { + case BLE_GATT_STATUS_SUCCESS: + characteristicDescriptorDiscoverer.process( + conn_handle, + discovered_descriptors + ); + break; + case BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND: + // end of discovery + characteristicDescriptorDiscoverer.terminate(conn_handle, BLE_ERROR_NONE); + break; + default: + characteristicDescriptorDiscoverer.terminate(conn_handle, BLE_ERROR_UNSPECIFIED); + break; + } + } break; } sdSingleton.progressCharacteristicDiscovery();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/nRF5xCharacteristicDescriptorDiscoverer.cpp Mon Jan 11 10:19:19 2016 +0000 @@ -0,0 +1,208 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2015 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 "nRF5xCharacteristicDescriptorDiscoverer.h" +#include "ble_err.h" +#include "mbed-drivers/mbed_error.h" +#include "ble/DiscoveredCharacteristicDescriptor.h" + +namespace { + void emptyDiscoveryCallback(const CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t*) { } + void emptyTerminationCallback(const CharacteristicDescriptorDiscovery::TerminationCallbackParams_t*) { } +} + +nRF5xCharacteristicDescriptorDiscoverer::nRF5xCharacteristicDescriptorDiscoverer(size_t concurrentConnectionsCount) : + maximumConcurrentConnectionsCount(concurrentConnectionsCount), + discoveryRunning(new Discovery[concurrentConnectionsCount]) { + +} + +nRF5xCharacteristicDescriptorDiscoverer::~nRF5xCharacteristicDescriptorDiscoverer() { + delete [] discoveryRunning; +} + +ble_error_t nRF5xCharacteristicDescriptorDiscoverer::launch( + const DiscoveredCharacteristic& characteristic, + const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback, + const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback +) { + Gap::Handle_t connHandle = characteristic.getConnectionHandle(); + // it is ok to deduce that the start handle for descriptors is after + // the characteristic declaration and the characteristic value declaration + // see BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part G] (3.3) + Gap::Handle_t descriptorStartHandle = characteristic.getDeclHandle() + 2; + Gap::Handle_t descriptorEndHandle = characteristic.getLastHandle(); + + // check if their is any descriptor to discover + if (descriptorEndHandle < descriptorStartHandle) { + CharacteristicDescriptorDiscovery::TerminationCallbackParams_t termParams = { + characteristic, + BLE_ERROR_NONE + }; + terminationCallback.call(&termParams); + return BLE_ERROR_NONE; + } + + // check if we can run this discovery + if (isConnectionInUse(connHandle)) { + return BLE_STACK_BUSY; + } + + // get a new discovery slot, if none are available, just return + Discovery* discovery = getAvailableDiscoverySlot(); + if(discovery == NULL) { + return BLE_STACK_BUSY; + } + + // try to launch the discovery + ble_error_t err = gattc_descriptors_discover(connHandle, descriptorStartHandle, descriptorEndHandle); + if(!err) { + // commit the new discovery to its slot + *discovery = Discovery(characteristic, discoveryCallback, terminationCallback); + } + + return err; +} + +bool nRF5xCharacteristicDescriptorDiscoverer::isActive(const DiscoveredCharacteristic& characteristic) const { + return findRunningDiscovery(characteristic) != NULL; +} + +void nRF5xCharacteristicDescriptorDiscoverer::requestTerminate(const DiscoveredCharacteristic& characteristic) { + Discovery* discovery = findRunningDiscovery(characteristic); + if(discovery) { + discovery->onDiscovery = emptyDiscoveryCallback; + // call terminate anyway + discovery->terminate(BLE_ERROR_NONE); + discovery->onTerminate = emptyTerminationCallback; + } +} + +void nRF5xCharacteristicDescriptorDiscoverer::process(uint16_t connectionHandle, const ble_gattc_evt_desc_disc_rsp_t& descriptors) { + Discovery* discovery = findRunningDiscovery(connectionHandle); + if(!discovery) { + error("logic error in nRF5xCharacteristicDescriptorDiscoverer::process !!!"); + } + + for (uint16_t i = 0; i < descriptors.count; ++i) { + discovery->process( + descriptors.descs[i].handle, UUID(descriptors.descs[i].uuid.uuid) + ); + } + + // prepare the next discovery request (if needed) + uint16_t startHandle = descriptors.descs[descriptors.count - 1].handle + 1; + uint16_t endHandle = discovery->characteristic.getLastHandle(); + + if(startHandle > endHandle || + (discovery->onDiscovery == emptyDiscoveryCallback && discovery->onTerminate == emptyTerminationCallback)) { + terminate(connectionHandle, BLE_ERROR_NONE); + return; + } + + ble_error_t err = gattc_descriptors_discover(connectionHandle, startHandle, endHandle); + if(err) { + terminate(connectionHandle, err); + return; + } +} + +void nRF5xCharacteristicDescriptorDiscoverer::terminate(uint16_t handle, ble_error_t err) { + Discovery* discovery = findRunningDiscovery(handle); + if(!discovery) { + error("logic error in nRF5xCharacteristicDescriptorDiscoverer::process !!!"); + } + + Discovery tmp = *discovery; + *discovery = Discovery(); + tmp.terminate(err); +} + +nRF5xCharacteristicDescriptorDiscoverer::Discovery* +nRF5xCharacteristicDescriptorDiscoverer::findRunningDiscovery(const DiscoveredCharacteristic& characteristic) { + for(size_t i = 0; i < maximumConcurrentConnectionsCount; ++i) { + if(discoveryRunning[i].characteristic == characteristic) { + return &discoveryRunning[i]; + } + } + return NULL; +} + +nRF5xCharacteristicDescriptorDiscoverer::Discovery* +nRF5xCharacteristicDescriptorDiscoverer::findRunningDiscovery(const DiscoveredCharacteristic& characteristic) const { + for(size_t i = 0; i < maximumConcurrentConnectionsCount; ++i) { + if(discoveryRunning[i].characteristic == characteristic) { + return &discoveryRunning[i]; + } + } + return NULL; +} + +nRF5xCharacteristicDescriptorDiscoverer::Discovery* +nRF5xCharacteristicDescriptorDiscoverer::findRunningDiscovery(uint16_t handle) { + for(size_t i = 0; i < maximumConcurrentConnectionsCount; ++i) { + if(discoveryRunning[i].characteristic.getConnectionHandle() == handle && + discoveryRunning[i] != Discovery()) { + return &discoveryRunning[i]; + } + } + return NULL; +} + +void nRF5xCharacteristicDescriptorDiscoverer::removeDiscovery(Discovery* discovery) { + for(size_t i = 0; i < maximumConcurrentConnectionsCount; ++i) { + if(&discoveryRunning[i] == discovery) { + discoveryRunning[i] = Discovery(); + } + } +} + +nRF5xCharacteristicDescriptorDiscoverer::Discovery* +nRF5xCharacteristicDescriptorDiscoverer::getAvailableDiscoverySlot() { + for(size_t i = 0; i < maximumConcurrentConnectionsCount; ++i) { + if(discoveryRunning[i] == Discovery()) { + return &discoveryRunning[i]; + } + } + return NULL; +} + +bool nRF5xCharacteristicDescriptorDiscoverer::isConnectionInUse(uint16_t connHandle) { + return findRunningDiscovery(connHandle) != NULL; +} + +ble_error_t nRF5xCharacteristicDescriptorDiscoverer::gattc_descriptors_discover( + uint16_t connection_handle, uint16_t start_handle, uint16_t end_handle) { + + ble_gattc_handle_range_t discoveryRange = { + start_handle, + end_handle + }; + uint32_t err = sd_ble_gattc_descriptors_discover(connection_handle, &discoveryRange); + + switch(err) { + case NRF_SUCCESS: + return BLE_ERROR_NONE; + case BLE_ERROR_INVALID_CONN_HANDLE: + return BLE_ERROR_INVALID_PARAM; + case NRF_ERROR_INVALID_ADDR: + return BLE_ERROR_PARAM_OUT_OF_RANGE; + case NRF_ERROR_BUSY: + return BLE_STACK_BUSY; + default: + return BLE_ERROR_UNSPECIFIED; + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/nRF5xCharacteristicDescriptorDiscoverer.h Mon Jan 11 10:19:19 2016 +0000 @@ -0,0 +1,140 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2015 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_CHARACTERISTIC_DESCRIPTOR_DISCOVERY_H__ +#define __NRF_CHARACTERISTIC_DESCRIPTOR_DISCOVERY_H__ + +#include "ble/Gap.h" +#include "ble/DiscoveredCharacteristic.h" +#include "ble/CharacteristicDescriptorDiscovery.h" +#include "ble/GattClient.h" +#include "ble_gattc.h" + +/** + * @brief Manage the discovery of Characteristic descriptors + * @details is a bridge beetween BLE API and nordic stack regarding Characteristic + * Descriptor discovery. The BLE API can launch, monitorate and ask for termination + * of a discovery. The nordic stack will provide new descriptors and indicate when + * the discovery is done + */ +class nRF5xCharacteristicDescriptorDiscoverer +{ + typedef CharacteristicDescriptorDiscovery::DiscoveryCallback_t DiscoveryCallback_t; + typedef CharacteristicDescriptorDiscovery::TerminationCallback_t TerminationCallback_t; + +public: + nRF5xCharacteristicDescriptorDiscoverer(size_t concurrentConnectionsCount = 3); + + ~nRF5xCharacteristicDescriptorDiscoverer(); + + /** + * Launch a new characteristic descriptor discovery for a given + * DiscoveredCharacteristic. + * @note: this will be called by BLE API side + */ + ble_error_t launch( + const DiscoveredCharacteristic& characteristic, + const DiscoveryCallback_t& callback, + const TerminationCallback_t& terminationCallback + ); + + /** + * @brief indicate if a characteristic descriptor discovery is active for a + * given DiscoveredCharacteristic + * @note: this will be called by BLE API side + */ + bool isActive(const DiscoveredCharacteristic& characteristic) const; + + /** + * @brief reauest the termination of characteristic descriptor discovery + * for a give DiscoveredCharacteristic + * @note: this will be called by BLE API side + */ + void requestTerminate(const DiscoveredCharacteristic& characteristic); + + /** + * @brief process descriptors discovered from the nordic stack + */ + void process(uint16_t handle, const ble_gattc_evt_desc_disc_rsp_t& descriptors); + + /** + * @brief Called by the nordic stack when the discovery is over. + */ + void terminate(uint16_t handle, ble_error_t err); + +private: + nRF5xCharacteristicDescriptorDiscoverer(const nRF5xCharacteristicDescriptorDiscoverer&); + nRF5xCharacteristicDescriptorDiscoverer& operator=(const nRF5xCharacteristicDescriptorDiscoverer&); + + struct Discovery { + Discovery() : characteristic(), onDiscovery(), onTerminate() { } + + Discovery(const DiscoveredCharacteristic& c, const DiscoveryCallback_t& dCb, const TerminationCallback_t& tCb) : + characteristic(c), + onDiscovery(dCb), + onTerminate(tCb) { + } + + DiscoveredCharacteristic characteristic; + DiscoveryCallback_t onDiscovery; + TerminationCallback_t onTerminate; + + void process(GattAttribute::Handle_t handle, const UUID& uuid) { + CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t params = { + characteristic, + DiscoveredCharacteristicDescriptor( + characteristic.getGattClient(), + characteristic.getConnectionHandle(), + handle, + uuid + ) + }; + onDiscovery.call(¶ms); + } + + void terminate(ble_error_t err) { + CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = { + characteristic, + err + }; + onTerminate.call(¶ms); + } + + friend bool operator==(const Discovery& lhs, const Discovery& rhs) { + return lhs.characteristic == rhs.characteristic && + lhs.onDiscovery == rhs.onDiscovery && + lhs.onTerminate == rhs.onTerminate; + } + + friend bool operator!=(const Discovery& lhs, const Discovery& rhs) { + return !(lhs == rhs); + } + }; + + Discovery* findRunningDiscovery(const DiscoveredCharacteristic& characteristic); + Discovery* findRunningDiscovery(const DiscoveredCharacteristic& characteristic) const; + Discovery* findRunningDiscovery(uint16_t handle); + void removeDiscovery(Discovery* discovery); + Discovery* getAvailableDiscoverySlot(); + bool isConnectionInUse(uint16_t connHandle); + static ble_error_t gattc_descriptors_discover(uint16_t connection_handle, uint16_t start_handle, uint16_t end_handle); + + + size_t maximumConcurrentConnectionsCount; + Discovery *discoveryRunning; +}; + +#endif /*__NRF_CHARACTERISTIC_DESCRIPTOR_DISCOVERY_H__*/ \ No newline at end of file
--- a/source/nRF5xDiscoveredCharacteristic.h Mon Jan 11 10:19:18 2016 +0000 +++ b/source/nRF5xDiscoveredCharacteristic.h Mon Jan 11 10:19:19 2016 +0000 @@ -36,6 +36,10 @@ ble_gatt_char_props_t propsIn, GattAttribute::Handle_t declHandleIn, GattAttribute::Handle_t valueHandleIn); + + void setLastHandle(GattAttribute::Handle_t last) { + lastHandle = last; + } }; #endif /* __NRF_DISCOVERED_CHARACTERISTIC_H__ */ \ No newline at end of file
--- a/source/nRF5xGap.cpp Mon Jan 11 10:19:18 2016 +0000 +++ b/source/nRF5xGap.cpp Mon Jan 11 10:19:19 2016 +0000 @@ -367,7 +367,7 @@ @code uint8_t device_address[6] = { 0xca, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0 }; - nrf.getGap().setAddress(Gap::BLEProtocol::AddressType::RANDOM_STATIC, device_address); + nrf.getGap().setAddress(Gap::ADDR_TYPE_RANDOM_STATIC, device_address); @endcode */ @@ -381,12 +381,12 @@ When using Random Private addresses, the cycle mode must be Auto. In auto mode, the given address is ignored. */ - if ((type == BLEProtocol::AddressType::PUBLIC) || (type == BLEProtocol::AddressType::RANDOM_STATIC)) + if ((type == ADDR_TYPE_PUBLIC) || (type == ADDR_TYPE_RANDOM_STATIC)) { cycle_mode = BLE_GAP_ADDR_CYCLE_MODE_NONE; memcpy(dev_addr.addr, address, ADDR_LEN); } - else if ((type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) || (type == BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE)) + else if ((type == ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE) || (type == ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE)) { cycle_mode = BLE_GAP_ADDR_CYCLE_MODE_AUTO; // address is ignored when in auto mode
--- a/source/nRF5xGattClient.cpp Mon Jan 11 10:19:18 2016 +0000 +++ b/source/nRF5xGattClient.cpp Mon Jan 11 10:19:19 2016 +0000 @@ -33,6 +33,27 @@ const UUID &matchingServiceUUIDIn, const UUID &matchingCharacteristicUUIDIn) { - return discovery.launch(connectionHandle, sc, cc, matchingServiceUUIDIn, matchingCharacteristicUUIDIn); + return _discovery.launch(connectionHandle, sc, cc, matchingServiceUUIDIn, matchingCharacteristicUUIDIn); } + +ble_error_t nRF5xGattClient::discoverCharacteristicDescriptors( + const DiscoveredCharacteristic& characteristic, + const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback, + const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback) +{ + return _characteristicDescriptorDiscoverer.launch( + characteristic, + discoveryCallback, + terminationCallback + ); +} + +bool nRF5xGattClient::isCharacteristicDescriptorsDiscoveryActive(const DiscoveredCharacteristic& characteristic) const { + return _characteristicDescriptorDiscoverer.isActive(characteristic); +} + +void nRF5xGattClient::terminateCharacteristicDescriptorsDiscovery(const DiscoveredCharacteristic& characteristic) { + return _characteristicDescriptorDiscoverer.requestTerminate(characteristic); +} + #endif \ No newline at end of file
--- a/source/nRF5xGattClient.h Mon Jan 11 10:19:18 2016 +0000 +++ b/source/nRF5xGattClient.h Mon Jan 11 10:19:19 2016 +0000 @@ -19,6 +19,7 @@ #include "ble/GattClient.h" #include "nRF5xServiceDiscovery.h" +#include "nRF5xCharacteristicDescriptorDiscoverer.h" class nRF5xGattClient : public GattClient { @@ -87,14 +88,14 @@ const UUID &matchingCharacteristicUUIDIn = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)); virtual void onServiceDiscoveryTermination(ServiceDiscovery::TerminationCallback_t callback) { - discovery.onTermination(callback); + _discovery.onTermination(callback); } /** * Is service-discovery currently active? */ virtual bool isServiceDiscoveryActive(void) const { - return discovery.isActive(); + return _discovery.isActive(); } /** @@ -102,9 +103,31 @@ * invocation of the TerminationCallback if service-discovery is active. */ virtual void terminateServiceDiscovery(void) { - discovery.terminate(); + _discovery.terminate(); } + /** + * @brief Implementation of GattClient::discoverCharacteristicDescriptors + * @see GattClient::discoverCharacteristicDescriptors + */ + virtual ble_error_t discoverCharacteristicDescriptors( + const DiscoveredCharacteristic& characteristic, + const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback, + const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback + ); + + /** + * @brief Implementation of GattClient::isCharacteristicDiscoveryActive + * @see GattClient::isCharacteristicDiscoveryActive + */ + virtual bool isCharacteristicDescriptorsDiscoveryActive(const DiscoveredCharacteristic& characteristic) const; + + /** + * @brief Implementation of GattClient::terminateCharacteristicDiscovery + * @see GattClient::terminateCharacteristicDiscovery + */ + virtual void terminateCharacteristicDescriptorsDiscovery(const DiscoveredCharacteristic& characteristic); + 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) { @@ -148,18 +171,25 @@ } public: - nRF5xGattClient() : discovery(this) { + nRF5xGattClient() : _discovery(this) { /* empty */ } - friend void bleGattcEventHandler(const ble_evt_t *p_ble_evt); + nRF5xServiceDiscovery& discovery() { + return _discovery; + } + + nRF5xCharacteristicDescriptorDiscoverer& characteristicDescriptorDiscoverer() { + return _characteristicDescriptorDiscoverer; + } private: nRF5xGattClient(const nRF5xGattClient &); const nRF5xGattClient& operator=(const nRF5xGattClient &); private: - nRF5xServiceDiscovery discovery; + nRF5xServiceDiscovery _discovery; + nRF5xCharacteristicDescriptorDiscoverer _characteristicDescriptorDiscoverer; #endif // if !S110 };
--- a/source/nRF5xServiceDiscovery.cpp Mon Jan 11 10:19:18 2016 +0000 +++ b/source/nRF5xServiceDiscovery.cpp Mon Jan 11 10:19:19 2016 +0000 @@ -27,22 +27,32 @@ .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; - } + uint32_t rc = sd_ble_gattc_characteristics_discover(connectionHandle, &handleRange); + ble_error_t err = BLE_ERROR_NONE; + + switch (rc) { + case NRF_SUCCESS: + err = BLE_ERROR_NONE; + break; + case BLE_ERROR_INVALID_CONN_HANDLE: + case NRF_ERROR_INVALID_ADDR: + err = BLE_ERROR_INVALID_PARAM; + break; + case NRF_ERROR_BUSY: + err = BLE_STACK_BUSY; + break; + case NRF_ERROR_INVALID_STATE: + err = BLE_ERROR_INVALID_STATE; + break; + default: + err = BLE_ERROR_UNSPECIFIED; + break; } - return BLE_ERROR_NONE; + if (err) { + terminateCharacteristicDiscovery(err); + } + return err; } void @@ -78,7 +88,6 @@ 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. */ @@ -114,38 +123,62 @@ void nRF5xServiceDiscovery::progressCharacteristicDiscovery(void) { - /* Iterate through the previously discovered characteristics cached in characteristics[]. */ - while ((state == CHARACTERISTIC_DISCOVERY_ACTIVE) && (characteristicIndex < numCharacteristics)) { + if (state != CHARACTERISTIC_DISCOVERY_ACTIVE) { + return; + } + + if ((discoveredCharacteristic != nRF5xDiscoveredCharacteristic()) && (numCharacteristics > 0)) { + discoveredCharacteristic.setLastHandle(characteristics[0].getDeclHandle() - 1); + if ((matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) || - ((matchingCharacteristicUUID == characteristics[characteristicIndex].getUUID()) && + ((matchingCharacteristicUUID == discoveredCharacteristic.getUUID()) && (matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) { if (characteristicCallback) { - characteristicCallback(&characteristics[characteristicIndex]); + characteristicCallback(&discoveredCharacteristic); } } - - 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. */ + for (uint8_t i = 0; i < numCharacteristics; ++i) { + if (state != CHARACTERISTIC_DISCOVERY_ACTIVE) { + return; + } + + if (i == (numCharacteristics - 1)) { + discoveredCharacteristic = characteristics[i]; + break; + } else { + characteristics[i].setLastHandle(characteristics[i + 1].getDeclHandle() - 1); + } - 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(); + if ((matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) || + ((matchingCharacteristicUUID == characteristics[i].getUUID()) && + (matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) { + if (characteristicCallback) { + characteristicCallback(&characteristics[i]); } - } else { - terminateCharacteristicDiscovery(); } } + + if (state != CHARACTERISTIC_DISCOVERY_ACTIVE) { + return; + } + + Gap::Handle_t startHandle = (numCharacteristics > 0) ? characteristics[numCharacteristics - 1].getValueHandle() + 1 : SRV_DISC_END_HANDLE; + 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(BLE_ERROR_UNSPECIFIED); + } + } else { + terminateCharacteristicDiscovery(BLE_ERROR_NONE); + } } void
--- a/source/nRF5xServiceDiscovery.h Mon Jan 11 10:19:18 2016 +0000 +++ b/source/nRF5xServiceDiscovery.h Mon Jan 11 10:19:19 2016 +0000 @@ -41,7 +41,6 @@ gattc(gattcIn), serviceIndex(0), numServices(0), - characteristicIndex(0), numCharacteristics(0), state(INACTIVE), services(), @@ -95,6 +94,12 @@ terminateServiceDiscovery(); } + void terminate(Gap::Handle_t connectionHandle) { + if(connHandle == connectionHandle) { + terminate(); + } + } + virtual void onTermination(ServiceDiscovery::TerminationCallback_t callback) { onTerminationCallback = callback; } @@ -111,6 +116,8 @@ void removeFirstServiceNeedingUUIDDiscovery(void); void terminateServiceDiscovery(void) { + discoveredCharacteristic = nRF5xDiscoveredCharacteristic(); + bool wasActive = isActive(); state = INACTIVE; @@ -119,8 +126,24 @@ } } - void terminateCharacteristicDiscovery(void) { + void terminateCharacteristicDiscovery(ble_error_t err) { if (state == CHARACTERISTIC_DISCOVERY_ACTIVE) { + if(discoveredCharacteristic != nRF5xDiscoveredCharacteristic()) { + if(err == BLE_ERROR_NONE) { + // fullfill the last characteristic + discoveredCharacteristic.setLastHandle(services[serviceIndex].getEndHandle()); + + if ((matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) || + ((matchingCharacteristicUUID == discoveredCharacteristic.getUUID()) && + (matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) { + if (characteristicCallback) { + characteristicCallback(&discoveredCharacteristic); + } + } + } + discoveredCharacteristic = nRF5xDiscoveredCharacteristic(); + } + state = SERVICE_DISCOVERY_ACTIVE; } serviceIndex++; /* Progress service index to keep discovery alive. */ @@ -134,7 +157,6 @@ void resetDiscoveredCharacteristics(void) { numCharacteristics = 0; - characteristicIndex = 0; } private: @@ -281,7 +303,6 @@ 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 { @@ -300,6 +321,19 @@ CharUUIDDiscoveryQueue charUUIDDiscoveryQueue; TerminationCallback_t onTerminationCallback; + + /* + * The currently discovered characteristic. Discovery of a characteristic + * is a two phase process. + * First, declaration handle is fetched, it provide the UUID, the value handle and + * the properties of a characteristic. + * Second, the next declaration handle is fetched, with its declaration handle, it is + * possible to compute the last handle of the discovered characteristic and fill the + * missing part of the object. + * If there is no remaining characteristic to discover, the last handle of the + * discovered characteristic will be set to the last handle of its enclosing service. + */ + nRF5xDiscoveredCharacteristic discoveredCharacteristic; }; #endif /*__NRF_SERVICE_DISCOVERY_H__*/ \ No newline at end of file