Skip to content

Commit

Permalink
[BREAKING] - Refactor NimBLEUtils
Browse files Browse the repository at this point in the history
* Add functions `NimBLEUtils::taskWait` and `NimBLEUtils::taskRelease` to simplify task blocking/messaging.
* `NimBLEUtils::buildHexData` replaced with `NimBLEUtils::dataToHexString`
* Add missing GAP event strings.
* Add missing return code strings.
* `NimBLEUtils::dumpGapEvent` function removed.
* Event/error code strings optimized.
  • Loading branch information
h2zero committed Nov 12, 2024
1 parent a0221ff commit 1386043
Show file tree
Hide file tree
Showing 12 changed files with 481 additions and 524 deletions.
22 changes: 10 additions & 12 deletions src/NimBLEAdvertisedDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ NimBLEScan* NimBLEAdvertisedDevice::getScan() const {
* @return The number of addresses.
*/
uint8_t NimBLEAdvertisedDevice::getTargetAddressCount() const {
uint8_t count = findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR);
uint8_t count = findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR);
count += findAdvField(BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR);

return count;
Expand All @@ -269,7 +269,7 @@ NimBLEAddress NimBLEAdvertisedDevice::getTargetAddress(uint8_t index) const {
uint8_t count = findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR, index, &data_loc);
if (count < index + 1) {
index -= count;
count = findAdvField(BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR, index, &data_loc);
count = findAdvField(BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR, index, &data_loc);
}

if (count > 0 && data_loc != ULONG_MAX) {
Expand Down Expand Up @@ -368,14 +368,14 @@ size_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t* bytes) co
}

index -= found;
found = findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID32, index, &data_loc);
found = findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID32, index, &data_loc);
if (found > index) {
*bytes = 4;
return data_loc;
}

index -= found;
found = findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID128, index, &data_loc);
found = findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID128, index, &data_loc);
if (found > index) {
*bytes = 16;
return data_loc;
Expand All @@ -389,7 +389,7 @@ size_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t* bytes) co
* @return The number of service data UUIDS in the vector.
*/
uint8_t NimBLEAdvertisedDevice::getServiceDataCount() const {
uint8_t count = findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID16);
uint8_t count = findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID16);
count += findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID32);
count += findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID128);

