Add Characteristic Descriptor Discovery implementation

This commit is contained in:
Vincent Coubard 2015-11-13 14:53:46 +00:00
parent 1b42c27110
commit e15d59a758
6 changed files with 364 additions and 0 deletions

View file

@ -183,6 +183,7 @@ static void btle_handler(ble_evt_t *p_ble_evt)
break;
}
nRF5xGap::getInstance().processDisconnectionEvent(handle, reason);
// TODO: close pending discoveries
break;
}

View file

@ -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;
nRF5xCharacteristicDescriptorDiscoverer &characteristicDescriptorDiscoverer =
nRF5xGattClient::getInstance().characteristicDescriptorDiscoverer;
switch (p_ble_evt->header.evt_id) {
case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
@ -91,6 +94,20 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt)
nRF5xGattClient::getInstance().processHVXEvent(&params);
}
break;
case BLE_GATTC_EVT_DESC_DISC_RSP: {
uint16_t conn_handle = p_ble_evt->evt.gattc_evt.conn_handle;
if (p_ble_evt->evt.gattc_evt.gatt_status != BLE_GATT_STATUS_SUCCESS) {
characteristicDescriptorDiscoverer.terminate(conn_handle);
return;
}
characteristicDescriptorDiscoverer.process(
conn_handle,
/* discoveredDescriptors */ p_ble_evt->evt.gattc_evt.params.desc_disc_rsp
);
} break;
}
sdSingleton.progressCharacteristicDiscovery();

View file

@ -0,0 +1,168 @@
#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
};
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_gattc_handle_range_t discoveryRange = {
descriptorStartHandle,
descriptorEndHandle
};
uint32_t err = sd_ble_gattc_descriptors_discover(characteristic.getConnectionHandle(), &discoveryRange);
switch(err) {
case NRF_SUCCESS:
// commit the new discovery to its slot
*discovery = Discovery(
characteristic,
discoveryCallback,
terminationCallback
);
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;
}
}
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();
discovery->onTerminate = emptyTerminationCallback;
}
}
void nRF5xCharacteristicDescriptorDiscoverer::process(uint16_t handle, const ble_gattc_evt_desc_disc_rsp_t& descriptors) {
Discovery* discovery = findRunningDiscovery(handle);
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)
);
}
}
void nRF5xCharacteristicDescriptorDiscoverer::terminate(uint16_t handle) {
Discovery* discovery = findRunningDiscovery(handle);
if(!discovery) {
error("logic error in nRF5xCharacteristicDescriptorDiscoverer::process !!!");
}
discovery->terminate();
removeDiscovery(discovery);
}
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) {
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;
}

View file

@ -0,0 +1,133 @@
/* 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);
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(&params);
}
void terminate() {
CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = {
characteristic
};
onTerminate.call(&params);
}
friend bool operator==(const Discovery& lhs, const Discovery& rhs) {
return lhs.characteristic == rhs.characteristic &&
lhs.onDiscovery == rhs.onDiscovery &&
lhs.onTerminate == lhs.onTerminate;
}
};
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);
size_t maximumConcurrentConnectionsCount;
Discovery *discoveryRunning;
};
#endif /*__NRF_CHARACTERISTIC_DESCRIPTOR_DISCOVERY_H__*/

View file

@ -35,4 +35,25 @@ nRF5xGattClient::launchServiceDiscovery(Gap::Handle_t
{
return discovery.launch(connectionHandle, sc, cc, matchingServiceUUIDIn, matchingCharacteristicUUIDIn);
}
ble_error_t nRF5xGattClient::discoverCharacteristicDescriptors(
const DiscoveredCharacteristic& characteristic,
CharacteristicDescriptorDiscovery::DiscoveryCallback_t discoveryCallback,
CharacteristicDescriptorDiscovery::TerminationCallback_t terminationCallback)
{
return characteristicDescriptorDiscoverer.launch(
characteristic,
discoveryCallback,
terminationCallback
);
}
bool nRF5xGattClient::isCharacteristicDiscoveryActive(const DiscoveredCharacteristic& characteristic) const {
return characteristicDescriptorDiscoverer.isActive(characteristic);
}
void nRF5xGattClient::terminateCharacteristicDiscovery(const DiscoveredCharacteristic& characteristic) {
return characteristicDescriptorDiscoverer.requestTerminate(characteristic);
}
#endif

View file

@ -19,6 +19,7 @@
#include "ble/GattClient.h"
#include "nRF5xServiceDiscovery.h"
#include "nRF5xCharacteristicDescriptorDiscoverer.h"
class nRF5xGattClient : public GattClient
{
@ -105,6 +106,28 @@ public:
discovery.terminate();
}
/**
* @brief Implementation of GattClient::discoverCharacteristicDescriptors
* @see GattClient::discoverCharacteristicDescriptors
*/
virtual ble_error_t discoverCharacteristicDescriptors(
const DiscoveredCharacteristic& characteristic,
CharacteristicDescriptorDiscovery::DiscoveryCallback_t discoveryCallback,
CharacteristicDescriptorDiscovery::TerminationCallback_t terminationCallback
);
/**
* @brief Implementation of GattClient::isCharacteristicDiscoveryActive
* @see GattClient::isCharacteristicDiscoveryActive
*/
virtual bool isCharacteristicDiscoveryActive(const DiscoveredCharacteristic& characteristic) const;
/**
* @brief Implementation of GattClient::terminateCharacteristicDiscovery
* @see GattClient::terminateCharacteristicDiscovery
*/
virtual void terminateCharacteristicDiscovery(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) {
@ -160,6 +183,7 @@ private:
private:
nRF5xServiceDiscovery discovery;
nRF5xCharacteristicDescriptorDiscoverer characteristicDescriptorDiscoverer;
#endif // if !S110
};