Add Characteristic Descriptor Discovery implementation
This commit is contained in:
parent
1b42c27110
commit
e15d59a758
6 changed files with 364 additions and 0 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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(¶ms);
|
||||
}
|
||||
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();
|
||||
|
|
168
source/nRF5xCharacteristicDescriptorDiscoverer.cpp
Normal file
168
source/nRF5xCharacteristicDescriptorDiscoverer.cpp
Normal 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;
|
||||
}
|
133
source/nRF5xCharacteristicDescriptorDiscoverer.h
Normal file
133
source/nRF5xCharacteristicDescriptorDiscoverer.h
Normal 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(¶ms);
|
||||
}
|
||||
|
||||
void terminate() {
|
||||
CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = {
|
||||
characteristic
|
||||
};
|
||||
onTerminate.call(¶ms);
|
||||
}
|
||||
|
||||
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__*/
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue