mirror of https://github.com/ARMmbed/mbed-os.git
ble: GattClient PIMPL
parent
909676d159
commit
e3cf59e6cd
|
@ -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;
|
||||||
|
|
|
@ -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__ */
|
||||||
|
|
|
@ -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 ¬ification =
|
||||||
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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue