diff --git a/connectivity/FEATURE_BLE/include/ble/gatt/GattCharacteristic.h b/connectivity/FEATURE_BLE/include/ble/gatt/GattCharacteristic.h index 2e0510854b..3b26255834 100644 --- a/connectivity/FEATURE_BLE/include/ble/gatt/GattCharacteristic.h +++ b/connectivity/FEATURE_BLE/include/ble/gatt/GattCharacteristic.h @@ -1429,6 +1429,12 @@ public: GattCharacteristic(const GattCharacteristic &) = delete; GattCharacteristic& operator=(const GattCharacteristic &) = delete; + ~GattCharacteristic() { + if(_implicit_cccd != nullptr) { + delete _implicit_cccd; + } + } + public: /** @@ -1714,7 +1720,7 @@ public: */ uint8_t getDescriptorCount() const { - return _descriptorCount; + return (_implicit_cccd == nullptr? _descriptorCount : _descriptorCount+1); } /** @@ -1750,16 +1756,40 @@ public: * * @return A pointer the requested descriptor if @p index is within the * range of the descriptor array or nullptr otherwise. + * + * @note if this characteristic has an implicitly-created CCCD this + * descriptor will be available at the highest index + * (ie: return of getDescriptorCount() - 1) */ GattAttribute *getDescriptor(uint8_t index) { - if (index >= _descriptorCount) { + + if(index == _descriptorCount) { + // If _implicit_cccd is nullptr, we want to return that anyway + return _implicit_cccd; + } + else if (index > _descriptorCount) { return nullptr; } return _descriptors[index]; } + /** + * Sets this GattCharacteristic's implicitly-created CCCD, if + * applicable. + * + * @note once this is called, the pointed-to GattAttribute + * is owned by this GattCharacteristic and will be deleted + * during this object's destructor + * + * @note this is an internal function and should not be called + * by the application + */ + void _setImplicitCCCD(GattAttribute *implicit_cccd) { + _implicit_cccd = implicit_cccd; + } + private: /** @@ -1783,6 +1813,16 @@ private: */ uint8_t _descriptorCount; + /** + * Pointer to characteristic's implicit CCCD, if applicable + * + * @note this is only populated if the stack creates an implicit CCCD + * for this GattCharacteristic. If the descriptors array passed into + * the constructor includes a CCCD this field is left as nullptr to + * indicate the CCCD was explicitly created. + */ + GattAttribute* _implicit_cccd; + /** * The registered callback handler for read authorization reply. */ diff --git a/connectivity/FEATURE_BLE/source/cordio/source/GattServerImpl.cpp b/connectivity/FEATURE_BLE/source/cordio/source/GattServerImpl.cpp index a7ca14d567..e1bc17eccf 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/GattServerImpl.cpp +++ b/connectivity/FEATURE_BLE/source/cordio/source/GattServerImpl.cpp @@ -588,6 +588,23 @@ ble_error_t GattServer::insert_cccd( cccds[cccd_cnt].secLevel = characteristic->getUpdateSecurityRequirement().value(); cccd_handles[cccd_cnt] = characteristic->getValueAttribute().getHandle(); + /** + * Set the characteristic's implicitly-created CCCD + * + * Ownership is passed to the GattCharacteristic + */ + GattAttribute* implicit_cccd = new GattAttribute( + CCCD_UUID, + attribute_it->pValue, + *attribute_it->pLen, + attribute_it->maxLen, + false); + + implicit_cccd->setHandle(cccds[cccd_cnt].handle); + implicit_cccd->allowRead(true); + implicit_cccd->allowWrite(true); + characteristic->_setImplicitCCCD(implicit_cccd); + cccd_cnt++; attribute_it++;