Merge pull request #74 from pan-/characteristicDescriptorDiscovery
Implementation of Characteristic descriptor discovery
This commit is contained in:
commit
05763f7854
|
@ -39,6 +39,10 @@ extern "C" {
|
|||
#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);
|
||||
|
||||
|
@ -184,6 +188,12 @@ static void btle_handler(ble_evt_t *p_ble_evt)
|
|||
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 = ble.getGattClient();
|
||||
gattClient.characteristicDescriptorDiscoverer().terminate(handle, BLE_ERROR_INVALID_STATE);
|
||||
gattClient.discovery().terminate(handle);
|
||||
|
||||
gap.processDisconnectionEvent(handle, reason);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "nRF5xServiceDiscovery.h"
|
||||
#include "nRF5xCharacteristicDescriptorDiscoverer.h"
|
||||
#include "nRF5xGattClient.h"
|
||||
#include "nRF5xn.h"
|
||||
|
||||
#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
|
||||
|
@ -22,7 +25,9 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt)
|
|||
nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE);
|
||||
nRF5xGap &gap = (nRF5xGap &) ble.getGap();
|
||||
nRF5xGattClient &gattClient = (nRF5xGattClient &) ble.getGattClient();
|
||||
nRF5xServiceDiscovery &sdSingleton = gattClient.discovery;
|
||||
nRF5xServiceDiscovery &sdSingleton = gattClient.discovery();
|
||||
nRF5xCharacteristicDescriptorDiscoverer &characteristicDescriptorDiscoverer =
|
||||
gattClient.characteristicDescriptorDiscoverer();
|
||||
|
||||
switch (p_ble_evt->header.evt_id) {
|
||||
case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
|
||||
|
@ -46,7 +51,7 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt)
|
|||
|
||||
case BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND:
|
||||
default:
|
||||
sdSingleton.terminateCharacteristicDiscovery();
|
||||
sdSingleton.terminateCharacteristicDiscovery(BLE_ERROR_NONE);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -93,6 +98,28 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt)
|
|||
gattClient.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();
|
||||
|
|
|
@ -0,0 +1,236 @@
|
|||
/* 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"
|
||||
|
||||
nRF5xCharacteristicDescriptorDiscoverer::nRF5xCharacteristicDescriptorDiscoverer() :
|
||||
discoveryRunning() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
nRF5xCharacteristicDescriptorDiscoverer::~nRF5xCharacteristicDescriptorDiscoverer() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
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 there 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 {
|
||||
for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) {
|
||||
if(discoveryRunning[i].getCharacteristic() == characteristic) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void nRF5xCharacteristicDescriptorDiscoverer::requestTerminate(const DiscoveredCharacteristic& characteristic) {
|
||||
Discovery* discovery = findRunningDiscovery(characteristic);
|
||||
if(discovery) {
|
||||
// call terminate anyway
|
||||
terminate(discovery, BLE_ERROR_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
void nRF5xCharacteristicDescriptorDiscoverer::process(uint16_t connectionHandle, const ble_gattc_evt_desc_disc_rsp_t& descriptors) {
|
||||
Discovery* discovery = findRunningDiscovery(connectionHandle);
|
||||
// the discovery has been removed
|
||||
if(!discovery) {
|
||||
return;
|
||||
}
|
||||
|
||||
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->getCharacteristic().getLastHandle();
|
||||
|
||||
if(startHandle > endHandle) {
|
||||
terminate(discovery, BLE_ERROR_NONE);
|
||||
return;
|
||||
}
|
||||
|
||||
ble_error_t err = gattc_descriptors_discover(connectionHandle, startHandle, endHandle);
|
||||
if(err) {
|
||||
terminate(discovery, err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void nRF5xCharacteristicDescriptorDiscoverer::terminate(uint16_t handle, ble_error_t err) {
|
||||
Discovery* discovery = findRunningDiscovery(handle);
|
||||
// the discovery has already been terminated
|
||||
if(!discovery) {
|
||||
return;
|
||||
}
|
||||
|
||||
terminate(discovery, err);
|
||||
}
|
||||
|
||||
void nRF5xCharacteristicDescriptorDiscoverer::terminate(Discovery* discovery, ble_error_t err) {
|
||||
// temporary copy, user code can try to launch a new discovery in the onTerminate
|
||||
// callback. So, this discovery should not appear in such case.
|
||||
Discovery tmp = *discovery;
|
||||
*discovery = Discovery();
|
||||
tmp.terminate(err);
|
||||
}
|
||||
|
||||
nRF5xCharacteristicDescriptorDiscoverer::Discovery*
|
||||
nRF5xCharacteristicDescriptorDiscoverer::findRunningDiscovery(const DiscoveredCharacteristic& characteristic) {
|
||||
for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) {
|
||||
if((discoveryRunning[i].getCharacteristic() == characteristic) &&
|
||||
(discoveryRunning[i].isEmpty() == false)) {
|
||||
return &discoveryRunning[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nRF5xCharacteristicDescriptorDiscoverer::Discovery*
|
||||
nRF5xCharacteristicDescriptorDiscoverer::findRunningDiscovery(uint16_t handle) {
|
||||
for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) {
|
||||
if((discoveryRunning[i].getCharacteristic().getConnectionHandle() == handle) &&
|
||||
(discoveryRunning[i].isEmpty() == false)) {
|
||||
return &discoveryRunning[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nRF5xCharacteristicDescriptorDiscoverer::Discovery*
|
||||
nRF5xCharacteristicDescriptorDiscoverer::getAvailableDiscoverySlot() {
|
||||
for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) {
|
||||
if(discoveryRunning[i].isEmpty()) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// implementation of nRF5xCharacteristicDescriptorDiscoverer::Discovery
|
||||
|
||||
nRF5xCharacteristicDescriptorDiscoverer::Discovery::Discovery() :
|
||||
characteristic(), onDiscovery(), onTerminate() {
|
||||
}
|
||||
|
||||
nRF5xCharacteristicDescriptorDiscoverer::Discovery::Discovery(
|
||||
const DiscoveredCharacteristic& c, const DiscoveryCallback_t& dCb, const TerminationCallback_t& tCb) :
|
||||
characteristic(c), onDiscovery(dCb), onTerminate(tCb) {
|
||||
}
|
||||
|
||||
void nRF5xCharacteristicDescriptorDiscoverer::Discovery::process(
|
||||
GattAttribute::Handle_t handle, const UUID& uuid) {
|
||||
CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t params = {
|
||||
characteristic,
|
||||
DiscoveredCharacteristicDescriptor(
|
||||
characteristic.getGattClient(),
|
||||
characteristic.getConnectionHandle(),
|
||||
handle,
|
||||
uuid
|
||||
)
|
||||
};
|
||||
onDiscovery.call(¶ms);
|
||||
}
|
||||
|
||||
void nRF5xCharacteristicDescriptorDiscoverer::Discovery::terminate(ble_error_t err) {
|
||||
CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = {
|
||||
characteristic,
|
||||
err
|
||||
};
|
||||
|
||||
onTerminate.call(¶ms);
|
||||
}
|
||||
|
||||
bool nRF5xCharacteristicDescriptorDiscoverer::Discovery::isEmpty() const {
|
||||
return *this == Discovery();
|
||||
}
|
||||
|
||||
const DiscoveredCharacteristic& nRF5xCharacteristicDescriptorDiscoverer::Discovery::getCharacteristic() const {
|
||||
return characteristic;
|
||||
}
|
|
@ -0,0 +1,214 @@
|
|||
/* 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 between BLE API and Nordic stack regarding Characteristic
|
||||
* Descriptor discovery. The BLE API can launch, monitor 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:
|
||||
/**
|
||||
* @brief Construct a new characteristic descriptor discoverer.
|
||||
*/
|
||||
nRF5xCharacteristicDescriptorDiscoverer();
|
||||
|
||||
/**
|
||||
* @brief Destroy a characteristic descriptor discoverer.
|
||||
*/
|
||||
~nRF5xCharacteristicDescriptorDiscoverer();
|
||||
|
||||
/**
|
||||
* Launch a new characteristic descriptor discovery for a given DiscoveredCharacteristic.
|
||||
* @param characteristic The characteristic owning the descriptors to discover.
|
||||
* @param discoveryCallback The callback called when a descriptor is discovered.
|
||||
* @param terminationCallback The callback called when the discovery process end.
|
||||
* @return BLE_ERROR_NONE if characteristic descriptor discovery is launched successfully;
|
||||
* else an appropriate error.
|
||||
* @note: this will be called by BLE API side.
|
||||
*/
|
||||
ble_error_t launch(
|
||||
const DiscoveredCharacteristic& characteristic,
|
||||
const DiscoveryCallback_t& discoveryCallback,
|
||||
const TerminationCallback_t& terminationCallback
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief indicate if a characteristic descriptor discovery is active for a
|
||||
* given DiscoveredCharacteristic.
|
||||
* @param characteristic The characteristic for whom the descriptor might be
|
||||
* currently discovered.
|
||||
* @return true if descriptors of characteristic are discovered, false otherwise.
|
||||
* @note: this will be called by BLE API side.
|
||||
*/
|
||||
bool isActive(const DiscoveredCharacteristic& characteristic) const;
|
||||
|
||||
/**
|
||||
* @brief request the termination of characteristic descriptor discovery
|
||||
* for a give DiscoveredCharacteristic
|
||||
* @param characteristic The characteristic for whom the descriptor discovery
|
||||
* should be stopped.
|
||||
* @note: this will be called by BLE API side.
|
||||
*/
|
||||
void requestTerminate(const DiscoveredCharacteristic& characteristic);
|
||||
|
||||
/**
|
||||
* @brief process descriptors discovered from the Nordic stack.
|
||||
* @param connectionHandle The connection handle upon which descriptors has been
|
||||
* discovered.
|
||||
* @param descriptors Discovered descriptors.
|
||||
* @note This will be called by the Nordic stack.
|
||||
*/
|
||||
void process(uint16_t connectionHandle, const ble_gattc_evt_desc_disc_rsp_t& descriptors);
|
||||
|
||||
/**
|
||||
* @brief Called by the Nordic stack when the discovery is over.
|
||||
* @param The connection handle upon which the discovery process is done.
|
||||
* @param err An error if the termination is due to an error.
|
||||
*/
|
||||
void terminate(uint16_t connectionHandle, ble_error_t err);
|
||||
|
||||
private:
|
||||
// protection against copy construction and assignment
|
||||
nRF5xCharacteristicDescriptorDiscoverer(const nRF5xCharacteristicDescriptorDiscoverer&);
|
||||
nRF5xCharacteristicDescriptorDiscoverer& operator=(const nRF5xCharacteristicDescriptorDiscoverer&);
|
||||
|
||||
/**
|
||||
* @brief Discovery process, it store the DiscoveredCharacteristic, the
|
||||
* discovery callback and the termination callback.
|
||||
*/
|
||||
class Discovery {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct an empty discovery, such can be considerate as a not running discovery.
|
||||
* @note #isEmpty function will return true
|
||||
*/
|
||||
Discovery();
|
||||
|
||||
/**
|
||||
* @brief Construct a valid discovery process.
|
||||
*
|
||||
* @param c the characteristic from whom descriptors will be discovered.
|
||||
* @param dCb The discovery callback called each time a descriptor is discovered.
|
||||
* @param tCb The termination callback called when the discovery terminate.
|
||||
*
|
||||
* @note #isEmpty function will return false
|
||||
*/
|
||||
Discovery(const DiscoveredCharacteristic& c, const DiscoveryCallback_t& dCb, const TerminationCallback_t& tCb);
|
||||
|
||||
/**
|
||||
* @brief Process the discovery of a descriptor.
|
||||
*
|
||||
* @param handle The attribute handle of the descriptor found
|
||||
* @param uuid The UUID of the descriptor found.
|
||||
*/
|
||||
void process(GattAttribute::Handle_t handle, const UUID& uuid);
|
||||
|
||||
/**
|
||||
* @brief Terminate the discovery process.
|
||||
*
|
||||
* @param err Error associate with the termination
|
||||
* @note after this call #isEmpty function will return true.
|
||||
*/
|
||||
void terminate(ble_error_t err);
|
||||
|
||||
/**
|
||||
* @brief check if the discovery process is empty or not. Empty discovery are
|
||||
* not running.
|
||||
*
|
||||
* @detail Discovery are empty after:
|
||||
* - a default construction
|
||||
* - a copy construction form a default constructed
|
||||
* - an assignment from a default constructed Discovery
|
||||
* @return true if the Discovery is empty and false otherwise.
|
||||
*/
|
||||
bool isEmpty() const;
|
||||
|
||||
/**
|
||||
* @brief return the characteristic from whom descriptors are discovered.
|
||||
* @return the characteristic from whom descriptors are discovered.
|
||||
*/
|
||||
const DiscoveredCharacteristic& getCharacteristic() const;
|
||||
|
||||
/**
|
||||
* @brief equal to operator, test if two discovery process are equal
|
||||
*
|
||||
* @param lhs left hand side of the expression
|
||||
* @param rhs right hand side of the expression
|
||||
* @return true if lhs == rhs
|
||||
*/
|
||||
friend bool operator==(const Discovery& lhs, const Discovery& rhs) {
|
||||
return lhs.characteristic == rhs.characteristic &&
|
||||
lhs.onDiscovery == rhs.onDiscovery &&
|
||||
lhs.onTerminate == rhs.onTerminate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief not equal to operator, test if two discovery process are not equal
|
||||
*
|
||||
* @param lhs left hand side of the expression
|
||||
* @param rhs right hand side of the expression
|
||||
* @return true if lhs != rhs
|
||||
*/
|
||||
friend bool operator!=(const Discovery& lhs, const Discovery& rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
private:
|
||||
DiscoveredCharacteristic characteristic;
|
||||
DiscoveryCallback_t onDiscovery;
|
||||
TerminationCallback_t onTerminate;
|
||||
};
|
||||
|
||||
// find a running discovery process
|
||||
Discovery* findRunningDiscovery(const DiscoveredCharacteristic& characteristic);
|
||||
Discovery* findRunningDiscovery(uint16_t handle);
|
||||
|
||||
// Called to terminate a discovery is over.
|
||||
void terminate(Discovery* discovery, ble_error_t err);
|
||||
|
||||
// get one slot for a discovery process
|
||||
Discovery* getAvailableDiscoverySlot();
|
||||
|
||||
// indicate if a connection is already running a discovery
|
||||
bool isConnectionInUse(uint16_t connHandle);
|
||||
|
||||
// low level start of a discovery
|
||||
static ble_error_t gattc_descriptors_discover(uint16_t connection_handle, uint16_t start_handle, uint16_t end_handle);
|
||||
|
||||
// count of concurrent connections which can run a descriptor discovery process
|
||||
static const size_t MAXIMUM_CONCURRENT_CONNECTIONS_COUNT = 3;
|
||||
|
||||
// array of running discoveries
|
||||
Discovery discoveryRunning[MAXIMUM_CONCURRENT_CONNECTIONS_COUNT];
|
||||
};
|
||||
|
||||
#endif /*__NRF_CHARACTERISTIC_DESCRIPTOR_DISCOVERY_H__*/
|
|
@ -36,6 +36,10 @@ public:
|
|||
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__ */
|
||||
|
|
|
@ -24,6 +24,27 @@ nRF5xGattClient::launchServiceDiscovery(Gap::Handle_t
|
|||
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
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "ble/GattClient.h"
|
||||
#include "nRF5xServiceDiscovery.h"
|
||||
#include "nRF5xCharacteristicDescriptorDiscoverer.h"
|
||||
|
||||
class nRF5xGattClient : public GattClient
|
||||
{
|
||||
|
@ -85,14 +86,14 @@ public:
|
|||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -100,9 +101,31 @@ public:
|
|||
* 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) {
|
||||
|
@ -158,7 +181,7 @@ public:
|
|||
}
|
||||
|
||||
/* Clear derived class members */
|
||||
discovery.reset();
|
||||
_discovery.reset();
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
@ -169,18 +192,25 @@ public:
|
|||
*/
|
||||
friend class nRF5xn;
|
||||
|
||||
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
|
||||
};
|
||||
|
|
|
@ -27,22 +27,32 @@ nRF5xServiceDiscovery::launchCharacteristicDiscovery(Gap::Handle_t connectionHan
|
|||
.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 @@ nRF5xServiceDiscovery::setupDiscoveredServices(const ble_gattc_evt_prim_srvc_dis
|
|||
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 @@ nRF5xServiceDiscovery::setupDiscoveredCharacteristics(const ble_gattc_evt_char_d
|
|||
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].getUUID()) &&
|
||||
(matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) {
|
||||
if (characteristicCallback) {
|
||||
characteristicCallback(&characteristics[characteristicIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
characteristicIndex++;
|
||||
if (state != CHARACTERISTIC_DISCOVERY_ACTIVE) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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 ((discoveredCharacteristic != nRF5xDiscoveredCharacteristic()) && (numCharacteristics > 0)) {
|
||||
discoveredCharacteristic.setLastHandle(characteristics[0].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 == discoveredCharacteristic.getUUID()) &&
|
||||
(matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) {
|
||||
if (characteristicCallback) {
|
||||
characteristicCallback(&discoveredCharacteristic);
|
||||
}
|
||||
} else {
|
||||
terminateCharacteristicDiscovery();
|
||||
}
|
||||
}
|
||||
|
||||
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 ((matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) ||
|
||||
((matchingCharacteristicUUID == characteristics[i].getUUID()) &&
|
||||
(matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) {
|
||||
if (characteristicCallback) {
|
||||
characteristicCallback(&characteristics[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -41,7 +41,6 @@ public:
|
|||
gattc(gattcIn),
|
||||
serviceIndex(0),
|
||||
numServices(0),
|
||||
characteristicIndex(0),
|
||||
numCharacteristics(0),
|
||||
state(INACTIVE),
|
||||
services(),
|
||||
|
@ -95,6 +94,12 @@ public:
|
|||
terminateServiceDiscovery();
|
||||
}
|
||||
|
||||
void terminate(Gap::Handle_t connectionHandle) {
|
||||
if(connHandle == connectionHandle) {
|
||||
terminate();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void onTermination(ServiceDiscovery::TerminationCallback_t callback) {
|
||||
onTerminationCallback = callback;
|
||||
}
|
||||
|
@ -114,7 +119,6 @@ public:
|
|||
/* Clear derived class members */
|
||||
serviceIndex = 0;
|
||||
numServices = 0;
|
||||
characteristicIndex = 0;
|
||||
numCharacteristics = 0;
|
||||
|
||||
state = INACTIVE;
|
||||
|
@ -139,6 +143,8 @@ private:
|
|||
void removeFirstServiceNeedingUUIDDiscovery(void);
|
||||
|
||||
void terminateServiceDiscovery(void) {
|
||||
discoveredCharacteristic = nRF5xDiscoveredCharacteristic();
|
||||
|
||||
bool wasActive = isActive();
|
||||
state = INACTIVE;
|
||||
|
||||
|
@ -147,8 +153,24 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
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. */
|
||||
|
@ -162,7 +184,6 @@ private:
|
|||
|
||||
void resetDiscoveredCharacteristics(void) {
|
||||
numCharacteristics = 0;
|
||||
characteristicIndex = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -309,7 +330,6 @@ private:
|
|||
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 {
|
||||
|
@ -328,6 +348,19 @@ private:
|
|||
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__*/
|
||||
|
|
|
@ -77,7 +77,7 @@ public:
|
|||
*
|
||||
* @return A reference to GattClient.
|
||||
*/
|
||||
virtual GattClient &getGattClient() {
|
||||
virtual nRF5xGattClient &getGattClient() {
|
||||
if (gattClientInstance == NULL) {
|
||||
gattClientInstance = new nRF5xGattClient();
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ public:
|
|||
*
|
||||
* @return A reference to GattServer.
|
||||
*/
|
||||
virtual SecurityManager &getSecurityManager() {
|
||||
virtual nRF5xSecurityManager &getSecurityManager() {
|
||||
if (securityManagerInstance == NULL) {
|
||||
securityManagerInstance = new nRF5xSecurityManager();
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ public:
|
|||
* @note The accessor is able to modify the object's state because the
|
||||
* internal pointer has been declared mutable.
|
||||
*/
|
||||
virtual const Gap &getGap() const {
|
||||
virtual const nRF5xGap &getGap() const {
|
||||
return gapInstance;
|
||||
};
|
||||
|
||||
|
@ -126,7 +126,7 @@ public:
|
|||
* @note The accessor is able to modify the object's state because the
|
||||
* internal pointer has been declared mutable.
|
||||
*/
|
||||
virtual const GattServer &getGattServer() const {
|
||||
virtual const nRF5xGattServer &getGattServer() const {
|
||||
if (gattServerInstance == NULL) {
|
||||
gattServerInstance = new nRF5xGattServer();
|
||||
}
|
||||
|
@ -143,7 +143,7 @@ public:
|
|||
* @note The accessor is able to modify the object's state because the
|
||||
* internal pointer has been declared mutable.
|
||||
*/
|
||||
virtual const SecurityManager &getSecurityManager() const {
|
||||
virtual const nRF5xSecurityManager &getSecurityManager() const {
|
||||
if (securityManagerInstance == NULL) {
|
||||
securityManagerInstance = new nRF5xSecurityManager();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue