Improve Characteristic descriptor discovery:

- all member of
  CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t are now
  const by default
- CharacteristicDescriptorDiscovery::TerminationCallbackParams_t now
  accept a status parameter which indicate if the operation ends properly
  or not
- Remove DiscoveredCharacteristicDescriptor declaration from
  DiscoveredCharacteristic.h file
- Add comparison operation to DiscoveredCharacteristic::Properties_t type
- Add lastHandle member to DiscoveredCharacteristic
- Add equality operator to DiscoveredCharacteristic
- make FunctionPointerWithContext call operation const, so that it mirror
  std::function and allow to call this kind of objects to be called when
  they are passed by const reference
- Add primitive operations to GattClient for dicovering characteristic
  descriptors
- Fullfil DiscoveredCharacteristic::discoverDescriptors function
  implementation
This commit is contained in:
Vincent Coubard 2015-11-17 10:15:17 +00:00
parent c9261773ac
commit 62a1c4a9cc
5 changed files with 130 additions and 40 deletions

View File

@ -28,24 +28,25 @@ public:
* Exposed application callback types.
*/
struct DiscoveryCallbackParams_t {
DiscoveredCharacteristic& characteristic;
DiscoveredCharacteristicDescriptor& descriptor;
const DiscoveredCharacteristic& characteristic;
const DiscoveredCharacteristicDescriptor& descriptor;
};
struct TerminationCallbackParams_t {
DiscoveredCharacteristic& characteristic;
const DiscoveredCharacteristic& characteristic;
ble_error_t status;
};
/**
* Callback type for when a matching characteristic descriptor is found during
* characteristic descriptor discovery. The receiving function is passed in a
* pointer to a DiscoveredCharacteristicDescriptor object which will remain
* pointer to a DiscoveryCallbackParams_t object which will remain
* valid for the lifetime of the callback. Memory for this object is owned by
* the BLE_API eventing framework. The application can safely make a persistent
* shallow-copy of this object in order to work with the service beyond the
* callback.
*/
typedef FunctionPointerWithContext<const DiscoveredCharacteristicDescriptor*> DiscoveryCallback_t;
typedef FunctionPointerWithContext<const DiscoveryCallbackParams_t*> DiscoveryCallback_t;
/**
* Callback type for when characteristic descriptor discovery terminates.

View File

@ -21,6 +21,9 @@
#include "Gap.h"
#include "GattAttribute.h"
#include "GattClient.h"
#include "CharacteristicDescriptorDiscovery.h"
#include "ble/DiscoveredCharacteristicDescriptor.h"
/**
* Structure for holding information about the service and the characteristics
@ -46,30 +49,21 @@ public:
bool indicate(void) const {return _indicate; }
bool authSignedWrite(void) const {return _authSignedWrite;}
friend bool operator==(Properties_t rhs, Properties_t lhs) {
return rhs._broadcast == lhs._broadcast &&
rhs._read == lhs._read &&
rhs._writeWoResp == lhs._writeWoResp &&
rhs._write == lhs._write &&
rhs._notify == lhs._notify &&
rhs._indicate == lhs._indicate &&
rhs._authSignedWrite == lhs._authSignedWrite;
}
private:
operator uint8_t() const; /* disallow implicit conversion into an integer */
operator unsigned() const; /* disallow implicit conversion into an integer */
};
/**
* Structure for holding information about the service and the characteristics
* found during the discovery process.
*/
struct DiscoveredDescriptor {
GattAttribute::Handle_t handle; /**< Descriptor Handle. */
UUID uuid; /**< Descriptor UUID. */
};
/**
* Callback type for when a characteristic descriptor is found during descriptor-
* discovery. The receiving function is passed in a pointer to a
* DiscoveredDescriptor object which will remain valid for the lifetime
* of the callback. Memory for this object is owned by the BLE_API eventing
* framework. The application can safely make a persistent shallow-copy of
* this object in order to work with the characteristic beyond the callback.
*/
typedef void (*DescriptorCallback_t)(const DiscoveredDescriptor *);
/**
* Initiate (or continue) a read for the value attribute, optionally at a
* given offset. If the Characteristic or Descriptor to be read is longer
@ -108,13 +102,13 @@ public:
/**
* Initiate a GATT Characteristic Descriptor Discovery procedure for descriptors within this characteristic.
*
* @param callback
* @param matchingUUID
* filter for descriptors. Defaults to wildcard which will discover all descriptors.
* @param onCharacteristicDiscovered This callback will be called every time a descriptor is discovered
* @param onTermination This callback will be called when the discovery process is over.
*
* @return BLE_ERROR_NONE if descriptor discovery is launched successfully; else an appropriate error.
*/
ble_error_t discoverDescriptors(DescriptorCallback_t callback, const UUID &matchingUUID = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) const;
ble_error_t discoverDescriptors(CharacteristicDescriptorDiscovery::DiscoveryCallback_t onCharacteristicDiscovered,
CharacteristicDescriptorDiscovery::TerminationCallback_t onTermination) const;
/**
* Perform a write procedure.
@ -148,19 +142,47 @@ public:
return props;
}
const GattAttribute::Handle_t& getDeclHandle(void) const {
GattAttribute::Handle_t getDeclHandle(void) const {
return declHandle;
}
const GattAttribute::Handle_t& getValueHandle(void) const {
GattAttribute::Handle_t getValueHandle(void) const {
return valueHandle;
}
GattAttribute::Handle_t getLastHandle(void) const {
return lastHandle;
}
GattClient* getGattClient() {
return gattc;
}
const GattClient* getGattClient() const {
return gattc;
}
Gap::Handle_t getConnectionHandle() const {
return connHandle;
}
friend bool operator==(const DiscoveredCharacteristic& rhs, const DiscoveredCharacteristic& lhs) {
return rhs.gattc == rhs.gattc &&
rhs.uuid == lhs.uuid &&
rhs.props == rhs.props &&
rhs.declHandle == lhs.declHandle &&
rhs.valueHandle == lhs.valueHandle &&
rhs.lastHandle == lhs.lastHandle &&
rhs.connHandle == lhs.connHandle;
}
public:
DiscoveredCharacteristic() : gattc(NULL),
uuid(UUID::ShortUUIDBytes_t(0)),
props(),
declHandle(GattAttribute::INVALID_HANDLE),
valueHandle(GattAttribute::INVALID_HANDLE) {
valueHandle(GattAttribute::INVALID_HANDLE),
lastHandle(GattAttribute::INVALID_HANDLE) {
/* empty */
}
@ -172,6 +194,7 @@ protected:
Properties_t props;
GattAttribute::Handle_t declHandle;
GattAttribute::Handle_t valueHandle;
GattAttribute::Handle_t lastHandle;
Gap::Handle_t connHandle;
};

