mirror of
https://github.com/h2zero/esp-nimble-cpp.git
synced 2025-12-23 07:12:36 +01:00
Compare commits
20 Commits
stream-cla
...
release/2.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5a70ac4b0 | ||
|
|
2feaedb755 | ||
|
|
60290cd75c | ||
|
|
2f6ab7589b | ||
|
|
ed51076d0c | ||
|
|
4972f3e08b | ||
|
|
95a35ec081 | ||
|
|
a127aba925 | ||
|
|
c655b21590 | ||
|
|
d10ffa19db | ||
|
|
dc53052411 | ||
|
|
da48844e2f | ||
|
|
ea1c055826 | ||
|
|
65f6ee18ca | ||
|
|
fd0187bfc9 | ||
|
|
275def333c | ||
|
|
ec4d4c43e1 | ||
|
|
3e0ce87a94 | ||
|
|
3743eb954e | ||
|
|
6357a0dbea |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1 +1 @@
|
||||
docs/doxydocs
|
||||
docs/doxydocs
|
||||
|
||||
37
CHANGELOG.md
37
CHANGELOG.md
@@ -1,6 +1,43 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [2.0.3] 2025-01-05
|
||||
|
||||
## Fixed
|
||||
- Unused variable warning when log level is below info.
|
||||
- Build error missing definition of CONFIG_NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT in platformio.
|
||||
- Race condition in `NimBLEScan` that can cause a crash due to heap corruption if `NimBLEScan::stop` is called from the `onResult` callback.
|
||||
- Advertisement data not set if scan response is enabled after the data is set.
|
||||
- `NimBLECharacteristic`/`NimBLEDescriptor` not able to update their values in the `onRead` callback.
|
||||
- Too short of a timeout being requested in NimBLE_Server example leading to frequent disconnects.
|
||||
|
||||
## Changed
|
||||
- `NimBLEHIDDevice` now allows for the same report ID in multiple input/output/feature reports.
|
||||
|
||||
## Added
|
||||
- Config for custom log colors pre level.
|
||||
- Error logs in the case that NIMBLE_CPP_DEBUG_ASSERT is not defined.
|
||||
- Error logs when setting advertisement data fails.
|
||||
- Missing documentation in the migration guide about enabling automatic advertising on disconnect, which was disabled by default in 2.x.
|
||||
|
||||
## [2.0.2] 2024-12-21
|
||||
|
||||
## Fixed
|
||||
- Compile error when only advertising role is enabled.
|
||||
- Possible crash if bonded client reconnects.
|
||||
|
||||
## Changed
|
||||
- `NimBLEHIDDevice` can now create more than one in/out/feature report map.
|
||||
|
||||
## [2.0.1] 2024-12-16
|
||||
|
||||
## Fixed
|
||||
- `NimBLEHIDDevice::getOutputReport` will now return the correct characteristic.
|
||||
- Compile error when central is disabled, class `NimBLEServer` has no member named `m_pClient`.
|
||||
|
||||
## Changed
|
||||
- Added missing includes for `NimBLEConnInfo` and `NimBLEUtils` to `NimBLEDevice.h`.
|
||||
|
||||
## [2.0.0] 2024-12-14
|
||||
|
||||
## **Breaking changes**
|
||||
|
||||
@@ -65,7 +65,8 @@ This returns a pointer to `const ble_addr_t` instead of a pointer to the address
|
||||
## Server
|
||||
- `NimBLEServer::disconnect` now returns `bool`, true = success, instead of `int` to be consistent with the rest of the library.
|
||||
- `NimBLEServerCallbacks::onMTUChanged` renamed to `NimBLEServerCallbacks::onMTUChange` to be consistent with the client callback.
|
||||
- `NimBLEServer::getPeerIDInfo` renamed to `NimBLEServer::getPeerInfoByHandle` to better describe it's use.
|
||||
- `NimBLEServer::getPeerIDInfo` renamed to `NimBLEServer::getPeerInfoByHandle` to better describe it's use.
|
||||
- Advertising is no longer automatically restarted when a peer disconnects, to re-enable this feature either call `NimBLEServer::advertiseOnDisconnect(true);` after creating the server or manually restart advertising in the `onDisconnect` callback.
|
||||
<br/>
|
||||
|
||||
### Services
|
||||
|
||||
@@ -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.0
|
||||
PROJECT_NUMBER = 2.0.3
|
||||
|
||||
# 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
|
||||
|
||||
@@ -26,7 +26,7 @@ class ServerCallbacks : public NimBLEServerCallbacks {
|
||||
* Latency: number of intervals allowed to skip.
|
||||
* Timeout: 10 millisecond increments.
|
||||
*/
|
||||
pServer->updateConnParams(connInfo.getConnHandle(), 24, 48, 0, 18);
|
||||
pServer->updateConnParams(connInfo.getConnHandle(), 24, 48, 0, 180);
|
||||
}
|
||||
|
||||
void onDisconnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo, int reason) override {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
## IDF Component Manager Manifest File
|
||||
version: "2.0.0"
|
||||
version: "2.0.3"
|
||||
license: "Apache-2.0"
|
||||
description: "C++ wrapper for the NimBLE BLE stack"
|
||||
url: "https://github.com/h2zero/esp-nimble-cpp"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "esp-nimble-cpp",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.3",
|
||||
"description": "C++ wrapper for the NimBLE BLE stack",
|
||||
"keywords": [
|
||||
"BLE",
|
||||
|
||||
@@ -39,7 +39,7 @@ static const char* LOG_TAG = "NimBLEAdvertisementData";
|
||||
* @param [in] length The size of data to be added to the payload.
|
||||
*/
|
||||
bool NimBLEAdvertisementData::addData(const uint8_t* data, size_t length) {
|
||||
if ((m_payload.size() + length) > BLE_HS_ADV_MAX_SZ) {
|
||||
if (m_payload.size() + length > BLE_HS_ADV_MAX_SZ) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Data length exceeded");
|
||||
return false;
|
||||
}
|
||||
@@ -159,6 +159,7 @@ bool NimBLEAdvertisementData::addServiceUUID(const NimBLEUUID& serviceUUID) {
|
||||
type = BLE_HS_ADV_TYPE_COMP_UUIDS128;
|
||||
break;
|
||||
default:
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot add UUID, invalid size!");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -169,10 +170,11 @@ bool NimBLEAdvertisementData::addServiceUUID(const NimBLEUUID& serviceUUID) {
|
||||
}
|
||||
|
||||
if (length + getPayload().size() > BLE_HS_ADV_MAX_SZ) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot add UUID, data length exceeded!");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t data[31];
|
||||
uint8_t data[BLE_HS_ADV_MAX_SZ];
|
||||
const uint8_t* uuid = serviceUUID.getValue();
|
||||
if (dataLoc == -1) {
|
||||
data[0] = 1 + bytes;
|
||||
@@ -214,6 +216,7 @@ bool NimBLEAdvertisementData::removeServiceUUID(const NimBLEUUID& serviceUUID) {
|
||||
type = BLE_HS_ADV_TYPE_COMP_UUIDS128;
|
||||
break;
|
||||
default:
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot remove UUID, invalid size!");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -266,12 +269,12 @@ bool NimBLEAdvertisementData::removeServices() {
|
||||
* @return True if successful.
|
||||
*/
|
||||
bool NimBLEAdvertisementData::setManufacturerData(const uint8_t* data, size_t length) {
|
||||
if (length > 29) {
|
||||
if (length > BLE_HS_ADV_MAX_FIELD_SZ) {
|
||||
NIMBLE_LOGE(LOG_TAG, "MFG data too long");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t mdata[31];
|
||||
uint8_t mdata[BLE_HS_ADV_MAX_SZ];
|
||||
mdata[0] = length + 1;
|
||||
mdata[1] = BLE_HS_ADV_TYPE_MFG_DATA;
|
||||
memcpy(&mdata[2], data, length);
|
||||
@@ -302,12 +305,12 @@ bool NimBLEAdvertisementData::setManufacturerData(const std::vector<uint8_t>& da
|
||||
* @return True if successful.
|
||||
*/
|
||||
bool NimBLEAdvertisementData::setURI(const std::string& uri) {
|
||||
if (uri.length() > 29) {
|
||||
if (uri.length() > BLE_HS_ADV_MAX_FIELD_SZ) {
|
||||
NIMBLE_LOGE(LOG_TAG, "URI too long");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t data[31];
|
||||
uint8_t data[BLE_HS_ADV_MAX_SZ];
|
||||
uint8_t length = 2 + uri.length();
|
||||
data[0] = length - 1;
|
||||
data[1] = BLE_HS_ADV_TYPE_URI;
|
||||
@@ -324,16 +327,16 @@ bool NimBLEAdvertisementData::setURI(const std::string& uri) {
|
||||
* @return True if successful.
|
||||
*/
|
||||
bool NimBLEAdvertisementData::setName(const std::string& name, bool isComplete) {
|
||||
if (name.length() > 29) {
|
||||
if (name.length() > BLE_HS_ADV_MAX_FIELD_SZ) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Name too long - truncating");
|
||||
isComplete = false;
|
||||
}
|
||||
|
||||
uint8_t data[31];
|
||||
uint8_t length = 2 + std::min<uint8_t>(name.length(), 29);
|
||||
uint8_t data[BLE_HS_ADV_MAX_SZ];
|
||||
uint8_t length = 2 + std::min<uint8_t>(name.length(), BLE_HS_ADV_MAX_FIELD_SZ);
|
||||
data[0] = length - 1;
|
||||
data[1] = isComplete ? BLE_HS_ADV_TYPE_COMP_NAME : BLE_HS_ADV_TYPE_INCOMP_NAME;
|
||||
memcpy(&data[2], name.c_str(), std::min<uint8_t>(name.length(), 29));
|
||||
memcpy(&data[2], name.c_str(), std::min<uint8_t>(name.length(), BLE_HS_ADV_MAX_FIELD_SZ));
|
||||
return addData(data, length);
|
||||
} // setName
|
||||
|
||||
@@ -411,14 +414,14 @@ bool NimBLEAdvertisementData::setPartialServices32(const std::vector<NimBLEUUID>
|
||||
bool NimBLEAdvertisementData::setServices(bool complete, uint8_t size, const std::vector<NimBLEUUID>& uuids) {
|
||||
uint8_t bytes = size / 8;
|
||||
uint8_t length = 2; // start with 2 for length + type bytes
|
||||
uint8_t data[31];
|
||||
uint8_t data[BLE_HS_ADV_MAX_SZ];
|
||||
|
||||
for (const auto& uuid : uuids) {
|
||||
if (uuid.bitSize() != size) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Service UUID(%d) invalid", size);
|
||||
continue;
|
||||
} else {
|
||||
if (length + bytes >= 31) {
|
||||
if (length + bytes >= BLE_HS_ADV_MAX_SZ) {
|
||||
NIMBLE_LOGW(LOG_TAG, "Too many services - truncating");
|
||||
complete = false;
|
||||
break;
|
||||
@@ -441,6 +444,7 @@ bool NimBLEAdvertisementData::setServices(bool complete, uint8_t size, const std
|
||||
data[1] = (complete ? BLE_HS_ADV_TYPE_COMP_UUIDS128 : BLE_HS_ADV_TYPE_INCOMP_UUIDS128);
|
||||
break;
|
||||
default:
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot set services, invalid size!");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -458,7 +462,7 @@ bool NimBLEAdvertisementData::setServices(bool complete, uint8_t size, const std
|
||||
bool NimBLEAdvertisementData::setServiceData(const NimBLEUUID& uuid, const uint8_t* data, size_t length) {
|
||||
uint8_t uuidBytes = uuid.bitSize() / 8;
|
||||
uint8_t sDataLen = 2 + uuidBytes + length;
|
||||
if (sDataLen > 31) {
|
||||
if (sDataLen > BLE_HS_ADV_MAX_SZ) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Service Data too long");
|
||||
return false;
|
||||
}
|
||||
@@ -475,6 +479,7 @@ bool NimBLEAdvertisementData::setServiceData(const NimBLEUUID& uuid, const uint8
|
||||
type = BLE_HS_ADV_TYPE_SVC_DATA_UUID128;
|
||||
break;
|
||||
default:
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot set service data, invalid size!");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -483,7 +488,7 @@ bool NimBLEAdvertisementData::setServiceData(const NimBLEUUID& uuid, const uint8
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t sData[31];
|
||||
uint8_t sData[BLE_HS_ADV_MAX_SZ];
|
||||
sData[0] = uuidBytes + length + 1;
|
||||
sData[1] = type;
|
||||
memcpy(&sData[2], uuid.getValue(), uuidBytes);
|
||||
|
||||
@@ -408,7 +408,7 @@ bool NimBLEAdvertising::refreshAdvertisingData() {
|
||||
* @return True if the service was added successfully.
|
||||
*/
|
||||
bool NimBLEAdvertising::addServiceUUID(const NimBLEUUID& serviceUUID) {
|
||||
if (!m_advData.addServiceUUID(serviceUUID) && m_scanResp) {
|
||||
if (!m_advData.addServiceUUID(serviceUUID)) {
|
||||
if (!m_scanData.addServiceUUID(serviceUUID)) {
|
||||
return false;
|
||||
}
|
||||
@@ -466,7 +466,7 @@ bool NimBLEAdvertising::removeServices() {
|
||||
* @return True if the appearance was set successfully.
|
||||
*/
|
||||
bool NimBLEAdvertising::setAppearance(uint16_t appearance) {
|
||||
if (!m_advData.setAppearance(appearance) && m_scanResp) {
|
||||
if (!m_advData.setAppearance(appearance)) {
|
||||
if (!m_scanData.setAppearance(appearance)) {
|
||||
return false;
|
||||
}
|
||||
@@ -484,7 +484,7 @@ bool NimBLEAdvertising::setAppearance(uint16_t appearance) {
|
||||
* @details Range = 0x0006(7.5ms) to 0x0C80(4000ms), values not within the range will be limited to this range.
|
||||
*/
|
||||
bool NimBLEAdvertising::setPreferredParams(uint16_t minInterval, uint16_t maxInterval) {
|
||||
if (!m_advData.setPreferredParams(minInterval, maxInterval) && m_scanResp) {
|
||||
if (!m_advData.setPreferredParams(minInterval, maxInterval)) {
|
||||
if (!m_scanData.setPreferredParams(minInterval, maxInterval)) {
|
||||
return false;
|
||||
}
|
||||
@@ -499,7 +499,7 @@ bool NimBLEAdvertising::setPreferredParams(uint16_t minInterval, uint16_t maxInt
|
||||
* @return True if the transmission power level was added successfully.
|
||||
*/
|
||||
bool NimBLEAdvertising::addTxPower() {
|
||||
if (!m_advData.addTxPower() && m_scanResp) {
|
||||
if (!m_advData.addTxPower()) {
|
||||
if (!m_scanData.addTxPower()) {
|
||||
return false;
|
||||
}
|
||||
@@ -537,7 +537,7 @@ bool NimBLEAdvertising::setName(const std::string& name) {
|
||||
* @return True if the manufacturer data was set successfully.
|
||||
*/
|
||||
bool NimBLEAdvertising::setManufacturerData(const uint8_t* data, size_t length) {
|
||||
if (!m_advData.setManufacturerData(data, length) && m_scanResp) {
|
||||
if (!m_advData.setManufacturerData(data, length)) {
|
||||
if (!m_scanData.setManufacturerData(data, length)) {
|
||||
return false;
|
||||
}
|
||||
@@ -571,7 +571,7 @@ bool NimBLEAdvertising::setManufacturerData(const std::vector<uint8_t>& data) {
|
||||
* @return True if the URI was set successfully.
|
||||
*/
|
||||
bool NimBLEAdvertising::setURI(const std::string& uri) {
|
||||
if (!m_advData.setURI(uri) && m_scanResp) {
|
||||
if (!m_advData.setURI(uri)) {
|
||||
if (!m_scanData.setURI(uri)) {
|
||||
return false;
|
||||
}
|
||||
@@ -590,7 +590,7 @@ bool NimBLEAdvertising::setURI(const std::string& uri) {
|
||||
* @note If data length is 0 the service data will not be advertised.
|
||||
*/
|
||||
bool NimBLEAdvertising::setServiceData(const NimBLEUUID& uuid, const uint8_t* data, size_t length) {
|
||||
if (!m_advData.setServiceData(uuid, data, length) && m_scanResp) {
|
||||
if (!m_advData.setServiceData(uuid, data, length)) {
|
||||
if (!m_scanData.setServiceData(uuid, data, length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
# endif
|
||||
|
||||
# include "NimBLEAttValue.h"
|
||||
# include "NimBLELog.h"
|
||||
|
||||
static const char* LOG_TAG = "NimBLEAttValue";
|
||||
|
||||
// Default constructor implementation.
|
||||
NimBLEAttValue::NimBLEAttValue(uint16_t init_len, uint16_t max_len)
|
||||
@@ -38,13 +41,17 @@ NimBLEAttValue::NimBLEAttValue(uint16_t init_len, uint16_t max_len)
|
||||
# endif
|
||||
{
|
||||
NIMBLE_CPP_DEBUG_ASSERT(m_attr_value);
|
||||
if (m_attr_value == nullptr) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Failed to calloc ctx");
|
||||
}
|
||||
}
|
||||
|
||||
// Value constructor implementation.
|
||||
NimBLEAttValue::NimBLEAttValue(const uint8_t* value, uint16_t len, uint16_t max_len) : NimBLEAttValue(len, max_len) {
|
||||
memcpy(m_attr_value, value, len);
|
||||
m_attr_value[len] = '\0';
|
||||
m_attr_len = len;
|
||||
if (m_attr_value != nullptr) {
|
||||
memcpy(m_attr_value, value, len);
|
||||
m_attr_len = len;
|
||||
}
|
||||
}
|
||||
|
||||
// Destructor implementation.
|
||||
@@ -81,6 +88,10 @@ NimBLEAttValue& NimBLEAttValue::operator=(const NimBLEAttValue& source) {
|
||||
void NimBLEAttValue::deepCopy(const NimBLEAttValue& source) {
|
||||
uint8_t* res = static_cast<uint8_t*>(realloc(m_attr_value, source.m_capacity + 1));
|
||||
NIMBLE_CPP_DEBUG_ASSERT(res);
|
||||
if (res == nullptr) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Failed to realloc deepCopy");
|
||||
return;
|
||||
}
|
||||
|
||||
ble_npl_hw_enter_critical();
|
||||
m_attr_value = res;
|
||||
@@ -106,7 +117,7 @@ NimBLEAttValue& NimBLEAttValue::append(const uint8_t* value, uint16_t len) {
|
||||
}
|
||||
|
||||
if ((m_attr_len + len) > m_attr_max_len) {
|
||||
NIMBLE_LOGE("NimBLEAttValue", "val > max, len=%u, max=%u", len, m_attr_max_len);
|
||||
NIMBLE_LOGE(LOG_TAG, "val > max, len=%u, max=%u", len, m_attr_max_len);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -117,6 +128,10 @@ NimBLEAttValue& NimBLEAttValue::append(const uint8_t* value, uint16_t len) {
|
||||
m_capacity = new_len;
|
||||
}
|
||||
NIMBLE_CPP_DEBUG_ASSERT(res);
|
||||
if (res == nullptr) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Failed to realloc append");
|
||||
return *this;
|
||||
}
|
||||
|
||||
# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
||||
time_t t = time(nullptr);
|
||||
@@ -135,4 +150,13 @@ NimBLEAttValue& NimBLEAttValue::append(const uint8_t* value, uint16_t len) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint8_t NimBLEAttValue::operator[](int pos) const {
|
||||
NIMBLE_CPP_DEBUG_ASSERT(pos < m_attr_len);
|
||||
if (pos >= m_attr_len) {
|
||||
NIMBLE_LOGE(LOG_TAG, "pos >= len, pos=%u, len=%u", pos, m_attr_len);
|
||||
return 0;
|
||||
}
|
||||
return m_attr_value[pos];
|
||||
}
|
||||
|
||||
#endif // CONFIG_BT_ENABLED
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
# include <Arduino.h>
|
||||
# endif
|
||||
|
||||
# include "NimBLELog.h"
|
||||
# include <string>
|
||||
# include <vector>
|
||||
# include <ctime>
|
||||
@@ -323,10 +322,7 @@ class NimBLEAttValue {
|
||||
/*********************** Operators ************************/
|
||||
|
||||
/** @brief Subscript operator */
|
||||
uint8_t operator[](int pos) const {
|
||||
NIMBLE_CPP_DEBUG_ASSERT(pos < m_attr_len);
|
||||
return m_attr_value[pos];
|
||||
}
|
||||
uint8_t operator[](int pos) const;
|
||||
|
||||
/** @brief Operator; Get the value as a std::vector<uint8_t>. */
|
||||
operator std::vector<uint8_t>() const { return std::vector<uint8_t>(m_attr_value, m_attr_value + m_attr_len); }
|
||||
|
||||
@@ -21,17 +21,12 @@
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
class NimBLEDescriptor;
|
||||
class NimBLEDescriptorCallbacks;
|
||||
|
||||
# include "NimBLELocalValueAttribute.h"
|
||||
# include "NimBLECharacteristic.h"
|
||||
# include "NimBLEUUID.h"
|
||||
# include "NimBLEAttValue.h"
|
||||
# include "NimBLEConnInfo.h"
|
||||
|
||||
# include <string>
|
||||
|
||||
class NimBLECharacteristic;
|
||||
class NimBLEDescriptorCallbacks;
|
||||
|
||||
/**
|
||||
* @brief A model of a BLE descriptor.
|
||||
*/
|
||||
|
||||
@@ -1154,6 +1154,7 @@ bool NimBLEDevice::startSecurity(uint16_t connHandle, int* rcPtr) {
|
||||
return rc == 0 || rc == BLE_HS_EALREADY;
|
||||
} // startSecurity
|
||||
|
||||
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) || defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
/**
|
||||
* @brief Inject the provided passkey into the Security Manager.
|
||||
* @param [in] peerInfo Connection information for the peer.
|
||||
@@ -1178,6 +1179,7 @@ bool NimBLEDevice::injectConfirmPasskey(const NimBLEConnInfo& peerInfo, bool acc
|
||||
NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_NUMCMP; ble_sm_inject_io result: %d", rc);
|
||||
return rc == 0;
|
||||
}
|
||||
# endif // CONFIG_BT_NIMBLE_ROLE_CENTRAL || CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* UTILITIES */
|
||||
|
||||
@@ -282,5 +282,11 @@ class NimBLEDevice {
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) || defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
# include "NimBLEConnInfo.h"
|
||||
# endif
|
||||
|
||||
# include "NimBLEUtils.h"
|
||||
|
||||
#endif // CONFIG_BT_ENABLED
|
||||
#endif // NIMBLE_CPP_DEVICE_H_
|
||||
|
||||
@@ -701,6 +701,7 @@ bool NimBLEExtAdvertisement::addServiceUUID(const NimBLEUUID& serviceUUID) {
|
||||
type = BLE_HS_ADV_TYPE_COMP_UUIDS128;
|
||||
break;
|
||||
default:
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot add UUID, invalid size!");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -711,10 +712,11 @@ bool NimBLEExtAdvertisement::addServiceUUID(const NimBLEUUID& serviceUUID) {
|
||||
}
|
||||
|
||||
if (length + getDataSize() > CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot add UUID, data length exceeded!");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t data[31];
|
||||
uint8_t data[BLE_HS_ADV_MAX_SZ];
|
||||
const uint8_t* uuid = serviceUUID.getValue();
|
||||
if (dataLoc == -1) {
|
||||
data[0] = 1 + bytes;
|
||||
@@ -756,6 +758,7 @@ bool NimBLEExtAdvertisement::removeServiceUUID(const NimBLEUUID& serviceUUID) {
|
||||
type = BLE_HS_ADV_TYPE_COMP_UUIDS128;
|
||||
break;
|
||||
default:
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot remove UUID, invalid size!");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -878,6 +881,7 @@ bool NimBLEExtAdvertisement::setServices(bool complete, uint8_t size, const std:
|
||||
header[1] = complete ? BLE_HS_ADV_TYPE_COMP_UUIDS128 : BLE_HS_ADV_TYPE_INCOMP_UUIDS128;
|
||||
break;
|
||||
default:
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot set services, invalid size!");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -932,6 +936,7 @@ bool NimBLEExtAdvertisement::setServiceData(const NimBLEUUID& uuid, const uint8_
|
||||
type = BLE_HS_ADV_TYPE_SVC_DATA_UUID128;
|
||||
break;
|
||||
default:
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot set service data, invalid size!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -149,14 +149,35 @@ void NimBLEHIDDevice::setBatteryLevel(uint8_t level, bool notify) {
|
||||
}
|
||||
} // setBatteryLevel
|
||||
|
||||
/**
|
||||
* @brief Locate the characteristic for a report ID and a report type.
|
||||
*
|
||||
* @param [in] reportId Report identifier to locate.
|
||||
* @param [in] reportType Type of report (input/output/feature).
|
||||
* @return NimBLECharacteristic* The characteristic.
|
||||
* @return nullptr If the characteristic does not exist.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEHIDDevice::locateReportCharacteristicByIdAndType(uint8_t reportId, uint8_t reportType) {
|
||||
NimBLECharacteristic* candidate = m_hidSvc->getCharacteristic(inputReportChrUuid, 0);
|
||||
for (uint16_t i = 1; (candidate != nullptr) && (i != 0); i++) {
|
||||
NimBLEDescriptor* dsc = candidate->getDescriptorByUUID(featureReportDscUuid);
|
||||
NimBLEAttValue desc1_val_att = dsc->getValue();
|
||||
const uint8_t* desc1_val = desc1_val_att.data();
|
||||
if ((desc1_val[0] == reportId) && (desc1_val[1] == reportType)) return candidate;
|
||||
candidate = m_hidSvc->getCharacteristic(inputReportChrUuid, i);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the input report characteristic.
|
||||
* @param [in] reportId input report ID, the same as in report map for input object related to the characteristic.
|
||||
* @return A pointer to the input report characteristic.
|
||||
* @param [in] reportId Input report ID, the same as in report map for input object related to the characteristic.
|
||||
* @return NimBLECharacteristic* A pointer to the input report characteristic.
|
||||
* Store this value to avoid computational overhead.
|
||||
* @details This will create the characteristic if not already created.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEHIDDevice::getInputReport(uint8_t reportId) {
|
||||
NimBLECharacteristic* inputReportChr = m_hidSvc->getCharacteristic(inputReportChrUuid);
|
||||
NimBLECharacteristic* inputReportChr = locateReportCharacteristicByIdAndType(reportId, 0x01);
|
||||
if (inputReportChr == nullptr) {
|
||||
inputReportChr =
|
||||
m_hidSvc->createCharacteristic(inputReportChrUuid,
|
||||
@@ -174,11 +195,12 @@ NimBLECharacteristic* NimBLEHIDDevice::getInputReport(uint8_t reportId) {
|
||||
/**
|
||||
* @brief Get the output report characteristic.
|
||||
* @param [in] reportId Output report ID, the same as in report map for output object related to the characteristic.
|
||||
* @return A pointer to the output report characteristic.
|
||||
* @return NimBLECharacteristic* A pointer to the output report characteristic.
|
||||
* Store this value to avoid computational overhead.
|
||||
* @details This will create the characteristic if not already created.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEHIDDevice::getOutputReport(uint8_t reportId) {
|
||||
NimBLECharacteristic* outputReportChr = m_hidSvc->getCharacteristic(inputReportChrUuid);
|
||||
NimBLECharacteristic* outputReportChr = locateReportCharacteristicByIdAndType(reportId, 0x02);
|
||||
if (outputReportChr == nullptr) {
|
||||
outputReportChr =
|
||||
m_hidSvc->createCharacteristic(inputReportChrUuid,
|
||||
@@ -187,7 +209,6 @@ NimBLECharacteristic* NimBLEHIDDevice::getOutputReport(uint8_t reportId) {
|
||||
NimBLEDescriptor* outputReportDsc = outputReportChr->createDescriptor(
|
||||
featureReportDscUuid,
|
||||
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC);
|
||||
|
||||
uint8_t desc1_val[] = {reportId, 0x02};
|
||||
outputReportDsc->setValue(desc1_val, 2);
|
||||
}
|
||||
@@ -198,11 +219,12 @@ NimBLECharacteristic* NimBLEHIDDevice::getOutputReport(uint8_t reportId) {
|
||||
/**
|
||||
* @brief Get the feature report characteristic.
|
||||
* @param [in] reportId Feature report ID, the same as in report map for feature object related to the characteristic.
|
||||
* @return A pointer to feature report characteristic.
|
||||
* @return NimBLECharacteristic* A pointer to feature report characteristic.
|
||||
* Store this value to avoid computational overhead.
|
||||
* @details This will create the characteristic if not already created.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEHIDDevice::getFeatureReport(uint8_t reportId) {
|
||||
NimBLECharacteristic* featureReportChr = m_hidSvc->getCharacteristic(inputReportChrUuid);
|
||||
NimBLECharacteristic* featureReportChr = locateReportCharacteristicByIdAndType(reportId, 0x03);
|
||||
if (featureReportChr == nullptr) {
|
||||
featureReportChr = m_hidSvc->createCharacteristic(
|
||||
inputReportChrUuid,
|
||||
|
||||
@@ -81,6 +81,8 @@ class NimBLEHIDDevice {
|
||||
NimBLECharacteristic* m_hidControlChr{nullptr}; // 0x2a4c
|
||||
NimBLECharacteristic* m_protocolModeChr{nullptr}; // 0x2a4e
|
||||
NimBLECharacteristic* m_batteryLevelChr{nullptr}; // 0x2a19
|
||||
|
||||
NimBLECharacteristic* locateReportCharacteristicByIdAndType(uint8_t reportId, uint8_t reportType);
|
||||
};
|
||||
|
||||
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
@@ -72,14 +72,8 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(
|
||||
const auto pChr = (NimBLERemoteCharacteristic*)pTaskData->m_pInstance;
|
||||
const NimBLEUUID* uuidFilter = filter->uuid;
|
||||
|
||||
if (error->status == BLE_HS_ENOTCONN) {
|
||||
NIMBLE_LOGE(LOG_TAG, "<< Descriptor Discovery; Not connected");
|
||||
NimBLEUtils::taskRelease(*pTaskData, error->status);
|
||||
return error->status;
|
||||
}
|
||||
|
||||
if (pChr->getHandle() != chr_val_handle) {
|
||||
rc = BLE_HS_EDONE; // descriptor not for this characteristic
|
||||
return 0; // Descriptor not for this characteristic
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
@@ -92,6 +86,7 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(
|
||||
}
|
||||
|
||||
pChr->m_vDescriptors.push_back(new NimBLERemoteDescriptor(pChr, dsc));
|
||||
return 0;
|
||||
}
|
||||
|
||||
NimBLEUtils::taskRelease(*pTaskData, rc);
|
||||
|
||||
@@ -147,7 +147,10 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle,
|
||||
const ble_gatt_error* error,
|
||||
const ble_gatt_chr* chr,
|
||||
void* arg) {
|
||||
NIMBLE_LOGD(LOG_TAG, "Characteristic Discovery >>");
|
||||
NIMBLE_LOGD(LOG_TAG,
|
||||
"Characteristic Discovery >> status: %d handle: %d",
|
||||
error->status,
|
||||
(error->status == 0) ? chr->def_handle : -1);
|
||||
auto pTaskData = (NimBLETaskData*)arg;
|
||||
const auto pSvc = (NimBLERemoteService*)pTaskData->m_pInstance;
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
# include "NimBLERemoteValueAttribute.h"
|
||||
# include "NimBLEClient.h"
|
||||
# include "NimBLEUtils.h"
|
||||
# include "NimBLELog.h"
|
||||
|
||||
# include <climits>
|
||||
|
||||
|
||||
@@ -119,19 +119,19 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
|
||||
}
|
||||
|
||||
if (!advertisedDevice->m_callbackSent) {
|
||||
pScan->m_pScanCallbacks->onDiscovered(advertisedDevice);
|
||||
advertisedDevice->m_callbackSent++;
|
||||
pScan->m_pScanCallbacks->onDiscovered(advertisedDevice);
|
||||
}
|
||||
|
||||
// If not active scanning or scan response is not available
|
||||
// or extended advertisement scanning, report the result to the callback now.
|
||||
if (pScan->m_scanParams.passive || !isLegacyAdv || !advertisedDevice->isScannable()) {
|
||||
pScan->m_pScanCallbacks->onResult(advertisedDevice);
|
||||
advertisedDevice->m_callbackSent++;
|
||||
pScan->m_pScanCallbacks->onResult(advertisedDevice);
|
||||
} else if (isLegacyAdv && event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
|
||||
advertisedDevice->m_callbackSent++;
|
||||
// got the scan response report the full data.
|
||||
pScan->m_pScanCallbacks->onResult(advertisedDevice);
|
||||
advertisedDevice->m_callbackSent++;
|
||||
}
|
||||
|
||||
// If not storing results and we have invoked the callback, delete the device.
|
||||
|
||||
@@ -70,9 +70,11 @@ NimBLEServer::~NimBLEServer() {
|
||||
delete m_pServerCallbacks;
|
||||
}
|
||||
|
||||
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
if (m_pClient != nullptr) {
|
||||
delete m_pClient;
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -399,10 +401,12 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
|
||||
}
|
||||
}
|
||||
|
||||
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
if (pServer->m_pClient && pServer->m_pClient->m_connHandle == event->disconnect.conn.conn_handle) {
|
||||
// If this was also the client make sure it's flagged as disconnected.
|
||||
pServer->m_pClient->m_connHandle = BLE_HS_CONN_HANDLE_NONE;
|
||||
}
|
||||
# endif
|
||||
|
||||
if (pServer->m_svcChanged) {
|
||||
pServer->resetGATT();
|
||||
@@ -607,8 +611,9 @@ int NimBLEServer::handleGattEvent(uint16_t connHandle, uint16_t attrHandle, ble_
|
||||
NIMBLE_LOGD(LOG_TAG,
|
||||
"Gatt %s event",
|
||||
(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR || ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC) ? "Read" : "Write");
|
||||
auto pAtt = static_cast<NimBLELocalValueAttribute*>(arg);
|
||||
auto val = pAtt->getAttVal();
|
||||
auto pAtt = static_cast<NimBLELocalValueAttribute*>(arg);
|
||||
const NimBLEAttValue& val = pAtt->getAttVal();
|
||||
|
||||
NimBLEConnInfo peerInfo{};
|
||||
ble_gap_conn_find(connHandle, &peerInfo.m_desc);
|
||||
|
||||
@@ -619,7 +624,7 @@ int NimBLEServer::handleGattEvent(uint16_t connHandle, uint16_t attrHandle, ble_
|
||||
if (connHandle != BLE_HS_CONN_HANDLE_NONE) {
|
||||
// If the packet header is only 8 bytes then this is a follow up of a long read
|
||||
// so we don't want to call the onRead() callback again.
|
||||
if (ctxt->om->om_pkthdr_len > 8 || pAtt->getAttVal().size() <= (ble_att_mtu(connHandle) - 3)) {
|
||||
if (ctxt->om->om_pkthdr_len > 8 || val.size() <= (ble_att_mtu(connHandle) - 3)) {
|
||||
pAtt->readEvent(peerInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +91,13 @@ void NimBLEService::dump() const {
|
||||
*/
|
||||
bool NimBLEService::start() {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> start(): Starting service: %s", toString().c_str());
|
||||
|
||||
// If started previously and no characteristics have been added or removed,
|
||||
// then we can skip the service registration process.
|
||||
if (m_pSvcDef->characteristics && !getServer()->m_svcChanged) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If started previously, clear everything and start over
|
||||
if (m_pSvcDef->characteristics) {
|
||||
if (m_pSvcDef->characteristics->descriptors) {
|
||||
|
||||
@@ -37,6 +37,9 @@
|
||||
# include <climits>
|
||||
|
||||
# if defined INC_FREERTOS_H
|
||||
# ifndef CONFIG_NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT
|
||||
# define CONFIG_NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT 31
|
||||
# endif
|
||||
constexpr uint32_t TASK_BLOCK_BIT = (1 << CONFIG_NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT);
|
||||
# endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user