Expand Down Expand Up @@ -448,7 +448,7 @@ NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) const {
* @return The count of services in the advertising packet.
*/
uint8_t NimBLEAdvertisedDevice::getServiceUUIDCount() const {
uint8_t count = findAdvField(BLE_HS_ADV_TYPE_INCOMP_UUIDS16);
uint8_t count = findAdvField(BLE_HS_ADV_TYPE_INCOMP_UUIDS16);
count += findAdvField(BLE_HS_ADV_TYPE_COMP_UUIDS16);
count += findAdvField(BLE_HS_ADV_TYPE_INCOMP_UUIDS32);
count += findAdvField(BLE_HS_ADV_TYPE_COMP_UUIDS32);
Expand Down Expand Up @@ -695,11 +695,9 @@ std::string NimBLEAdvertisedDevice::toString() const {
}

if (haveManufacturerData()) {
char* pHex =
NimBLEUtils::buildHexData(nullptr, (uint8_t*)getManufacturerData().data(), getManufacturerData().length());
res += ", manufacturer data: ";
res += pHex;
free(pHex);
auto mfgData = getManufacturerData();
res += ", manufacturer data: ";
res += NimBLEUtils::dataToHexString(reinterpret_cast<const uint8_t*>(mfgData.data()), mfgData.length());
}

if (haveServiceUUID()) {
Expand All @@ -714,7 +712,7 @@ std::string NimBLEAdvertisedDevice::toString() const {
}

if (haveServiceData()) {
uint8_t count = getServiceDataCount();
uint8_t count = getServiceDataCount();
res += "\nService Data:";
for (uint8_t i = 0; i < count; i++) {
res += "\nUUID: " + std::string(getServiceDataUUID(i));
Expand Down
87 changes: 28 additions & 59 deletions src/NimBLEClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,11 +201,10 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes,
deleteServices();
}

int rc = 0;
m_asyncConnect = asyncConnect;
m_exchangeMTU = exchangeMTU;
TaskHandle_t curTask = xTaskGetCurrentTaskHandle();
BleTaskData taskData = {this, curTask, 0, nullptr};
int rc = 0;
m_asyncConnect = asyncConnect;
m_exchangeMTU = exchangeMTU;
NimBLETaskData taskData(this);
if (!asyncConnect) {
m_pTaskData = &taskData;
}
Expand Down Expand Up @@ -276,12 +275,8 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes,
return true;
}

# ifdef ulTaskNotifyValueClear
// Clear the task notification value to ensure we block
ulTaskNotifyValueClear(curTask, ULONG_MAX);
# endif
// Wait for the connect timeout time +1 second for the connection to complete
if (ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(m_connectTimeout + 1000)) == pdFALSE) {
if (!NimBLEUtils::taskWait(*m_pTaskData, m_connectTimeout + 1000)) {
m_pTaskData = nullptr;
// If a connection was made but no response from MTU exchange; disconnect
if (isConnected()) {
Expand All @@ -296,9 +291,9 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes,

return false;

} else if (taskData.rc != 0) {
m_lastErr = taskData.rc;
NIMBLE_LOGE(LOG_TAG, "Connection failed; status=%d %s", taskData.rc, NimBLEUtils::returnCodeToString(taskData.rc));
} else if (taskData.m_flags != 0) {
m_lastErr = taskData.m_flags;
NIMBLE_LOGE(LOG_TAG, "Connection failed; status=%d %s", m_lastErr, NimBLEUtils::returnCodeToString(m_lastErr));
// If the failure was not a result of a disconnection, make sure we disconnect now to avoid dangling connections
if (isConnected()) {
disconnect();
Expand All @@ -324,9 +319,8 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes,
*/
bool NimBLEClient::secureConnection() const {
NIMBLE_LOGD(LOG_TAG, ">> secureConnection()");
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
BleTaskData taskData = {const_cast<NimBLEClient*>(this), cur_task, 0, nullptr};
int retryCount = 1;
NimBLETaskData taskData(const_cast<NimBLEClient*>(this));
int retryCount = 1;

do {
m_pTaskData = &taskData;
Expand All @@ -337,16 +331,12 @@ bool NimBLEClient::secureConnection() const {
return false;
}

# ifdef ulTaskNotifyValueClear
// Clear the task notification value to ensure we block
ulTaskNotifyValueClear(cur_task, ULONG_MAX);
# endif
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
} while (taskData.rc == (BLE_HS_ERR_HCI_BASE + BLE_ERR_PINKEY_MISSING) && retryCount--);
NimBLEUtils::taskWait(*m_pTaskData, BLE_NPL_TIME_FOREVER);
} while (taskData.m_flags == (BLE_HS_ERR_HCI_BASE + BLE_ERR_PINKEY_MISSING) && retryCount--);

if (taskData.rc != 0) {
m_lastErr = taskData.rc;
NIMBLE_LOGE(LOG_TAG, "secureConnection: failed rc=%d", taskData.rc);
if (taskData.m_flags != 0) {
m_lastErr = taskData.m_flags;
NIMBLE_LOGE(LOG_TAG, "secureConnection: failed rc=%d", taskData.m_flags);
return false;
}

Expand Down Expand Up @@ -736,9 +726,8 @@ bool NimBLEClient::retrieveServices(const NimBLEUUID* uuidFilter) {
return false;
}

int rc = 0;
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
BleTaskData taskData = {this, cur_task, 0, nullptr};
int rc = 0;
NimBLETaskData taskData(this);

if (uuidFilter == nullptr) {
rc = ble_gattc_disc_all_svcs(m_connHandle, NimBLEClient::serviceDiscoveredCB, &taskData);
Expand All @@ -752,24 +741,15 @@ bool NimBLEClient::retrieveServices(const NimBLEUUID* uuidFilter) {
return false;
}

# ifdef ulTaskNotifyValueClear
// Clear the task notification value to ensure we block
ulTaskNotifyValueClear(cur_task, ULONG_MAX);
# endif

// wait until we have all the services
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
m_lastErr = taskData.rc;

if (taskData.rc == 0) {
NimBLEUtils::taskWait(taskData, BLE_NPL_TIME_FOREVER);
rc = taskData.m_flags;
if (rc == 0 || rc == BLE_HS_EDONE) {
return true;
} else {
NIMBLE_LOGE(LOG_TAG,
"Could not retrieve services, rc=%d %s",
taskData.rc,
NimBLEUtils::returnCodeToString(taskData.rc));
return false;
}

m_lastErr = rc;
NIMBLE_LOGE(LOG_TAG, "Could not retrieve services, rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
return false;
} // getServices

/**
Expand All @@ -786,8 +766,8 @@ int NimBLEClient::serviceDiscoveredCB(uint16_t connHandle,
error->status,
(error->status == 0) ? service->start_handle : -1);

BleTaskData* pTaskData = (BleTaskData*)arg;
NimBLEClient* pClient = (NimBLEClient*)pTaskData->pATT;
NimBLETaskData* pTaskData = (NimBLETaskData*)arg;
NimBLEClient* pClient = (NimBLEClient*)pTaskData->m_pInstance;

// Make sure the service discovery is for this device
if (pClient->getConnHandle() != connHandle) {
Expand All @@ -800,15 +780,7 @@ int NimBLEClient::serviceDiscoveredCB(uint16_t connHandle,
return 0;
}

if (error->status == BLE_HS_EDONE) {
pTaskData->rc = 0;
} else {
NIMBLE_LOGE(LOG_TAG, "serviceDiscoveredCB() rc=%d %s", error->status, NimBLEUtils::returnCodeToString(error->status));
pTaskData->rc = error->status;
}

xTaskNotifyGive(pTaskData->task);

NimBLEUtils::taskRelease(*pTaskData, error->status);
NIMBLE_LOGD(LOG_TAG, "<< Service Discovered");
return error->status;
}
Expand Down Expand Up @@ -1204,10 +1176,7 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) {
} // Switch

if (pClient->m_pTaskData != nullptr) {
pClient->m_pTaskData->rc = rc;
if (pClient->m_pTaskData->task) {
xTaskNotifyGive(pClient->m_pTaskData->task);
}
NimBLEUtils::taskRelease(*pClient->m_pTaskData, rc);
pClient->m_pTaskData = nullptr;
}

Expand Down
4 changes: 2 additions & 2 deletions src/NimBLEClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class NimBLEAdvertisedDevice;
class NimBLEAttValue;
class NimBLEClientCallbacks;
class NimBLEConnInfo;
struct BleTaskData;
struct NimBLETaskData;

/**
* @brief A model of a BLE client.
Expand Down Expand Up @@ -112,7 +112,7 @@ class NimBLEClient {
NimBLEAddress m_peerAddress;
mutable int m_lastErr;
int32_t m_connectTimeout;
mutable BleTaskData* m_pTaskData;
mutable NimBLETaskData* m_pTaskData;
std::vector<NimBLERemoteService*> m_svcVec;
NimBLEClientCallbacks* m_pClientCallbacks;
uint16_t m_connHandle;
Expand Down
36 changes: 12 additions & 24 deletions src/NimBLERemoteCharacteristic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(
NIMBLE_LOGD(LOG_TAG, "Descriptor Discovery >> status: %d handle: %d", rc, (rc == 0) ? dsc->handle : -1);

auto filter = (desc_filter_t*)arg;
auto pTaskData = (BleTaskData*)filter->task_data;
const auto pChr = (NimBLERemoteCharacteristic*)pTaskData->pATT;
auto pTaskData = (NimBLETaskData*)filter->task_data;
const auto pChr = (NimBLERemoteCharacteristic*)pTaskData->m_pInstance;
const NimBLEUUID* uuidFilter = filter->uuid;

if (pChr->getHandle() != chr_val_handle) {
Expand All @@ -85,12 +85,8 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(
pChr->m_vDescriptors.push_back(new NimBLERemoteDescriptor(pChr, dsc));
}

if (rc != 0) {
pTaskData->rc = rc == BLE_HS_EDONE ? 0 : rc;
NIMBLE_LOGD(LOG_TAG, "<< Descriptor Discovery");
xTaskNotifyGive(pTaskData->task);
}

NimBLEUtils::taskRelease(*pTaskData, rc);
NIMBLE_LOGD(LOG_TAG, "<< Descriptor Discovery");
return rc;
}

Expand All @@ -101,9 +97,8 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(
bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuidFilter) const {
NIMBLE_LOGD(LOG_TAG, ">> retrieveDescriptors() for characteristic: %s", getUUID().toString().c_str());

TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
BleTaskData taskData = {const_cast<NimBLERemoteCharacteristic*>(this), cur_task, 0, nullptr};
desc_filter_t filter = {uuidFilter, &taskData};
NimBLETaskData taskData(const_cast<NimBLERemoteCharacteristic*>(this));
desc_filter_t filter = {uuidFilter, &taskData};

int rc = ble_gattc_disc_all_dscs(getClient()->getConnHandle(),
getHandle(),
Expand All @@ -115,22 +110,15 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuidFilte
return false;
}

# ifdef ulTaskNotifyValueClear
// Clear the task notification value to ensure we block
ulTaskNotifyValueClear(cur_task, ULONG_MAX);
# endif
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);

if (taskData.rc != 0) {
NIMBLE_LOGE(LOG_TAG,
"<< retrieveDescriptors(): failed: rc=%d %s",
taskData.rc,
NimBLEUtils::returnCodeToString(taskData.rc));
} else {
NimBLEUtils::taskWait(taskData, BLE_NPL_TIME_FOREVER);
rc = taskData.m_flags;
if (rc == 0 || rc == BLE_HS_EDONE) {
NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): found %d descriptors.", m_vDescriptors.size());
return true;
}

return taskData.rc == 0;
NIMBLE_LOGE(LOG_TAG, "<< retrieveDescriptors(): failed: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
return false;
} // retrieveDescriptors

/**
Expand Down
35 changes: 16 additions & 19 deletions src/NimBLERemoteService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle,
const ble_gatt_chr* chr,
void* arg) {
NIMBLE_LOGD(LOG_TAG, "Characteristic Discovery >>");
auto pTaskData = (BleTaskData*)arg;
const auto pSvc = (NimBLERemoteService*)pTaskData->pATT;
auto pTaskData = (NimBLETaskData*)arg;
const auto pSvc = (NimBLERemoteService*)pTaskData->m_pInstance;

// Make sure the discovery is for this device
if (pSvc->getClient()->getConnHandle() != conn_handle) {
Expand All @@ -155,12 +155,11 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle,

if (error->status == 0) {
pSvc->m_vChars.push_back(new NimBLERemoteCharacteristic(pSvc, chr));
} else {
pTaskData->rc = error->status == BLE_HS_EDONE ? 0 : error->status;
NIMBLE_LOGD(LOG_TAG, "<< Characteristic Discovery");
xTaskNotifyGive(pTaskData->task);
return 0;
}

NimBLEUtils::taskRelease(*pTaskData, error->status);
NIMBLE_LOGD(LOG_TAG, "<< Characteristic Discovery");
return error->status;
}

Expand All @@ -171,9 +170,8 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle,
*/
bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID* uuidFilter) const {
NIMBLE_LOGD(LOG_TAG, ">> retrieveCharacteristics()");
int rc = 0;
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
BleTaskData taskData = {const_cast<NimBLERemoteService*>(this), cur_task, 0, nullptr};
int rc = 0;
NimBLETaskData taskData(const_cast<NimBLERemoteService*>(this));

if (uuidFilter == nullptr) {
rc = ble_gattc_disc_all_chrs(m_pClient->getConnHandle(),
Expand All @@ -190,21 +188,20 @@ bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID* uuidFilter)
&taskData);
}

if (rc == 0) {
# ifdef ulTaskNotifyValueClear
// Clear the task notification value to ensure we block
ulTaskNotifyValueClear(cur_task, ULONG_MAX);
# endif
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_chrs rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
return false;
}

if (taskData.rc != 0) {
NIMBLE_LOGE(LOG_TAG, "<< retrieveCharacteristics() rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
} else {
NimBLEUtils::taskWait(taskData, BLE_NPL_TIME_FOREVER);
rc = taskData.m_flags;
if (rc == 0 || rc == BLE_HS_EDONE) {
NIMBLE_LOGD(LOG_TAG, "<< retrieveCharacteristics()");
return true;
}

return taskData.rc == 0;
NIMBLE_LOGE(LOG_TAG, "<< retrieveCharacteristics() rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
return false;
} // retrieveCharacteristics

/**
Expand Down
Loading

0 comments on commit 1386043

Please sign in to comment.