ble: GattClient PIMPL

pull/13475/head
Vincent Coubard 2020-08-20 23:51:03 +01:00
parent 909676d159
commit e3cf59e6cd
4 changed files with 506 additions and 186 deletions

View File

@ -90,7 +90,9 @@ namespace ble {
* if it intends to register to server initiated events. * if it intends to register to server initiated events.
*/ */
#if !defined(DOXYGEN_ONLY) #if !defined(DOXYGEN_ONLY)
namespace interface { namespace impl {
class GattClient;
}
#endif // !defined(DOXYGEN_ONLY) #endif // !defined(DOXYGEN_ONLY)
class GattClient { class GattClient {
public: public:
@ -703,6 +705,9 @@ public:
* registered handlers. * registered handlers.
*/ */
void processHVXEvent(const GattHVXCallbackParams *params); void processHVXEvent(const GattHVXCallbackParams *params);
private:
impl::GattClient *impl;
}; };
/** /**
@ -711,14 +716,11 @@ public:
* @} * @}
*/ */
#if !defined(DOXYGEN_ONLY)
} // namespace interface
#endif // !defined(DOXYGEN_ONLY)
} // namespace ble } // namespace ble
/* This includes the concrete class implementation, to provide a an alternative API implementation /* This includes the concrete class implementation, to provide a an alternative API implementation
* disable ble-api-implementation and place your header in a path with the same structure */ * disable ble-api-implementation and place your header in a path with the same structure */
#include "ble/internal/GattClientImpl.h" //#include "ble/internal/GattClientImpl.h"
/** @deprecated Use the namespaced ble::GattClient instead of the global GattClient. */ /** @deprecated Use the namespaced ble::GattClient instead of the global GattClient. */
using ble::GattClient; using ble::GattClient;

View File

@ -19,9 +19,12 @@
#ifndef IMPL_GATT_CLIENT_H__ #ifndef IMPL_GATT_CLIENT_H__
#define IMPL_GATT_CLIENT_H__ #define IMPL_GATT_CLIENT_H__
#include "ble/BLE.h"
#include "CallChainOfFunctionPointersWithContext.h" #include "CallChainOfFunctionPointersWithContext.h"
#include <algorithm> #include <algorithm>
#include "ble/common/ble/blecommon.h" #include "ble/common/ble/blecommon.h"
#include "ble/common/ble/GattAttribute.h" #include "ble/common/ble/GattAttribute.h"
#include "ble/common/ble/ServiceDiscovery.h" #include "ble/common/ble/ServiceDiscovery.h"
@ -33,14 +36,27 @@
namespace ble { namespace ble {
class BLEInstanceBase;
namespace impl {
class GattClient : class GattClient :
public ble::interface::GattClient,
public PalSigningMonitor, public PalSigningMonitor,
public PalGattClientEventHandler public PalGattClientEventHandler {
{
friend PalSigningMonitor; friend PalSigningMonitor;
friend BLEInstanceBase; friend BLEInstanceBase;
public: public:
using EventHandler = ble::GattClient::EventHandler;
using WriteOp_t = ble::GattClient::WriteOp_t;
using HVXCallback_t = ble::GattClient::HVXCallback_t ;
using GattClientShutdownCallback_t = ble::GattClient::GattClientShutdownCallback_t ;
using GattClientShutdownCallbackChain_t = ble::GattClient::GattClientShutdownCallbackChain_t ;
using HVXCallbackChain_t = ble::GattClient::HVXCallbackChain_t ;
using ReadCallbackChain_t = ble::GattClient::ReadCallbackChain_t ;
using WriteCallbackChain_t = ble::GattClient::WriteCallbackChain_t ;
void setEventHandler(EventHandler *handler); void setEventHandler(EventHandler *handler);
ble_error_t launchServiceDiscovery( ble_error_t launchServiceDiscovery(
@ -86,28 +102,28 @@ public:
void onDataRead(ReadCallback_t callback); void onDataRead(ReadCallback_t callback);
ReadCallbackChain_t& onDataRead(); ReadCallbackChain_t &onDataRead();
void onDataWritten(WriteCallback_t callback); void onDataWritten(WriteCallback_t callback);
WriteCallbackChain_t& onDataWritten(); WriteCallbackChain_t &onDataWritten();
void onServiceDiscoveryTermination( void onServiceDiscoveryTermination(
ServiceDiscovery::TerminationCallback_t callback ServiceDiscovery::TerminationCallback_t callback
); );
ble_error_t discoverCharacteristicDescriptors( ble_error_t discoverCharacteristicDescriptors(
const DiscoveredCharacteristic& characteristic, const DiscoveredCharacteristic &characteristic,
const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback, const CharacteristicDescriptorDiscovery::DiscoveryCallback_t &discoveryCallback,
const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback const CharacteristicDescriptorDiscovery::TerminationCallback_t &terminationCallback
); );
bool isCharacteristicDescriptorDiscoveryActive( bool isCharacteristicDescriptorDiscoveryActive(
const DiscoveredCharacteristic& characteristic const DiscoveredCharacteristic &characteristic
) const; ) const;
void terminateCharacteristicDescriptorDiscovery( void terminateCharacteristicDescriptorDiscovery(
const DiscoveredCharacteristic& characteristic const DiscoveredCharacteristic &characteristic
); );
ble_error_t negotiateAttMtu(ble::connection_handle_t connection); ble_error_t negotiateAttMtu(ble::connection_handle_t connection);
@ -122,14 +138,14 @@ public:
*/ */
void onHVX(HVXCallback_t callback); void onHVX(HVXCallback_t callback);
void onShutdown(const GattClientShutdownCallback_t& callback); void onShutdown(const GattClientShutdownCallback_t &callback);
template <typename T> template<typename T>
void onShutdown(T *objPtr, void (T::*memberPtr)(const GattClient *)); void onShutdown(T *objPtr, void (T::*memberPtr)(const GattClient *));
GattClientShutdownCallbackChain_t& onShutdown(); GattClientShutdownCallbackChain_t &onShutdown();
HVXCallbackChain_t& onHVX(); HVXCallbackChain_t &onHVX();
ble_error_t reset(void); ble_error_t reset(void);
@ -144,7 +160,8 @@ public:
private: private:
/* Disallow copy and assignment. */ /* Disallow copy and assignment. */
GattClient(const GattClient &); GattClient(const GattClient &);
GattClient& operator=(const GattClient &);
GattClient &operator=(const GattClient &);
/* ===================================================================== */ /* ===================================================================== */
/* private implementation follows */ /* private implementation follows */
@ -179,15 +196,22 @@ private:
struct WriteControlBlock; struct WriteControlBlock;
struct DescriptorDiscoveryControlBlock; struct DescriptorDiscoveryControlBlock;
ProcedureControlBlock* get_control_block(connection_handle_t connection); ProcedureControlBlock *get_control_block(connection_handle_t connection);
const ProcedureControlBlock* get_control_block(connection_handle_t connection) const;
void insert_control_block(ProcedureControlBlock* cb) const; const ProcedureControlBlock *get_control_block(connection_handle_t connection) const;
void remove_control_block(ProcedureControlBlock* cb) const;
void insert_control_block(ProcedureControlBlock *cb) const;
void remove_control_block(ProcedureControlBlock *cb) const;
void on_termination(connection_handle_t connection_handle); void on_termination(connection_handle_t connection_handle);
void on_server_message_received(connection_handle_t, const AttServerMessage&);
void on_server_response(connection_handle_t, const AttServerMessage&); void on_server_message_received(connection_handle_t, const AttServerMessage &);
void on_server_event(connection_handle_t, const AttServerMessage&);
void on_server_response(connection_handle_t, const AttServerMessage &);
void on_server_event(connection_handle_t, const AttServerMessage &);
void on_transaction_timeout(connection_handle_t); void on_transaction_timeout(connection_handle_t);
uint16_t get_mtu(connection_handle_t connection) const; uint16_t get_mtu(connection_handle_t connection) const;
@ -222,21 +246,27 @@ private:
*/ */
GattClientShutdownCallbackChain_t shutdownCallChain; GattClientShutdownCallbackChain_t shutdownCallChain;
PalGattClient& _pal_client; PalGattClient &_pal_client;
ServiceDiscovery::TerminationCallback_t _termination_callback; ServiceDiscovery::TerminationCallback_t _termination_callback;
PalSigningMonitorEventHandler* _signing_event_handler; PalSigningMonitorEventHandler *_signing_event_handler;
mutable ProcedureControlBlock* control_blocks; mutable ProcedureControlBlock *control_blocks;
bool _is_reseting; bool _is_reseting;
// TODO initialize
::ble::GattClient *client;
private: private:
/** /**
* Create a PalGattClient from a PalGattClient * Create a PalGattClient from a PalGattClient
*/ */
GattClient(PalGattClient& pal_client); GattClient(PalGattClient &pal_client);
~GattClient() { } ~GattClient()
{
}
}; };
} // namespace impl
} // namespace ble } // namespace ble
#endif /* ifndef IMPL_GATT_CLIENT_H__ */ #endif /* ifndef IMPL_GATT_CLIENT_H__ */

View File

@ -23,10 +23,10 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "ble/internal/GattClientImpl.h"
#include "ble/internal/AttServerMessage.h" #include "ble/internal/AttServerMessage.h"
#include "ble/common/ble/DiscoveredService.h" #include "ble/common/ble/DiscoveredService.h"
#include "ble/common/ble/DiscoveredCharacteristic.h" #include "ble/common/ble/DiscoveredCharacteristic.h"
#include "ble/GattClient.h"
#include "ble/common/ble/blecommon.h" #include "ble/common/ble/blecommon.h"
#include "ble/internal/BLEInstanceBase.h" #include "ble/internal/BLEInstanceBase.h"
#include "ble/SecurityManager.h" #include "ble/SecurityManager.h"
@ -53,6 +53,14 @@ using ble::AttFindInformationResponse;
#define MAC_COUNTER_LENGTH 4 #define MAC_COUNTER_LENGTH 4
namespace ble { namespace ble {
namespace impl {
namespace {
static constexpr auto GATT_OP_SIGNED_WRITE_CMD = ble::GattClient::GATT_OP_SIGNED_WRITE_CMD;
static constexpr auto GATT_OP_WRITE_CMD = ble::GattClient::GATT_OP_WRITE_CMD;
static constexpr auto GATT_OP_WRITE_REQ = ble::GattClient::GATT_OP_WRITE_REQ;
}
/* /*
* Type of procedures which can be launched by the client. * Type of procedures which can be launched by the client.
@ -74,19 +82,23 @@ struct GattClient::ProcedureControlBlock {
* Base constructor for procedure control block. * Base constructor for procedure control block.
*/ */
ProcedureControlBlock(procedure_type_t type, connection_handle_t handle) : ProcedureControlBlock(procedure_type_t type, connection_handle_t handle) :
type(type), connection_handle(handle), next(nullptr) { } type(type), connection_handle(handle), next(nullptr)
{
}
virtual ~ProcedureControlBlock() { } virtual ~ProcedureControlBlock()
{
}
/* /*
* Entry point of the control block stack machine. * Entry point of the control block stack machine.
*/ */
virtual void handle(GattClient* client, const AttServerMessage& message) = 0; virtual void handle(GattClient *client, const AttServerMessage &message) = 0;
/* /*
* Function call in case of timeout * Function call in case of timeout
*/ */
virtual void handle_timeout_error(GattClient* client) = 0; virtual void handle_timeout_error(GattClient *client) = 0;
/** /**
* Function called when the procedure is aborted * Function called when the procedure is aborted
@ -95,7 +107,7 @@ struct GattClient::ProcedureControlBlock {
procedure_type_t type; procedure_type_t type;
connection_handle_t connection_handle; connection_handle_t connection_handle;
ProcedureControlBlock* next; ProcedureControlBlock *next;
}; };
@ -118,50 +130,55 @@ struct GattClient::DiscoveryControlBlock : public ProcedureControlBlock {
matching_service_uuid(matching_service_uuid), matching_service_uuid(matching_service_uuid),
matching_characteristic_uuid(matching_characteristic_uuid), matching_characteristic_uuid(matching_characteristic_uuid),
services_discovered(nullptr), services_discovered(nullptr),
done(false) { done(false)
{
} }
virtual ~DiscoveryControlBlock() { virtual ~DiscoveryControlBlock()
while(services_discovered) { {
service_t* tmp = services_discovered->next; while (services_discovered) {
service_t *tmp = services_discovered->next;
delete services_discovered; delete services_discovered;
services_discovered = tmp; services_discovered = tmp;
} }
} }
virtual void handle_timeout_error(GattClient* client) { virtual void handle_timeout_error(GattClient *client)
{
terminate(client); terminate(client);
} }
virtual void abort(GattClient *client) { virtual void abort(GattClient *client)
{
terminate(client); terminate(client);
} }
virtual void handle(GattClient* client, const AttServerMessage& message) { virtual void handle(GattClient *client, const AttServerMessage &message)
{
// if end of discovery has been requested, ends it immediately // if end of discovery has been requested, ends it immediately
if (done) { if (done) {
terminate(client); terminate(client);
return; return;
} }
switch(message.opcode) { switch (message.opcode) {
case AttributeOpcode::READ_BY_GROUP_TYPE_RESPONSE: case AttributeOpcode::READ_BY_GROUP_TYPE_RESPONSE:
handle_service_discovered( handle_service_discovered(
client, static_cast<const AttReadByGroupTypeResponse&>(message) client, static_cast<const AttReadByGroupTypeResponse &>(message)
); );
break; break;
case AttributeOpcode::FIND_BY_VALUE_TYPE_RESPONSE: case AttributeOpcode::FIND_BY_VALUE_TYPE_RESPONSE:
handle_service_discovered( handle_service_discovered(
client, static_cast<const AttFindByTypeValueResponse&>(message) client, static_cast<const AttFindByTypeValueResponse &>(message)
); );
break; break;
case AttributeOpcode::READ_BY_TYPE_RESPONSE: case AttributeOpcode::READ_BY_TYPE_RESPONSE:
handle_characteristic_discovered( handle_characteristic_discovered(
client, static_cast<const AttReadByTypeResponse&>(message) client, static_cast<const AttReadByTypeResponse &>(message)
); );
break; break;
case AttributeOpcode::ERROR_RESPONSE: { case AttributeOpcode::ERROR_RESPONSE: {
const AttErrorResponse& error = static_cast<const AttErrorResponse&>(message); const AttErrorResponse &error = static_cast<const AttErrorResponse &>(message);
if (error.error_code != AttErrorResponse::ATTRIBUTE_NOT_FOUND) { if (error.error_code != AttErrorResponse::ATTRIBUTE_NOT_FOUND) {
terminate(client); terminate(client);
return; return;
@ -187,7 +204,8 @@ struct GattClient::DiscoveryControlBlock : public ProcedureControlBlock {
} }
template<typename Response> template<typename Response>
void handle_service_discovered(GattClient* client, const Response& response) { void handle_service_discovered(GattClient *client, const Response &response)
{
if (!response.size()) { if (!response.size()) {
terminate(client); terminate(client);
return; return;
@ -204,7 +222,7 @@ struct GattClient::DiscoveryControlBlock : public ProcedureControlBlock {
discovered_service.setup(uuid, start_handle, end_handle); discovered_service.setup(uuid, start_handle, end_handle);
service_callback(&discovered_service); service_callback(&discovered_service);
} else { } else {
service_t* discovered_service = new (std::nothrow) service_t( service_t *discovered_service = new(std::nothrow) service_t(
start_handle, end_handle, uuid start_handle, end_handle, uuid
); );
@ -230,7 +248,8 @@ struct GattClient::DiscoveryControlBlock : public ProcedureControlBlock {
} }
} }
void start_characteristic_discovery(GattClient* client) { void start_characteristic_discovery(GattClient *client)
{
if (!services_discovered) { if (!services_discovered) {
terminate(client); terminate(client);
return; return;
@ -261,7 +280,8 @@ struct GattClient::DiscoveryControlBlock : public ProcedureControlBlock {
); );
} }
void handle_characteristic_discovered(GattClient* client, const AttReadByTypeResponse& response) { void handle_characteristic_discovered(GattClient *client, const AttReadByTypeResponse &response)
{
for (size_t i = 0; i < response.size(); ++i) { for (size_t i = 0; i < response.size(); ++i) {
if (last_characteristic.is_valid() == false) { if (last_characteristic.is_valid() == false) {
last_characteristic.set_last_handle(response[i].handle - 1); last_characteristic.set_last_handle(response[i].handle - 1);
@ -294,7 +314,8 @@ struct GattClient::DiscoveryControlBlock : public ProcedureControlBlock {
} }
} }
void handle_all_characteristics_discovered(GattClient* client) { void handle_all_characteristics_discovered(GattClient *client)
{
if (last_characteristic.is_valid() == false) { if (last_characteristic.is_valid() == false) {
if (matching_characteristic_uuid == UUID() if (matching_characteristic_uuid == UUID()
|| matching_characteristic_uuid == last_characteristic.getUUID()) { || matching_characteristic_uuid == last_characteristic.getUUID()) {
@ -303,7 +324,7 @@ struct GattClient::DiscoveryControlBlock : public ProcedureControlBlock {
} }
} }
service_t* old = services_discovered; service_t *old = services_discovered;
services_discovered = services_discovered->next; services_discovered = services_discovered->next;
delete old; delete old;
@ -314,7 +335,8 @@ struct GattClient::DiscoveryControlBlock : public ProcedureControlBlock {
} }
} }
void terminate(GattClient* client) { void terminate(GattClient *client)
{
// unknown error, terminate the procedure immediately // unknown error, terminate the procedure immediately
client->remove_control_block(this); client->remove_control_block(this);
connection_handle_t handle = connection_handle; connection_handle_t handle = connection_handle;
@ -322,23 +344,28 @@ struct GattClient::DiscoveryControlBlock : public ProcedureControlBlock {
client->on_termination(handle); client->on_termination(handle);
} }
uint16_t get_start_handle(const AttReadByGroupTypeResponse::attribute_data_t& data) { uint16_t get_start_handle(const AttReadByGroupTypeResponse::attribute_data_t &data)
{
return data.group_range.begin; return data.group_range.begin;
} }
uint16_t get_start_handle(const attribute_handle_range_t& range) { uint16_t get_start_handle(const attribute_handle_range_t &range)
{
return range.begin; return range.begin;
} }
uint16_t get_end_handle(const AttReadByGroupTypeResponse::attribute_data_t& data) { uint16_t get_end_handle(const AttReadByGroupTypeResponse::attribute_data_t &data)
{
return data.group_range.end; return data.group_range.end;
} }
uint16_t get_end_handle(const attribute_handle_range_t& range) { uint16_t get_end_handle(const attribute_handle_range_t &range)
{
return range.end; return range.end;
} }
UUID get_uuid(const AttReadByGroupTypeResponse::attribute_data_t& data) { UUID get_uuid(const AttReadByGroupTypeResponse::attribute_data_t &data)
{
if (data.value.size() == 2) { if (data.value.size() == 2) {
return UUID(data.value[0] | data.value[1] << 8); return UUID(data.value[0] | data.value[1] << 8);
} else { } else {
@ -346,31 +373,37 @@ struct GattClient::DiscoveryControlBlock : public ProcedureControlBlock {
} }
} }
UUID get_uuid(const attribute_handle_range_t& range) { UUID get_uuid(const attribute_handle_range_t &range)
{
return matching_service_uuid; return matching_service_uuid;
} }
struct service_t { struct service_t {
service_t(uint16_t begin, uint16_t end, const UUID& uuid) : service_t(uint16_t begin, uint16_t end, const UUID &uuid) :
begin(begin), end(end), uuid(uuid), next(nullptr) { } begin(begin), end(end), uuid(uuid), next(nullptr)
{
}
uint16_t begin; uint16_t begin;
uint16_t end; uint16_t end;
UUID uuid; UUID uuid;
service_t* next; service_t *next;
}; };
struct characteristic_t : DiscoveredCharacteristic { struct characteristic_t : DiscoveredCharacteristic {
characteristic_t() : DiscoveredCharacteristic() { characteristic_t() : DiscoveredCharacteristic()
{
lastHandle = 0x0001; lastHandle = 0x0001;
} }
characteristic_t( characteristic_t(
GattClient* client, GattClient *client,
connection_handle_t connection_handle, connection_handle_t connection_handle,
uint16_t decl_handle, uint16_t decl_handle,
const Span<const uint8_t> value const Span<const uint8_t> value
) : DiscoveredCharacteristic() { ) : DiscoveredCharacteristic()
gattc = client; {
gattc = client->client;
uuid = get_uuid(value); uuid = get_uuid(value);
props = get_properties(value); props = get_properties(value);
declHandle = decl_handle; declHandle = decl_handle;
@ -379,7 +412,8 @@ struct GattClient::DiscoveryControlBlock : public ProcedureControlBlock {
connHandle = connection_handle; connHandle = connection_handle;
} }
static UUID get_uuid(const Span<const uint8_t>& value) { static UUID get_uuid(const Span<const uint8_t> &value)
{
if (value.size() == 5) { if (value.size() == 5) {
return UUID(value[3] | (value[4] << 8)); return UUID(value[3] | (value[4] << 8));
} else { } else {
@ -387,7 +421,8 @@ struct GattClient::DiscoveryControlBlock : public ProcedureControlBlock {
} }
} }
static DiscoveredCharacteristic::Properties_t get_properties(const Span<const uint8_t>& value) { static DiscoveredCharacteristic::Properties_t get_properties(const Span<const uint8_t> &value)
{
uint8_t raw_properties = value[0]; uint8_t raw_properties = value[0];
DiscoveredCharacteristic::Properties_t result; DiscoveredCharacteristic::Properties_t result;
result._broadcast = (raw_properties & (1 << 0)) ? true : false; result._broadcast = (raw_properties & (1 << 0)) ? true : false;
@ -400,26 +435,30 @@ struct GattClient::DiscoveryControlBlock : public ProcedureControlBlock {
return result; return result;
} }
static uint16_t get_value_handle(const Span<const uint8_t>& value) { static uint16_t get_value_handle(const Span<const uint8_t> &value)
{
return value[1] | (value[2] << 8); return value[1] | (value[2] << 8);
} }
void set_last_handle(uint16_t last_handle) { void set_last_handle(uint16_t last_handle)
{
lastHandle = last_handle; lastHandle = last_handle;
} }
bool is_valid() const { bool is_valid() const
{
return lastHandle != 0x0000; return lastHandle != 0x0000;
} }
}; };
void insert_service(service_t* service) { void insert_service(service_t *service)
{
if (services_discovered == nullptr) { if (services_discovered == nullptr) {
services_discovered = service; services_discovered = service;
return; return;
} }
service_t* current = services_discovered; service_t *current = services_discovered;
while (current->next) { while (current->next) {
current = current->next; current = current->next;
} }
@ -430,13 +469,12 @@ struct GattClient::DiscoveryControlBlock : public ProcedureControlBlock {
ServiceDiscovery::CharacteristicCallback_t characteristic_callback; ServiceDiscovery::CharacteristicCallback_t characteristic_callback;
UUID matching_service_uuid; UUID matching_service_uuid;
UUID matching_characteristic_uuid; UUID matching_characteristic_uuid;
service_t* services_discovered; service_t *services_discovered;
characteristic_t last_characteristic; characteristic_t last_characteristic;
bool done; bool done;
}; };
struct GattClient::ReadControlBlock : public ProcedureControlBlock { struct GattClient::ReadControlBlock : public ProcedureControlBlock {
using ProcedureControlBlock::connection_handle; using ProcedureControlBlock::connection_handle;
@ -444,16 +482,19 @@ struct GattClient::ReadControlBlock : public ProcedureControlBlock {
connection_handle_t connection_handle, uint16_t attribute_handle, uint16_t offset connection_handle_t connection_handle, uint16_t attribute_handle, uint16_t offset
) : ProcedureControlBlock(READ_PROCEDURE, connection_handle), ) : ProcedureControlBlock(READ_PROCEDURE, connection_handle),
attribute_handle(attribute_handle), attribute_handle(attribute_handle),
offset(offset), current_offset(offset), data(nullptr) { offset(offset), current_offset(offset), data(nullptr)
{
} }
virtual ~ReadControlBlock() { virtual ~ReadControlBlock()
{
if (data != nullptr) { if (data != nullptr) {
free(data); free(data);
} }
} }
virtual void handle_timeout_error(GattClient* client) { virtual void handle_timeout_error(GattClient *client)
{
GattReadCallbackParams response = { GattReadCallbackParams response = {
connection_handle, connection_handle,
attribute_handle, attribute_handle,
@ -465,7 +506,8 @@ struct GattClient::ReadControlBlock : public ProcedureControlBlock {
terminate(client, response); terminate(client, response);
} }
virtual void abort(GattClient *client) { virtual void abort(GattClient *client)
{
GattReadCallbackParams response = { GattReadCallbackParams response = {
connection_handle, connection_handle,
attribute_handle, attribute_handle,
@ -477,24 +519,26 @@ struct GattClient::ReadControlBlock : public ProcedureControlBlock {
terminate(client, response); terminate(client, response);
} }
void terminate(GattClient* client, const GattReadCallbackParams& response) { void terminate(GattClient *client, const GattReadCallbackParams &response)
{
client->remove_control_block(this); client->remove_control_block(this);
client->processReadResponse(&response); client->processReadResponse(&response);
delete this; delete this;
} }
virtual void handle(GattClient* client, const AttServerMessage& message) { virtual void handle(GattClient *client, const AttServerMessage &message)
switch(message.opcode) { {
switch (message.opcode) {
case AttributeOpcode::ERROR_RESPONSE: case AttributeOpcode::ERROR_RESPONSE:
handle_error(client, static_cast<const AttErrorResponse&>(message)); handle_error(client, static_cast<const AttErrorResponse &>(message));
break; break;
case AttributeOpcode::READ_RESPONSE: case AttributeOpcode::READ_RESPONSE:
handle_read_response(client, static_cast<const AttReadResponse&>(message)); handle_read_response(client, static_cast<const AttReadResponse &>(message));
break; break;
case AttributeOpcode::READ_BLOB_RESPONSE: case AttributeOpcode::READ_BLOB_RESPONSE:
handle_read_response(client, static_cast<const AttReadBlobResponse&>(message)); handle_read_response(client, static_cast<const AttReadBlobResponse &>(message));
break; break;
default: { default: {
@ -514,7 +558,8 @@ struct GattClient::ReadControlBlock : public ProcedureControlBlock {
} }
template<typename ResponseType> template<typename ResponseType>
void handle_read_response(GattClient* client, const ResponseType& read_response) { void handle_read_response(GattClient *client, const ResponseType &read_response)
{
uint16_t mtu_size = client->get_mtu(connection_handle); uint16_t mtu_size = client->get_mtu(connection_handle);
// end of responses ? // end of responses ?
@ -542,7 +587,7 @@ struct GattClient::ReadControlBlock : public ProcedureControlBlock {
terminate(client, response); terminate(client, response);
} else { } else {
// allocation which will contain the response data plus the next one. // allocation which will contain the response data plus the next one.
data = (uint8_t*) realloc(data, (current_offset - offset) + ((mtu_size - 1) * 2)); data = (uint8_t *) realloc(data, (current_offset - offset) + ((mtu_size - 1) * 2));
if (data == nullptr) { if (data == nullptr) {
GattReadCallbackParams response = { GattReadCallbackParams response = {
connection_handle, connection_handle,
@ -578,7 +623,8 @@ struct GattClient::ReadControlBlock : public ProcedureControlBlock {
} }
} }
void handle_error(GattClient* client, const AttErrorResponse& error) { void handle_error(GattClient *client, const AttErrorResponse &error)
{
ble_error_t status = BLE_ERROR_UNSPECIFIED; ble_error_t status = BLE_ERROR_UNSPECIFIED;
switch (error.error_code) { switch (error.error_code) {
@ -626,7 +672,7 @@ struct GattClient::ReadControlBlock : public ProcedureControlBlock {
uint16_t attribute_handle; uint16_t attribute_handle;
uint16_t offset; uint16_t offset;
uint16_t current_offset; uint16_t current_offset;
uint8_t* data; uint8_t *data;
}; };
/* /*
@ -643,14 +689,17 @@ struct GattClient::WriteControlBlock : public ProcedureControlBlock {
uint16_t write_length uint16_t write_length
) : ProcedureControlBlock(WRITE_PROCEDURE, connection_handle), ) : ProcedureControlBlock(WRITE_PROCEDURE, connection_handle),
attribute_handle(attribute_handle), write_length(write_length), offset(0), data(data), attribute_handle(attribute_handle), write_length(write_length), offset(0), data(data),
prepare_success(false), status(BLE_ERROR_INITIALIZATION_INCOMPLETE), error_code(0xFF) { prepare_success(false), status(BLE_ERROR_INITIALIZATION_INCOMPLETE), error_code(0xFF)
{
} }
virtual ~WriteControlBlock() { virtual ~WriteControlBlock()
{
free(data); free(data);
} }
virtual void handle_timeout_error(GattClient* client) { virtual void handle_timeout_error(GattClient* client)
{
GattWriteCallbackParams response = { GattWriteCallbackParams response = {
connection_handle, connection_handle,
attribute_handle, attribute_handle,
@ -661,7 +710,8 @@ struct GattClient::WriteControlBlock : public ProcedureControlBlock {
terminate(client, response); terminate(client, response);
} }
virtual void abort(GattClient *client) { virtual void abort(GattClient *client)
{
GattWriteCallbackParams response = { GattWriteCallbackParams response = {
connection_handle, connection_handle,
attribute_handle, attribute_handle,
@ -672,13 +722,15 @@ struct GattClient::WriteControlBlock : public ProcedureControlBlock {
terminate(client, response); terminate(client, response);
} }
void terminate(GattClient* client, const GattWriteCallbackParams& response) { void terminate(GattClient *client, const GattWriteCallbackParams &response)
{
client->remove_control_block(this); client->remove_control_block(this);
client->processWriteResponse(&response); client->processWriteResponse(&response);
delete this; delete this;
} }
virtual void handle(GattClient* client, const AttServerMessage& message) { virtual void handle(GattClient* client, const AttServerMessage& message)
{
switch(message.opcode) { switch(message.opcode) {
case AttributeOpcode::ERROR_RESPONSE: case AttributeOpcode::ERROR_RESPONSE:
handle_error(client, static_cast<const AttErrorResponse&>(message)); handle_error(client, static_cast<const AttErrorResponse&>(message));
@ -710,7 +762,8 @@ struct GattClient::WriteControlBlock : public ProcedureControlBlock {
} }
} }
void handle_write_response(GattClient* client, const AttWriteResponse& write_response) { void handle_write_response(GattClient* client, const AttWriteResponse& write_response)
{
GattWriteCallbackParams response = { GattWriteCallbackParams response = {
connection_handle, connection_handle,
attribute_handle, attribute_handle,
@ -722,7 +775,8 @@ struct GattClient::WriteControlBlock : public ProcedureControlBlock {
terminate(client, response); terminate(client, response);
} }
void handle_prepare_write_response(GattClient* client, const AttPrepareWriteResponse& write_response) { void handle_prepare_write_response(GattClient* client, const AttPrepareWriteResponse& write_response)
{
ble_error_t err = BLE_ERROR_UNSPECIFIED; ble_error_t err = BLE_ERROR_UNSPECIFIED;
offset += write_response.partial_value.size(); offset += write_response.partial_value.size();
uint16_t data_left = write_length - offset; /* offset is guaranteed to be less of equal to write_length */ uint16_t data_left = write_length - offset; /* offset is guaranteed to be less of equal to write_length */
@ -749,7 +803,8 @@ struct GattClient::WriteControlBlock : public ProcedureControlBlock {
} }
} }
void handle_execute_write_response(GattClient* client, const AttExecuteWriteResponse& execute_response) { void handle_execute_write_response(GattClient* client, const AttExecuteWriteResponse& execute_response)
{
if (prepare_success) { if (prepare_success) {
status = BLE_ERROR_NONE; status = BLE_ERROR_NONE;
error_code = 0x00; error_code = 0x00;
@ -766,7 +821,8 @@ struct GattClient::WriteControlBlock : public ProcedureControlBlock {
terminate(client, response); terminate(client, response);
} }
void clear_prepare_queue(GattClient* client, ble_error_t s, uint8_t e) { void clear_prepare_queue(GattClient* client, ble_error_t s, uint8_t e)
{
prepare_success = false; prepare_success = false;
status = s; status = s;
error_code = e; error_code = e;
@ -787,7 +843,8 @@ struct GattClient::WriteControlBlock : public ProcedureControlBlock {
} }
} }
void handle_error(GattClient* client, const AttErrorResponse& error) { void handle_error(GattClient* client, const AttErrorResponse& error)
{
ble_error_t status = BLE_ERROR_UNSPECIFIED; ble_error_t status = BLE_ERROR_UNSPECIFIED;
switch (error.error_code) { switch (error.error_code) {
@ -849,20 +906,24 @@ struct GattClient::DescriptorDiscoveryControlBlock : public ProcedureControlBloc
using ProcedureControlBlock::connection_handle; using ProcedureControlBlock::connection_handle;
DescriptorDiscoveryControlBlock( DescriptorDiscoveryControlBlock(
const DiscoveredCharacteristic& characteristic, const DiscoveredCharacteristic &characteristic,
const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback, const CharacteristicDescriptorDiscovery::DiscoveryCallback_t &discoveryCallback,
const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback const CharacteristicDescriptorDiscovery::TerminationCallback_t &terminationCallback
) : ProcedureControlBlock(DESCRIPTOR_DISCOVERY_PROCEDURE, characteristic.getConnectionHandle()), ) : ProcedureControlBlock(DESCRIPTOR_DISCOVERY_PROCEDURE, characteristic.getConnectionHandle()),
characteristic(characteristic), characteristic(characteristic),
discovery_cb(discoveryCallback), discovery_cb(discoveryCallback),
termination_cb(terminationCallback), termination_cb(terminationCallback),
next_handle(characteristic.getValueHandle() + 1), next_handle(characteristic.getValueHandle() + 1),
done(false) { done(false)
{
} }
virtual ~DescriptorDiscoveryControlBlock() { } virtual ~DescriptorDiscoveryControlBlock()
{
}
ble_error_t start(GattClient* client) { ble_error_t start(GattClient *client)
{
return client->_pal_client.discover_characteristics_descriptors( return client->_pal_client.discover_characteristics_descriptors(
connection_handle, connection_handle,
attribute_handle_range( attribute_handle_range(
@ -872,27 +933,30 @@ struct GattClient::DescriptorDiscoveryControlBlock : public ProcedureControlBloc
); );
} }
virtual void handle_timeout_error(GattClient* client) { virtual void handle_timeout_error(GattClient *client)
{
terminate(client, BLE_ERROR_UNSPECIFIED); terminate(client, BLE_ERROR_UNSPECIFIED);
} }
virtual void abort(GattClient *client) { virtual void abort(GattClient *client)
{
terminate(client, BLE_ERROR_INVALID_STATE); terminate(client, BLE_ERROR_INVALID_STATE);
} }
virtual void handle(GattClient* client, const AttServerMessage& message) { virtual void handle(GattClient *client, const AttServerMessage &message)
{
if (done) { if (done) {
terminate(client, BLE_ERROR_NONE); terminate(client, BLE_ERROR_NONE);
return; return;
} }
switch(message.opcode) { switch (message.opcode) {
case AttributeOpcode::ERROR_RESPONSE: case AttributeOpcode::ERROR_RESPONSE:
handle_error(client, static_cast<const AttErrorResponse&>(message)); handle_error(client, static_cast<const AttErrorResponse &>(message));
return; return;
case AttributeOpcode::FIND_INFORMATION_RESPONSE: case AttributeOpcode::FIND_INFORMATION_RESPONSE:
handle_response(client, static_cast<const AttFindInformationResponse&>(message)); handle_response(client, static_cast<const AttFindInformationResponse &>(message));
return; return;
default: default:
@ -900,7 +964,8 @@ struct GattClient::DescriptorDiscoveryControlBlock : public ProcedureControlBloc
} }
} }
void handle_error(GattClient* client, const AttErrorResponse& error) { void handle_error(GattClient *client, const AttErrorResponse &error)
{
if (error.error_code == AttErrorResponse::ATTRIBUTE_NOT_FOUND) { if (error.error_code == AttErrorResponse::ATTRIBUTE_NOT_FOUND) {
terminate(client, BLE_ERROR_NONE); terminate(client, BLE_ERROR_NONE);
} else { } else {
@ -908,10 +973,11 @@ struct GattClient::DescriptorDiscoveryControlBlock : public ProcedureControlBloc
} }
} }
void handle_response(GattClient* client, const AttFindInformationResponse& response) { void handle_response(GattClient *client, const AttFindInformationResponse &response)
{
for (size_t i = 0; i < response.size(); ++i) { for (size_t i = 0; i < response.size(); ++i) {
DiscoveredCharacteristicDescriptor descriptor( DiscoveredCharacteristicDescriptor descriptor(
client, connection_handle, response[i].handle, response[i].uuid client->client, connection_handle, response[i].handle, response[i].uuid
); );
CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t params = { CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t params = {
characteristic, characteristic,
@ -936,7 +1002,8 @@ struct GattClient::DescriptorDiscoveryControlBlock : public ProcedureControlBloc
} }
} }
void terminate(GattClient* client, ble_error_t status, uint8_t error_code = 0x00) { void terminate(GattClient *client, ble_error_t status, uint8_t error_code = 0x00)
{
client->remove_control_block(this); client->remove_control_block(this);
CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = { CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = {
characteristic, characteristic,
@ -955,7 +1022,7 @@ struct GattClient::DescriptorDiscoveryControlBlock : public ProcedureControlBloc
}; };
GattClient::GattClient(PalGattClient& pal_client) : GattClient::GattClient(PalGattClient &pal_client) :
eventHandler(nullptr), eventHandler(nullptr),
_pal_client(pal_client), _pal_client(pal_client),
_termination_callback(), _termination_callback(),
@ -963,7 +1030,8 @@ GattClient::GattClient(PalGattClient& pal_client) :
_signing_event_handler(nullptr), _signing_event_handler(nullptr),
#endif #endif
control_blocks(nullptr), control_blocks(nullptr),
_is_reseting(false) { _is_reseting(false)
{
_pal_client.when_server_message_received( _pal_client.when_server_message_received(
mbed::callback(this, &GattClient::on_server_message_received) mbed::callback(this, &GattClient::on_server_message_received)
); );
@ -978,8 +1046,8 @@ ble_error_t GattClient::launchServiceDiscovery(
connection_handle_t connection_handle, connection_handle_t connection_handle,
ServiceDiscovery::ServiceCallback_t service_callback, ServiceDiscovery::ServiceCallback_t service_callback,
ServiceDiscovery::CharacteristicCallback_t characteristic_callback, ServiceDiscovery::CharacteristicCallback_t characteristic_callback,
const UUID& matching_service_uuid, const UUID &matching_service_uuid,
const UUID& matching_characteristic_uuid const UUID &matching_characteristic_uuid
) )
{ {
// verify that there is no other procedures going on this connection // verify that there is no other procedures going on this connection
@ -993,7 +1061,7 @@ ble_error_t GattClient::launchServiceDiscovery(
return BLE_ERROR_NONE; return BLE_ERROR_NONE;
} }
DiscoveryControlBlock* discovery_pcb = new(std::nothrow) DiscoveryControlBlock( DiscoveryControlBlock *discovery_pcb = new(std::nothrow) DiscoveryControlBlock(
connection_handle, connection_handle,
service_callback, service_callback,
characteristic_callback, characteristic_callback,
@ -1048,8 +1116,9 @@ ble_error_t GattClient::discoverServices(
); );
} }
bool GattClient::isServiceDiscoveryActive() const { bool GattClient::isServiceDiscoveryActive() const
ProcedureControlBlock* pcb = control_blocks; {
ProcedureControlBlock *pcb = control_blocks;
while (pcb) { while (pcb) {
if (pcb->type == COMPLETE_DISCOVERY_PROCEDURE) { if (pcb->type == COMPLETE_DISCOVERY_PROCEDURE) {
@ -1064,10 +1133,10 @@ bool GattClient::isServiceDiscoveryActive() const {
void GattClient::terminateServiceDiscovery() void GattClient::terminateServiceDiscovery()
{ {
ProcedureControlBlock* pcb = control_blocks; ProcedureControlBlock *pcb = control_blocks;
while (pcb) { while (pcb) {
if (pcb->type == COMPLETE_DISCOVERY_PROCEDURE) { if (pcb->type == COMPLETE_DISCOVERY_PROCEDURE) {
static_cast<DiscoveryControlBlock*>(pcb)->done = true; static_cast<DiscoveryControlBlock *>(pcb)->done = true;
} }
pcb = pcb->next; pcb = pcb->next;
} }
@ -1077,14 +1146,15 @@ void GattClient::terminateServiceDiscovery()
ble_error_t GattClient::read( ble_error_t GattClient::read(
connection_handle_t connection_handle, connection_handle_t connection_handle,
GattAttribute::Handle_t attribute_handle, GattAttribute::Handle_t attribute_handle,
uint16_t offset) const uint16_t offset
) const
{ {
// verify that there is no other procedures going on this connection // verify that there is no other procedures going on this connection
if (_is_reseting || get_control_block(connection_handle)) { if (_is_reseting || get_control_block(connection_handle)) {
return BLE_ERROR_INVALID_STATE; return BLE_ERROR_INVALID_STATE;
} }
ReadControlBlock* read_pcb = new(std::nothrow) ReadControlBlock( ReadControlBlock *read_pcb = new(std::nothrow) ReadControlBlock(
connection_handle, connection_handle,
attribute_handle, attribute_handle,
offset offset
@ -1122,8 +1192,9 @@ ble_error_t GattClient::write(
connection_handle_t connection_handle, connection_handle_t connection_handle,
GattAttribute::Handle_t attribute_handle, GattAttribute::Handle_t attribute_handle,
size_t length, size_t length,
const uint8_t* value const uint8_t *value
) const { ) const
{
// verify that there is no other procedures going on this connection // verify that there is no other procedures going on this connection
if (_is_reseting || get_control_block(connection_handle)) { if (_is_reseting || get_control_block(connection_handle)) {
return BLE_ERROR_INVALID_STATE; return BLE_ERROR_INVALID_STATE;
@ -1173,18 +1244,18 @@ ble_error_t GattClient::write(
} }
return status; return status;
#endif // BLE_FEATURE_SIGNING #endif // BLE_FEATURE_SIGNING
} else if (cmd == GattClient::GATT_OP_WRITE_REQ) { } else if (cmd == GATT_OP_WRITE_REQ) {
uint8_t* data = nullptr; uint8_t *data = nullptr;
if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH)) { if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH)) {
data = (uint8_t*) malloc(length); data = (uint8_t *) malloc(length);
if (data == nullptr) { if (data == nullptr) {
return BLE_ERROR_NO_MEM; return BLE_ERROR_NO_MEM;
} }
memcpy(data, value, length); memcpy(data, value, length);
} }
WriteControlBlock* write_pcb = new (std::nothrow) WriteControlBlock( WriteControlBlock *write_pcb = new(std::nothrow) WriteControlBlock(
connection_handle, connection_handle,
attribute_handle, attribute_handle,
data, data,
@ -1235,9 +1306,9 @@ void GattClient::onServiceDiscoveryTermination(
ble_error_t GattClient::discoverCharacteristicDescriptors( ble_error_t GattClient::discoverCharacteristicDescriptors(
const DiscoveredCharacteristic& characteristic, const DiscoveredCharacteristic &characteristic,
const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback, const CharacteristicDescriptorDiscovery::DiscoveryCallback_t &discoveryCallback,
const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback const CharacteristicDescriptorDiscovery::TerminationCallback_t &terminationCallback
) )
{ {
// verify that there is no other procedures going on this connection // verify that there is no other procedures going on this connection
@ -1256,7 +1327,7 @@ ble_error_t GattClient::discoverCharacteristicDescriptors(
return BLE_ERROR_NONE; return BLE_ERROR_NONE;
} }
DescriptorDiscoveryControlBlock* discovery_pcb = DescriptorDiscoveryControlBlock *discovery_pcb =
new(std::nothrow) DescriptorDiscoveryControlBlock( new(std::nothrow) DescriptorDiscoveryControlBlock(
characteristic, characteristic,
discoveryCallback, discoveryCallback,
@ -1281,13 +1352,14 @@ ble_error_t GattClient::discoverCharacteristicDescriptors(
bool GattClient::isCharacteristicDescriptorDiscoveryActive( bool GattClient::isCharacteristicDescriptorDiscoveryActive(
const DiscoveredCharacteristic& characteristic const DiscoveredCharacteristic &characteristic
) const { ) const
ProcedureControlBlock* pcb = control_blocks; {
ProcedureControlBlock *pcb = control_blocks;
while (pcb) { while (pcb) {
if (pcb->type == DESCRIPTOR_DISCOVERY_PROCEDURE && if (pcb->type == DESCRIPTOR_DISCOVERY_PROCEDURE &&
static_cast<DescriptorDiscoveryControlBlock*>(pcb)->characteristic == characteristic) { static_cast<DescriptorDiscoveryControlBlock *>(pcb)->characteristic == characteristic) {
return true; return true;
} }
pcb = pcb->next; pcb = pcb->next;
@ -1298,15 +1370,15 @@ bool GattClient::isCharacteristicDescriptorDiscoveryActive(
void GattClient::terminateCharacteristicDescriptorDiscovery( void GattClient::terminateCharacteristicDescriptorDiscovery(
const DiscoveredCharacteristic& characteristic const DiscoveredCharacteristic &characteristic
) )
{ {
ProcedureControlBlock* pcb = control_blocks; ProcedureControlBlock *pcb = control_blocks;
while (pcb) { while (pcb) {
if (pcb->type == DESCRIPTOR_DISCOVERY_PROCEDURE) { if (pcb->type == DESCRIPTOR_DISCOVERY_PROCEDURE) {
DescriptorDiscoveryControlBlock* dpcb = DescriptorDiscoveryControlBlock *dpcb =
static_cast<DescriptorDiscoveryControlBlock*>(pcb); static_cast<DescriptorDiscoveryControlBlock *>(pcb);
if (dpcb->characteristic == characteristic) { if (dpcb->characteristic == characteristic) {
dpcb->done = true; dpcb->done = true;
return; return;
@ -1330,7 +1402,7 @@ ble_error_t GattClient::negotiateAttMtu(
ble_error_t GattClient::reset(void) ble_error_t GattClient::reset(void)
{ {
/* Notify that the instance is about to shut down. */ /* Notify that the instance is about to shut down. */
shutdownCallChain.call(this); shutdownCallChain.call(client);
shutdownCallChain.clear(); shutdownCallChain.clear();
onDataReadCallbackChain.clear(); onDataReadCallbackChain.clear();
@ -1357,6 +1429,7 @@ void GattClient::set_signing_event_handler(
{ {
_signing_event_handler = signing_event_handler; _signing_event_handler = signing_event_handler;
} }
#endif // BLE_FEATURE_SIGNING #endif // BLE_FEATURE_SIGNING
@ -1389,7 +1462,6 @@ void GattClient::on_write_command_sent(
} }
void GattClient::on_termination(connection_handle_t connection_handle) void GattClient::on_termination(connection_handle_t connection_handle)
{ {
if (_termination_callback) { if (_termination_callback) {
@ -1400,10 +1472,10 @@ void GattClient::on_termination(connection_handle_t connection_handle)
void GattClient::on_server_message_received( void GattClient::on_server_message_received(
connection_handle_t connection_handle, connection_handle_t connection_handle,
const AttServerMessage& message const AttServerMessage &message
) )
{ {
switch(message.opcode) { switch (message.opcode) {
case AttributeOpcode::ERROR_RESPONSE: case AttributeOpcode::ERROR_RESPONSE:
case AttributeOpcode::EXCHANGE_MTU_RESPONSE: case AttributeOpcode::EXCHANGE_MTU_RESPONSE:
case AttributeOpcode::FIND_INFORMATION_RESPONSE: case AttributeOpcode::FIND_INFORMATION_RESPONSE:
@ -1433,10 +1505,10 @@ void GattClient::on_server_message_received(
void GattClient::on_server_response( void GattClient::on_server_response(
connection_handle_t connection, connection_handle_t connection,
const AttServerMessage& message const AttServerMessage &message
) )
{ {
ProcedureControlBlock* pcb = get_control_block(connection); ProcedureControlBlock *pcb = get_control_block(connection);
if (pcb == nullptr) { if (pcb == nullptr) {
return; return;
} }
@ -1445,7 +1517,7 @@ void GattClient::on_server_response(
} }
void GattClient::on_server_event(connection_handle_t connection, const AttServerMessage& message) void GattClient::on_server_event(connection_handle_t connection, const AttServerMessage &message)
{ {
GattHVXCallbackParams callbacks_params = { GattHVXCallbackParams callbacks_params = {
(connection_handle_t) connection, 0 (connection_handle_t) connection, 0
@ -1453,8 +1525,8 @@ void GattClient::on_server_event(connection_handle_t connection, const AttServer
switch (message.opcode) { switch (message.opcode) {
case AttributeOpcode::HANDLE_VALUE_NOTIFICATION: { case AttributeOpcode::HANDLE_VALUE_NOTIFICATION: {
const AttHandleValueNotification& notification = const AttHandleValueNotification &notification =
static_cast<const AttHandleValueNotification&>(message); static_cast<const AttHandleValueNotification &>(message);
callbacks_params.handle = notification.attribute_handle; callbacks_params.handle = notification.attribute_handle;
callbacks_params.type = BLE_HVX_NOTIFICATION; callbacks_params.type = BLE_HVX_NOTIFICATION;
callbacks_params.len = notification.attribute_value.size(); callbacks_params.len = notification.attribute_value.size();
@ -1462,8 +1534,8 @@ void GattClient::on_server_event(connection_handle_t connection, const AttServer
} break; } break;
case AttributeOpcode::HANDLE_VALUE_INDICATION: { case AttributeOpcode::HANDLE_VALUE_INDICATION: {
const AttHandleValueIndication& indication = const AttHandleValueIndication &indication =
static_cast<const AttHandleValueIndication&>(message); static_cast<const AttHandleValueIndication &>(message);
callbacks_params.handle = indication.attribute_handle; callbacks_params.handle = indication.attribute_handle;
callbacks_params.type = BLE_HVX_INDICATION; callbacks_params.type = BLE_HVX_INDICATION;
callbacks_params.len = indication.attribute_value.size(); callbacks_params.len = indication.attribute_value.size();
@ -1480,7 +1552,7 @@ void GattClient::on_server_event(connection_handle_t connection, const AttServer
void GattClient::on_transaction_timeout(connection_handle_t connection) void GattClient::on_transaction_timeout(connection_handle_t connection)
{ {
ProcedureControlBlock* pcb = get_control_block(connection); ProcedureControlBlock *pcb = get_control_block(connection);
if (pcb == nullptr) { if (pcb == nullptr) {
return; return;
} }
@ -1489,10 +1561,10 @@ void GattClient::on_transaction_timeout(connection_handle_t connection)
} }
typename GattClient::ProcedureControlBlock* typename GattClient::ProcedureControlBlock *
GattClient::get_control_block(connection_handle_t connection) GattClient::get_control_block(connection_handle_t connection)
{ {
ProcedureControlBlock* it = control_blocks; ProcedureControlBlock *it = control_blocks;
while (it && it->connection_handle != connection) { while (it && it->connection_handle != connection) {
it = it->next; it = it->next;
} }
@ -1500,9 +1572,10 @@ GattClient::get_control_block(connection_handle_t connection)
} }
const typename GattClient::ProcedureControlBlock* const typename GattClient::ProcedureControlBlock *
GattClient::get_control_block(connection_handle_t connection) const { GattClient::get_control_block(connection_handle_t connection) const
ProcedureControlBlock* it = control_blocks; {
ProcedureControlBlock *it = control_blocks;
while (it && it->connection_handle != connection) { while (it && it->connection_handle != connection) {
it = it->next; it = it->next;
} }
@ -1510,13 +1583,14 @@ GattClient::get_control_block(connection_handle_t connection) const {
} }
void GattClient::insert_control_block(ProcedureControlBlock* cb) const { void GattClient::insert_control_block(ProcedureControlBlock *cb) const
{
if (control_blocks == nullptr) { if (control_blocks == nullptr) {
control_blocks = cb; control_blocks = cb;
return; return;
} }
ProcedureControlBlock* current = control_blocks; ProcedureControlBlock *current = control_blocks;
while (current->next) { while (current->next) {
current = current->next; current = current->next;
} }
@ -1524,7 +1598,8 @@ void GattClient::insert_control_block(ProcedureControlBlock* cb) const {
} }
void GattClient::remove_control_block(ProcedureControlBlock* cb) const { void GattClient::remove_control_block(ProcedureControlBlock *cb) const
{
if (control_blocks == nullptr) { if (control_blocks == nullptr) {
return; return;
} }
@ -1534,7 +1609,7 @@ void GattClient::remove_control_block(ProcedureControlBlock* cb) const {
return; return;
} }
ProcedureControlBlock* current = control_blocks; ProcedureControlBlock *current = control_blocks;
while (current->next && current->next != cb) { while (current->next && current->next != cb) {
current = current->next; current = current->next;
} }
@ -1548,9 +1623,10 @@ void GattClient::remove_control_block(ProcedureControlBlock* cb) const {
} }
uint16_t GattClient::get_mtu(connection_handle_t connection) const { uint16_t GattClient::get_mtu(connection_handle_t connection) const
{
uint16_t result = 23; uint16_t result = 23;
if(_pal_client.get_mtu_size((connection_handle_t) connection, result) != BLE_ERROR_NONE) { if (_pal_client.get_mtu_size((connection_handle_t) connection, result) != BLE_ERROR_NONE) {
result = 23; result = 23;
} }
return result; return result;
@ -1575,7 +1651,7 @@ void GattClient::onDataRead(ReadCallback_t callback)
/** /**
* @see GattClient::onDataRead * @see GattClient::onDataRead
*/ */
GattClient::ReadCallbackChain_t& GattClient::onDataRead() GattClient::ReadCallbackChain_t &GattClient::onDataRead()
{ {
return onDataReadCallbackChain; return onDataReadCallbackChain;
} }
@ -1591,7 +1667,7 @@ void GattClient::onDataWritten(WriteCallback_t callback)
/** /**
* @see GattClient::onDataWritten * @see GattClient::onDataWritten
*/ */
GattClient::WriteCallbackChain_t& GattClient::onDataWritten() GattClient::WriteCallbackChain_t &GattClient::onDataWritten()
{ {
return onDataWriteCallbackChain; return onDataWriteCallbackChain;
} }
@ -1607,7 +1683,7 @@ void GattClient::onHVX(HVXCallback_t callback)
/** /**
* @see GattClient::onShutdown * @see GattClient::onShutdown
*/ */
void GattClient::onShutdown(const GattClientShutdownCallback_t& callback) void GattClient::onShutdown(const GattClientShutdownCallback_t &callback)
{ {
shutdownCallChain.add(callback); shutdownCallChain.add(callback);
} }
@ -1615,7 +1691,7 @@ void GattClient::onShutdown(const GattClientShutdownCallback_t& callback)
/** /**
* @see GattClient::onShutdown * @see GattClient::onShutdown
*/ */
template <typename T> template<typename T>
void GattClient::onShutdown(T *objPtr, void (T::*memberPtr)(const GattClient *)) void GattClient::onShutdown(T *objPtr, void (T::*memberPtr)(const GattClient *))
{ {
shutdownCallChain.add(objPtr, memberPtr); shutdownCallChain.add(objPtr, memberPtr);
@ -1624,7 +1700,7 @@ void GattClient::onShutdown(T *objPtr, void (T::*memberPtr)(const GattClient *))
/** /**
* @see GattClient::onShutdown * @see GattClient::onShutdown
*/ */
GattClient::GattClientShutdownCallbackChain_t& GattClient::onShutdown() GattClient::GattClientShutdownCallbackChain_t &GattClient::onShutdown()
{ {
return shutdownCallChain; return shutdownCallChain;
} }
@ -1632,7 +1708,7 @@ GattClient::GattClientShutdownCallbackChain_t& GattClient::onShutdown()
/** /**
* @see GattClient::onHVX * @see GattClient::onHVX
*/ */
GattClient::HVXCallbackChain_t& GattClient::onHVX() GattClient::HVXCallbackChain_t &GattClient::onHVX()
{ {
return onHVXCallbackChain; return onHVXCallbackChain;
} }
@ -1663,6 +1739,7 @@ void GattClient::processHVXEvent(const GattHVXCallbackParams *params)
} }
} }
} // namespace impl
} // namespace ble } // namespace ble
#endif // BLE_FEATURE_GATT_SERVER #endif // BLE_FEATURE_GATT_SERVER

View File

@ -0,0 +1,211 @@
/* mbed Microcontroller Library
* Copyright (c) 2020 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* 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.
*/
/* mbed Microcontroller Library
* Copyright (c) 2006-2020 ARM Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* 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 "ble/GattClient.h"
#include "ble/internal/GattClientImpl.h"
namespace ble {
void GattClient::setEventHandler(EventHandler *handler)
{
impl->setEventHandler(handler);
}
ble_error_t GattClient::launchServiceDiscovery(
ble::connection_handle_t connectionHandle,
ServiceDiscovery::ServiceCallback_t sc,
ServiceDiscovery::CharacteristicCallback_t cc,
const UUID &matchingServiceUUID,
const UUID &matchingCharacteristicUUIDIn
)
{
return impl->launchServiceDiscovery(
connectionHandle, sc, cc, matchingServiceUUID, matchingCharacteristicUUIDIn
);
}
ble_error_t GattClient::discoverServices(
ble::connection_handle_t connectionHandle,
ServiceDiscovery::ServiceCallback_t callback,
const UUID &matchingServiceUUID
)
{
return impl->discoverServices(connectionHandle, callback, matchingServiceUUID);
}
ble_error_t GattClient::discoverServices(
ble::connection_handle_t connectionHandle,
ServiceDiscovery::ServiceCallback_t callback,
GattAttribute::Handle_t startHandle,
GattAttribute::Handle_t endHandle
)
{
return impl->discoverServices(connectionHandle, callback, startHandle, endHandle);
}
bool GattClient::isServiceDiscoveryActive(void) const
{
return impl->isServiceDiscoveryActive();
}
void GattClient::terminateServiceDiscovery(void)
{
return impl->terminateServiceDiscovery();
}
ble_error_t GattClient::read(
ble::connection_handle_t connHandle,
GattAttribute::Handle_t attributeHandle,
uint16_t offset
) const
{
return impl->read(connHandle, attributeHandle, offset);
}
ble_error_t GattClient::write(
GattClient::WriteOp_t cmd,
ble::connection_handle_t connHandle,
GattAttribute::Handle_t attributeHandle,
size_t length,
const uint8_t *value
) const
{
return impl->write(cmd, connHandle, attributeHandle, length, value);
}
/* Event callback handlers. */
void GattClient::onDataRead(ble::ReadCallback_t callback)
{
return impl->onDataRead(callback);
}
ble::ReadCallbackChain_t& GattClient::onDataRead()
{
return impl->onDataRead();
}
void GattClient::onDataWritten(ble::WriteCallback_t callback)
{
impl->onDataWritten(callback);
}
ble::WriteCallbackChain_t& GattClient::onDataWritten()
{
return impl->onDataWritten();
}
void GattClient::onServiceDiscoveryTermination(
ServiceDiscovery::TerminationCallback_t callback
)
{
return impl->onServiceDiscoveryTermination(callback);
}
ble_error_t GattClient::discoverCharacteristicDescriptors(
const DiscoveredCharacteristic& characteristic,
const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback,
const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback
)
{
return impl->discoverCharacteristicDescriptors(
characteristic,
discoveryCallback,
terminationCallback
);
}
bool GattClient::isCharacteristicDescriptorDiscoveryActive(
const DiscoveredCharacteristic& characteristic
) const
{
return impl->isCharacteristicDescriptorDiscoveryActive(characteristic);
}
void GattClient::terminateCharacteristicDescriptorDiscovery(
const DiscoveredCharacteristic& characteristic
)
{
return impl->terminateCharacteristicDescriptorDiscovery(characteristic);
}
ble_error_t GattClient::negotiateAttMtu(ble::connection_handle_t connection)
{
return impl->negotiateAttMtu(connection);
}
void GattClient::onHVX(HVXCallback_t callback)
{
return impl->onHVX(callback);
}
void GattClient::onShutdown(const GattClientShutdownCallback_t& callback)
{
return impl->onShutdown(callback);
}
GattClient::GattClientShutdownCallbackChain_t& GattClient::onShutdown()
{
return impl->onShutdown();
}
GattClient::HVXCallbackChain_t& GattClient::onHVX()
{
return impl->onHVX();
}
ble_error_t GattClient::reset(void)
{
return impl->reset();
}
void GattClient::processReadResponse(const GattReadCallbackParams *params)
{
return impl->processReadResponse(params);
}
void GattClient::processWriteResponse(const GattWriteCallbackParams *params)
{
return impl->processWriteResponse(params);
}
void GattClient::processHVXEvent(const GattHVXCallbackParams *params)
{
return impl->processHVXEvent(params);
}
} // namespace ble