refactor(RemoteChar): Reduce nesting

* Renamed desc_filter_t to NimBLEDescriptorFilter
* Added NimBLERemoteDescriptor pointer to NimBLEDescriptorFilter
* retrieveDescriptors changed to take NimBLEDescriptorFilter pointer
* General cleanup
This commit is contained in:
thekurtovic 2025-01-10 18:55:41 -05:00
parent 5ac7272f5d
commit d64e087968
2 changed files with 60 additions and 79 deletions

View file

@ -27,17 +27,18 @@
# include <climits> # include <climits>
typedef struct { struct NimBLEDescriptorFilter {
const NimBLEUUID* uuid; NimBLERemoteDescriptor* dsc;
void* task_data; const NimBLEUUID* uuid;
} desc_filter_t; void* taskData;
};
static const char* LOG_TAG = "NimBLERemoteCharacteristic"; static const char* LOG_TAG = "NimBLERemoteCharacteristic";
/** /**
* @brief Constructor. * @brief Constructor.
* @param [in] svc A pointer to the service this characteristic belongs to. * @param [in] svc A pointer to the service this characteristic belongs to.
* @param [in] ble_gatt_chr struct defined as: * @param [in] chr struct defined as:
* struct ble_gatt_chr { * struct ble_gatt_chr {
* uint16_t def_handle; * uint16_t def_handle;
* uint16_t val_handle; * uint16_t val_handle;
@ -63,66 +64,59 @@ 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( int NimBLERemoteCharacteristic::descriptorDiscCB(
uint16_t conn_handle, const ble_gatt_error* error, uint16_t chr_val_handle, 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) {
int rc = error->status; int rc = error->status;
NIMBLE_LOGD(LOG_TAG, "Descriptor Discovery >> status: %d handle: %d", rc, (rc == 0) ? dsc->handle : -1); NIMBLE_LOGD(LOG_TAG, "Descriptor Discovery >> status: %d handle: %d", rc, (rc == 0) ? dsc->handle : -1);
auto filter = (desc_filter_t*)arg; auto filter = (NimBLEDescriptorFilter*)arg;
auto pTaskData = (NimBLETaskData*)filter->task_data; auto pTaskData = (NimBLETaskData*)filter->taskData;
const auto pChr = (NimBLERemoteCharacteristic*)pTaskData->m_pInstance; const auto pChr = (NimBLERemoteCharacteristic*)pTaskData->m_pInstance;
const NimBLEUUID* uuidFilter = filter->uuid; const auto uuid = filter->uuid; // UUID to filter for
if (pChr->getHandle() != chr_val_handle) {
return 0; // Descriptor not for this characteristic
}
if (rc == 0) {
if (uuidFilter != nullptr) {
if (ble_uuid_cmp(uuidFilter->getBase(), &dsc->uuid.u) == 0) {
rc = BLE_HS_EDONE; // Found the descriptor, stop the search
} else {
return 0; // Not the descriptor we are looking for
}
}
// Results for chrHandle added until rc != 0
// Must find specified UUID if filter is used
if (rc == 0 && pChr->getHandle() == chrHandle
&& (!uuid || 0 == ble_uuid_cmp(uuid->getBase(), &dsc->uuid.u))) {
// 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));
return 0; rc = !!uuid * BLE_HS_EDONE;
} }
NimBLEUtils::taskRelease(*pTaskData, rc); if (rc != 0) {
NIMBLE_LOGD(LOG_TAG, "<< Descriptor Discovery"); NimBLEUtils::taskRelease(*pTaskData, rc);
NIMBLE_LOGD(LOG_TAG, "<< Descriptor Discovery");
}
return rc; return rc;
} }
/** /**
* @brief Populate the descriptors (if any) for this characteristic. * @brief Populate the descriptors (if any) for this characteristic.
* @param [in] the end handle of the characteristic, or the service, whichever comes first. * @param [in] filter Structure containing pointers to descriptor, UUID, and task data.
* @return True if successfully retrieved, success = BLE_HS_EDONE.
*/ */
bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuidFilter) const { bool NimBLERemoteCharacteristic::retrieveDescriptors(NimBLEDescriptorFilter* filter) 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());
NimBLETaskData taskData(const_cast<NimBLERemoteCharacteristic*>(this));
desc_filter_t filter = {uuidFilter, &taskData};
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); filter);
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(taskData, BLE_NPL_TIME_FOREVER); NimBLEUtils::taskWait(filter->taskData, BLE_NPL_TIME_FOREVER);
rc = taskData.m_flags; rc = ((NimBLETaskData*)filter->taskData)->m_flags;
if (rc == 0 || rc == BLE_HS_EDONE) { if (rc != BLE_HS_EDONE) {
NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): found %d descriptors.", m_vDescriptors.size()); NIMBLE_LOGE(LOG_TAG, "<< retrieveDescriptors(): failed: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
return true; return false;
} }
NIMBLE_LOGE(LOG_TAG, "<< retrieveDescriptors(): failed: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); filter->dsc = m_vDescriptors.back();
return false; NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): found %d descriptors.", m_vDescriptors.size());
return true;
} // retrieveDescriptors } // retrieveDescriptors
/** /**
@ -132,51 +126,36 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuidFilte
*/ */
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());
NimBLERemoteDescriptor* pDsc = nullptr; NimBLETaskData taskData(const_cast<NimBLERemoteCharacteristic*>(this));
size_t prev_size = m_vDescriptors.size(); NimBLEDescriptorFilter filter = {nullptr, &uuid, &taskData};
NimBLEUUID uuidTmp;
for (const auto& it : m_vDescriptors) { for (const auto& dsc : m_vDescriptors) {
if (it->getUUID() == uuid) { if (dsc->getUUID() == uuid) {
pDsc = it; filter.dsc = dsc;
goto Done; goto Done;
} }
} }
if (retrieveDescriptors(&uuid)) { if (!retrieveDescriptors(&filter) || filter.dsc) {
if (m_vDescriptors.size() > prev_size) { goto Done;
pDsc = m_vDescriptors.back(); }
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) {
uuidTmp = NimBLEUUID(uuid).to128();
// If the request was successful but 16/32 bit uuid not found retrieveDescriptors(&filter);
// try again with the 128 bit uuid. goto Done;
if (uuid.bitSize() == BLE_UUID_TYPE_16 || uuid.bitSize() == BLE_UUID_TYPE_32) { }
NimBLEUUID uuid128(uuid); // Try again with 16 bit uuid if request succeeded with no uuid found.
uuid128.to128(); // If the uuid was 128 bit but not of the BLE base type this check will fail.
if (retrieveDescriptors(&uuid128)) { uuidTmp = NimBLEUUID(uuid).to16();
if (m_vDescriptors.size() > prev_size) { if (uuidTmp.bitSize() == BLE_UUID_TYPE_16) {
pDsc = m_vDescriptors.back(); retrieveDescriptors(&filter);
}
}
} else {
// If the request was successful but the 128 bit uuid not found
// try again with the 16 bit uuid.
NimBLEUUID uuid16(uuid);
uuid16.to16();
// if the uuid was 128 bit but not of the BLE base type this check will fail
if (uuid16.bitSize() == BLE_UUID_TYPE_16) {
if (retrieveDescriptors(&uuid16)) {
if (m_vDescriptors.size() > prev_size) {
pDsc = m_vDescriptors.back();
}
}
}
}
} }
Done: Done:
NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: %sfound", pDsc ? "" : "not "); NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: %sfound", filter.dsc ? "" : "not ");
return pDsc; return filter.dsc;
} // getDescriptor } // getDescriptor
/** /**
@ -305,7 +284,7 @@ size_t NimBLERemoteCharacteristic::deleteDescriptor(const NimBLEUUID& uuid) cons
* @return True if supported. * @return True if supported.
*/ */
bool NimBLERemoteCharacteristic::canBroadcast() const { bool NimBLERemoteCharacteristic::canBroadcast() const {
return (m_properties & BLE_GATT_CHR_PROP_BROADCAST) != 0; return (m_properties & BLE_GATT_CHR_PROP_BROADCAST);
}; };
/** /**

View file

@ -25,8 +25,10 @@
# include <vector> # include <vector>
# include <functional> # include <functional>
class NimBLEUUID;
class NimBLERemoteService; class NimBLERemoteService;
class NimBLERemoteDescriptor; class NimBLERemoteDescriptor;
struct NimBLEDescriptorFilter;
/** /**
* @brief A model of a remote BLE characteristic. * @brief A model of a remote BLE characteristic.
@ -65,10 +67,10 @@ 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(const NimBLEUUID* uuidFilter = nullptr) const; bool retrieveDescriptors(NimBLEDescriptorFilter* filter = nullptr) const;
static int descriptorDiscCB( static int descriptorDiscCB(
uint16_t conn_handle, const ble_gatt_error* error, uint16_t chr_val_handle, 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);
const NimBLERemoteService* m_pRemoteService{nullptr}; const NimBLERemoteService* m_pRemoteService{nullptr};
uint8_t m_properties{0}; uint8_t m_properties{0};