6 Commits

Author SHA1 Message Date
h2zero
ee895d386e Release 2.1.1 2025-01-26 18:22:37 -07:00
thekurtovic
5add3442e9 refactor(RemoteChar): Reduce nesting
* Renamed desc_filter_t to NimBLEDescriptorFilter
* Added NimBLERemoteDescriptor pointer to NimBLEDescriptorFilter
* retrieveDescriptors changed to take NimBLEDescriptorFilter pointer
* General cleanup
2025-01-26 18:16:03 -07:00
h2zero
aea55ccda2 Rename config macros to enable duplicate scan options on s3/c3 2025-01-26 18:16:00 -07:00
h2zero
83e9919457 Workaround for P4 CI build error. 2025-01-26 18:15:57 -07:00
Guo-Rong
edeaf3977a Fix characteristic discovery with no descriptors.
Avoid discovery of descriptors if there are no handles remaining.
2025-01-26 18:15:54 -07:00
h2zero
4e80e1ee38 Release 2.1.0 2025-01-12 18:16:42 -07:00
7 changed files with 113 additions and 85 deletions

View File

@@ -1,6 +1,29 @@
# Changelog
All notable changes to this project will be documented in this file.
## [2.1.1] 2025-01-26
## Fixed
- remote descriptor discovery error when no descriptors exist.
- scan filter settings not enabled for esp32s3/c3.
- remote descriptor discovery returning more than the desired descriptor.
## [2.1.0] 2025-01-12
## Fixed
- Crash when retrieving descriptors if more than one exists.
- Incorrect TX power value being advertised.
- New user guide code for 2.x
- Potential race condition if `NimBLEScan::clearResults1 is called from multiple tasks.
## Changed
- If privacy is not enabled identity keys will not be shared.
- `NimBLEDevice::setPower` and `NimBLEDevice::getPower` now take an additional parameter `NimBLETxPowerType` to set/get the power level for different operations.
## Added
- Config option `CONFIG_NIMBLE_CPP_ADDR_FMT_EXCLUDE_DELIMITER`, if defined will remove the ":" delimiter from the BLE address string.
- Config option `CONFIG_NIMBLE_CPP_ADDR_FMT_UPPERCASE` if defined will make the BLE address strings uppercase.
## [2.0.3] 2025-01-05
## Fixed

View File

@@ -48,7 +48,7 @@ PROJECT_NAME = esp-nimble-cpp
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 2.0.3
PROJECT_NUMBER = 2.1.1
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a

View File

@@ -1,5 +1,5 @@
## IDF Component Manager Manifest File
version: "2.0.3"
version: "2.1.1"
license: "Apache-2.0"
description: "C++ wrapper for the NimBLE BLE stack"
url: "https://github.com/h2zero/esp-nimble-cpp"
@@ -16,7 +16,7 @@ dependencies:
rules:
- if: "target in [esp32p4]"
espressif/esp_wifi_remote:
version: "*"
version: "<0.5.4"
rules:
- if: "target in [esp32p4]"
idf:

View File

@@ -1,6 +1,6 @@
{
"name": "esp-nimble-cpp",
"version": "2.0.3",
"version": "2.1.1",
"description": "C++ wrapper for the NimBLE BLE stack",
"keywords": [
"BLE",

View File

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

View File

@@ -25,8 +25,10 @@
# include <vector>
# include <functional>
class NimBLEUUID;
class NimBLERemoteService;
class NimBLERemoteDescriptor;
struct NimBLEDescriptorFilter;
/**
* @brief A model of a remote BLE characteristic.
@@ -65,10 +67,10 @@ class NimBLERemoteCharacteristic : public NimBLERemoteValueAttribute {
~NimBLERemoteCharacteristic();
bool setNotify(uint16_t val, notify_callback notifyCallback = nullptr, bool response = true) const;
bool retrieveDescriptors(const NimBLEUUID* uuidFilter = nullptr) const;
bool retrieveDescriptors(NimBLEDescriptorFilter* filter = nullptr) const;
static int descriptorDiscCB(
uint16_t conn_handle, const ble_gatt_error* error, uint16_t chr_val_handle, const ble_gatt_dsc* dsc, void* arg);
uint16_t connHandle, const ble_gatt_error* error, uint16_t chrHandle, const ble_gatt_dsc* dsc, void* arg);
const NimBLERemoteService* m_pRemoteService{nullptr};
uint8_t m_properties{0};

View File

@@ -63,3 +63,19 @@
#if defined(CONFIG_BT_NIMBLE_EXT_ADV_MAX_SIZE) && !defined(CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN)
#define CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN CONFIG_BT_NIMBLE_EXT_ADV_MAX_SIZE
#endif
#if !defined(CONFIG_BTDM_BLE_SCAN_DUPL) && defined(CONFIG_BT_CTRL_BLE_SCAN_DUPL)
#define CONFIG_BTDM_BLE_SCAN_DUPL CONFIG_BT_CTRL_BLE_SCAN_DUPL
#endif
#if !defined(CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE) && defined(CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DEVICE)
#define CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DEVICE
#endif
#if !defined(CONFIG_BTDM_SCAN_DUPL_TYPE_DATA) && defined(CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA)
#define CONFIG_BTDM_SCAN_DUPL_TYPE_DATA CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA
#endif
#if !defined(CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE) && defined(CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE)
#define CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE
#endif