View File

@ -26,6 +26,7 @@ template <typename ContextType>
class FunctionPointerWithContext {
public:
typedef FunctionPointerWithContext<ContextType> *pFunctionPointerWithContext_t;
typedef const FunctionPointerWithContext<ContextType> *cpFunctionPointerWithContext_t;
typedef void (*pvoidfcontext_t)(ContextType context);
/** Create a FunctionPointerWithContext, attaching a static function
@ -73,7 +74,7 @@ public:
* FunctionPointers their callbacks are invoked as well.
* @Note: all chained callbacks stack up; so hopefully there won't be too
* many FunctionPointers in a chain. */
void call(ContextType context) {
void call(ContextType context) const {
_caller(this, context);
/* Propagate the call to next in the chain. */
@ -101,9 +102,18 @@ public:
return (pvoidfcontext_t)_function;
}
friend bool operator==(const FunctionPointerWithContext& lhs, const FunctionPointerWithContext& rhs) {
return rhs._caller == lhs._caller &&
memcmp(
&rhs._memberFunctionAndPointer,
&lhs._memberFunctionAndPointer,
sizeof(rhs._memberFunctionAndPointer)
) == 0;
}
private:
template<typename T>
static void membercaller(pFunctionPointerWithContext_t self, ContextType context) {
static void membercaller(cpFunctionPointerWithContext_t self, ContextType context) {
if (self->_memberFunctionAndPointer._object) {
T *o = static_cast<T *>(self->_memberFunctionAndPointer._object);
void (T::*m)(ContextType);
@ -112,7 +122,7 @@ private:
}
}
static void functioncaller(pFunctionPointerWithContext_t self, ContextType context) {
static void functioncaller(cpFunctionPointerWithContext_t self, ContextType context) {
if (self->_function) {
self->_function(context);
}
@ -141,10 +151,10 @@ private:
* object this pointer and pointer to member -
* _memberFunctionAndPointer._object will be NULL if none attached
*/
MemberFunctionAndPtr _memberFunctionAndPointer;
mutable MemberFunctionAndPtr _memberFunctionAndPointer;
};
void (*_caller)(FunctionPointerWithContext*, ContextType);
void (*_caller)(const FunctionPointerWithContext*, ContextType);
pFunctionPointerWithContext_t _next; /**< Optional link to make a chain out of functionPointers; this
* allows chaining function pointers without requiring

View File

@ -20,6 +20,7 @@
#include "Gap.h"
#include "GattAttribute.h"
#include "ServiceDiscovery.h"
#include "CharacteristicDescriptorDiscovery.h"
#include "GattCallbackParamTypes.h"
@ -275,6 +276,52 @@ public:
/* Requesting action from porter(s): override this API if this capability is supported. */
}
/**
* @brief launch discovery of descriptors for a given characteristic
* @details This function will discover all descriptors available for a
* specific characteristic.
*
* @param characteristic The characteristic targeted by this discovery
* @param callback This is the application callback for each descriptors
* found.
* @note service discovery may still be active when the callback is issued;
* calling asynchronous BLE-stack APIs from within this application callback
* might cause the stack to abort the discovery. If this becomes an issue,
* it may be better to make local copy of the DiscoveredCharacteristicDescriptor
* and wait for characteristic descriptor discovery to terminate before
* operating on the descriptor.
*
* @return
* BLE_ERROR_NONE if characteristic descriptor discovery is launched
* successfully; else an appropriate error.
*/
virtual ble_error_t discoverCharacteristicDescriptors(
const DiscoveredCharacteristic& characteristic,
CharacteristicDescriptorDiscovery::DiscoveryCallback_t discoveryCallback,
CharacteristicDescriptorDiscovery::TerminationCallback_t terminationCallback) {
(void) characteristic;
(void) discoveryCallback;
(void) terminationCallback;
return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porter(s): override this API if this capability is supported. */
}
/**
* Is characteristic descriptor discovery currently active?
*/
virtual bool isCharacteristicDiscoveryActive(const DiscoveredCharacteristic& characteristic) const {
(void) characteristic;
return false; /* Requesting action from porter(s): override this API if this capability is supported. */
}
/**
* Terminate an ongoing characteristic descriptor discovery. This should result
* in an invocation of the TerminationCallback if characteristic descriptor discovery is active.
*/
virtual void terminateCharacteristicDiscovery(const DiscoveredCharacteristic& characteristic) {
/* Requesting action from porter(s): override this API if this capability is supported. */
(void) characteristic;
}
/**
* Setup a callback for when GattClient receives an update event
* corresponding to a change in value of a characteristic on the remote

View File

@ -59,8 +59,17 @@ DiscoveredCharacteristic::writeWoResponse(uint16_t length, const uint8_t *value)
return gattc->write(GattClient::GATT_OP_WRITE_CMD, connHandle, valueHandle, length, value);
}
ble_error_t
DiscoveredCharacteristic::discoverDescriptors(DescriptorCallback_t callback, const UUID &matchingUUID) const
{
return BLE_ERROR_NOT_IMPLEMENTED; /* TODO: this needs to be filled in. */
ble_error_t DiscoveredCharacteristic::discoverDescriptors(
CharacteristicDescriptorDiscovery::DiscoveryCallback_t onCharacteristicDiscovered,
CharacteristicDescriptorDiscovery::TerminationCallback_t onTermination) const {
if(!gattc) {
return BLE_ERROR_INVALID_STATE;
}
ble_error_t err = gattc->discoverCharacteristicDescriptors(
*this, onCharacteristicDiscovered, onTermination
);
return err;
}