[BugFix] Provide default task data when retrieving all descriptors.

* Update the descriptor filter when trying again with different UUID sizes.
This commit is contained in:
h2zero 2025-02-06 18:05:21 -07:00 committed by Ryan Powell
parent b6379848ae
commit 60efffdf2b
2 changed files with 26 additions and 22 deletions

View file

@ -63,11 +63,8 @@ NimBLERemoteCharacteristic::~NimBLERemoteCharacteristic() {
/** /**
* @brief Callback used by the API when a descriptor is discovered or search complete. * @brief Callback used by the API when a descriptor is discovered or search complete.
*/ */
int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t connHandle, int NimBLERemoteCharacteristic::descriptorDiscCB(
const ble_gatt_error* error, uint16_t connHandle, const ble_gatt_error* error, uint16_t chrHandle, const ble_gatt_dsc* dsc, void* arg) {
uint16_t chrHandle,
const ble_gatt_dsc* dsc,
void* arg) {
int rc = error->status; int rc = error->status;
auto filter = (NimBLEDescriptorFilter*)arg; auto filter = (NimBLEDescriptorFilter*)arg;
auto pTaskData = (NimBLETaskData*)filter->taskData; auto pTaskData = (NimBLETaskData*)filter->taskData;
@ -77,8 +74,7 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t connHandle,
// Results for chrHandle added until rc != 0 // Results for chrHandle added until rc != 0
// Must find specified UUID if filter is used // Must find specified UUID if filter is used
if (rc == 0 && pChr->getHandle() == chrHandle if (rc == 0 && pChr->getHandle() == chrHandle && (!uuid || 0 == ble_uuid_cmp(uuid->getBase(), &dsc->uuid.u))) {
&& (!uuid || 0 == ble_uuid_cmp(uuid->getBase(), &dsc->uuid.u))) {
// Return BLE_HS_EDONE if the descriptor was found, stop the search // Return BLE_HS_EDONE if the descriptor was found, stop the search
pChr->m_vDescriptors.push_back(new NimBLERemoteDescriptor(pChr, dsc)); pChr->m_vDescriptors.push_back(new NimBLERemoteDescriptor(pChr, dsc));
rc = !!uuid * BLE_HS_EDONE; rc = !!uuid * BLE_HS_EDONE;
@ -93,10 +89,10 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t connHandle,
/** /**
* @brief Populate the descriptors (if any) for this characteristic. * @brief Populate the descriptors (if any) for this characteristic.
* @param [in] filter Structure containing pointers to descriptor, UUID, and task data. * @param [in] pFilter Pointer to a filter containing pointers to descriptor, UUID, and task data.
* @return True if successfully retrieved, success = BLE_HS_EDONE. * @return True if successfully retrieved, success = BLE_HS_EDONE.
*/ */
bool NimBLERemoteCharacteristic::retrieveDescriptors(NimBLEDescriptorFilter* filter) const { bool NimBLERemoteCharacteristic::retrieveDescriptors(NimBLEDescriptorFilter* pFilter) const {
NIMBLE_LOGD(LOG_TAG, ">> retrieveDescriptors() for characteristic: %s", getUUID().toString().c_str()); NIMBLE_LOGD(LOG_TAG, ">> retrieveDescriptors() for characteristic: %s", getUUID().toString().c_str());
// If this is the last handle then there are no descriptors // If this is the last handle then there are no descriptors
@ -105,24 +101,30 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(NimBLEDescriptorFilter* fil
return true; return true;
} }
NimBLETaskData taskData(const_cast<NimBLERemoteCharacteristic*>(this));
NimBLEDescriptorFilter defaultFilter{nullptr, nullptr, &taskData};
if (pFilter == nullptr) {
pFilter = &defaultFilter;
}
int rc = ble_gattc_disc_all_dscs(getClient()->getConnHandle(), int rc = ble_gattc_disc_all_dscs(getClient()->getConnHandle(),
getHandle(), getHandle(),
getRemoteService()->getEndHandle(), getRemoteService()->getEndHandle(),
NimBLERemoteCharacteristic::descriptorDiscCB, NimBLERemoteCharacteristic::descriptorDiscCB,
filter); pFilter);
if (rc != 0) { if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_dscs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_dscs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
return false; return false;
} }
NimBLEUtils::taskWait(filter->taskData, BLE_NPL_TIME_FOREVER); NimBLEUtils::taskWait(pFilter->taskData, BLE_NPL_TIME_FOREVER);
rc = ((NimBLETaskData*)filter->taskData)->m_flags; rc = ((NimBLETaskData*)pFilter->taskData)->m_flags;
if (rc != BLE_HS_EDONE) { if (rc != BLE_HS_EDONE) {
NIMBLE_LOGE(LOG_TAG, "<< retrieveDescriptors(): failed: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); NIMBLE_LOGE(LOG_TAG, "<< retrieveDescriptors(): failed: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
return false; return false;
} }
filter->dsc = m_vDescriptors.back(); pFilter->dsc = m_vDescriptors.back();
NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): found %d descriptors.", m_vDescriptors.size()); NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): found %d descriptors.", m_vDescriptors.size());
return true; return true;
} // retrieveDescriptors } // retrieveDescriptors
@ -134,9 +136,9 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(NimBLEDescriptorFilter* fil
*/ */
NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUUID& uuid) const { NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUUID& uuid) const {
NIMBLE_LOGD(LOG_TAG, ">> getDescriptor: uuid: %s", uuid.toString().c_str()); NIMBLE_LOGD(LOG_TAG, ">> getDescriptor: uuid: %s", uuid.toString().c_str());
NimBLEUUID uuidTmp{uuid};
NimBLETaskData taskData(const_cast<NimBLERemoteCharacteristic*>(this)); NimBLETaskData taskData(const_cast<NimBLERemoteCharacteristic*>(this));
NimBLEDescriptorFilter filter = {nullptr, &uuid, &taskData}; NimBLEDescriptorFilter filter{nullptr, &uuidTmp, &taskData};
NimBLEUUID uuidTmp;
for (const auto& dsc : m_vDescriptors) { for (const auto& dsc : m_vDescriptors) {
if (dsc->getUUID() == uuid) { if (dsc->getUUID() == uuid) {
@ -148,16 +150,18 @@ NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUU
if (!retrieveDescriptors(&filter) || filter.dsc) { if (!retrieveDescriptors(&filter) || filter.dsc) {
goto Done; goto Done;
} }
// Try again with 128 bit uuid if request succeeded with no uuid found.
if (uuid.bitSize() == BLE_UUID_TYPE_16 || uuid.bitSize() == BLE_UUID_TYPE_32) { // Try again with 128 bit uuid if request succeeded but no descriptor found.
uuidTmp = NimBLEUUID(uuid).to128(); if (uuid.bitSize() != BLE_UUID_TYPE_128) {
uuidTmp.to128();
retrieveDescriptors(&filter); retrieveDescriptors(&filter);
goto Done; goto Done;
} }
// Try again with 16 bit uuid if request succeeded with no uuid found.
// If the uuid was 128 bit but not of the BLE base type this check will fail. // If the uuid was 128 bit, try again with 16 bit uuid.
uuidTmp = NimBLEUUID(uuid).to16(); uuidTmp.to16();
if (uuidTmp.bitSize() == BLE_UUID_TYPE_16) { if (uuidTmp.bitSize() == BLE_UUID_TYPE_16) {
filter.uuid = &uuidTmp;
retrieveDescriptors(&filter); retrieveDescriptors(&filter);
} }

View file

@ -67,7 +67,7 @@ class NimBLERemoteCharacteristic : public NimBLERemoteValueAttribute {
~NimBLERemoteCharacteristic(); ~NimBLERemoteCharacteristic();
bool setNotify(uint16_t val, notify_callback notifyCallback = nullptr, bool response = true) const; bool setNotify(uint16_t val, notify_callback notifyCallback = nullptr, bool response = true) const;
bool retrieveDescriptors(NimBLEDescriptorFilter* filter = nullptr) const; bool retrieveDescriptors(NimBLEDescriptorFilter* pFilter = nullptr) const;
static int descriptorDiscCB( static int descriptorDiscCB(
uint16_t connHandle, const ble_gatt_error* error, uint16_t chrHandle, const ble_gatt_dsc* dsc, void* arg); uint16_t connHandle, const ble_gatt_error* error, uint16_t chrHandle, const ble_gatt_dsc* dsc, void* arg);