From d33b02818adfb54c0de4ee174888ff55a1b62474 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 10 Jan 2018 14:31:52 +0000 Subject: [PATCH] BLE: Implement Generic GattClient reset logic. --- .../ble/generic/GenericGattClient.h | 1 + .../source/generic/GenericGattClient.cpp | 60 +++++++++++++++++-- 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericGattClient.h b/features/FEATURE_BLE/ble/generic/GenericGattClient.h index 364d17b270..268673e522 100644 --- a/features/FEATURE_BLE/ble/generic/GenericGattClient.h +++ b/features/FEATURE_BLE/ble/generic/GenericGattClient.h @@ -137,6 +137,7 @@ private: pal::GattClient* const _pal_client; ServiceDiscovery::TerminationCallback_t _termination_callback; mutable ProcedureControlBlock* control_blocks; + bool _is_reseting; }; } diff --git a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp index 9028eca7b3..97c6d57fc0 100644 --- a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp @@ -74,6 +74,11 @@ struct GenericGattClient::ProcedureControlBlock { */ virtual void handle_timeout_error(GenericGattClient* client) = 0; + /** + * Function called when the procedure is aborted + */ + virtual void abort(GenericGattClient *client) = 0; + procedure_type_t type; Gap::Handle_t connection_handle; ProcedureControlBlock* next; @@ -111,6 +116,10 @@ struct GenericGattClient::DiscoveryControlBlock : public ProcedureControlBlock { terminate(client); } + virtual void abort(GenericGattClient *client) { + terminate(client); + } + virtual void handle(GenericGattClient* client, const AttServerMessage& message) { // if end of discovery has been requested, ends it immediately if (done) { @@ -436,6 +445,19 @@ struct GenericGattClient::ReadControlBlock : public ProcedureControlBlock { terminate(client, response); } + virtual void abort(GenericGattClient *client) { + GattReadCallbackParams response = { + connection_handle, + attribute_handle, + offset, + 0, // size of 0 + NULL, // no data + BLE_ERROR_INVALID_STATE, + + }; + terminate(client, response); + } + void terminate(GenericGattClient* client, const GattReadCallbackParams& response) { client->remove_control_block(this); client->processReadResponse(&response); @@ -617,6 +639,17 @@ struct GenericGattClient::WriteControlBlock : public ProcedureControlBlock { terminate(client, response); } + virtual void abort(GenericGattClient *client) { + GattWriteCallbackParams response = { + connection_handle, + attribute_handle, + GattWriteCallbackParams::OP_WRITE_REQ, + BLE_ERROR_INVALID_STATE, + 0x00 + }; + terminate(client, response); + } + void terminate(GenericGattClient* client, const GattWriteCallbackParams& response) { client->remove_control_block(this); client->processWriteResponse(&response); @@ -814,6 +847,10 @@ struct GenericGattClient::DescriptorDiscoveryControlBlock : public ProcedureCont terminate(client, BLE_ERROR_UNSPECIFIED); } + virtual void abort(GenericGattClient *client) { + terminate(client, BLE_ERROR_INVALID_STATE); + } + virtual void handle(GenericGattClient* client, const AttServerMessage& message) { if (done) { terminate(client, BLE_ERROR_NONE); @@ -892,7 +929,8 @@ struct GenericGattClient::DescriptorDiscoveryControlBlock : public ProcedureCont GenericGattClient::GenericGattClient(pal::GattClient* pal_client) : _pal_client(pal_client), _termination_callback(), - control_blocks(NULL) { + control_blocks(NULL), + _is_reseting(false) { _pal_client->when_server_message_received( mbed::callback(this, &GenericGattClient::on_server_message_received) ); @@ -909,7 +947,7 @@ ble_error_t GenericGattClient::launchServiceDiscovery( const UUID& matching_characteristic_uuid ) { // verify that there is no other procedures going on this connection - if (get_control_block(connection_handle)) { + if (_is_reseting || get_control_block(connection_handle)) { return BLE_ERROR_INVALID_STATE; } @@ -988,7 +1026,7 @@ ble_error_t GenericGattClient::read( uint16_t offset) const { // verify that there is no other procedures going on this connection - if (get_control_block(connection_handle)) { + if (_is_reseting || get_control_block(connection_handle)) { return BLE_ERROR_INVALID_STATE; } @@ -1032,7 +1070,7 @@ ble_error_t GenericGattClient::write( const uint8_t* value ) const { // verify that there is no other procedures going on this connection - if (get_control_block(connection_handle)) { + if (_is_reseting || get_control_block(connection_handle)) { return BLE_ERROR_INVALID_STATE; } @@ -1111,7 +1149,7 @@ ble_error_t GenericGattClient::discoverCharacteristicDescriptors( const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback ) { // verify that there is no other procedures going on this connection - if (get_control_block(characteristic.getConnectionHandle())) { + if (_is_reseting || get_control_block(characteristic.getConnectionHandle())) { return BLE_ERROR_INVALID_STATE; } @@ -1186,7 +1224,17 @@ void GenericGattClient::terminateCharacteristicDescriptorDiscovery( } ble_error_t GenericGattClient::reset(void) { - return BLE_ERROR_NOT_IMPLEMENTED; + + // _is_reseting prevent executions of new procedure while the instance resets. + // otherwise new procedures can be launched from callbacks generated by the + // reset. + _is_reseting = true; + while (control_blocks) { + control_blocks->abort(this); + } + _is_reseting = false; + + return BLE_ERROR_NONE; } void GenericGattClient::on_termination(Gap::Handle_t connection_handle) {