From cdc8845b3cd254727bb9d307f6f23601e50e6908 Mon Sep 17 00:00:00 2001 From: Paul Szczeanek Date: Wed, 23 Dec 2020 11:57:43 +0000 Subject: [PATCH 1/2] copy authorsation callbacks to gattserver --- .../source/cordio/source/GattServerImpl.cpp | 77 +++++++++++++------ .../source/cordio/source/GattServerImpl.h | 19 ++++- 2 files changed, 68 insertions(+), 28 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/cordio/source/GattServerImpl.cpp b/connectivity/FEATURE_BLE/source/cordio/source/GattServerImpl.cpp index d171bb05120..786012e7dd7 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/GattServerImpl.cpp +++ b/connectivity/FEATURE_BLE/source/cordio/source/GattServerImpl.cpp @@ -416,11 +416,34 @@ ble_error_t GattServer::insert_characteristic_value_attribute( characteristic->isReadAuthorizationEnabled() || characteristic->isWriteAuthorizationEnabled() ) { - if (_auth_char_count >= MBED_CONF_BLE_API_IMPLEMENTATION_MAX_CHARACTERISTIC_AUTHORISATION_COUNT) { + if (_auth_callbacks_count >= MBED_CONF_BLE_API_IMPLEMENTATION_MAX_CHARACTERISTIC_AUTHORISATION_COUNT) { return BLE_ERROR_NO_MEM; } - _auth_char[_auth_char_count] = characteristic; - ++_auth_char_count; + + char_auth_callback *new_cb = (char_auth_callback *) alloc_block(sizeof(char_auth_callback)); + + if (!new_cb) { + return BLE_ERROR_NO_MEM; + } + + new_cb->read_cb = characteristic->readAuthorizationCallback; + new_cb->write_cb = characteristic->writeAuthorizationCallback; + new_cb->handle = characteristic->getValueHandle(); + new_cb->update_security = characteristic->getUpdateSecurityRequirement(); + new_cb->_next = nullptr; + + /* add it to the list */ + if (_auth_callbacks) { + char_auth_callback *last_cb = _auth_callbacks; + while (last_cb->_next) { + last_cb = last_cb->_next; + } + last_cb->_next = new_cb; + } else { + _auth_callbacks = new_cb; + }; + + ++_auth_callbacks_count; } ++attribute_it; @@ -941,7 +964,8 @@ ble_error_t GattServer::reset(ble::GattServer* server) currentHandle = 0; cccd_cnt = 0; - _auth_char_count = 0; + _auth_callbacks_count = 0; + _auth_callbacks = nullptr; AttsCccRegister(cccd_cnt, (attsCccSet_t *) cccds, cccd_cb); @@ -978,8 +1002,8 @@ uint8_t GattServer::atts_read_cb( attsAttr_t *pAttr ) { - GattCharacteristic *auth_char = getInstance().get_auth_char(handle); - if (auth_char && auth_char->isReadAuthorizationEnabled()) { + char_auth_callback *auth_cb = getInstance().get_auth_callback(handle); + if (auth_cb && auth_cb->read_cb) { GattReadAuthCallbackParams read_auth_params = { connId, handle, @@ -989,9 +1013,10 @@ uint8_t GattServer::atts_read_cb( AUTH_CALLBACK_REPLY_SUCCESS }; - GattAuthCallbackReply_t ret = auth_char->authorizeRead(&read_auth_params); - if (ret != AUTH_CALLBACK_REPLY_SUCCESS) { - return ret & 0xFF; + auth_cb->read_cb.call(&read_auth_params); + + if (read_auth_params.authorizationReply != AUTH_CALLBACK_REPLY_SUCCESS) { + return read_auth_params.authorizationReply & 0xFF; } pAttr->pValue = read_auth_params.data; @@ -1021,8 +1046,8 @@ uint8_t GattServer::atts_write_cb( attsAttr_t *pAttr ) { - GattCharacteristic* auth_char = getInstance().get_auth_char(handle); - if (auth_char && auth_char->isWriteAuthorizationEnabled()) { + char_auth_callback* auth_cb = getInstance().get_auth_callback(handle); + if (auth_cb && auth_cb->write_cb) { GattWriteAuthCallbackParams write_auth_params = { connId, handle, @@ -1032,9 +1057,10 @@ uint8_t GattServer::atts_write_cb( AUTH_CALLBACK_REPLY_SUCCESS }; - GattAuthCallbackReply_t ret = auth_char->authorizeWrite(&write_auth_params); - if (ret!= AUTH_CALLBACK_REPLY_SUCCESS) { - return ret & 0xFF; + auth_cb->write_cb.call(&write_auth_params); + + if (write_auth_params.authorizationReply != AUTH_CALLBACK_REPLY_SUCCESS) { + return write_auth_params.authorizationReply & 0xFF; } } @@ -1329,14 +1355,16 @@ void *GattServer::alloc_block(size_t block_size) return block->data; } -GattCharacteristic *GattServer::get_auth_char(uint16_t value_handle) +GattServer::char_auth_callback *GattServer::get_auth_callback(uint16_t value_handle) { - for (size_t i = 0; i < _auth_char_count; ++i) { - if (_auth_char[i]->getValueHandle() == value_handle) { - return _auth_char[i]; + GattServer::char_auth_callback* current = _auth_callbacks; + while (current) { + if (current->handle == value_handle) { + break; } + current = current->_next; } - return nullptr; + return current; } bool GattServer::get_cccd_index_by_cccd_handle(GattAttribute::Handle_t cccd_handle, uint8_t &idx) const @@ -1364,13 +1392,12 @@ bool GattServer::is_update_authorized( GattAttribute::Handle_t value_handle ) { - GattCharacteristic *auth_char = get_auth_char(value_handle); - if (!auth_char) { + char_auth_callback *auth_cb = get_auth_callback(value_handle); + if (!auth_cb) { return true; } - att_security_requirement_t sec_req = - auth_char->getUpdateSecurityRequirement(); + const att_security_requirement_t sec_req = auth_cb->update_security; if (sec_req == att_security_requirement_t::NONE) { return true; @@ -1426,8 +1453,8 @@ GattServer::GattServer() : cccd_values(), cccd_handles(), cccd_cnt(0), - _auth_char(), - _auth_char_count(0), + _auth_callbacks(nullptr), + _auth_callbacks_count(0), generic_access_service(), generic_attribute_service(), registered_service(nullptr), diff --git a/connectivity/FEATURE_BLE/source/cordio/source/GattServerImpl.h b/connectivity/FEATURE_BLE/source/cordio/source/GattServerImpl.h index 0d60cb6f039..0fb255c1feb 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/GattServerImpl.h +++ b/connectivity/FEATURE_BLE/source/cordio/source/GattServerImpl.h @@ -185,6 +185,19 @@ class GattServer : public PalSigningMonitor { GapAdvertisingData::Appearance getAppearance(); #endif // Disabled until reworked and reintroduced to GattServer API +private: + struct char_auth_callback { + /** The registered callback handler for read authorization reply. */ + FunctionPointerWithContext read_cb; + /** The registered callback handler for write authorization reply. */ + FunctionPointerWithContext write_cb; + /** built in list */ + char_auth_callback *_next = nullptr; + /** Characteristic handle the callbacks belong to. */ + ble::attribute_handle_t handle = 0; + /** security requirement of update operations */ + ble::att_security_requirement_t update_security = ble::att_security_requirement_t::NONE; + }; public: /** @@ -274,7 +287,7 @@ class GattServer : public PalSigningMonitor { void *alloc_block(size_t block_size); - GattCharacteristic *get_auth_char(uint16_t value_handle); + char_auth_callback *get_auth_callback(uint16_t value_handle); bool get_cccd_index_by_cccd_handle(GattAttribute::Handle_t cccd_handle, uint8_t &idx) const; @@ -354,8 +367,8 @@ class GattServer : public PalSigningMonitor { uint16_t cccd_handles[MBED_CONF_BLE_API_IMPLEMENTATION_MAX_CCCD_COUNT]; uint8_t cccd_cnt; - GattCharacteristic *_auth_char[MBED_CONF_BLE_API_IMPLEMENTATION_MAX_CHARACTERISTIC_AUTHORISATION_COUNT]; - uint8_t _auth_char_count; + char_auth_callback *_auth_callbacks; + uint8_t _auth_callbacks_count; struct { attsGroup_t service; From 5e99ea8d7e387ba165f723672e6856b1242c6034 Mon Sep 17 00:00:00 2001 From: Paul Szczeanek Date: Wed, 23 Dec 2020 11:58:11 +0000 Subject: [PATCH 2/2] correct the documentation for GattServer::addService --- connectivity/FEATURE_BLE/include/ble/GattServer.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/connectivity/FEATURE_BLE/include/ble/GattServer.h b/connectivity/FEATURE_BLE/include/ble/GattServer.h index f14126bc025..682911159eb 100644 --- a/connectivity/FEATURE_BLE/include/ble/GattServer.h +++ b/connectivity/FEATURE_BLE/include/ble/GattServer.h @@ -316,14 +316,18 @@ class GattServer { * * The process assigns a unique attribute handle to all the elements added * into the attribute table. This handle is an ID that must be used for - * subsequent interractions with the elements. + * subsequent interactions with the elements. * * @note There is no mirror function that removes a single service. * Application code can remove all the registered services by calling * reset(). * - * @attention Service, characteristics and descriptors objects registered - * within the GattServer must remain reachable until reset() is called. + * @attention GattServer allocates its own memory for all the attributes. + * The GattServer will set the handles on the service passed in and the + * characteristics it contains. You may record the handles you want to + * interact with in the future. After that the service and characteristics + * you passed in as the parameter may be freed. To write to the GattServer + * instances of the characteristics you have to use the saved handles. * * @param[in] service The service to be added; attribute handle of services, * characteristic and characteristic descriptors are updated by the