mirror of
https://github.com/h2zero/esp-nimble-cpp.git
synced 2024-12-18 01:00:47 +01:00
[BREAKING] - Refactor NimBLEUtils
* 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.
This commit is contained in:
parent
65e05e6c57
commit
beac19cc92
12 changed files with 481 additions and 524 deletions
|
@ -253,7 +253,7 @@ NimBLEScan* NimBLEAdvertisedDevice::getScan() const {
|
||||||
* @return The number of addresses.
|
* @return The number of addresses.
|
||||||
*/
|
*/
|
||||||
uint8_t NimBLEAdvertisedDevice::getTargetAddressCount() const {
|
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);
|
count += findAdvField(BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR);
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
|
@ -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);
|
uint8_t count = findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR, index, &data_loc);
|
||||||
if (count < index + 1) {
|
if (count < index + 1) {
|
||||||
index -= count;
|
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) {
|
if (count > 0 && data_loc != ULONG_MAX) {
|
||||||
|
@ -368,14 +368,14 @@ size_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t* bytes) co
|
||||||
}
|
}
|
||||||
|
|
||||||
index -= found;
|
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) {
|
if (found > index) {
|
||||||
*bytes = 4;
|
*bytes = 4;
|
||||||
return data_loc;
|
return data_loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
index -= found;
|
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) {
|
if (found > index) {
|
||||||
*bytes = 16;
|
*bytes = 16;
|
||||||
return data_loc;
|
return data_loc;
|
||||||
|
@ -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.
|
* @return The number of service data UUIDS in the vector.
|
||||||
*/
|
*/
|
||||||
uint8_t NimBLEAdvertisedDevice::getServiceDataCount() const {
|
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_UUID32);
|
||||||
count += findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID128);
|
count += findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID128);
|
||||||
|
|
||||||
|
@ -448,7 +448,7 @@ NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) const {
|
||||||
* @return The count of services in the advertising packet.
|
* @return The count of services in the advertising packet.
|
||||||
*/
|
*/
|
||||||
uint8_t NimBLEAdvertisedDevice::getServiceUUIDCount() const {
|
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_COMP_UUIDS16);
|
||||||
count += findAdvField(BLE_HS_ADV_TYPE_INCOMP_UUIDS32);
|
count += findAdvField(BLE_HS_ADV_TYPE_INCOMP_UUIDS32);
|
||||||
count += findAdvField(BLE_HS_ADV_TYPE_COMP_UUIDS32);
|
count += findAdvField(BLE_HS_ADV_TYPE_COMP_UUIDS32);
|
||||||
|
@ -695,11 +695,9 @@ std::string NimBLEAdvertisedDevice::toString() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (haveManufacturerData()) {
|
if (haveManufacturerData()) {
|
||||||
char* pHex =
|
auto mfgData = getManufacturerData();
|
||||||
NimBLEUtils::buildHexData(nullptr, (uint8_t*)getManufacturerData().data(), getManufacturerData().length());
|
res += ", manufacturer data: ";
|
||||||
res += ", manufacturer data: ";
|
res += NimBLEUtils::dataToHexString(reinterpret_cast<const uint8_t*>(mfgData.data()), mfgData.length());
|
||||||
res += pHex;
|
|
||||||
free(pHex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (haveServiceUUID()) {
|
if (haveServiceUUID()) {
|
||||||
|
@ -714,7 +712,7 @@ std::string NimBLEAdvertisedDevice::toString() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (haveServiceData()) {
|
if (haveServiceData()) {
|
||||||
uint8_t count = getServiceDataCount();
|
uint8_t count = getServiceDataCount();
|
||||||
res += "\nService Data:";
|
res += "\nService Data:";
|
||||||
for (uint8_t i = 0; i < count; i++) {
|
for (uint8_t i = 0; i < count; i++) {
|
||||||
res += "\nUUID: " + std::string(getServiceDataUUID(i));
|
res += "\nUUID: " + std::string(getServiceDataUUID(i));
|
||||||
|
|
|
@ -201,11 +201,10 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes,
|
||||||
deleteServices();
|
deleteServices();
|
||||||
}
|
}
|
||||||
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
m_asyncConnect = asyncConnect;
|
m_asyncConnect = asyncConnect;
|
||||||
m_exchangeMTU = exchangeMTU;
|
m_exchangeMTU = exchangeMTU;
|
||||||
TaskHandle_t curTask = xTaskGetCurrentTaskHandle();
|
NimBLETaskData taskData(this);
|
||||||
BleTaskData taskData = {this, curTask, 0, nullptr};
|
|
||||||
if (!asyncConnect) {
|
if (!asyncConnect) {
|
||||||
m_pTaskData = &taskData;
|
m_pTaskData = &taskData;
|
||||||
}
|
}
|
||||||
|
@ -276,12 +275,8 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes,
|
||||||
return true;
|
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
|
// 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;
|
m_pTaskData = nullptr;
|
||||||
// If a connection was made but no response from MTU exchange; disconnect
|
// If a connection was made but no response from MTU exchange; disconnect
|
||||||
if (isConnected()) {
|
if (isConnected()) {
|
||||||
|
@ -296,9 +291,9 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes,
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
} else if (taskData.rc != 0) {
|
} else if (taskData.m_flags != 0) {
|
||||||
m_lastErr = taskData.rc;
|
m_lastErr = taskData.m_flags;
|
||||||
NIMBLE_LOGE(LOG_TAG, "Connection failed; status=%d %s", taskData.rc, NimBLEUtils::returnCodeToString(taskData.rc));
|
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 the failure was not a result of a disconnection, make sure we disconnect now to avoid dangling connections
|
||||||
if (isConnected()) {
|
if (isConnected()) {
|
||||||
disconnect();
|
disconnect();
|
||||||
|
@ -324,9 +319,8 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes,
|
||||||
*/
|
*/
|
||||||
bool NimBLEClient::secureConnection() const {
|
bool NimBLEClient::secureConnection() const {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> secureConnection()");
|
NIMBLE_LOGD(LOG_TAG, ">> secureConnection()");
|
||||||
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
|
NimBLETaskData taskData(const_cast<NimBLEClient*>(this));
|
||||||
BleTaskData taskData = {const_cast<NimBLEClient*>(this), cur_task, 0, nullptr};
|
int retryCount = 1;
|
||||||
int retryCount = 1;
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
m_pTaskData = &taskData;
|
m_pTaskData = &taskData;
|
||||||
|
@ -337,16 +331,12 @@ bool NimBLEClient::secureConnection() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
# ifdef ulTaskNotifyValueClear
|
NimBLEUtils::taskWait(*m_pTaskData, BLE_NPL_TIME_FOREVER);
|
||||||
// Clear the task notification value to ensure we block
|
} while (taskData.m_flags == (BLE_HS_ERR_HCI_BASE + BLE_ERR_PINKEY_MISSING) && retryCount--);
|
||||||
ulTaskNotifyValueClear(cur_task, ULONG_MAX);
|
|
||||||
# endif
|
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
|
||||||
} while (taskData.rc == (BLE_HS_ERR_HCI_BASE + BLE_ERR_PINKEY_MISSING) && retryCount--);
|
|
||||||
|
|
||||||
if (taskData.rc != 0) {
|
if (taskData.m_flags != 0) {
|
||||||
m_lastErr = taskData.rc;
|
m_lastErr = taskData.m_flags;
|
||||||
NIMBLE_LOGE(LOG_TAG, "secureConnection: failed rc=%d", taskData.rc);
|
NIMBLE_LOGE(LOG_TAG, "secureConnection: failed rc=%d", taskData.m_flags);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -736,9 +726,8 @@ bool NimBLEClient::retrieveServices(const NimBLEUUID* uuidFilter) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
|
NimBLETaskData taskData(this);
|
||||||
BleTaskData taskData = {this, cur_task, 0, nullptr};
|
|
||||||
|
|
||||||
if (uuidFilter == nullptr) {
|
if (uuidFilter == nullptr) {
|
||||||
rc = ble_gattc_disc_all_svcs(m_connHandle, NimBLEClient::serviceDiscoveredCB, &taskData);
|
rc = ble_gattc_disc_all_svcs(m_connHandle, NimBLEClient::serviceDiscoveredCB, &taskData);
|
||||||
|
@ -752,24 +741,15 @@ bool NimBLEClient::retrieveServices(const NimBLEUUID* uuidFilter) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
# ifdef ulTaskNotifyValueClear
|
NimBLEUtils::taskWait(taskData, BLE_NPL_TIME_FOREVER);
|
||||||
// Clear the task notification value to ensure we block
|
rc = taskData.m_flags;
|
||||||
ulTaskNotifyValueClear(cur_task, ULONG_MAX);
|
if (rc == 0 || rc == BLE_HS_EDONE) {
|
||||||
# endif
|
|
||||||
|
|
||||||
// wait until we have all the services
|
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
|
||||||
m_lastErr = taskData.rc;
|
|
||||||
|
|
||||||
if (taskData.rc == 0) {
|
|
||||||
return true;
|
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
|
} // getServices
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -786,8 +766,8 @@ int NimBLEClient::serviceDiscoveredCB(uint16_t connHandle,
|
||||||
error->status,
|
error->status,
|
||||||
(error->status == 0) ? service->start_handle : -1);
|
(error->status == 0) ? service->start_handle : -1);
|
||||||
|
|
||||||
BleTaskData* pTaskData = (BleTaskData*)arg;
|
NimBLETaskData* pTaskData = (NimBLETaskData*)arg;
|
||||||
NimBLEClient* pClient = (NimBLEClient*)pTaskData->pATT;
|
NimBLEClient* pClient = (NimBLEClient*)pTaskData->m_pInstance;
|
||||||
|
|
||||||
// Make sure the service discovery is for this device
|
// Make sure the service discovery is for this device
|
||||||
if (pClient->getConnHandle() != connHandle) {
|
if (pClient->getConnHandle() != connHandle) {
|
||||||
|
@ -800,15 +780,7 @@ int NimBLEClient::serviceDiscoveredCB(uint16_t connHandle,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error->status == BLE_HS_EDONE) {
|
NimBLEUtils::taskRelease(*pTaskData, error->status);
|
||||||
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);
|
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< Service Discovered");
|
NIMBLE_LOGD(LOG_TAG, "<< Service Discovered");
|
||||||
return error->status;
|
return error->status;
|
||||||
}
|
}
|
||||||
|
@ -1204,10 +1176,7 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) {
|
||||||
} // Switch
|
} // Switch
|
||||||
|
|
||||||
if (pClient->m_pTaskData != nullptr) {
|
if (pClient->m_pTaskData != nullptr) {
|
||||||
pClient->m_pTaskData->rc = rc;
|
NimBLEUtils::taskRelease(*pClient->m_pTaskData, rc);
|
||||||
if (pClient->m_pTaskData->task) {
|
|
||||||
xTaskNotifyGive(pClient->m_pTaskData->task);
|
|
||||||
}
|
|
||||||
pClient->m_pTaskData = nullptr;
|
pClient->m_pTaskData = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ class NimBLEAdvertisedDevice;
|
||||||
class NimBLEAttValue;
|
class NimBLEAttValue;
|
||||||
class NimBLEClientCallbacks;
|
class NimBLEClientCallbacks;
|
||||||
class NimBLEConnInfo;
|
class NimBLEConnInfo;
|
||||||
struct BleTaskData;
|
struct NimBLETaskData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A model of a BLE client.
|
* @brief A model of a BLE client.
|
||||||
|
@ -112,7 +112,7 @@ class NimBLEClient {
|
||||||
NimBLEAddress m_peerAddress;
|
NimBLEAddress m_peerAddress;
|
||||||
mutable int m_lastErr;
|
mutable int m_lastErr;
|
||||||
int32_t m_connectTimeout;
|
int32_t m_connectTimeout;
|
||||||
mutable BleTaskData* m_pTaskData;
|
mutable NimBLETaskData* m_pTaskData;
|
||||||
std::vector<NimBLERemoteService*> m_svcVec;
|
std::vector<NimBLERemoteService*> m_svcVec;
|
||||||
NimBLEClientCallbacks* m_pClientCallbacks;
|
NimBLEClientCallbacks* m_pClientCallbacks;
|
||||||
uint16_t m_connHandle;
|
uint16_t m_connHandle;
|
||||||
|
|
|
@ -65,8 +65,8 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(
|
||||||
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 = (desc_filter_t*)arg;
|
||||||
auto pTaskData = (BleTaskData*)filter->task_data;
|
auto pTaskData = (NimBLETaskData*)filter->task_data;
|
||||||
const auto pChr = (NimBLERemoteCharacteristic*)pTaskData->pATT;
|
const auto pChr = (NimBLERemoteCharacteristic*)pTaskData->m_pInstance;
|
||||||
const NimBLEUUID* uuidFilter = filter->uuid;
|
const NimBLEUUID* uuidFilter = filter->uuid;
|
||||||
|
|
||||||
if (pChr->getHandle() != chr_val_handle) {
|
if (pChr->getHandle() != chr_val_handle) {
|
||||||
|
@ -85,12 +85,8 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(
|
||||||
pChr->m_vDescriptors.push_back(new NimBLERemoteDescriptor(pChr, dsc));
|
pChr->m_vDescriptors.push_back(new NimBLERemoteDescriptor(pChr, dsc));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc != 0) {
|
NimBLEUtils::taskRelease(*pTaskData, rc);
|
||||||
pTaskData->rc = rc == BLE_HS_EDONE ? 0 : rc;
|
NIMBLE_LOGD(LOG_TAG, "<< Descriptor Discovery");
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< Descriptor Discovery");
|
|
||||||
xTaskNotifyGive(pTaskData->task);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,9 +97,8 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(
|
||||||
bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuidFilter) const {
|
bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuidFilter) 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());
|
||||||
|
|
||||||
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
|
NimBLETaskData taskData(const_cast<NimBLERemoteCharacteristic*>(this));
|
||||||
BleTaskData taskData = {const_cast<NimBLERemoteCharacteristic*>(this), cur_task, 0, nullptr};
|
desc_filter_t filter = {uuidFilter, &taskData};
|
||||||
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(),
|
||||||
|
@ -115,22 +110,15 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuidFilte
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
# ifdef ulTaskNotifyValueClear
|
NimBLEUtils::taskWait(taskData, BLE_NPL_TIME_FOREVER);
|
||||||
// Clear the task notification value to ensure we block
|
rc = taskData.m_flags;
|
||||||
ulTaskNotifyValueClear(cur_task, ULONG_MAX);
|
if (rc == 0 || rc == BLE_HS_EDONE) {
|
||||||
# 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 {
|
|
||||||
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 taskData.rc == 0;
|
NIMBLE_LOGE(LOG_TAG, "<< retrieveDescriptors(): failed: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
|
return false;
|
||||||
} // retrieveDescriptors
|
} // retrieveDescriptors
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -145,8 +145,8 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle,
|
||||||
const ble_gatt_chr* chr,
|
const ble_gatt_chr* chr,
|
||||||
void* arg) {
|
void* arg) {
|
||||||
NIMBLE_LOGD(LOG_TAG, "Characteristic Discovery >>");
|
NIMBLE_LOGD(LOG_TAG, "Characteristic Discovery >>");
|
||||||
auto pTaskData = (BleTaskData*)arg;
|
auto pTaskData = (NimBLETaskData*)arg;
|
||||||
const auto pSvc = (NimBLERemoteService*)pTaskData->pATT;
|
const auto pSvc = (NimBLERemoteService*)pTaskData->m_pInstance;
|
||||||
|
|
||||||
// Make sure the discovery is for this device
|
// Make sure the discovery is for this device
|
||||||
if (pSvc->getClient()->getConnHandle() != conn_handle) {
|
if (pSvc->getClient()->getConnHandle() != conn_handle) {
|
||||||
|
@ -155,12 +155,11 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle,
|
||||||
|
|
||||||
if (error->status == 0) {
|
if (error->status == 0) {
|
||||||
pSvc->m_vChars.push_back(new NimBLERemoteCharacteristic(pSvc, chr));
|
pSvc->m_vChars.push_back(new NimBLERemoteCharacteristic(pSvc, chr));
|
||||||
} else {
|
return 0;
|
||||||
pTaskData->rc = error->status == BLE_HS_EDONE ? 0 : error->status;
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< Characteristic Discovery");
|
|
||||||
xTaskNotifyGive(pTaskData->task);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NimBLEUtils::taskRelease(*pTaskData, error->status);
|
||||||
|
NIMBLE_LOGD(LOG_TAG, "<< Characteristic Discovery");
|
||||||
return error->status;
|
return error->status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,9 +170,8 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle,
|
||||||
*/
|
*/
|
||||||
bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID* uuidFilter) const {
|
bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID* uuidFilter) const {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> retrieveCharacteristics()");
|
NIMBLE_LOGD(LOG_TAG, ">> retrieveCharacteristics()");
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
|
NimBLETaskData taskData(const_cast<NimBLERemoteService*>(this));
|
||||||
BleTaskData taskData = {const_cast<NimBLERemoteService*>(this), cur_task, 0, nullptr};
|
|
||||||
|
|
||||||
if (uuidFilter == nullptr) {
|
if (uuidFilter == nullptr) {
|
||||||
rc = ble_gattc_disc_all_chrs(m_pClient->getConnHandle(),
|
rc = ble_gattc_disc_all_chrs(m_pClient->getConnHandle(),
|
||||||
|
@ -190,21 +188,20 @@ bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID* uuidFilter)
|
||||||
&taskData);
|
&taskData);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc == 0) {
|
if (rc != 0) {
|
||||||
# ifdef ulTaskNotifyValueClear
|
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_chrs rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
// Clear the task notification value to ensure we block
|
return false;
|
||||||
ulTaskNotifyValueClear(cur_task, ULONG_MAX);
|
|
||||||
# endif
|
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (taskData.rc != 0) {
|
NimBLEUtils::taskWait(taskData, BLE_NPL_TIME_FOREVER);
|
||||||
NIMBLE_LOGE(LOG_TAG, "<< retrieveCharacteristics() rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
rc = taskData.m_flags;
|
||||||
} else {
|
if (rc == 0 || rc == BLE_HS_EDONE) {
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< retrieveCharacteristics()");
|
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
|
} // retrieveCharacteristics
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -20,11 +20,10 @@ bool NimBLERemoteValueAttribute::writeValue(const uint8_t* data, size_t length,
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> writeValue()");
|
NIMBLE_LOGD(LOG_TAG, ">> writeValue()");
|
||||||
|
|
||||||
const NimBLEClient* pClient = getClient();
|
const NimBLEClient* pClient = getClient();
|
||||||
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
|
|
||||||
BleTaskData taskData = {const_cast<NimBLERemoteValueAttribute*>(this), cur_task, 0, nullptr};
|
|
||||||
int retryCount = 1;
|
int retryCount = 1;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
uint16_t mtu = pClient->getMTU() - 3;
|
uint16_t mtu = pClient->getMTU() - 3;
|
||||||
|
NimBLETaskData taskData(const_cast<NimBLERemoteValueAttribute*>(this));
|
||||||
|
|
||||||
// Check if the data length is longer than we can write in one connection event.
|
// Check if the data length is longer than we can write in one connection event.
|
||||||
// If so we must do a long write which requires a response.
|
// If so we must do a long write which requires a response.
|
||||||
|
@ -51,13 +50,8 @@ bool NimBLERemoteValueAttribute::writeValue(const uint8_t* data, size_t length,
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
# ifdef ulTaskNotifyValueClear
|
NimBLEUtils::taskWait(taskData, BLE_NPL_TIME_FOREVER);
|
||||||
// Clear the task notification value to ensure we block
|
rc = taskData.m_flags;
|
||||||
ulTaskNotifyValueClear(cur_task, ULONG_MAX);
|
|
||||||
# endif
|
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
|
||||||
rc = taskData.rc;
|
|
||||||
|
|
||||||
switch (rc) {
|
switch (rc) {
|
||||||
case 0:
|
case 0:
|
||||||
case BLE_HS_EDONE:
|
case BLE_HS_EDONE:
|
||||||
|
@ -83,7 +77,7 @@ Done:
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "<< writeValue failed, rc: %d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
NIMBLE_LOGE(LOG_TAG, "<< writeValue failed, rc: %d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
} else {
|
} else {
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< writeValue, rc: %d", rc);
|
NIMBLE_LOGD(LOG_TAG, "<< writeValue");
|
||||||
}
|
}
|
||||||
|
|
||||||
return (rc == 0);
|
return (rc == 0);
|
||||||
|
@ -94,16 +88,15 @@ Done:
|
||||||
* @return success == 0 or error code.
|
* @return success == 0 or error code.
|
||||||
*/
|
*/
|
||||||
int NimBLERemoteValueAttribute::onWriteCB(uint16_t conn_handle, const ble_gatt_error* error, ble_gatt_attr* attr, void* arg) {
|
int NimBLERemoteValueAttribute::onWriteCB(uint16_t conn_handle, const ble_gatt_error* error, ble_gatt_attr* attr, void* arg) {
|
||||||
auto pTaskData = static_cast<BleTaskData*>(arg);
|
auto pTaskData = static_cast<NimBLETaskData*>(arg);
|
||||||
const auto pAtt = static_cast<NimBLERemoteValueAttribute*>(pTaskData->pATT);
|
const auto pAtt = static_cast<NimBLERemoteValueAttribute*>(pTaskData->m_pInstance);
|
||||||
|
|
||||||
if (pAtt->getClient()->getConnHandle() != conn_handle) {
|
if (pAtt->getClient()->getConnHandle() != conn_handle) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
NIMBLE_LOGI(LOG_TAG, "Write complete; status=%d", error->status);
|
NIMBLE_LOGI(LOG_TAG, "Write complete; status=%d", error->status);
|
||||||
pTaskData->rc = error->status;
|
NimBLEUtils::taskRelease(*pTaskData, error->status);
|
||||||
xTaskNotifyGive(pTaskData->task);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,8 +112,7 @@ NimBLEAttValue NimBLERemoteValueAttribute::readValue(time_t* timestamp) const {
|
||||||
const NimBLEClient* pClient = getClient();
|
const NimBLEClient* pClient = getClient();
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int retryCount = 1;
|
int retryCount = 1;
|
||||||
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
|
NimBLETaskData taskData(const_cast<NimBLERemoteValueAttribute*>(this), 0, &value);
|
||||||
BleTaskData taskData = {const_cast<NimBLERemoteValueAttribute*>(this), cur_task, 0, &value};
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
rc = ble_gattc_read_long(pClient->getConnHandle(), getHandle(), 0, NimBLERemoteValueAttribute::onReadCB, &taskData);
|
rc = ble_gattc_read_long(pClient->getConnHandle(), getHandle(), 0, NimBLERemoteValueAttribute::onReadCB, &taskData);
|
||||||
|
@ -128,13 +120,8 @@ NimBLEAttValue NimBLERemoteValueAttribute::readValue(time_t* timestamp) const {
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
# ifdef ulTaskNotifyValueClear
|
NimBLEUtils::taskWait(taskData, BLE_NPL_TIME_FOREVER);
|
||||||
// Clear the task notification value to ensure we block
|
rc = taskData.m_flags;
|
||||||
ulTaskNotifyValueClear(cur_task, ULONG_MAX);
|
|
||||||
# endif
|
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
|
||||||
rc = taskData.rc;
|
|
||||||
|
|
||||||
switch (rc) {
|
switch (rc) {
|
||||||
case 0:
|
case 0:
|
||||||
case BLE_HS_EDONE:
|
case BLE_HS_EDONE:
|
||||||
|
@ -169,7 +156,7 @@ Done:
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "<< readValue failed rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
NIMBLE_LOGE(LOG_TAG, "<< readValue failed rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
} else {
|
} else {
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< readValue rc=%d", rc);
|
NIMBLE_LOGD(LOG_TAG, "<< readValue");
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
|
@ -180,8 +167,8 @@ Done:
|
||||||
* @return success == 0 or error code.
|
* @return success == 0 or error code.
|
||||||
*/
|
*/
|
||||||
int NimBLERemoteValueAttribute::onReadCB(uint16_t conn_handle, const ble_gatt_error* error, ble_gatt_attr* attr, void* arg) {
|
int NimBLERemoteValueAttribute::onReadCB(uint16_t conn_handle, const ble_gatt_error* error, ble_gatt_attr* attr, void* arg) {
|
||||||
auto pTaskData = static_cast<BleTaskData*>(arg);
|
auto pTaskData = static_cast<NimBLETaskData*>(arg);
|
||||||
const auto pAtt = static_cast<NimBLERemoteValueAttribute*>(pTaskData->pATT);
|
const auto pAtt = static_cast<NimBLERemoteValueAttribute*>(pTaskData->m_pInstance);
|
||||||
|
|
||||||
if (pAtt->getClient()->getConnHandle() != conn_handle) {
|
if (pAtt->getClient()->getConnHandle() != conn_handle) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -192,7 +179,7 @@ int NimBLERemoteValueAttribute::onReadCB(uint16_t conn_handle, const ble_gatt_er
|
||||||
|
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
if (attr) {
|
if (attr) {
|
||||||
auto valBuf = static_cast<NimBLEAttValue*>(pTaskData->buf);
|
auto valBuf = static_cast<NimBLEAttValue*>(pTaskData->m_pBuf);
|
||||||
uint16_t data_len = OS_MBUF_PKTLEN(attr->om);
|
uint16_t data_len = OS_MBUF_PKTLEN(attr->om);
|
||||||
if ((valBuf->size() + data_len) > BLE_ATT_ATTR_MAX_LEN) {
|
if ((valBuf->size() + data_len) > BLE_ATT_ATTR_MAX_LEN) {
|
||||||
rc = BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
rc = BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
||||||
|
@ -204,9 +191,7 @@ int NimBLERemoteValueAttribute::onReadCB(uint16_t conn_handle, const ble_gatt_er
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pTaskData->rc = rc;
|
NimBLEUtils::taskRelease(*pTaskData, rc);
|
||||||
xTaskNotifyGive(pTaskData->task);
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
} // onReadCB
|
} // onReadCB
|
||||||
|
|
||||||
|
|
|
@ -167,8 +167,7 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pScan->m_pTaskData != nullptr) {
|
if(pScan->m_pTaskData != nullptr) {
|
||||||
pScan->m_pTaskData->rc = event->disc_complete.reason;
|
NimBLEUtils::taskRelease(*pScan->m_pTaskData, event->disc_complete.reason);
|
||||||
xTaskNotifyGive(pScan->m_pTaskData->task);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -393,7 +392,7 @@ bool NimBLEScan::stop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_pTaskData != nullptr) {
|
if(m_pTaskData != nullptr) {
|
||||||
xTaskNotifyGive(m_pTaskData->task);
|
NimBLEUtils::taskRelease(*m_pTaskData);
|
||||||
}
|
}
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< stop()");
|
NIMBLE_LOGD(LOG_TAG, "<< stop()");
|
||||||
|
@ -461,16 +460,11 @@ NimBLEScanResults NimBLEScan::getResults(uint32_t duration, bool is_continue) {
|
||||||
NIMBLE_LOGW(LOG_TAG, "Blocking scan called with duration = forever");
|
NIMBLE_LOGW(LOG_TAG, "Blocking scan called with duration = forever");
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
|
NimBLETaskData taskData;
|
||||||
BleTaskData taskData = {nullptr, cur_task, 0, nullptr};
|
|
||||||
m_pTaskData = &taskData;
|
m_pTaskData = &taskData;
|
||||||
|
|
||||||
if(start(duration, is_continue)) {
|
if(start(duration, is_continue)) {
|
||||||
#ifdef ulTaskNotifyValueClear
|
NimBLEUtils::taskWait(taskData, BLE_NPL_TIME_FOREVER);
|
||||||
// Clear the task notification value to ensure we block
|
|
||||||
ulTaskNotifyValueClear(cur_task, ULONG_MAX);
|
|
||||||
#endif
|
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pTaskData = nullptr;
|
m_pTaskData = nullptr;
|
||||||
|
|
|
@ -94,7 +94,7 @@ private:
|
||||||
bool m_ignoreResults;
|
bool m_ignoreResults;
|
||||||
NimBLEScanResults m_scanResults;
|
NimBLEScanResults m_scanResults;
|
||||||
uint32_t m_duration;
|
uint32_t m_duration;
|
||||||
BleTaskData *m_pTaskData;
|
NimBLETaskData *m_pTaskData;
|
||||||
uint8_t m_maxResults;
|
uint8_t m_maxResults;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -368,8 +368,8 @@ int NimBLEServer::peerNameCB(uint16_t conn_handle,
|
||||||
const struct ble_gatt_error *error,
|
const struct ble_gatt_error *error,
|
||||||
struct ble_gatt_attr *attr,
|
struct ble_gatt_attr *attr,
|
||||||
void *arg) {
|
void *arg) {
|
||||||
BleTaskData *pTaskData = (BleTaskData*)arg;
|
NimBLETaskData *pTaskData = (NimBLETaskData*)arg;
|
||||||
std::string *name = (std::string*)pTaskData->buf;
|
std::string *name = (std::string*)pTaskData->m_pBuf;
|
||||||
int rc = error->status;
|
int rc = error->status;
|
||||||
|
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
|
@ -380,16 +380,15 @@ int NimBLEServer::peerNameCB(uint16_t conn_handle,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc == BLE_HS_EDONE) {
|
if (rc == BLE_HS_EDONE) {
|
||||||
// No ask means this was read for a callback.
|
if (pTaskData->m_flags != -1) {
|
||||||
if (pTaskData->task == nullptr) {
|
NimBLEServer* pServer = (NimBLEServer*)pTaskData->m_pInstance;
|
||||||
NimBLEServer* pServer = (NimBLEServer*)pTaskData->pATT;
|
|
||||||
NimBLEConnInfo peerInfo{};
|
NimBLEConnInfo peerInfo{};
|
||||||
ble_gap_conn_find(conn_handle, &peerInfo.m_desc);
|
ble_gap_conn_find(conn_handle, &peerInfo.m_desc);
|
||||||
|
|
||||||
// Use the rc value as a flag to indicate which callback should be called.
|
// check the flag to indicate which callback should be called.
|
||||||
if (pTaskData->rc == NIMBLE_SERVER_GET_PEER_NAME_ON_CONNECT_CB) {
|
if (pTaskData->m_flags == NIMBLE_SERVER_GET_PEER_NAME_ON_CONNECT_CB) {
|
||||||
pServer->m_pServerCallbacks->onConnect(pServer, peerInfo, *name);
|
pServer->m_pServerCallbacks->onConnect(pServer, peerInfo, *name);
|
||||||
} else if (pTaskData->rc == NIMBLE_SERVER_GET_PEER_NAME_ON_AUTH_CB) {
|
} else if (pTaskData->m_flags == NIMBLE_SERVER_GET_PEER_NAME_ON_AUTH_CB) {
|
||||||
pServer->m_pServerCallbacks->onAuthenticationComplete(peerInfo, *name);
|
pServer->m_pServerCallbacks->onAuthenticationComplete(peerInfo, *name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -397,9 +396,8 @@ int NimBLEServer::peerNameCB(uint16_t conn_handle,
|
||||||
NIMBLE_LOGE(LOG_TAG, "NimBLEServerPeerNameCB rc=%d; %s", rc, NimBLEUtils::returnCodeToString(rc));
|
NIMBLE_LOGE(LOG_TAG, "NimBLEServerPeerNameCB rc=%d; %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pTaskData->task != nullptr) {
|
if (pTaskData->m_flags == -1) {
|
||||||
pTaskData->rc = rc;
|
NimBLEUtils::taskRelease(*pTaskData, rc);
|
||||||
xTaskNotifyGive(pTaskData->task);
|
|
||||||
} else {
|
} else {
|
||||||
// If the read was triggered for callback use then these were allocated.
|
// If the read was triggered for callback use then these were allocated.
|
||||||
delete name;
|
delete name;
|
||||||
|
@ -412,16 +410,16 @@ int NimBLEServer::peerNameCB(uint16_t conn_handle,
|
||||||
/**
|
/**
|
||||||
* @brief Internal method that sends the read command.
|
* @brief Internal method that sends the read command.
|
||||||
*/
|
*/
|
||||||
std::string NimBLEServer::getPeerNameInternal(uint16_t conn_handle, TaskHandle_t task, int cb_type) {
|
std::string NimBLEServer::getPeerNameInternal(uint16_t conn_handle, int cb_type) {
|
||||||
std::string *buf = new std::string{};
|
std::string *buf = new std::string{};
|
||||||
BleTaskData *taskData = new BleTaskData{this, task, cb_type, buf};
|
NimBLETaskData *pTaskData = new NimBLETaskData(this, cb_type, buf);
|
||||||
ble_uuid16_t uuid {{BLE_UUID_TYPE_16}, BLE_SVC_GAP_CHR_UUID16_DEVICE_NAME};
|
ble_uuid16_t uuid {{BLE_UUID_TYPE_16}, BLE_SVC_GAP_CHR_UUID16_DEVICE_NAME};
|
||||||
int rc = ble_gattc_read_by_uuid(conn_handle,
|
int rc = ble_gattc_read_by_uuid(conn_handle,
|
||||||
1,
|
1,
|
||||||
0xffff,
|
0xffff,
|
||||||
&uuid.u,
|
&uuid.u,
|
||||||
NimBLEServer::peerNameCB,
|
NimBLEServer::peerNameCB,
|
||||||
taskData);
|
pTaskData);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "ble_gattc_read_by_uuid rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
NIMBLE_LOGE(LOG_TAG, "ble_gattc_read_by_uuid rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
NimBLEConnInfo peerInfo{};
|
NimBLEConnInfo peerInfo{};
|
||||||
|
@ -432,17 +430,13 @@ std::string NimBLEServer::getPeerNameInternal(uint16_t conn_handle, TaskHandle_t
|
||||||
m_pServerCallbacks->onAuthenticationComplete(peerInfo, *buf);
|
m_pServerCallbacks->onAuthenticationComplete(peerInfo, *buf);
|
||||||
}
|
}
|
||||||
delete buf;
|
delete buf;
|
||||||
delete taskData;
|
delete pTaskData;
|
||||||
} else if (task != nullptr) {
|
} else if (cb_type == -1) {
|
||||||
#ifdef ulTaskNotifyValueClear
|
NimBLEUtils::taskWait(*pTaskData, BLE_NPL_TIME_FOREVER);
|
||||||
// Clear the task notification value to ensure we block
|
rc = pTaskData->m_flags;
|
||||||
ulTaskNotifyValueClear(task, ULONG_MAX);
|
std::string name{*(std::string*)pTaskData->m_pBuf};
|
||||||
#endif
|
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
|
||||||
rc = taskData->rc;
|
|
||||||
std::string name{*(std::string*)taskData->buf};
|
|
||||||
delete buf;
|
delete buf;
|
||||||
delete taskData;
|
delete pTaskData;
|
||||||
|
|
||||||
if (rc != 0 && rc != BLE_HS_EDONE) {
|
if (rc != 0 && rc != BLE_HS_EDONE) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "getPeerName rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
NIMBLE_LOGE(LOG_TAG, "getPeerName rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
|
@ -461,7 +455,7 @@ std::string NimBLEServer::getPeerNameInternal(uint16_t conn_handle, TaskHandle_t
|
||||||
* @note This is a blocking call and should NOT be called from any callbacks!
|
* @note This is a blocking call and should NOT be called from any callbacks!
|
||||||
*/
|
*/
|
||||||
std::string NimBLEServer::getPeerName(const NimBLEConnInfo& connInfo) {
|
std::string NimBLEServer::getPeerName(const NimBLEConnInfo& connInfo) {
|
||||||
std::string name = getPeerNameInternal(connInfo.getConnHandle(), xTaskGetCurrentTaskHandle());
|
std::string name = getPeerNameInternal(connInfo.getConnHandle());
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,7 +494,6 @@ int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
||||||
|
|
||||||
if (pServer->m_getPeerNameOnConnect) {
|
if (pServer->m_getPeerNameOnConnect) {
|
||||||
pServer->getPeerNameInternal(event->connect.conn_handle,
|
pServer->getPeerNameInternal(event->connect.conn_handle,
|
||||||
nullptr,
|
|
||||||
NIMBLE_SERVER_GET_PEER_NAME_ON_CONNECT_CB);
|
NIMBLE_SERVER_GET_PEER_NAME_ON_CONNECT_CB);
|
||||||
} else {
|
} else {
|
||||||
pServer->m_pServerCallbacks->onConnect(pServer, peerInfo);
|
pServer->m_pServerCallbacks->onConnect(pServer, peerInfo);
|
||||||
|
@ -661,7 +654,6 @@ int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
||||||
|
|
||||||
if (pServer->m_getPeerNameOnConnect) {
|
if (pServer->m_getPeerNameOnConnect) {
|
||||||
pServer->getPeerNameInternal(event->enc_change.conn_handle,
|
pServer->getPeerNameInternal(event->enc_change.conn_handle,
|
||||||
nullptr,
|
|
||||||
NIMBLE_SERVER_GET_PEER_NAME_ON_AUTH_CB);
|
NIMBLE_SERVER_GET_PEER_NAME_ON_AUTH_CB);
|
||||||
} else {
|
} else {
|
||||||
pServer->m_pServerCallbacks->onAuthenticationComplete(peerInfo);
|
pServer->m_pServerCallbacks->onAuthenticationComplete(peerInfo);
|
||||||
|
|
|
@ -115,7 +115,7 @@ private:
|
||||||
static int handleGapEvent(struct ble_gap_event *event, void *arg);
|
static int handleGapEvent(struct ble_gap_event *event, void *arg);
|
||||||
static int peerNameCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
static int peerNameCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
||||||
struct ble_gatt_attr *attr, void *arg);
|
struct ble_gatt_attr *attr, void *arg);
|
||||||
std::string getPeerNameInternal(uint16_t conn_handle, TaskHandle_t task, int cb_type = -1);
|
std::string getPeerNameInternal(uint16_t conn_handle, int cb_type = -1);
|
||||||
void serviceChanged();
|
void serviceChanged();
|
||||||
void resetGATT();
|
void resetGATT();
|
||||||
bool setIndicateWait(uint16_t conn_handle);
|
bool setIndicateWait(uint16_t conn_handle);
|
||||||
|
|
|
@ -9,9 +9,9 @@
|
||||||
#include "nimconfig.h"
|
#include "nimconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
#include "NimBLEUtils.h"
|
# include "NimBLEUtils.h"
|
||||||
#include "NimBLEAddress.h"
|
# include "NimBLEAddress.h"
|
||||||
#include "NimBLELog.h"
|
# include "NimBLELog.h"
|
||||||
|
|
||||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||||
# include "host/ble_hs.h"
|
# include "host/ble_hs.h"
|
||||||
|
@ -20,474 +20,497 @@
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
/**** FIX COMPILATION ****/
|
/**** FIX COMPILATION ****/
|
||||||
#undef min
|
# undef min
|
||||||
#undef max
|
# undef max
|
||||||
/**************************/
|
/**************************/
|
||||||
|
|
||||||
#include <stdlib.h>
|
# include <stdlib.h>
|
||||||
|
# include <climits>
|
||||||
|
|
||||||
static const char* LOG_TAG = "NimBLEUtils";
|
static const char* LOG_TAG = "NimBLEUtils";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Blocks the calling task until released or timeout.
|
||||||
|
* @param [in] taskData A pointer to the task data structure.
|
||||||
|
* @param [in] timeout The time to wait in milliseconds.
|
||||||
|
* @return True if the task completed, false if the timeout was reached.
|
||||||
|
*/
|
||||||
|
bool NimBLEUtils::taskWait(const NimBLETaskData& taskData, uint32_t timeout) {
|
||||||
|
ble_npl_time_t ticks;
|
||||||
|
if (timeout == BLE_NPL_TIME_FOREVER) {
|
||||||
|
ticks = BLE_NPL_TIME_FOREVER;
|
||||||
|
} else {
|
||||||
|
ble_npl_time_ms_to_ticks(timeout, &ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
# if defined INC_FREERTOS_H
|
||||||
|
taskData.m_pHandle = xTaskGetCurrentTaskHandle();
|
||||||
|
# ifdef ulTaskNotifyValueClear
|
||||||
|
// Clear the task notification value to ensure we block
|
||||||
|
ulTaskNotifyValueClear(static_cast<TaskHandle_t>(taskData.m_pHandle), ULONG_MAX);
|
||||||
|
# endif
|
||||||
|
return ulTaskNotifyTake(pdTRUE, ticks) == pdTRUE;
|
||||||
|
|
||||||
|
# else
|
||||||
|
ble_npl_sem sem;
|
||||||
|
ble_npl_error_t err = ble_npl_sem_init(&sem, 0);
|
||||||
|
if (err != BLE_NPL_OK) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Failed to create semaphore");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
taskData.m_pHandle = &sem;
|
||||||
|
err = ble_npl_sem_pend(&sem, ticks);
|
||||||
|
ble_npl_sem_deinit(&sem);
|
||||||
|
taskData.m_pHandle = nullptr;
|
||||||
|
return err == BLE_NPL_OK;
|
||||||
|
# endif
|
||||||
|
} // taskWait
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release a task.
|
||||||
|
* @param [in] taskData A pointer to the task data structure.
|
||||||
|
* @param [in] flags A return value to set in the task data structure.
|
||||||
|
*/
|
||||||
|
void NimBLEUtils::taskRelease(const NimBLETaskData& taskData, int flags) {
|
||||||
|
if (taskData.m_pHandle != nullptr) {
|
||||||
|
taskData.m_flags = flags;
|
||||||
|
# if defined INC_FREERTOS_H
|
||||||
|
xTaskNotifyGive(static_cast<TaskHandle_t>(taskData.m_pHandle));
|
||||||
|
# else
|
||||||
|
ble_npl_sem_release(static_cast<ble_npl_sem*>(taskData.m_pHandle));
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
} // taskRelease
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Converts a return code from the NimBLE stack to a text string.
|
* @brief Converts a return code from the NimBLE stack to a text string.
|
||||||
* @param [in] rc The return code to convert.
|
* @param [in] rc The return code to convert.
|
||||||
* @return A string representation of the return code.
|
* @return A string representation of the return code.
|
||||||
*/
|
*/
|
||||||
const char* NimBLEUtils::returnCodeToString(int rc) {
|
const char* NimBLEUtils::returnCodeToString(int rc) {
|
||||||
#if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
|
# if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
|
||||||
switch(rc) {
|
switch (rc) {
|
||||||
case 0:
|
case 0:
|
||||||
return "SUCCESS";
|
return "SUCCESS";
|
||||||
case BLE_HS_EAGAIN:
|
case BLE_HS_EAGAIN:
|
||||||
return "Temporary failure; try again.";
|
return "Temporary failure; try again";
|
||||||
case BLE_HS_EALREADY:
|
case BLE_HS_EALREADY:
|
||||||
return "Operation already in progress or completed.";
|
return "Operation already in progress or complete";
|
||||||
case BLE_HS_EINVAL:
|
case BLE_HS_EINVAL:
|
||||||
return "One or more arguments are invalid.";
|
return "One or more arguments are invalid";
|
||||||
case BLE_HS_EMSGSIZE:
|
case BLE_HS_EMSGSIZE:
|
||||||
return "The provided buffer is too small.";
|
return "Buffer too small";
|
||||||
case BLE_HS_ENOENT:
|
case BLE_HS_ENOENT:
|
||||||
return "No entry matching the specified criteria.";
|
return "No matching entry found";
|
||||||
case BLE_HS_ENOMEM:
|
case BLE_HS_ENOMEM:
|
||||||
return "Operation failed due to resource exhaustion.";
|
return "Not enough memory";
|
||||||
case BLE_HS_ENOTCONN:
|
case BLE_HS_ENOTCONN:
|
||||||
return "No open connection with the specified handle.";
|
return "No open connection with handle";
|
||||||
case BLE_HS_ENOTSUP:
|
case BLE_HS_ENOTSUP:
|
||||||
return "Operation disabled at compile time.";
|
return "Operation disabled at compile time";
|
||||||
case BLE_HS_EAPP:
|
case BLE_HS_EAPP:
|
||||||
return "Application callback behaved unexpectedly.";
|
return "Application error";
|
||||||
case BLE_HS_EBADDATA:
|
case BLE_HS_EBADDATA:
|
||||||
return "Command from peer is invalid.";
|
return "Invalid command from peer";
|
||||||
case BLE_HS_EOS:
|
case BLE_HS_EOS:
|
||||||
return "Mynewt OS error.";
|
return "OS error";
|
||||||
case BLE_HS_ECONTROLLER:
|
case BLE_HS_ECONTROLLER:
|
||||||
return "Event from controller is invalid.";
|
return "Controller error";
|
||||||
case BLE_HS_ETIMEOUT:
|
case BLE_HS_ETIMEOUT:
|
||||||
return "Operation timed out.";
|
return "Operation timed out";
|
||||||
case BLE_HS_EDONE:
|
case BLE_HS_EDONE:
|
||||||
return "Operation completed successfully.";
|
return "Operation completed successfully";
|
||||||
case BLE_HS_EBUSY:
|
case BLE_HS_EBUSY:
|
||||||
return "Operation cannot be performed until procedure completes.";
|
return "Busy";
|
||||||
case BLE_HS_EREJECT:
|
case BLE_HS_EREJECT:
|
||||||
return "Peer rejected a connection parameter update request.";
|
return "Peer rejected request";
|
||||||
case BLE_HS_EUNKNOWN:
|
case BLE_HS_EUNKNOWN:
|
||||||
return "Unexpected failure; catch all.";
|
return "Unknown failure";
|
||||||
case BLE_HS_EROLE:
|
case BLE_HS_EROLE:
|
||||||
return "Operation requires different role (e.g., central vs. peripheral).";
|
return "Operation requires different role";
|
||||||
case BLE_HS_ETIMEOUT_HCI:
|
case BLE_HS_ETIMEOUT_HCI:
|
||||||
return "HCI request timed out; controller unresponsive.";
|
return "HCI request timed out";
|
||||||
case BLE_HS_ENOMEM_EVT:
|
case BLE_HS_ENOMEM_EVT:
|
||||||
return "Controller failed to send event due to memory exhaustion (combined host-controller only).";
|
return "Controller error; not enough memory";
|
||||||
case BLE_HS_ENOADDR:
|
case BLE_HS_ENOADDR:
|
||||||
return "Operation requires an identity address but none configured.";
|
return "No identity address";
|
||||||
case BLE_HS_ENOTSYNCED:
|
case BLE_HS_ENOTSYNCED:
|
||||||
return "Attempt to use the host before it is synced with controller.";
|
return "Host not synced with controller";
|
||||||
case BLE_HS_EAUTHEN:
|
case BLE_HS_EAUTHEN:
|
||||||
return "Insufficient authentication.";
|
return "Insufficient authentication";
|
||||||
case BLE_HS_EAUTHOR:
|
case BLE_HS_EAUTHOR:
|
||||||
return "Insufficient authorization.";
|
return "Insufficient authorization";
|
||||||
case BLE_HS_EENCRYPT:
|
case BLE_HS_EENCRYPT:
|
||||||
return "Insufficient encryption level.";
|
return "Insufficient encryption level";
|
||||||
case BLE_HS_EENCRYPT_KEY_SZ:
|
case BLE_HS_EENCRYPT_KEY_SZ:
|
||||||
return "Insufficient key size.";
|
return "Insufficient key size";
|
||||||
case BLE_HS_ESTORE_CAP:
|
case BLE_HS_ESTORE_CAP:
|
||||||
return "Storage at capacity.";
|
return "Storage at capacity";
|
||||||
case BLE_HS_ESTORE_FAIL:
|
case BLE_HS_ESTORE_FAIL:
|
||||||
return "Storage IO error.";
|
return "Storage IO error";
|
||||||
case (0x0100+BLE_ATT_ERR_INVALID_HANDLE ):
|
case BLE_HS_EPREEMPTED:
|
||||||
return "The attribute handle given was not valid on this server.";
|
return "Host preempted";
|
||||||
case (0x0100+BLE_ATT_ERR_READ_NOT_PERMITTED ):
|
case BLE_HS_EDISABLED:
|
||||||
return "The attribute cannot be read.";
|
return "Host disabled";
|
||||||
case (0x0100+BLE_ATT_ERR_WRITE_NOT_PERMITTED ):
|
case BLE_HS_ESTALLED:
|
||||||
return "The attribute cannot be written.";
|
return "CoC module is stalled";
|
||||||
case (0x0100+BLE_ATT_ERR_INVALID_PDU ):
|
case (BLE_HS_ERR_ATT_BASE + BLE_ATT_ERR_INVALID_HANDLE):
|
||||||
return "The attribute PDU was invalid.";
|
return "Invalid attribute handle";
|
||||||
case (0x0100+BLE_ATT_ERR_INSUFFICIENT_AUTHEN ):
|
case (BLE_HS_ERR_ATT_BASE + BLE_ATT_ERR_READ_NOT_PERMITTED):
|
||||||
return "The attribute requires authentication before it can be read or written.";
|
return "The attribute cannot be read";
|
||||||
case (0x0100+BLE_ATT_ERR_REQ_NOT_SUPPORTED ):
|
case (BLE_HS_ERR_ATT_BASE + BLE_ATT_ERR_WRITE_NOT_PERMITTED):
|
||||||
return "Attribute server does not support the request received from the client.";
|
return "The attribute cannot be written";
|
||||||
case (0x0100+BLE_ATT_ERR_INVALID_OFFSET ):
|
case (BLE_HS_ERR_ATT_BASE + BLE_ATT_ERR_INVALID_PDU):
|
||||||
return "Offset specified was past the end of the attribute.";
|
return "Invalid attribute PDU";
|
||||||
case (0x0100+BLE_ATT_ERR_INSUFFICIENT_AUTHOR ):
|
case (BLE_HS_ERR_ATT_BASE + BLE_ATT_ERR_INSUFFICIENT_AUTHEN):
|
||||||
return "The attribute requires authorization before it can be read or written.";
|
return "Insufficient authentication";
|
||||||
case (0x0100+BLE_ATT_ERR_PREPARE_QUEUE_FULL ):
|
case (BLE_HS_ERR_ATT_BASE + BLE_ATT_ERR_REQ_NOT_SUPPORTED):
|
||||||
return "Too many prepare writes have been queued.";
|
return "Unsupported request";
|
||||||
case (0x0100+BLE_ATT_ERR_ATTR_NOT_FOUND ):
|
case (BLE_HS_ERR_ATT_BASE + BLE_ATT_ERR_INVALID_OFFSET):
|
||||||
return "No attribute found within the given attribute handle range.";
|
return "Invalid offset";
|
||||||
case (0x0100+BLE_ATT_ERR_ATTR_NOT_LONG ):
|
case (BLE_HS_ERR_ATT_BASE + BLE_ATT_ERR_INSUFFICIENT_AUTHOR):
|
||||||
return "The attribute cannot be read or written using the Read Blob Request.";
|
return "Insufficient authorization";
|
||||||
case (0x0100+BLE_ATT_ERR_INSUFFICIENT_KEY_SZ ):
|
case (BLE_HS_ERR_ATT_BASE + BLE_ATT_ERR_PREPARE_QUEUE_FULL):
|
||||||
return "The Encryption Key Size used for encrypting this link is insufficient.";
|
return "Prepare write queue full";
|
||||||
case (0x0100+BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN ):
|
case (BLE_HS_ERR_ATT_BASE + BLE_ATT_ERR_ATTR_NOT_FOUND):
|
||||||
return "The attribute value length is invalid for the operation.";
|
return "Attribute not found";
|
||||||
case (0x0100+BLE_ATT_ERR_UNLIKELY ):
|
case (BLE_HS_ERR_ATT_BASE + BLE_ATT_ERR_ATTR_NOT_LONG):
|
||||||
return "The attribute request has encountered an error that was unlikely, could not be completed as requested.";
|
return "Long read not supported";
|
||||||
case (0x0100+BLE_ATT_ERR_INSUFFICIENT_ENC ):
|
case (BLE_HS_ERR_ATT_BASE + BLE_ATT_ERR_INSUFFICIENT_KEY_SZ):
|
||||||
return "The attribute requires encryption before it can be read or written.";
|
return "Insufficient encryption key size";
|
||||||
case (0x0100+BLE_ATT_ERR_UNSUPPORTED_GROUP ):
|
case (BLE_HS_ERR_ATT_BASE + BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN):
|
||||||
return "The attribute type is not a supported grouping attribute as defined by a higher layer specification.";
|
return "Invalid attribute value length";
|
||||||
case (0x0100+BLE_ATT_ERR_INSUFFICIENT_RES ):
|
case (BLE_HS_ERR_ATT_BASE + BLE_ATT_ERR_UNLIKELY):
|
||||||
return "Insufficient Resources to complete the request.";
|
return "Unlikely attribute error";
|
||||||
case (0x0200+BLE_ERR_UNKNOWN_HCI_CMD ):
|
case (BLE_HS_ERR_ATT_BASE + BLE_ATT_ERR_INSUFFICIENT_ENC):
|
||||||
|
return "Insufficient encryption";
|
||||||
|
case (BLE_HS_ERR_ATT_BASE + BLE_ATT_ERR_UNSUPPORTED_GROUP):
|
||||||
|
return "Not a supported grouping attribute type";
|
||||||
|
case (BLE_HS_ERR_ATT_BASE + BLE_ATT_ERR_INSUFFICIENT_RES):
|
||||||
|
return "Insufficient Resources";
|
||||||
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_UNKNOWN_HCI_CMD):
|
||||||
return "Unknown HCI Command";
|
return "Unknown HCI Command";
|
||||||
case (0x0200+BLE_ERR_UNK_CONN_ID ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_UNK_CONN_ID):
|
||||||
return "Unknown Connection Identifier";
|
return "Unknown Connection Identifier";
|
||||||
case (0x0200+BLE_ERR_HW_FAIL ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_HW_FAIL):
|
||||||
return "Hardware Failure";
|
return "Hardware Failure";
|
||||||
case (0x0200+BLE_ERR_PAGE_TMO ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_PAGE_TMO):
|
||||||
return "Page Timeout";
|
return "Page Timeout";
|
||||||
case (0x0200+BLE_ERR_AUTH_FAIL ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_AUTH_FAIL):
|
||||||
return "Authentication Failure";
|
return "Authentication Failure";
|
||||||
case (0x0200+BLE_ERR_PINKEY_MISSING ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_PINKEY_MISSING):
|
||||||
return "PIN or Key Missing";
|
return "PIN or Key Missing";
|
||||||
case (0x0200+BLE_ERR_MEM_CAPACITY ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_MEM_CAPACITY):
|
||||||
return "Memory Capacity Exceeded";
|
return "Memory Capacity Exceeded";
|
||||||
case (0x0200+BLE_ERR_CONN_SPVN_TMO ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_CONN_SPVN_TMO):
|
||||||
return "Connection Timeout";
|
return "Connection Timeout";
|
||||||
case (0x0200+BLE_ERR_CONN_LIMIT ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_CONN_LIMIT):
|
||||||
return "Connection Limit Exceeded";
|
return "Connection Limit Exceeded";
|
||||||
case (0x0200+BLE_ERR_SYNCH_CONN_LIMIT ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_SYNCH_CONN_LIMIT):
|
||||||
return "Synchronous Connection Limit To A Device Exceeded";
|
return "Synchronous Connection Limit To A Device Exceeded";
|
||||||
case (0x0200+BLE_ERR_ACL_CONN_EXISTS ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_ACL_CONN_EXISTS):
|
||||||
return "ACL Connection Already Exists";
|
return "ACL Connection Already Exists";
|
||||||
case (0x0200+BLE_ERR_CMD_DISALLOWED ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_CMD_DISALLOWED):
|
||||||
return "Command Disallowed";
|
return "Command Disallowed";
|
||||||
case (0x0200+BLE_ERR_CONN_REJ_RESOURCES ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_CONN_REJ_RESOURCES):
|
||||||
return "Connection Rejected due to Limited Resources";
|
return "Connection Rejected due to Limited Resources";
|
||||||
case (0x0200+BLE_ERR_CONN_REJ_SECURITY ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_CONN_REJ_SECURITY):
|
||||||
return "Connection Rejected Due To Security Reasons";
|
return "Connection Rejected Due To Security Reasons";
|
||||||
case (0x0200+BLE_ERR_CONN_REJ_BD_ADDR ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_CONN_REJ_BD_ADDR):
|
||||||
return "Connection Rejected due to Unacceptable BD_ADDR";
|
return "Connection Rejected due to Unacceptable BD_ADDR";
|
||||||
case (0x0200+BLE_ERR_CONN_ACCEPT_TMO ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_CONN_ACCEPT_TMO):
|
||||||
return "Connection Accept Timeout Exceeded";
|
return "Connection Accept Timeout Exceeded";
|
||||||
case (0x0200+BLE_ERR_UNSUPPORTED ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_UNSUPPORTED):
|
||||||
return "Unsupported Feature or Parameter Value";
|
return "Unsupported Feature or Parameter Value";
|
||||||
case (0x0200+BLE_ERR_INV_HCI_CMD_PARMS ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_INV_HCI_CMD_PARMS):
|
||||||
return "Invalid HCI Command Parameters";
|
return "Invalid HCI Command Parameters";
|
||||||
case (0x0200+BLE_ERR_REM_USER_CONN_TERM ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_REM_USER_CONN_TERM):
|
||||||
return "Remote User Terminated Connection";
|
return "Remote User Terminated Connection";
|
||||||
case (0x0200+BLE_ERR_RD_CONN_TERM_RESRCS ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_RD_CONN_TERM_RESRCS):
|
||||||
return "Remote Device Terminated Connection due to Low Resources";
|
return "Remote Device Terminated Connection; Low Resources";
|
||||||
case (0x0200+BLE_ERR_RD_CONN_TERM_PWROFF ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_RD_CONN_TERM_PWROFF):
|
||||||
return "Remote Device Terminated Connection due to Power Off";
|
return "Remote Device Terminated Connection; Power Off";
|
||||||
case (0x0200+BLE_ERR_CONN_TERM_LOCAL ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_CONN_TERM_LOCAL):
|
||||||
return "Connection Terminated By Local Host";
|
return "Connection Terminated By Local Host";
|
||||||
case (0x0200+BLE_ERR_REPEATED_ATTEMPTS ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_REPEATED_ATTEMPTS):
|
||||||
return "Repeated Attempts";
|
return "Repeated Pairing Attempts";
|
||||||
case (0x0200+BLE_ERR_NO_PAIRING ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_NO_PAIRING):
|
||||||
return "Pairing Not Allowed";
|
return "Pairing Not Allowed";
|
||||||
case (0x0200+BLE_ERR_UNK_LMP ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_UNK_LMP):
|
||||||
return "Unknown LMP PDU";
|
return "Unknown LMP PDU";
|
||||||
case (0x0200+BLE_ERR_UNSUPP_REM_FEATURE ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_UNSUPP_REM_FEATURE):
|
||||||
return "Unsupported Remote Feature / Unsupported LMP Feature";
|
return "Unsupported Remote Feature";
|
||||||
case (0x0200+BLE_ERR_SCO_OFFSET ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_SCO_OFFSET):
|
||||||
return "SCO Offset Rejected";
|
return "SCO Offset Rejected";
|
||||||
case (0x0200+BLE_ERR_SCO_ITVL ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_SCO_ITVL):
|
||||||
return "SCO Interval Rejected";
|
return "SCO Interval Rejected";
|
||||||
case (0x0200+BLE_ERR_SCO_AIR_MODE ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_SCO_AIR_MODE):
|
||||||
return "SCO Air Mode Rejected";
|
return "SCO Air Mode Rejected";
|
||||||
case (0x0200+BLE_ERR_INV_LMP_LL_PARM ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_INV_LMP_LL_PARM):
|
||||||
return "Invalid LMP Parameters / Invalid LL Parameters";
|
return "Invalid LL Parameters";
|
||||||
case (0x0200+BLE_ERR_UNSPECIFIED ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_UNSPECIFIED):
|
||||||
return "Unspecified Error";
|
return "Unspecified Error";
|
||||||
case (0x0200+BLE_ERR_UNSUPP_LMP_LL_PARM ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_UNSUPP_LMP_LL_PARM):
|
||||||
return "Unsupported LMP Parameter Value / Unsupported LL Parameter Value";
|
return "Unsupported LL Parameter Value";
|
||||||
case (0x0200+BLE_ERR_NO_ROLE_CHANGE ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_NO_ROLE_CHANGE):
|
||||||
return "Role Change Not Allowed";
|
return "Role Change Not Allowed";
|
||||||
case (0x0200+BLE_ERR_LMP_LL_RSP_TMO ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_LMP_LL_RSP_TMO):
|
||||||
return "LMP Response Timeout / LL Response Timeout";
|
return "LL Response Timeout";
|
||||||
case (0x0200+BLE_ERR_LMP_COLLISION ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_LMP_COLLISION):
|
||||||
return "LMP Error Transaction Collision";
|
return "LMP Error Transaction Collision";
|
||||||
case (0x0200+BLE_ERR_LMP_PDU ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_LMP_PDU):
|
||||||
return "LMP PDU Not Allowed";
|
return "LMP PDU Not Allowed";
|
||||||
case (0x0200+BLE_ERR_ENCRYPTION_MODE ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_ENCRYPTION_MODE):
|
||||||
return "Encryption Mode Not Acceptable";
|
return "Encryption Mode Not Acceptable";
|
||||||
case (0x0200+BLE_ERR_LINK_KEY_CHANGE ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_LINK_KEY_CHANGE):
|
||||||
return "Link Key cannot be Changed";
|
return "Link Key cannot be Changed";
|
||||||
case (0x0200+BLE_ERR_UNSUPP_QOS ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_UNSUPP_QOS):
|
||||||
return "Requested QoS Not Supported";
|
return "Requested QoS Not Supported";
|
||||||
case (0x0200+BLE_ERR_INSTANT_PASSED ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_INSTANT_PASSED):
|
||||||
return "Instant Passed";
|
return "Instant Passed";
|
||||||
case (0x0200+BLE_ERR_UNIT_KEY_PAIRING ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_UNIT_KEY_PAIRING):
|
||||||
return "Pairing With Unit Key Not Supported";
|
return "Pairing With Unit Key Not Supported";
|
||||||
case (0x0200+BLE_ERR_DIFF_TRANS_COLL ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_DIFF_TRANS_COLL):
|
||||||
return "Different Transaction Collision";
|
return "Different Transaction Collision";
|
||||||
case (0x0200+BLE_ERR_QOS_PARM ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_QOS_PARM):
|
||||||
return "QoS Unacceptable Parameter";
|
return "QoS Unacceptable Parameter";
|
||||||
case (0x0200+BLE_ERR_QOS_REJECTED ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_QOS_REJECTED):
|
||||||
return "QoS Rejected";
|
return "QoS Rejected";
|
||||||
case (0x0200+BLE_ERR_CHAN_CLASS ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_CHAN_CLASS):
|
||||||
return "Channel Classification Not Supported";
|
return "Channel Classification Not Supported";
|
||||||
case (0x0200+BLE_ERR_INSUFFICIENT_SEC ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_INSUFFICIENT_SEC):
|
||||||
return "Insufficient Security";
|
return "Insufficient Security";
|
||||||
case (0x0200+BLE_ERR_PARM_OUT_OF_RANGE ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_PARM_OUT_OF_RANGE):
|
||||||
return "Parameter Out Of Mandatory Range";
|
return "Parameter Out Of Mandatory Range";
|
||||||
case (0x0200+BLE_ERR_PENDING_ROLE_SW ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_PENDING_ROLE_SW):
|
||||||
return "Role Switch Pending";
|
return "Role Switch Pending";
|
||||||
case (0x0200+BLE_ERR_RESERVED_SLOT ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_RESERVED_SLOT):
|
||||||
return "Reserved Slot Violation";
|
return "Reserved Slot Violation";
|
||||||
case (0x0200+BLE_ERR_ROLE_SW_FAIL ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_ROLE_SW_FAIL):
|
||||||
return "Role Switch Failed";
|
return "Role Switch Failed";
|
||||||
case (0x0200+BLE_ERR_INQ_RSP_TOO_BIG ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_INQ_RSP_TOO_BIG):
|
||||||
return "Extended Inquiry Response Too Large";
|
return "Extended Inquiry Response Too Large";
|
||||||
case (0x0200+BLE_ERR_SEC_SIMPLE_PAIR ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_SEC_SIMPLE_PAIR):
|
||||||
return "Secure Simple Pairing Not Supported By Host";
|
return "Secure Simple Pairing Not Supported By Host";
|
||||||
case (0x0200+BLE_ERR_HOST_BUSY_PAIR ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_HOST_BUSY_PAIR):
|
||||||
return "Host Busy - Pairing";
|
return "Host Busy - Pairing";
|
||||||
case (0x0200+BLE_ERR_CONN_REJ_CHANNEL ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_CONN_REJ_CHANNEL):
|
||||||
return "Connection Rejected, No Suitable Channel Found";
|
return "Connection Rejected, No Suitable Channel Found";
|
||||||
case (0x0200+BLE_ERR_CTLR_BUSY ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_CTLR_BUSY):
|
||||||
return "Controller Busy";
|
return "Controller Busy";
|
||||||
case (0x0200+BLE_ERR_CONN_PARMS ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_CONN_PARMS):
|
||||||
return "Unacceptable Connection Parameters";
|
return "Unacceptable Connection Parameters";
|
||||||
case (0x0200+BLE_ERR_DIR_ADV_TMO ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_DIR_ADV_TMO):
|
||||||
return "Directed Advertising Timeout";
|
return "Directed Advertising Timeout";
|
||||||
case (0x0200+BLE_ERR_CONN_TERM_MIC ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_CONN_TERM_MIC):
|
||||||
return "Connection Terminated due to MIC Failure";
|
return "Connection Terminated; MIC Failure";
|
||||||
case (0x0200+BLE_ERR_CONN_ESTABLISHMENT ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_CONN_ESTABLISHMENT):
|
||||||
return "Connection Failed to be Established";
|
return "Connection Failed to be Established";
|
||||||
case (0x0200+BLE_ERR_MAC_CONN_FAIL ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_MAC_CONN_FAIL):
|
||||||
return "MAC Connection Failed";
|
return "MAC Connection Failed";
|
||||||
case (0x0200+BLE_ERR_COARSE_CLK_ADJ ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_COARSE_CLK_ADJ):
|
||||||
return "Coarse Clock Adjustment Rejected";
|
return "Coarse Clock Adjustment Rejected";
|
||||||
case (0x0300+BLE_L2CAP_SIG_ERR_CMD_NOT_UNDERSTOOD ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_TYPE0_SUBMAP_NDEF):
|
||||||
return "Invalid or unsupported incoming L2CAP sig command.";
|
return "Type0 Submap Not Defined";
|
||||||
case (0x0300+BLE_L2CAP_SIG_ERR_MTU_EXCEEDED ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_UNK_ADV_INDENT):
|
||||||
return "Incoming packet too large.";
|
return "Unknown Advertising Identifier";
|
||||||
case (0x0300+BLE_L2CAP_SIG_ERR_INVALID_CID ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_LIMIT_REACHED):
|
||||||
return "No channel with specified ID.";
|
return "Limit Reached";
|
||||||
case (0x0400+BLE_SM_ERR_PASSKEY ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_OPERATION_CANCELLED):
|
||||||
return "The user input of passkey failed, for example, the user cancelled the operation.";
|
return "Operation Cancelled by Host";
|
||||||
case (0x0400+BLE_SM_ERR_OOB ):
|
case (BLE_HS_ERR_HCI_BASE + BLE_ERR_PACKET_TOO_LONG):
|
||||||
return "The OOB data is not available.";
|
return "Packet Too Long";
|
||||||
case (0x0400+BLE_SM_ERR_AUTHREQ ):
|
case (BLE_HS_ERR_L2C_BASE + BLE_L2CAP_SIG_ERR_CMD_NOT_UNDERSTOOD):
|
||||||
return "The pairing procedure cannot be performed as authentication requirements cannot be met due to IO capabilities of one or both devices.";
|
return "Invalid or unsupported incoming L2CAP sig command";
|
||||||
case (0x0400+BLE_SM_ERR_CONFIRM_MISMATCH ):
|
case (BLE_HS_ERR_L2C_BASE + BLE_L2CAP_SIG_ERR_MTU_EXCEEDED):
|
||||||
return "The confirm value does not match the calculated compare value.";
|
return "Incoming packet too large";
|
||||||
case (0x0400+BLE_SM_ERR_PAIR_NOT_SUPP ):
|
case (BLE_HS_ERR_L2C_BASE + BLE_L2CAP_SIG_ERR_INVALID_CID):
|
||||||
return "Pairing is not supported by the device.";
|
return "No channel with specified ID";
|
||||||
case (0x0400+BLE_SM_ERR_ENC_KEY_SZ ):
|
case (BLE_HS_ERR_SM_US_BASE + BLE_SM_ERR_PASSKEY):
|
||||||
return "The resultant encryption key size is insufficient for the security requirements of this device.";
|
case (BLE_HS_ERR_SM_PEER_BASE + BLE_SM_ERR_PASSKEY):
|
||||||
case (0x0400+BLE_SM_ERR_CMD_NOT_SUPP ):
|
return "Incorrect passkey or the user cancelled";
|
||||||
return "The SMP command received is not supported on this device.";
|
case (BLE_HS_ERR_SM_US_BASE + BLE_SM_ERR_OOB):
|
||||||
case (0x0400+BLE_SM_ERR_UNSPECIFIED ):
|
case (BLE_HS_ERR_SM_PEER_BASE + BLE_SM_ERR_OOB):
|
||||||
return "Pairing failed due to an unspecified reason.";
|
return "The OOB data is not available";
|
||||||
case (0x0400+BLE_SM_ERR_REPEATED ):
|
case (BLE_HS_ERR_SM_US_BASE + BLE_SM_ERR_AUTHREQ):
|
||||||
return "Pairing or authentication procedure disallowed, too little time has elapsed since last pairing request or security request.";
|
case (BLE_HS_ERR_SM_PEER_BASE + BLE_SM_ERR_AUTHREQ):
|
||||||
case (0x0400+BLE_SM_ERR_INVAL ):
|
return "Authentication requirements cannot be met due to IO capabilities";
|
||||||
return "Command length is invalid or that a parameter is outside of the specified range.";
|
case (BLE_HS_ERR_SM_US_BASE + BLE_SM_ERR_CONFIRM_MISMATCH):
|
||||||
case (0x0400+BLE_SM_ERR_DHKEY ):
|
case (BLE_HS_ERR_SM_PEER_BASE + BLE_SM_ERR_CONFIRM_MISMATCH):
|
||||||
return "DHKey Check value received doesn't match the one calculated by the local device.";
|
return "The confirm value does not match the calculated compare value";
|
||||||
case (0x0400+BLE_SM_ERR_NUMCMP ):
|
case (BLE_HS_ERR_SM_US_BASE + BLE_SM_ERR_PAIR_NOT_SUPP):
|
||||||
return "Confirm values in the numeric comparison protocol do not match.";
|
case (BLE_HS_ERR_SM_PEER_BASE + BLE_SM_ERR_PAIR_NOT_SUPP):
|
||||||
case (0x0400+BLE_SM_ERR_ALREADY ):
|
return "Pairing is not supported by the device";
|
||||||
return "Pairing over the LE transport failed - Pairing Request sent over the BR/EDR transport in process.";
|
case (BLE_HS_ERR_SM_US_BASE + BLE_SM_ERR_ENC_KEY_SZ):
|
||||||
case (0x0400+BLE_SM_ERR_CROSS_TRANS ):
|
case (BLE_HS_ERR_SM_PEER_BASE + BLE_SM_ERR_ENC_KEY_SZ):
|
||||||
return "BR/EDR Link Key generated on the BR/EDR transport cannot be used to derive and distribute keys for the LE transport.";
|
return "Insufficient encryption key size for this device";
|
||||||
case (0x0500+BLE_SM_ERR_PASSKEY ):
|
case (BLE_HS_ERR_SM_US_BASE + BLE_SM_ERR_CMD_NOT_SUPP):
|
||||||
return "The user input of passkey failed or the user cancelled the operation.";
|
case (BLE_HS_ERR_SM_PEER_BASE + BLE_SM_ERR_CMD_NOT_SUPP):
|
||||||
case (0x0500+BLE_SM_ERR_OOB ):
|
return "The SMP command received is not supported on this device";
|
||||||
return "The OOB data is not available.";
|
case (BLE_HS_ERR_SM_US_BASE + BLE_SM_ERR_UNSPECIFIED):
|
||||||
case (0x0500+BLE_SM_ERR_AUTHREQ ):
|
case (BLE_HS_ERR_SM_PEER_BASE + BLE_SM_ERR_UNSPECIFIED):
|
||||||
return "The pairing procedure cannot be performed as authentication requirements cannot be met due to IO capabilities of one or both devices.";
|
return "Pairing failed; unspecified reason";
|
||||||
case (0x0500+BLE_SM_ERR_CONFIRM_MISMATCH ):
|
case (BLE_HS_ERR_SM_US_BASE + BLE_SM_ERR_REPEATED):
|
||||||
return "The confirm value does not match the calculated compare value.";
|
case (BLE_HS_ERR_SM_PEER_BASE + BLE_SM_ERR_REPEATED):
|
||||||
case (0x0500+BLE_SM_ERR_PAIR_NOT_SUPP ):
|
return "Repeated pairing attempt";
|
||||||
return "Pairing is not supported by the device.";
|
case (BLE_HS_ERR_SM_US_BASE + BLE_SM_ERR_INVAL):
|
||||||
case (0x0500+BLE_SM_ERR_ENC_KEY_SZ ):
|
case (BLE_HS_ERR_SM_PEER_BASE + BLE_SM_ERR_INVAL):
|
||||||
return "The resultant encryption key size is insufficient for the security requirements of this device.";
|
return "Invalid command length or parameter";
|
||||||
case (0x0500+BLE_SM_ERR_CMD_NOT_SUPP ):
|
case (BLE_HS_ERR_SM_US_BASE + BLE_SM_ERR_DHKEY):
|
||||||
return "The SMP command received is not supported on this device.";
|
case (BLE_HS_ERR_SM_PEER_BASE + BLE_SM_ERR_DHKEY):
|
||||||
case (0x0500+BLE_SM_ERR_UNSPECIFIED ):
|
return "DHKey check value received doesn't match";
|
||||||
return "Pairing failed due to an unspecified reason.";
|
case (BLE_HS_ERR_SM_US_BASE + BLE_SM_ERR_NUMCMP):
|
||||||
case (0x0500+BLE_SM_ERR_REPEATED ):
|
case (BLE_HS_ERR_SM_PEER_BASE + BLE_SM_ERR_NUMCMP):
|
||||||
return "Pairing or authentication procedure is disallowed because too little time has elapsed since last pairing request or security request.";
|
return "Confirm values do not match";
|
||||||
case (0x0500+BLE_SM_ERR_INVAL ):
|
case (BLE_HS_ERR_SM_US_BASE + BLE_SM_ERR_ALREADY):
|
||||||
return "Command length is invalid or a parameter is outside of the specified range.";
|
case (BLE_HS_ERR_SM_PEER_BASE + BLE_SM_ERR_ALREADY):
|
||||||
case (0x0500+BLE_SM_ERR_DHKEY ):
|
return "Pairing already in process";
|
||||||
return "Indicates to the remote device that the DHKey Check value received doesn’t match the one calculated by the local device.";
|
case (BLE_HS_ERR_SM_US_BASE + BLE_SM_ERR_CROSS_TRANS):
|
||||||
case (0x0500+BLE_SM_ERR_NUMCMP ):
|
case (BLE_HS_ERR_SM_PEER_BASE + BLE_SM_ERR_CROSS_TRANS):
|
||||||
return "Confirm values in the numeric comparison protocol do not match.";
|
return "Invalid link key for the LE transport";
|
||||||
case (0x0500+BLE_SM_ERR_ALREADY ):
|
|
||||||
return "Pairing over the LE transport failed - Pairing Request sent over the BR/EDR transport in process.";
|
|
||||||
case (0x0500+BLE_SM_ERR_CROSS_TRANS ):
|
|
||||||
return "BR/EDR Link Key generated on the BR/EDR transport cannot be used to derive and distribute keys for the LE transport.";
|
|
||||||
default:
|
default:
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
#else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
|
# else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
|
||||||
(void)rc;
|
(void)rc;
|
||||||
return "";
|
return "";
|
||||||
#endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
|
# endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Convert the advertising type flag to a string.
|
* @brief Convert the advertising type flag to a string.
|
||||||
* @param advType The type to convert.
|
* @param advType The type to convert.
|
||||||
* @return A string representation of the advertising flags.
|
* @return A string representation of the advertising flags.
|
||||||
*/
|
*/
|
||||||
const char* NimBLEUtils::advTypeToString(uint8_t advType) {
|
const char* NimBLEUtils::advTypeToString(uint8_t advType) {
|
||||||
#if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT)
|
# if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT)
|
||||||
switch(advType) {
|
switch (advType) {
|
||||||
case BLE_HCI_ADV_TYPE_ADV_IND : //0
|
case BLE_HCI_ADV_TYPE_ADV_IND: // 0
|
||||||
return "Undirected - Connectable / Scannable";
|
return "Undirected - Connectable / Scannable";
|
||||||
case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD: //1
|
case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD: // 1
|
||||||
return "Directed High Duty - Connectable";
|
return "Directed High Duty - Connectable";
|
||||||
case BLE_HCI_ADV_TYPE_ADV_SCAN_IND: //2
|
case BLE_HCI_ADV_TYPE_ADV_SCAN_IND: // 2
|
||||||
return "Non-Connectable - Scan Response Available";
|
return "Non-Connectable - Scan Response Available";
|
||||||
case BLE_HCI_ADV_TYPE_ADV_NONCONN_IND: //3
|
case BLE_HCI_ADV_TYPE_ADV_NONCONN_IND: // 3
|
||||||
return "Non-Connectable - No Scan Response";
|
return "Non-Connectable - No Scan Response";
|
||||||
case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD: //4
|
case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD: // 4
|
||||||
return "Directed Low Duty - Connectable";
|
return "Directed Low Duty - Connectable";
|
||||||
default:
|
default:
|
||||||
return "Unknown flag";
|
return "Unknown flag";
|
||||||
}
|
}
|
||||||
#else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT)
|
# else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT)
|
||||||
(void)advType;
|
(void)advType;
|
||||||
return "";
|
return "";
|
||||||
#endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT)
|
# endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT)
|
||||||
} // adFlagsToString
|
} // adFlagsToString
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a hex representation of data.
|
|
||||||
*
|
|
||||||
* @param [in] target Where to write the hex string. If this is null, we malloc storage.
|
|
||||||
* @param [in] source The start of the binary data.
|
|
||||||
* @param [in] length The length of the data to convert.
|
|
||||||
* @return A pointer to the formatted buffer.
|
|
||||||
*/
|
|
||||||
char* NimBLEUtils::buildHexData(uint8_t* target, const uint8_t* source, uint8_t length) {
|
|
||||||
// Guard against too much data.
|
|
||||||
if (length > 100) length = 100;
|
|
||||||
|
|
||||||
if (target == nullptr) {
|
|
||||||
target = (uint8_t*) malloc(length * 2 + 1);
|
|
||||||
if (target == nullptr) {
|
|
||||||
NIMBLE_LOGE(LOG_TAG, "buildHexData: malloc failed");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
char* startOfData = (char*) target;
|
|
||||||
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
sprintf((char*) target, "%.2x", (char) *source);
|
|
||||||
source++;
|
|
||||||
target += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle the special case where there was no data.
|
|
||||||
if (length == 0) {
|
|
||||||
*startOfData = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return startOfData;
|
|
||||||
} // buildHexData
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Utility function to log the gap event info.
|
|
||||||
* @param [in] event A pointer to the gap event structure.
|
|
||||||
* @param [in] arg Unused.
|
|
||||||
*/
|
|
||||||
void NimBLEUtils::dumpGapEvent(ble_gap_event *event, void *arg){
|
|
||||||
(void)arg;
|
|
||||||
#if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "Received a GAP event: %s", gapEventToString(event->type));
|
|
||||||
#else
|
|
||||||
(void)event;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Convert a GAP event type to a string representation.
|
* @brief Convert a GAP event type to a string representation.
|
||||||
* @param [in] eventType The type of event.
|
* @param [in] eventType The type of event.
|
||||||
* @return A string representation of the event type.
|
* @return A string representation of the event type.
|
||||||
*/
|
*/
|
||||||
const char* NimBLEUtils::gapEventToString(uint8_t eventType) {
|
const char* NimBLEUtils::gapEventToString(uint8_t eventType) {
|
||||||
#if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
|
# if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
|
||||||
switch (eventType) {
|
switch (eventType) {
|
||||||
case BLE_GAP_EVENT_CONNECT : //0
|
case BLE_GAP_EVENT_CONNECT: // 0
|
||||||
return "BLE_GAP_EVENT_CONNECT ";
|
return "BLE_GAP_EVENT_CONNECT ";
|
||||||
|
case BLE_GAP_EVENT_DISCONNECT: // 1
|
||||||
case BLE_GAP_EVENT_DISCONNECT: //1
|
|
||||||
return "BLE_GAP_EVENT_DISCONNECT";
|
return "BLE_GAP_EVENT_DISCONNECT";
|
||||||
|
case BLE_GAP_EVENT_CONN_UPDATE: // 3
|
||||||
case BLE_GAP_EVENT_CONN_UPDATE: //3
|
|
||||||
return "BLE_GAP_EVENT_CONN_UPDATE";
|
return "BLE_GAP_EVENT_CONN_UPDATE";
|
||||||
|
case BLE_GAP_EVENT_CONN_UPDATE_REQ: // 4
|
||||||
case BLE_GAP_EVENT_CONN_UPDATE_REQ: //4
|
|
||||||
return "BLE_GAP_EVENT_CONN_UPDATE_REQ";
|
return "BLE_GAP_EVENT_CONN_UPDATE_REQ";
|
||||||
|
case BLE_GAP_EVENT_L2CAP_UPDATE_REQ: // 5
|
||||||
case BLE_GAP_EVENT_L2CAP_UPDATE_REQ: //5
|
|
||||||
return "BLE_GAP_EVENT_L2CAP_UPDATE_REQ";
|
return "BLE_GAP_EVENT_L2CAP_UPDATE_REQ";
|
||||||
|
case BLE_GAP_EVENT_TERM_FAILURE: // 6
|
||||||
case BLE_GAP_EVENT_TERM_FAILURE: //6
|
|
||||||
return "BLE_GAP_EVENT_TERM_FAILURE";
|
return "BLE_GAP_EVENT_TERM_FAILURE";
|
||||||
|
case BLE_GAP_EVENT_DISC: // 7
|
||||||
case BLE_GAP_EVENT_DISC: //7
|
|
||||||
return "BLE_GAP_EVENT_DISC";
|
return "BLE_GAP_EVENT_DISC";
|
||||||
|
case BLE_GAP_EVENT_DISC_COMPLETE: // 8
|
||||||
case BLE_GAP_EVENT_DISC_COMPLETE: //8
|
|
||||||
return "BLE_GAP_EVENT_DISC_COMPLETE";
|
return "BLE_GAP_EVENT_DISC_COMPLETE";
|
||||||
|
case BLE_GAP_EVENT_ADV_COMPLETE: // 9
|
||||||
case BLE_GAP_EVENT_ADV_COMPLETE: //9
|
|
||||||
return "BLE_GAP_EVENT_ADV_COMPLETE";
|
return "BLE_GAP_EVENT_ADV_COMPLETE";
|
||||||
|
case BLE_GAP_EVENT_ENC_CHANGE: // 10
|
||||||
case BLE_GAP_EVENT_ENC_CHANGE: //10
|
|
||||||
return "BLE_GAP_EVENT_ENC_CHANGE";
|
return "BLE_GAP_EVENT_ENC_CHANGE";
|
||||||
|
case BLE_GAP_EVENT_PASSKEY_ACTION: // 11
|
||||||
case BLE_GAP_EVENT_PASSKEY_ACTION : //11
|
|
||||||
return "BLE_GAP_EVENT_PASSKEY_ACTION";
|
return "BLE_GAP_EVENT_PASSKEY_ACTION";
|
||||||
|
case BLE_GAP_EVENT_NOTIFY_RX: // 12
|
||||||
case BLE_GAP_EVENT_NOTIFY_RX: //12
|
|
||||||
return "BLE_GAP_EVENT_NOTIFY_RX";
|
return "BLE_GAP_EVENT_NOTIFY_RX";
|
||||||
|
case BLE_GAP_EVENT_NOTIFY_TX: // 13
|
||||||
case BLE_GAP_EVENT_NOTIFY_TX : //13
|
|
||||||
return "BLE_GAP_EVENT_NOTIFY_TX";
|
return "BLE_GAP_EVENT_NOTIFY_TX";
|
||||||
|
case BLE_GAP_EVENT_SUBSCRIBE: // 14
|
||||||
case BLE_GAP_EVENT_SUBSCRIBE : //14
|
|
||||||
return "BLE_GAP_EVENT_SUBSCRIBE";
|
return "BLE_GAP_EVENT_SUBSCRIBE";
|
||||||
|
case BLE_GAP_EVENT_MTU: // 15
|
||||||
case BLE_GAP_EVENT_MTU: //15
|
|
||||||
return "BLE_GAP_EVENT_MTU";
|
return "BLE_GAP_EVENT_MTU";
|
||||||
|
case BLE_GAP_EVENT_IDENTITY_RESOLVED: // 16
|
||||||
case BLE_GAP_EVENT_IDENTITY_RESOLVED: //16
|
|
||||||
return "BLE_GAP_EVENT_IDENTITY_RESOLVED";
|
return "BLE_GAP_EVENT_IDENTITY_RESOLVED";
|
||||||
|
case BLE_GAP_EVENT_REPEAT_PAIRING: // 17
|
||||||
case BLE_GAP_EVENT_REPEAT_PAIRING: //17
|
|
||||||
return "BLE_GAP_EVENT_REPEAT_PAIRING";
|
return "BLE_GAP_EVENT_REPEAT_PAIRING";
|
||||||
|
case BLE_GAP_EVENT_PHY_UPDATE_COMPLETE: // 18
|
||||||
case BLE_GAP_EVENT_PHY_UPDATE_COMPLETE: //18
|
|
||||||
return "BLE_GAP_EVENT_PHY_UPDATE_COMPLETE";
|
return "BLE_GAP_EVENT_PHY_UPDATE_COMPLETE";
|
||||||
|
case BLE_GAP_EVENT_EXT_DISC: // 19
|
||||||
case BLE_GAP_EVENT_EXT_DISC: //19
|
|
||||||
return "BLE_GAP_EVENT_EXT_DISC";
|
return "BLE_GAP_EVENT_EXT_DISC";
|
||||||
#ifdef BLE_GAP_EVENT_PERIODIC_SYNC // IDF 4.0 does not support these
|
# ifdef BLE_GAP_EVENT_PERIODIC_SYNC // IDF 4.0 does not support these
|
||||||
case BLE_GAP_EVENT_PERIODIC_SYNC: //20
|
case BLE_GAP_EVENT_PERIODIC_SYNC: // 20
|
||||||
return "BLE_GAP_EVENT_PERIODIC_SYNC";
|
return "BLE_GAP_EVENT_PERIODIC_SYNC";
|
||||||
|
case BLE_GAP_EVENT_PERIODIC_REPORT: // 21
|
||||||
case BLE_GAP_EVENT_PERIODIC_REPORT: //21
|
|
||||||
return "BLE_GAP_EVENT_PERIODIC_REPORT";
|
return "BLE_GAP_EVENT_PERIODIC_REPORT";
|
||||||
|
case BLE_GAP_EVENT_PERIODIC_SYNC_LOST: // 22
|
||||||
case BLE_GAP_EVENT_PERIODIC_SYNC_LOST: //22
|
|
||||||
return "BLE_GAP_EVENT_PERIODIC_SYNC_LOST";
|
return "BLE_GAP_EVENT_PERIODIC_SYNC_LOST";
|
||||||
|
case BLE_GAP_EVENT_SCAN_REQ_RCVD: // 23
|
||||||
case BLE_GAP_EVENT_SCAN_REQ_RCVD: //23
|
|
||||||
return "BLE_GAP_EVENT_SCAN_REQ_RCVD";
|
return "BLE_GAP_EVENT_SCAN_REQ_RCVD";
|
||||||
#endif
|
case BLE_GAP_EVENT_PERIODIC_TRANSFER: // 24
|
||||||
|
return "BLE_GAP_EVENT_PERIODIC_TRANSFER";
|
||||||
|
case BLE_GAP_EVENT_PATHLOSS_THRESHOLD: // 25
|
||||||
|
return "BLE_GAP_EVENT_PATHLOSS_THRESHOLD";
|
||||||
|
case BLE_GAP_EVENT_TRANSMIT_POWER: // 26
|
||||||
|
return "BLE_GAP_EVENT_TRANSMIT_POWER";
|
||||||
|
case BLE_GAP_EVENT_SUBRATE_CHANGE: // 27
|
||||||
|
return "BLE_GAP_EVENT_SUBRATE_CHANGE";
|
||||||
|
case BLE_GAP_EVENT_VS_HCI: // 28
|
||||||
|
return "BLE_GAP_EVENT_VS_HCI";
|
||||||
|
case BLE_GAP_EVENT_REATTEMPT_COUNT: // 29
|
||||||
|
return "BLE_GAP_EVENT_REATTEMPT_COUNT";
|
||||||
|
case BLE_GAP_EVENT_AUTHORIZE: // 30
|
||||||
|
return "BLE_GAP_EVENT_AUTHORIZE";
|
||||||
|
case BLE_GAP_EVENT_TEST_UPDATE: // 31
|
||||||
|
return "BLE_GAP_EVENT_TEST_UPDATE";
|
||||||
|
case BLE_GAP_EVENT_DATA_LEN_CHG: // 32
|
||||||
|
return "BLE_GAP_EVENT_DATA_LEN_CHG";
|
||||||
|
case BLE_GAP_EVENT_LINK_ESTAB: // 33
|
||||||
|
return "BLE_GAP_EVENT_LINK_ESTAB";
|
||||||
|
# endif
|
||||||
default:
|
default:
|
||||||
NIMBLE_LOGD(LOG_TAG, "gapEventToString: Unknown event type %d 0x%.2x", eventType, eventType);
|
NIMBLE_LOGD(LOG_TAG, "Unknown event type %d 0x%.2x", eventType, eventType);
|
||||||
return "Unknown event type";
|
return "Unknown event type";
|
||||||
}
|
}
|
||||||
#else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
|
# else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
|
||||||
(void)eventType;
|
(void)eventType;
|
||||||
return "";
|
return "";
|
||||||
#endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
|
# endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
|
||||||
} // gapEventToString
|
} // gapEventToString
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a hexadecimal string representation of the input data.
|
||||||
|
* @param [in] source The start of the binary data.
|
||||||
|
* @param [in] length The length of the data to convert.
|
||||||
|
* @return A string representation of the data.
|
||||||
|
*/
|
||||||
|
std::string NimBLEUtils::dataToHexString(const uint8_t* source, uint8_t length) {
|
||||||
|
std::string str{};
|
||||||
|
str.reserve(length * 2 + 1);
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < length; i++) {
|
||||||
|
char c = (source[i] >> 4) & 0x0f;
|
||||||
|
str.push_back(c > 9 ? c + 'A' - 10 : c + '0');
|
||||||
|
c = source[i] & 0x0f;
|
||||||
|
str.push_back(c > 9 ? c + 'A' - 10 : c + '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
} // hexDataToString
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Generate a random BLE address.
|
* @brief Generate a random BLE address.
|
||||||
* @param [in] nrpa True to generate a non-resolvable private address,
|
* @param [in] nrpa True to generate a non-resolvable private address,
|
||||||
|
@ -496,7 +519,7 @@ const char* NimBLEUtils::gapEventToString(uint8_t eventType) {
|
||||||
*/
|
*/
|
||||||
NimBLEAddress NimBLEUtils::generateAddr(bool nrpa) {
|
NimBLEAddress NimBLEUtils::generateAddr(bool nrpa) {
|
||||||
ble_addr_t addr{};
|
ble_addr_t addr{};
|
||||||
int rc = ble_hs_id_gen_rnd(nrpa, &addr);
|
int rc = ble_hs_id_gen_rnd(nrpa, &addr);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "Generate address failed, rc=%d", rc);
|
NIMBLE_LOGE(LOG_TAG, "Generate address failed, rc=%d", rc);
|
||||||
}
|
}
|
||||||
|
@ -504,4 +527,4 @@ NimBLEAddress NimBLEUtils::generateAddr(bool nrpa) {
|
||||||
return NimBLEAddress{addr};
|
return NimBLEAddress{addr};
|
||||||
} // generateAddr
|
} // generateAddr
|
||||||
|
|
||||||
#endif //CONFIG_BT_ENABLED
|
#endif // CONFIG_BT_ENABLED
|
||||||
|
|
|
@ -6,40 +6,51 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef COMPONENTS_NIMBLEUTILS_H_
|
#ifndef NIMBLE_CPP_UTILS_H_
|
||||||
#define COMPONENTS_NIMBLEUTILS_H_
|
#define NIMBLE_CPP_UTILS_H_
|
||||||
|
|
||||||
#include "nimconfig.h"
|
#include "nimconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
# include <string>
|
||||||
# include <freertos/FreeRTOS.h>
|
|
||||||
# include <freertos/task.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
class NimBLEAddress;
|
class NimBLEAddress;
|
||||||
|
|
||||||
struct BleTaskData {
|
/**
|
||||||
void* pATT;
|
* @brief A structure to hold data for a task that is waiting for a response.
|
||||||
TaskHandle_t task;
|
* @details This structure is used in conjunction with NimBLEUtils::taskWait() and NimBLEUtils::taskRelease().
|
||||||
int rc;
|
* All items are optional, the m_pHandle will be set in taskWait().
|
||||||
void* buf;
|
*/
|
||||||
};
|
struct NimBLETaskData {
|
||||||
|
/**
|
||||||
|
* @brief Constructor.
|
||||||
|
* @param [in] pInstance An instance of the class that is waiting.
|
||||||
|
* @param [in] flags General purpose flags for the caller.
|
||||||
|
* @param [in] buf A buffer for data.
|
||||||
|
*/
|
||||||
|
NimBLETaskData(void* pInstance = nullptr, int flags = 0, void* buf = nullptr)
|
||||||
|
: m_pInstance(pInstance), m_flags(flags), m_pBuf(buf) {}
|
||||||
|
void* m_pInstance{nullptr};
|
||||||
|
mutable int m_flags{0};
|
||||||
|
void* m_pBuf{nullptr};
|
||||||
|
|
||||||
struct ble_gap_event;
|
private:
|
||||||
|
mutable void* m_pHandle{nullptr}; // semaphore or task handle
|
||||||
|
friend class NimBLEUtils;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A BLE Utility class with methods for debugging and general purpose use.
|
* @brief A BLE Utility class with methods for debugging and general purpose use.
|
||||||
*/
|
*/
|
||||||
class NimBLEUtils {
|
class NimBLEUtils {
|
||||||
public:
|
public:
|
||||||
static void dumpGapEvent(ble_gap_event *event, void *arg);
|
static const char* gapEventToString(uint8_t eventType);
|
||||||
static const char* gapEventToString(uint8_t eventType);
|
static std::string dataToHexString(const uint8_t* source, uint8_t length);
|
||||||
static char* buildHexData(uint8_t* target, const uint8_t* source, uint8_t length);
|
static const char* advTypeToString(uint8_t advType);
|
||||||
static const char* advTypeToString(uint8_t advType);
|
static const char* returnCodeToString(int rc);
|
||||||
static const char* returnCodeToString(int rc);
|
static NimBLEAddress generateAddr(bool nrpa);
|
||||||
static NimBLEAddress generateAddr(bool nrpa);
|
static bool taskWait(const NimBLETaskData& taskData, uint32_t timeout);
|
||||||
|
static void taskRelease(const NimBLETaskData& taskData, int rc = 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CONFIG_BT_ENABLED
|
#endif // CONFIG_BT_ENABLED
|
||||||
#endif // COMPONENTS_NIMBLEUTILS_H_
|
#endif // NIMBLE_CPP_UTILS_H_
|
||||||
|
|
Loading…
Reference in a new issue