parent
59ced0b4b1
commit
c8d826ffd0
|
@ -13,42 +13,36 @@
|
|||
* 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() :
|
||||
discoveryRunning() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
nRF5xCharacteristicDescriptorDiscoverer::nRF5xCharacteristicDescriptorDiscoverer(size_t concurrentConnectionsCount) :
|
||||
maximumConcurrentConnectionsCount(concurrentConnectionsCount),
|
||||
discoveryRunning(new Discovery[concurrentConnectionsCount]) {
|
||||
|
||||
}
|
||||
|
||||
nRF5xCharacteristicDescriptorDiscoverer::~nRF5xCharacteristicDescriptorDiscoverer() {
|
||||
delete [] discoveryRunning;
|
||||
nRF5xCharacteristicDescriptorDiscoverer::~nRF5xCharacteristicDescriptorDiscoverer() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
ble_error_t nRF5xCharacteristicDescriptorDiscoverer::launch(
|
||||
const DiscoveredCharacteristic& characteristic,
|
||||
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
|
||||
// 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 = {
|
||||
// check if there is any descriptor to discover
|
||||
if (descriptorEndHandle < descriptorStartHandle) {
|
||||
CharacteristicDescriptorDiscovery::TerminationCallbackParams_t termParams = {
|
||||
characteristic,
|
||||
BLE_ERROR_NONE
|
||||
};
|
||||
|
@ -57,19 +51,19 @@ ble_error_t nRF5xCharacteristicDescriptorDiscoverer::launch(
|
|||
}
|
||||
|
||||
// check if we can run this discovery
|
||||
if (isConnectionInUse(connHandle)) {
|
||||
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;
|
||||
return BLE_STACK_BUSY;
|
||||
}
|
||||
|
||||
// try to launch the discovery
|
||||
// try to launch the discovery
|
||||
ble_error_t err = gattc_descriptors_discover(connHandle, descriptorStartHandle, descriptorEndHandle);
|
||||
if(!err) {
|
||||
if(!err) {
|
||||
// commit the new discovery to its slot
|
||||
*discovery = Discovery(characteristic, discoveryCallback, terminationCallback);
|
||||
}
|
||||
|
@ -78,23 +72,27 @@ ble_error_t nRF5xCharacteristicDescriptorDiscoverer::launch(
|
|||
}
|
||||
|
||||
bool nRF5xCharacteristicDescriptorDiscoverer::isActive(const DiscoveredCharacteristic& characteristic) const {
|
||||
return findRunningDiscovery(characteristic) != NULL;
|
||||
for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) {
|
||||
if(discoveryRunning[i].characteristic == characteristic) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void nRF5xCharacteristicDescriptorDiscoverer::requestTerminate(const DiscoveredCharacteristic& characteristic) {
|
||||
Discovery* discovery = findRunningDiscovery(characteristic);
|
||||
if(discovery) {
|
||||
discovery->onDiscovery = emptyDiscoveryCallback;
|
||||
if(discovery) {
|
||||
// call terminate anyway
|
||||
discovery->terminate(BLE_ERROR_NONE);
|
||||
discovery->onTerminate = emptyTerminationCallback;
|
||||
terminate(discovery, BLE_ERROR_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
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 !!!");
|
||||
// the discovery has been removed
|
||||
if(!discovery) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint16_t i = 0; i < descriptors.count; ++i) {
|
||||
|
@ -107,76 +105,67 @@ void nRF5xCharacteristicDescriptorDiscoverer::process(uint16_t connectionHandle,
|
|||
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);
|
||||
if(startHandle > endHandle) {
|
||||
terminate(discovery, BLE_ERROR_NONE);
|
||||
return;
|
||||
}
|
||||
|
||||
ble_error_t err = gattc_descriptors_discover(connectionHandle, startHandle, endHandle);
|
||||
if(err) {
|
||||
terminate(connectionHandle, err);
|
||||
if(err) {
|
||||
terminate(discovery, err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void nRF5xCharacteristicDescriptorDiscoverer::terminate(uint16_t handle, ble_error_t err) {
|
||||
Discovery* discovery = findRunningDiscovery(handle);
|
||||
if(!discovery) {
|
||||
error("logic error in nRF5xCharacteristicDescriptorDiscoverer::process !!!");
|
||||
// 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::Discovery*
|
||||
nRF5xCharacteristicDescriptorDiscoverer::findRunningDiscovery(const DiscoveredCharacteristic& characteristic) {
|
||||
for(size_t i = 0; i < maximumConcurrentConnectionsCount; ++i) {
|
||||
if(discoveryRunning[i].characteristic == characteristic) {
|
||||
for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) {
|
||||
if(discoveryRunning[i].characteristic == characteristic && discoveryRunning[i].isEmpty() == false) {
|
||||
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::Discovery*
|
||||
nRF5xCharacteristicDescriptorDiscoverer::findRunningDiscovery(uint16_t handle) {
|
||||
for(size_t i = 0; i < maximumConcurrentConnectionsCount; ++i) {
|
||||
if(discoveryRunning[i].characteristic.getConnectionHandle() == handle &&
|
||||
discoveryRunning[i] != Discovery()) {
|
||||
for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) {
|
||||
if(discoveryRunning[i].characteristic.getConnectionHandle() == handle &&
|
||||
discoveryRunning[i].isEmpty() == false) {
|
||||
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::Discovery*
|
||||
nRF5xCharacteristicDescriptorDiscoverer::getAvailableDiscoverySlot() {
|
||||
for(size_t i = 0; i < maximumConcurrentConnectionsCount; ++i) {
|
||||
if(discoveryRunning[i] == Discovery()) {
|
||||
for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) {
|
||||
if(discoveryRunning[i].isEmpty()) {
|
||||
return &discoveryRunning[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -185,7 +174,7 @@ bool nRF5xCharacteristicDescriptorDiscoverer::isConnectionInUse(uint16_t connHan
|
|||
}
|
||||
|
||||
ble_error_t nRF5xCharacteristicDescriptorDiscoverer::gattc_descriptors_discover(
|
||||
uint16_t connection_handle, uint16_t start_handle, uint16_t end_handle) {
|
||||
uint16_t connection_handle, uint16_t start_handle, uint16_t end_handle) {
|
||||
|
||||
ble_gattc_handle_range_t discoveryRange = {
|
||||
start_handle,
|
||||
|
@ -193,9 +182,9 @@ ble_error_t nRF5xCharacteristicDescriptorDiscoverer::gattc_descriptors_discover(
|
|||
};
|
||||
uint32_t err = sd_ble_gattc_descriptors_discover(connection_handle, &discoveryRange);
|
||||
|
||||
switch(err) {
|
||||
switch(err) {
|
||||
case NRF_SUCCESS:
|
||||
return BLE_ERROR_NONE;
|
||||
return BLE_ERROR_NONE;
|
||||
case BLE_ERROR_INVALID_CONN_HANDLE:
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
case NRF_ERROR_INVALID_ADDR:
|
||||
|
|
|
@ -24,11 +24,11 @@
|
|||
#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
|
||||
* @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
|
||||
{
|
||||
|
@ -36,64 +36,109 @@ class nRF5xCharacteristicDescriptorDiscoverer
|
|||
typedef CharacteristicDescriptorDiscovery::TerminationCallback_t TerminationCallback_t;
|
||||
|
||||
public:
|
||||
nRF5xCharacteristicDescriptorDiscoverer(size_t concurrentConnectionsCount = 3);
|
||||
/**
|
||||
* @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.
|
||||
* @note: this will be called by BLE API side
|
||||
* 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& callback,
|
||||
const DiscoveredCharacteristic& characteristic,
|
||||
const DiscoveryCallback_t& discoveryCallback,
|
||||
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
|
||||
* @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 reauest the termination of characteristic descriptor discovery
|
||||
* @brief request the termination of characteristic descriptor discovery
|
||||
* for a give DiscoveredCharacteristic
|
||||
* @note: this will be called by BLE API side
|
||||
* @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
|
||||
* @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 handle, const ble_gattc_evt_desc_disc_rsp_t& descriptors);
|
||||
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.
|
||||
* @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 handle, ble_error_t err);
|
||||
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.
|
||||
*/
|
||||
struct Discovery {
|
||||
/**
|
||||
* @brief Construct an empty discovery, such can be considerate as a not running discovery.
|
||||
* @note #isEmpty function will return true
|
||||
*/
|
||||
Discovery() : characteristic(), onDiscovery(), onTerminate() { }
|
||||
|
||||
Discovery(const DiscoveredCharacteristic& c, const DiscoveryCallback_t& dCb, const TerminationCallback_t& tCb) :
|
||||
characteristic(c),
|
||||
onDiscovery(dCb),
|
||||
onTerminate(tCb) {
|
||||
/**
|
||||
* @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) :
|
||||
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 = {
|
||||
/**
|
||||
* @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) {
|
||||
CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t params = {
|
||||
characteristic,
|
||||
DiscoveredCharacteristicDescriptor(
|
||||
characteristic.getGattClient(),
|
||||
|
@ -105,36 +150,79 @@ private:
|
|||
onDiscovery.call(¶ms);
|
||||
}
|
||||
|
||||
void terminate(ble_error_t err) {
|
||||
/**
|
||||
* @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) {
|
||||
CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = {
|
||||
characteristic,
|
||||
err
|
||||
};
|
||||
|
||||
onTerminate.call(¶ms);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 {
|
||||
return *this == Discovery();
|
||||
}
|
||||
|
||||
/**
|
||||
* @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);
|
||||
}
|
||||
};
|
||||
|
||||
// find a running discovery process
|
||||
Discovery* findRunningDiscovery(const DiscoveredCharacteristic& characteristic);
|
||||
Discovery* findRunningDiscovery(const DiscoveredCharacteristic& characteristic) const;
|
||||
Discovery* findRunningDiscovery(uint16_t handle);
|
||||
void removeDiscovery(Discovery* discovery);
|
||||
Discovery* getAvailableDiscoverySlot();
|
||||
|
||||
// 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);
|
||||
static ble_error_t gattc_descriptors_discover(uint16_t connection_handle, uint16_t start_handle, uint16_t end_handle);
|
||||
|
||||
// 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);
|
||||
|
||||
size_t maximumConcurrentConnectionsCount;
|
||||
Discovery *discoveryRunning;
|
||||
// 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__*/
|
||||
|
|
Loading…
Reference in New Issue