20 Commits

Author SHA1 Message Date
h2zero
f80605aff8 Release 2.3.2 2025-09-02 14:54:56 -06:00
h2zero
e26c7406fb Improve macros for code enablement 2025-09-02 14:42:46 -06:00
h2zero
a547f2529a Fix docs build 2025-09-02 14:42:42 -06:00
h2zero
ad145ad503 Fix build with idf v5.5+ and specific roles are defined. 2025-09-02 14:42:40 -06:00
h2zero
ecc617f9eb Refactor to use MYNEWT_VAL macros.
This replaces the previously prefixed CONFIG_BT_X config macros with the underlying MYNEWT_VAL_X config macros that they affected.
2025-09-02 14:42:38 -06:00
iranl
485a01b78c Fix undefined reference to ble_svc_gap_device_name_set when GATT server is disabled (#349)
* Fix undefined reference to ble_svc_gap_device_name_set when GATT server is disabled

* Do not affect ESP-IDF <5.5.0
2025-09-02 14:42:32 -06:00
h2zero
f0ca3bf35d [Bugfix] OnConnectfail not called when connection not established.
Workaround for when the disconnect event is sent when no connection has been established.
Espressif changed this from a connect event with error code to disconnect event.
2025-09-02 14:42:30 -06:00
h2zero
ac55482b18 Change default security settings to BLE secure connections off.
Fixing some connection issues when enabled, users should enable if desired.
2025-09-02 14:42:28 -06:00
h2zero
8b9e430e5b [Bugfix](workaround) OnConnect not being called.
Upstream changes have resulted in a possible status of BLE_ERR_UNSUPP_REM_FEATURE, this resulted in the onConnect callback not being called despite the connection actually being created.
This works around that bug to ensure that the connections are correctly tracked.
2025-09-02 14:42:26 -06:00
h2zero
6da9905235 Fix build with idf versions < 5.x 2025-09-02 14:42:23 -06:00
h2zero
18cc463c2c [Bugfix] allow peripheral and central roles without broadcast/scan. 2025-09-02 14:42:21 -06:00
h2zero
e7a1462a99 Bump idf_component version 2025-06-11 11:40:56 -06:00
h2zero
9e141c9f58 Fix library.json version 2025-06-11 11:34:26 -06:00
h2zero
e5dbd26693 Release 2.3.1 2025-06-11 11:16:49 -06:00
h2zero
2272e3c4a7 Update docs 2025-06-11 11:16:46 -06:00
Larry Davis
8c6a9d4258 Support passing data directly from NimBLEBeacon.getData() to NimBLEAdvertisementData.setManufacturerData() 2025-06-11 11:16:42 -06:00
h2zero
e4d202f1ce [Bugfix] NimBLEScan delete.
Calling NimBLEDevice::deint with the `clearAll` parameter set to `true` will delete the scan and any scan results but it was calling `clearall` which uses critical sections, this could cause a crash because the stack has already been de-initialized.
2025-06-11 11:16:38 -06:00
h2zero
20349d9e8b Fix server client read/write not returning when encryption is used.
When the client created by the server reads or writes to an attribute and it triggers a pairing action the task will not be released because the client does not get the event.
This passes the event to the client to prevent the task from being hung.
2025-06-11 11:16:35 -06:00
h2zero
96c142034e Fix builds when exluding roles 2025-06-11 11:16:22 -06:00
John Boiles
252b4f5644 Allow esp_wifi_remote >= 0.5.3
`esp_wifi_remote` >= v0.10.0 is necessary to use esp-nimble-cpp with the latest ESP-IDF master branch.
2025-06-11 11:16:16 -06:00
32 changed files with 199 additions and 658 deletions

View File

@@ -18,7 +18,7 @@ jobs:
# https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-docker-image.html
# for details.
idf_ver: ["release-v4.4", "release-v5.4", "release-v5.5"]
idf_target: ["esp32", "esp32s3", "esp32c2", "esp32c3", "esp32c5", "esp32c6", "esp32c61", "esp32h2", "esp32p4"]
idf_target: ["esp32", "esp32s3", "esp32c2", "esp32c3", "esp32c5", "esp32c6", "esp32h2", "esp32p4"]
example:
- NimBLE_Client
- NimBLE_Server
@@ -35,10 +35,6 @@ jobs:
idf_target: "esp32c5"
- idf_ver: release-v4.4
idf_target: "esp32c6"
- idf_ver: release-v4.4
idf_target: "esp32c61"
- idf_ver: release-v5.4
idf_target: "esp32c61"
- idf_ver: release-v4.4
idf_target: "esp32h2"
- idf_ver: release-v4.4
@@ -49,7 +45,7 @@ jobs:
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v4
with:
path: components/esp-nimble-cpp
- name: Build examples

View File

@@ -8,7 +8,7 @@ jobs:
build_docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- name: Doxygen Action
uses: mattnotmitt/doxygen-action@v1.9.8
with:
@@ -17,27 +17,4 @@ jobs:
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/doxydocs/html
upload_to_component_registry:
permissions:
id-token: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
submodules: "recursive"
- name: Upload component to the component registry
uses: espressif/upload-components-ci-action@v2
with:
components: "esp-nimble-cpp: ."
namespace: "h2zero"
upload_to_platformio_registry:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Upload component to PlatformIO Registry
uses: bojit/platformio-publish@main
with:
token: ${{ secrets.PLATFORMIO_AUTH_TOKEN }}
publish_dir: ./docs/doxydocs/html

1
.gitignore vendored
View File

@@ -1,2 +1 @@
docs/doxydocs
dist

View File

@@ -1,15 +1,6 @@
# Changelog
All notable changes to this project will be documented in this file.
## [2.3.3] 2025-09-05
## Fixed
- NimBLEAdvertisedDevice::isConnectable returning incorrect result.
- Extended advertisements not reporting full data.
## Added
- Support up to 1650 bytes of advertisement with extended advertising
## [2.3.2] 2025-09-02
## Fixed

View File

@@ -37,7 +37,6 @@ idf_component_register(
"esp32c3"
"esp32c5"
"esp32c6"
"esp32c61"
"esp32h2"
"esp32p4"
INCLUDE_DIRS

View File

@@ -9,8 +9,6 @@
NimBLE CPP library for use with ESP32 that attempts to maintain compatibility with the [nkolban cpp_utils BLE API](https://github.com/nkolban/esp32-snippets/tree/master/cpp_utils).
The library is threadsafe, characteristics can be set from any thread.
**An Arduino version of this library, including NimBLE, can be [found here.](https://github.com/h2zero/NimBLE-Arduino)**
This library **significantly** reduces resource usage and improves performance for ESP32 BLE applications as compared

View File

@@ -55,7 +55,7 @@ The default address type is public `0`, whereas many devices use a random `1` ad
If you experience this issue please create your address instances with the address type specified, i.e. `NimBLEAddress address("11:22:33:44:55:66", TYPE_HERE)`
`NimBLEAddress::getNative` has been removed and replaced with `NimBLEAddress::getBase`.
This returns a pointer to `const ble_addr_t` instead of a pointer to the address value that `getNative` did. The value can be accessed through this struct via `ble_addr_t.val` and type is in `ble_addr_t.type`.
This returns a pointer to `const ble_addr_t` instead of a pointer to the address value that `getNative` did. The value can be accessed through this struct via `ble_addr_t.value` and type is in `ble_addr_t.type`.
<br/>
## BLE UUID's

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.3.3
PROJECT_NUMBER = 2.3.2
# 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
# quick idea about the purpose of the project. Keep the description short.

View File

@@ -1,8 +1,11 @@
# Usage Tips
## Threadsafety
## Put BLE functions in a task running on the NimBLE stack core
This library is threadsafe. Attribues can be manipulated freely.
When commands are sent to the stack from a different core they can experience delays in execution.
This library detects this and invokes the esp32 IPC to reroute these commands through the correct core but this also increases overhead.
Therefore it is highly recommended to create tasks for BLE to run on the same core, the macro `CONFIG_BT_NIMBLE_PINNED_TO_CORE` can be used to set the core.
<br/>
## Do not delete client instances unless necessary or unused
@@ -29,41 +32,6 @@ or nullptr such as when calling `NimBLEClient::getService`. The latter being a
Most of the functions in this library return something that should be checked before proceeding.
<br/>
## Persisted bonds can be lost due to low MAX_CCCDS
The symptom: CONFIG_BT_NIMBLE_MAX_BONDS is set to N, but a smaller number of bonds is preserved, perhaps even a single bond. The limitation of persisted bonds can be observed via NimBLEDevice::getNumBonds(). The number may not reach CONFIG_BT_NIMBLE_MAX_BONDS.
Cause: For each bond, NimBLE persists each of the CCCD (client characteristic configuration descriptor) values that have been subscribed
to by the client. If CONFIG_BT_NIMBLE_MAX_CCCDS is too low, the older CCCD values are overwritten by the newer ones. The loss of the older
CCCDs values results in those bonds being lost.
Fix: Increase CONFIG_BT_NIMBLE_MAX_CCCDS. These take approximately 40 bytes in NVS, 2 bytes for the CCCD value and the NVS metadata overhead. The value of
CONFIG_BT_NIMBLE_MAX_CCCDS should conservatively be no less than (CONFIG_BT_NIMBLE_MAX_BONDS * {maximum number of characteristics that can be subscribed to}).
## Device 'Local Name'
'Local name' refers to how the device is seen and displayed.
A devices 'Local name' can be thought of as coming from two places, the <i>Advertising "Local name"</i> and the <i>the GATT Device Name</i>.
### Advertising "Local name"
Field found in the advertising data payload. Value is set via NimBLEAdvertising::setName().
### GATT Device Name
Characteristic UUID 0x2A00 in the Generic Access service. Set via NimBLEDevice::init() or NimBLEDevice::setDeviceName().
This characteristic is read <b>after</b> connecting to the device.
### Important considerations
* OSes cache the <i>'GATT Device Name'</i>.
* OSes update the device name based on the <i>'GATT Device Name'</i> after connecting to a device. This means that if you set the <i>Advertising 'Local name'</i> to "ABCD" but the <i>'GATT Device Name'</i> to "12345", the device will be seen as "ABCD" until connecting to the device, at which time the devices name will change to "12345".
* If no <i>'Advertising "Local name"'</i> is set, OSes, such as iOS, may display the devices name as 'Unnamed' until the device is connected to, at which time the <i>'GATT Device Name'</i> is read and used instead.
It is recommended that both <i>'Advertising "Local name"'</i> <b>and</b> <i>'GATT Device Name'</i> be set appropriately, after considering the above described behavior.
## There will be bugs - please report them
No code is bug free and unit testing will not find them all on it's own. If you encounter a bug, please report it along with any logs and decoded backtrace if applicable.

View File

@@ -1,5 +1,5 @@
## IDF Component Manager Manifest File
version: "2.3.3"
version: "2.3.2"
license: "Apache-2.0"
description: "C++ wrapper for the NimBLE BLE stack"
url: "https://github.com/h2zero/esp-nimble-cpp"

View File

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

View File

@@ -22,29 +22,13 @@
# include <algorithm>
# ifndef MYNEWT_VAL_NIMBLE_CPP_ADDR_FMT_EXCLUDE_DELIMITER
# ifndef CONFIG_NIMBLE_CPP_ADDR_FMT_EXCLUDE_DELIMITER
# define MYNEWT_VAL_NIMBLE_CPP_ADDR_FMT_EXCLUDE_DELIMITER (0)
# else
# define MYNEWT_VAL_NIMBLE_CPP_ADDR_FMT_EXCLUDE_DELIMITER CONFIG_NIMBLE_CPP_ADDR_FMT_EXCLUDE_DELIMITER
# endif
# endif
# ifndef MYNEWT_VAL_NIMBLE_CPP_ADDR_FMT_UPPERCASE
# ifndef CONFIG_NIMBLE_CPP_ADDR_FMT_UPPERCASE
# define MYNEWT_VAL_NIMBLE_CPP_ADDR_FMT_UPPERCASE (1)
# else
# define MYNEWT_VAL_NIMBLE_CPP_ADDR_FMT_UPPERCASE CONFIG_NIMBLE_CPP_ADDR_FMT_UPPERCASE
# endif
# endif
# if MYNEWT_VAL(NIMBLE_CPP_ADDR_FMT_EXCLUDE_DELIMITER)
# ifdef CONFIG_NIMBLE_CPP_ADDR_FMT_EXCLUDE_DELIMITER
# define NIMBLE_CPP_ADDR_DELIMITER ""
# else
# define NIMBLE_CPP_ADDR_DELIMITER ":"
# endif
# if MYNEWT_VAL(NIMBLE_CPP_ADDR_FMT_UPPERCASE)
# ifdef CONFIG_NIMBLE_CPP_ADDR_FMT_UPPERCASE
# define NIMBLE_CPP_ADDR_FMT "%02X%s%02X%s%02X%s%02X%s%02X%s%02X"
# else
# define NIMBLE_CPP_ADDR_FMT "%02x%s%02x%s%02x%s%02x%s%02x%s%02x"

View File

@@ -38,7 +38,6 @@ NimBLEAdvertisedDevice::NimBLEAdvertisedDevice(const ble_gap_event* event, uint8
m_callbackSent{0},
m_advLength{event->ext_disc.length_data},
m_isLegacyAdv{!!(event->ext_disc.props & BLE_HCI_ADV_LEGACY_MASK)},
m_dataStatus{event->ext_disc.data_status},
m_sid{event->ext_disc.sid},
m_primPhy{event->ext_disc.prim_phy},
m_secPhy{event->ext_disc.sec_phy},
@@ -61,16 +60,7 @@ NimBLEAdvertisedDevice::NimBLEAdvertisedDevice(const ble_gap_event* event, uint8
void NimBLEAdvertisedDevice::update(const ble_gap_event* event, uint8_t eventType) {
# if MYNEWT_VAL(BLE_EXT_ADV)
const auto& disc = event->ext_disc;
if (m_dataStatus == BLE_GAP_EXT_ADV_DATA_STATUS_INCOMPLETE) {
m_payload.reserve(m_advLength + disc.length_data);
m_payload.insert(m_payload.end(), disc.data, disc.data + disc.length_data);
m_dataStatus = disc.data_status;
m_advLength = m_payload.size();
return;
}
m_dataStatus = disc.data_status;
m_isLegacyAdv = disc.props & BLE_HCI_ADV_LEGACY_MASK;
m_isLegacyAdv = disc.props & BLE_HCI_ADV_LEGACY_MASK;
# else
const auto& disc = event->disc;
# endif
@@ -96,11 +86,11 @@ const NimBLEAddress& NimBLEAdvertisedDevice::getAddress() const {
/**
* @brief Get the advertisement type.
* @return The advertising type the device is reporting:
* * BLE_HCI_ADV_RPT_EVTYPE_ADV_IND (0) - indirect advertising - connectable and scannable
* * BLE_HCI_ADV_RPT_EVTYPE_DIR_IND (1) - direct advertising - connectable
* * BLE_HCI_ADV_RPT_EVTYPE_SCAN_IND (2) - indirect scan response - not connectable - scannable
* * BLE_HCI_ADV_RPT_EVTYPE_NONCONN_IND (3) - beacon only - not connectable - not scannable
* * BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP (4) - scan response
* * BLE_HCI_ADV_TYPE_ADV_IND (0) - indirect advertising
* * BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD (1) - direct advertising - high duty cycle
* * BLE_HCI_ADV_TYPE_ADV_SCAN_IND (2) - indirect scan response
* * BLE_HCI_ADV_TYPE_ADV_NONCONN_IND (3) - indirect advertising - not connectable
* * BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD (4) - direct advertising - low duty cycle
*/
uint8_t NimBLEAdvertisedDevice::getAdvType() const {
return m_advType;
@@ -627,18 +617,6 @@ uint8_t NimBLEAdvertisedDevice::getSecondaryPhy() const {
uint16_t NimBLEAdvertisedDevice::getPeriodicInterval() const {
return m_periodicItvl;
} // getPeriodicInterval
/**
* @brief Get the advertisement data status.
* @return The advertisement data status.
* One of:
* * BLE_GAP_EXT_ADV_DATA_STATUS_COMPLETE (0) - Complete extended advertising data
* * BLE_GAP_EXT_ADV_DATA_STATUS_INCOMPLETE (1) - Incomplete extended advertising data, more to come
* * BLE_GAP_EXT_ADV_DATA_STATUS_TRUNCATED (2) - Incomplete extended advertising data, no more to come
*/
uint8_t NimBLEAdvertisedDevice::getDataStatus() const {
return m_dataStatus;
} // getDataStatus
# endif
uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, size_t* data_loc) const {
@@ -752,7 +730,7 @@ std::string NimBLEAdvertisedDevice::toString() const {
* @brief Get the length of the advertisement data in the payload.
* @return The number of bytes in the payload that is from the advertisement.
*/
uint16_t NimBLEAdvertisedDevice::getAdvLength() const {
uint8_t NimBLEAdvertisedDevice::getAdvLength() const {
return m_advLength;
}
@@ -774,12 +752,11 @@ uint8_t NimBLEAdvertisedDevice::getAddressType() const {
*/
bool NimBLEAdvertisedDevice::isConnectable() const {
# if MYNEWT_VAL(BLE_EXT_ADV)
if (!m_isLegacyAdv) {
return (m_advType & BLE_HCI_ADV_CONN_MASK) || (m_advType & BLE_HCI_ADV_DIRECT_MASK);
if (m_isLegacyAdv) {
return m_advType == BLE_HCI_ADV_RPT_EVTYPE_ADV_IND || m_advType == BLE_HCI_ADV_RPT_EVTYPE_DIR_IND;
}
# endif
return m_advType == BLE_HCI_ADV_RPT_EVTYPE_ADV_IND || m_advType == BLE_HCI_ADV_RPT_EVTYPE_DIR_IND;
return (m_advType & BLE_HCI_ADV_CONN_MASK) || (m_advType & BLE_HCI_ADV_DIRECT_MASK);
} // isConnectable
/**

View File

@@ -69,7 +69,7 @@ class NimBLEAdvertisedDevice {
NimBLEAddress getTargetAddress(uint8_t index = 0) const;
uint8_t getTargetAddressCount() const;
int8_t getTXPower() const;
uint16_t getAdvLength() const;
uint8_t getAdvLength() const;
uint8_t getAddressType() const;
bool isAdvertisingService(const NimBLEUUID& uuid) const;
bool haveAppearance() const;
@@ -92,7 +92,6 @@ class NimBLEAdvertisedDevice {
uint8_t getPrimaryPhy() const;
uint8_t getSecondaryPhy() const;
uint16_t getPeriodicInterval() const;
uint8_t getDataStatus() const;
# endif
operator NimBLEAddress() const;
@@ -162,11 +161,10 @@ class NimBLEAdvertisedDevice {
uint8_t m_advType{};
int8_t m_rssi{};
uint8_t m_callbackSent{};
uint16_t m_advLength{};
uint8_t m_advLength{};
# if MYNEWT_VAL(BLE_EXT_ADV)
bool m_isLegacyAdv{};
uint8_t m_dataStatus{};
uint8_t m_sid{};
uint8_t m_primPhy{};
uint8_t m_secPhy{};

View File

@@ -35,7 +35,7 @@ NimBLEAttValue::NimBLEAttValue(uint16_t init_len, uint16_t max_len)
m_attr_max_len{std::min<uint16_t>(BLE_ATT_ATTR_MAX_LEN, max_len)},
m_attr_len{},
m_capacity{init_len}
# if MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED)
# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
,
m_timestamp{}
# endif
@@ -134,7 +134,7 @@ NimBLEAttValue& NimBLEAttValue::append(const uint8_t* value, uint16_t len) {
return *this;
}
# if MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED)
# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
time_t t = time(nullptr);
# else
time_t t = 0;

View File

@@ -31,30 +31,20 @@
# include <cstring>
# include <cstdint>
# ifndef MYNEWT_VAL_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
# ifndef CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
# define MYNEWT_VAL_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED 0
# else
# define MYNEWT_VAL_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
# endif
# ifndef CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
# define CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED 0
# endif
# ifndef BLE_ATT_ATTR_MAX_LEN
# define BLE_ATT_ATTR_MAX_LEN 512
# endif
# ifndef MYNEWT_VAL_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH
# ifndef CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH
# define MYNEWT_VAL_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH 20
# else
# define MYNEWT_VAL_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH
# endif
# endif
# if MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_INIT_LENGTH) > BLE_ATT_ATTR_MAX_LEN
# error NIMBLE_CPP_ATT_VALUE_INIT_LENGTH cannot be larger than 512 (BLE_ATT_ATTR_MAX_LEN)
# elif MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_INIT_LENGTH) < 1
# error NIMBLE_CPP_ATT_VALUE_INIT_LENGTH cannot be less than 1; Range = 1 : 512
# if !defined(CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH)
# define CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH 20
# elif CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH > BLE_ATT_ATTR_MAX_LEN
# error CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH cannot be larger than 512 (BLE_ATT_ATTR_MAX_LEN)
# elif CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH < 1
# error CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH cannot be less than 1; Range = 1 : 512
# endif
/* Used to determine if the type passed to a template has a data() and size() method. */
@@ -73,14 +63,6 @@ template <typename T>
struct Has_c_str_length<T, decltype(void(std::declval<T&>().c_str())), decltype(void(std::declval<T&>().length()))>
: std::true_type {};
/* Used to determine if the type passed to a template has a value_type member (std::vector, std::array, std::string, etc.). */
template <typename T, typename = void>
struct Has_value_type : std::false_type {};
template <typename T>
struct Has_value_type<T, decltype(void(sizeof(typename T::value_type)))>
: std::true_type {};
/**
* @brief A specialized container class to hold BLE attribute values.
* @details This class is designed to be more memory efficient than using\n
@@ -92,7 +74,7 @@ class NimBLEAttValue {
uint16_t m_attr_max_len{};
uint16_t m_attr_len{};
uint16_t m_capacity{};
# if MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED)
# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
time_t m_timestamp{};
# endif
void deepCopy(const NimBLEAttValue& source);
@@ -103,7 +85,7 @@ class NimBLEAttValue {
* @param[in] init_len The initial size in bytes.
* @param[in] max_len The max size in bytes that the value can be.
*/
NimBLEAttValue(uint16_t init_len = MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_INIT_LENGTH), uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
NimBLEAttValue(uint16_t init_len = CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
/**
* @brief Construct with an initial value from a buffer.
@@ -188,7 +170,7 @@ class NimBLEAttValue {
/** @brief Iterator end */
const uint8_t* end() const { return m_attr_value + m_attr_len; }
# if MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED)
# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
/** @brief Returns a timestamp of when the value was last updated */
time_t getTimeStamp() const { return m_timestamp; }
@@ -228,7 +210,7 @@ class NimBLEAttValue {
const NimBLEAttValue& getValue(time_t* timestamp = nullptr) const {
if (timestamp != nullptr) {
# if MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED)
# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
*timestamp = m_timestamp;
# else
*timestamp = 0;
@@ -282,32 +264,13 @@ class NimBLEAttValue {
/**
* @brief Template to set value to the value of <type\>val.
* @param [in] v The <type\>value to set.
* @details Only used if the <type\> has a `data()` and `size()` method with `value_type`.
* Correctly calculates byte size for containers with multi-byte element types.
* @details Only used if the <type\> has a `data()` and `size()` method.
*/
template <typename T>
# ifdef _DOXYGEN_
bool
# else
typename std::enable_if<Has_data_size<T>::value && Has_value_type<T>::value, bool>::type
# endif
setValue(const T& v) {
return setValue(
reinterpret_cast<const uint8_t*>(v.data()),
v.size() * sizeof(typename T::value_type)
);
}
/**
* @brief Template to set value to the value of <type\>val.
* @param [in] v The <type\>value to set.
* @details Only used if the <type\> has a `data()` and `size()` method without `value_type`.
*/
template <typename T>
# ifdef _DOXYGEN_
bool
# else
typename std::enable_if<Has_data_size<T>::value && !Has_value_type<T>::value, bool>::type
typename std::enable_if<Has_data_size<T>::value, bool>::type
# endif
setValue(const T& v) {
return setValue(reinterpret_cast<const uint8_t*>(v.data()), v.size());
@@ -322,11 +285,7 @@ class NimBLEAttValue {
template <typename T>
typename std::enable_if<!std::is_pointer<T>::value, bool>::type setValue(const T& s) {
if constexpr (Has_data_size<T>::value) {
if constexpr (Has_value_type<T>::value) {
return setValue(reinterpret_cast<const uint8_t*>(s.data()), s.size() * sizeof(typename T::value_type));
} else {
return setValue(reinterpret_cast<const uint8_t*>(s.data()), s.size());
}
return setValue(reinterpret_cast<const uint8_t*>(s.data()), s.size());
} else if constexpr (Has_c_str_length<T>::value) {
return setValue(reinterpret_cast<const uint8_t*>(s.c_str()), s.length());
} else {
@@ -348,7 +307,7 @@ class NimBLEAttValue {
template <typename T>
T getValue(time_t* timestamp = nullptr, bool skipSizeCheck = false) const {
if (timestamp != nullptr) {
# if MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED)
# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
*timestamp = m_timestamp;
# else
*timestamp = 0;

View File

@@ -15,15 +15,15 @@
* limitations under the License.
*/
#include "NimBLECharacteristic.h"
# include "NimBLECharacteristic.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# if defined(CONFIG_NIMBLE_CPP_IDF)
# if !defined(ESP_IDF_VERSION_MAJOR) || ESP_IDF_VERSION_MAJOR < 5
# define ble_gatts_notify_custom ble_gattc_notify_custom
# define ble_gatts_indicate_custom ble_gattc_indicate_custom
# endif
#if defined(CONFIG_NIMBLE_CPP_IDF)
# if !defined(ESP_IDF_VERSION_MAJOR) || ESP_IDF_VERSION_MAJOR < 5
# define ble_gatts_notify_custom ble_gattc_notify_custom
# define ble_gatts_indicate_custom ble_gattc_indicate_custom
# endif
#endif
# include "NimBLE2904.h"
# include "NimBLEDevice.h"
@@ -225,8 +225,7 @@ void NimBLECharacteristic::setService(NimBLEService* pService) {
* @return True if the indication was sent successfully, false otherwise.
*/
bool NimBLECharacteristic::indicate(uint16_t connHandle) const {
auto value{m_value}; // make a copy to avoid issues if the value is changed while indicating
return sendValue(value.data(), value.size(), false, connHandle);
return sendValue(nullptr, 0, false, connHandle);
} // indicate
/**
@@ -248,8 +247,7 @@ bool NimBLECharacteristic::indicate(const uint8_t* value, size_t length, uint16_
* @return True if the notification was sent successfully, false otherwise.
*/
bool NimBLECharacteristic::notify(uint16_t connHandle) const {
auto value{m_value}; // make a copy to avoid issues if the value is changed while notifying
return sendValue(value.data(), value.size(), true, connHandle);
return sendValue(nullptr, 0, true, connHandle);
} // notify
/**
@@ -273,50 +271,55 @@ bool NimBLECharacteristic::notify(const uint8_t* value, size_t length, uint16_t
* @return True if the value was sent successfully, false otherwise.
*/
bool NimBLECharacteristic::sendValue(const uint8_t* value, size_t length, bool isNotification, uint16_t connHandle) const {
ble_npl_hw_enter_critical();
const auto subs = getSubscribers(); // make a copy to avoid issues if subscribers change while sending
ble_npl_hw_exit_critical(0);
int rc = 0;
bool chSpecified = connHandle != BLE_HS_CONN_HANDLE_NONE;
bool requireSecure = m_properties & (BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_READ_AUTHEN | BLE_GATT_CHR_F_READ_AUTHOR);
int rc = chSpecified ? BLE_HS_ENOENT : 0; // if handle specified, assume not found until sent
if (value != nullptr && length > 0) { // custom notification value
os_mbuf* om = nullptr;
// Notify all connected peers unless a specific handle is provided
for (const auto& entry : subs) {
uint16_t ch = entry.getConnHandle();
if (ch == BLE_HS_CONN_HANDLE_NONE || (chSpecified && ch != connHandle)) {
continue;
}
if (requireSecure && !entry.isSecured()) {
NIMBLE_LOGW(LOG_TAG, "skipping notify/indicate to connHandle=%d, link not secured", entry.getConnHandle());
continue;
}
// Must re-create the data buffer on each iteration because it is freed by the calls below.
uint8_t retries = 10; // wait up to 10ms for a free buffer
os_mbuf* om = ble_hs_mbuf_from_flat(value, length);
while (!om && --retries) {
ble_npl_time_delay(ble_npl_time_ms_to_ticks32(1));
if (connHandle != BLE_HS_CONN_HANDLE_NONE) { // only sending to specific peer
om = ble_hs_mbuf_from_flat(value, length);
if (!om) {
rc = BLE_HS_ENOMEM;
goto done;
}
// Null buffer will read the value from the characteristic
if (isNotification) {
rc = ble_gatts_notify_custom(connHandle, m_handle, om);
} else {
rc = ble_gatts_indicate_custom(connHandle, m_handle, om);
}
goto done;
}
if (!om) {
rc = BLE_HS_ENOMEM;
break;
}
// Notify all connected peers unless a specific handle is provided
for (const auto& ch : NimBLEDevice::getServer()->getPeerDevices()) {
// Must re-create the data buffer on each iteration because it is freed by the calls bellow.
om = ble_hs_mbuf_from_flat(value, length);
if (!om) {
rc = BLE_HS_ENOMEM;
goto done;
}
if (isNotification) {
rc = ble_gatts_notify_custom(ch, m_handle, om);
} else {
rc = ble_gatts_indicate_custom(ch, m_handle, om);
}
}
} else if (connHandle != BLE_HS_CONN_HANDLE_NONE) {
// Null buffer will read the value from the characteristic
if (isNotification) {
rc = ble_gatts_notify_custom(ch, m_handle, om);
rc = ble_gatts_notify_custom(connHandle, m_handle, nullptr);
} else {
rc = ble_gatts_indicate_custom(ch, m_handle, om);
}
if (rc != 0 || chSpecified) {
break;
rc = ble_gatts_indicate_custom(connHandle, m_handle, nullptr);
}
} else { // Notify or indicate to all connected peers the characteristic value
ble_gatts_chr_updated(m_handle);
}
done:
if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "failed to send value, rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
return false;
@@ -325,107 +328,10 @@ bool NimBLECharacteristic::sendValue(const uint8_t* value, size_t length, bool i
return true;
} // sendValue
/**
* @brief Process a subscription or unsubscription request from a peer.
* @param[in] connInfo A reference to the connection info of the peer.
* @param[in] subVal The subscription value (bitmask).
*/
void NimBLECharacteristic::processSubRequest(NimBLEConnInfo& connInfo, uint8_t subVal) const {
// Only allocate subscribers for characteristics that support notify or indicate.
const uint16_t props = getProperties();
if (!(props & (BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_INDICATE))) {
return;
}
auto found = false;
auto firstFree = -1;
for (auto& entry : m_subPeers) {
if (entry.getConnHandle() == connInfo.getConnHandle()) {
found = true;
if (!subVal) {
ble_npl_hw_enter_critical();
entry = SubPeerEntry{}; // unsubscribed, reset entry
ble_npl_hw_exit_critical(0);
}
break;
}
if (firstFree == -1 && entry.getConnHandle() == BLE_HS_CONN_HANDLE_NONE) {
firstFree = &entry - &m_subPeers[0];
}
}
if (!found && subVal) {
if (firstFree >= 0) {
ble_npl_hw_enter_critical();
m_subPeers[firstFree].setConnHandle(connInfo.getConnHandle());
m_subPeers[firstFree].setSubNotify(subVal & 0x1);
m_subPeers[firstFree].setSubIndicate(subVal & 0x2);
m_subPeers[firstFree].setSecured(connInfo.isEncrypted() || connInfo.isAuthenticated() || connInfo.isBonded());
if (m_properties & (BLE_GATT_CHR_F_READ_AUTHEN | BLE_GATT_CHR_F_READ_AUTHOR | BLE_GATT_CHR_F_READ_ENC)) {
// characteristic requires security/authorization
if (!m_subPeers[firstFree].isSecured()) {
m_subPeers[firstFree].setAwaitingSecure(true);
ble_npl_hw_exit_critical(0);
NimBLEDevice::startSecurity(connInfo.getConnHandle());
NIMBLE_LOGD(LOG_TAG,
"Subscription deferred until link is secured for connHandle=%d",
connInfo.getConnHandle());
return;
}
}
ble_npl_hw_exit_critical(0);
} else {
// should never happen, but log just in case
NIMBLE_LOGE(LOG_TAG, "No free subscription slots");
return;
}
}
m_pCallbacks->onSubscribe(const_cast<NimBLECharacteristic*>(this), const_cast<NimBLEConnInfo&>(connInfo), subVal);
}
/**
* @brief Update the security status of a subscribed peer.
* @param[in] peerInfo A reference to the connection info of the peer.
*/
void NimBLECharacteristic::updatePeerStatus(const NimBLEConnInfo& peerInfo) const {
if (!(getProperties() & (NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::INDICATE))) {
return;
}
ble_npl_hw_enter_critical();
for (auto& entry : m_subPeers) {
if (entry.getConnHandle() == peerInfo.getConnHandle()) {
entry.setSecured(peerInfo.isEncrypted() || peerInfo.isAuthenticated() || peerInfo.isBonded());
if (entry.isAwaitingSecure()) {
entry.setAwaitingSecure(false);
ble_npl_hw_exit_critical(0);
m_pCallbacks->onSubscribe(const_cast<NimBLECharacteristic*>(this),
const_cast<NimBLEConnInfo&>(peerInfo),
entry.isSubNotify() | (entry.isSubIndicate() << 1));
return;
}
break;
}
}
ble_npl_hw_exit_critical(0);
}
/**
* @brief Handle a read event from a client.
* @param [in] connInfo A reference to a NimBLEConnInfo instance containing the peer info.
*/
void NimBLECharacteristic::readEvent(NimBLEConnInfo& connInfo) {
m_pCallbacks->onRead(this, connInfo);
} // readEvent
/**
* @brief Handle a write event from a client.
* @param [in] val A pointer to the data written by the client.
* @param [in] len The length of the data written by the client.
* @param [in] connInfo A reference to a NimBLEConnInfo instance containing the peer info.
*/
void NimBLECharacteristic::writeEvent(const uint8_t* val, uint16_t len, NimBLEConnInfo& connInfo) {
setValue(val, len);
m_pCallbacks->onWrite(this, connInfo);
@@ -499,18 +405,6 @@ void NimBLECharacteristicCallbacks::onStatus(NimBLECharacteristic* pCharacterist
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onStatus: default");
} // onStatus
/**
* @brief Callback function to support a Notify/Indicate Status report.
* @param [in] pCharacteristic The characteristic that is the source of the event.
* @param [in] connInfo A reference to a NimBLEConnInfo instance containing the peer info.
* @param [in] code Status return code from the NimBLE stack.
* @details The status code for success is 0 for notifications and BLE_HS_EDONE for indications,
* any other value is an error.
*/
void NimBLECharacteristicCallbacks::onStatus(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo, int code) {
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onStatus: default");
} // onStatus
/**
* @brief Callback function called when a client changes subscription status.
* @param [in] pCharacteristic The characteristic that is the source of the event.

View File

@@ -31,7 +31,6 @@ class NimBLE2904;
# include <string>
# include <vector>
# include <array>
/**
* @brief The model of a BLE Characteristic.
@@ -113,27 +112,7 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
}
/**
* @brief Template to send a notification with a value from a class that has a data() and size() method with value_type.
* @param [in] v The value to send.
* @param [in] connHandle Optional, a connection handle to send the notification to.
* @details Correctly calculates byte size for containers with multi-byte element types.
*/
template <typename T>
# ifdef _DOXYGEN_
bool
# else
typename std::enable_if<Has_data_size<T>::value && Has_value_type<T>::value, bool>::type
# endif
notify(const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const {
return notify(
reinterpret_cast<const uint8_t*>(v.data()),
v.size() * sizeof(typename T::value_type),
connHandle
);
}
/**
* @brief Template to send a notification with a value from a class that has a data() and size() method without value_type.
* @brief Template to send a notification with a value from a class that has a data() and size() method.
* @param [in] v The value to send.
* @param [in] connHandle Optional, a connection handle to send the notification to.
*/
@@ -141,7 +120,7 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
# ifdef _DOXYGEN_
bool
# else
typename std::enable_if<Has_data_size<T>::value && !Has_value_type<T>::value, bool>::type
typename std::enable_if<Has_data_size<T>::value, bool>::type
# endif
notify(const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const {
return notify(reinterpret_cast<const uint8_t*>(v.data()), v.size(), connHandle);
@@ -181,27 +160,7 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
}
/**
* @brief Template to send a indication with a value from a class that has a data() and size() method with value_type.
* @param [in] v The value to send.
* @param [in] connHandle Optional, a connection handle to send the notification to.
* @details Correctly calculates byte size for containers with multi-byte element types.
*/
template <typename T>
# ifdef _DOXYGEN_
bool
# else
typename std::enable_if<Has_data_size<T>::value && Has_value_type<T>::value, bool>::type
# endif
indicate(const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const {
return indicate(
reinterpret_cast<const uint8_t*>(v.data()),
v.size() * sizeof(typename T::value_type),
connHandle
);
}
/**
* @brief Template to send a indication with a value from a class that has a data() and size() method without value_type.
* @brief Template to send a indication with a value from a class that has a data() and size() method.
* @param [in] v The value to send.
* @param [in] connHandle Optional, a connection handle to send the notification to.
*/
@@ -209,7 +168,7 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
# ifdef _DOXYGEN_
bool
# else
typename std::enable_if<Has_data_size<T>::value && !Has_value_type<T>::value, bool>::type
typename std::enable_if<Has_data_size<T>::value, bool>::type
# endif
indicate(const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const {
return indicate(reinterpret_cast<const uint8_t*>(v.data()), v.size(), connHandle);
@@ -231,11 +190,7 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
typename std::enable_if<!std::is_pointer<T>::value && !std::is_array<T>::value, bool>::type notify(
const T& value, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const {
if constexpr (Has_data_size<T>::value) {
if constexpr (Has_value_type<T>::value) {
return notify(reinterpret_cast<const uint8_t*>(value.data()), value.size() * sizeof(typename T::value_type), connHandle);
} else {
return notify(reinterpret_cast<const uint8_t*>(value.data()), value.size(), connHandle);
}
return notify(reinterpret_cast<const uint8_t*>(value.data()), value.size(), connHandle);
} else if constexpr (Has_c_str_length<T>::value) {
return notify(reinterpret_cast<const uint8_t*>(value.c_str()), value.length(), connHandle);
} else {
@@ -257,11 +212,7 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
typename std::enable_if<!std::is_pointer<T>::value && !std::is_array<T>::value, bool>::type indicate(
const T& value, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const {
if constexpr (Has_data_size<T>::value) {
if constexpr (Has_value_type<T>::value) {
return indicate(reinterpret_cast<const uint8_t*>(value.data()), value.size() * sizeof(typename T::value_type), connHandle);
} else {
return indicate(reinterpret_cast<const uint8_t*>(value.data()), value.size(), connHandle);
}
return indicate(reinterpret_cast<const uint8_t*>(value.data()), value.size(), connHandle);
} else if constexpr (Has_c_str_length<T>::value) {
return indicate(reinterpret_cast<const uint8_t*>(value.c_str()), value.length(), connHandle);
} else {
@@ -282,33 +233,9 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
bool is_notification = true,
uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const;
struct SubPeerEntry {
enum : uint8_t { AWAITING_SECURE = 1 << 0, SECURE = 1 << 1, SUB_NOTIFY = 1 << 2, SUB_INDICATE = 1 << 3 };
void setConnHandle(uint16_t connHandle) { m_connHandle = connHandle; }
uint16_t getConnHandle() const { return m_connHandle; }
void setAwaitingSecure(bool awaiting) { awaiting ? m_flags |= AWAITING_SECURE : m_flags &= ~AWAITING_SECURE; }
void setSecured(bool secure) { secure ? m_flags |= SECURE : m_flags &= ~SECURE; }
void setSubNotify(bool notify) { notify ? m_flags |= SUB_NOTIFY : m_flags &= ~SUB_NOTIFY; }
void setSubIndicate(bool indicate) { indicate ? m_flags |= SUB_INDICATE : m_flags &= ~SUB_INDICATE; }
bool isSubNotify() const { return m_flags & SUB_NOTIFY; }
bool isSubIndicate() const { return m_flags & SUB_INDICATE; }
bool isSecured() const { return m_flags & SECURE; }
bool isAwaitingSecure() const { return m_flags & AWAITING_SECURE; }
private:
uint16_t m_connHandle{BLE_HS_CONN_HANDLE_NONE};
uint8_t m_flags{0};
} __attribute__((packed));
using SubPeerArray = std::array<SubPeerEntry, MYNEWT_VAL(BLE_MAX_CONNECTIONS)>;
SubPeerArray getSubscribers() const { return m_subPeers; }
void processSubRequest(NimBLEConnInfo& connInfo, uint8_t subVal) const;
void updatePeerStatus(const NimBLEConnInfo& peerInfo) const;
NimBLECharacteristicCallbacks* m_pCallbacks{nullptr};
NimBLEService* m_pService{nullptr};
std::vector<NimBLEDescriptor*> m_vDescriptors{};
mutable SubPeerArray m_subPeers{};
}; // NimBLECharacteristic
/**
@@ -323,8 +250,7 @@ class NimBLECharacteristicCallbacks {
virtual ~NimBLECharacteristicCallbacks() {}
virtual void onRead(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo);
virtual void onWrite(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo);
virtual void onStatus(NimBLECharacteristic* pCharacteristic, int code); // deprecated
virtual void onStatus(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo, int code);
virtual void onStatus(NimBLECharacteristic* pCharacteristic, int code);
virtual void onSubscribe(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo, uint16_t subValue);
};

View File

@@ -940,11 +940,6 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) {
pClient = NimBLEDevice::getClientByPeerAddress(event->disconnect.conn.peer_id_addr);
}
// try by connection handle
if (pClient == nullptr) {
pClient = NimBLEDevice::getClientByHandle(event->disconnect.conn.conn_handle);
}
if (pClient == nullptr) {
NIMBLE_LOGE(LOG_TAG, "Disconnected client not found, conn_handle=%d",
event->disconnect.conn.conn_handle);

View File

@@ -1303,11 +1303,10 @@ bool NimBLEDevice::setDeviceName(const std::string& deviceName) {
/**
* @brief Set a custom callback for gap events.
* @param [in] handler The function to call when gap events occur.
* @param [in] arg Argument to pass to the handler.
* @returns
*/
bool NimBLEDevice::setCustomGapHandler(gap_event_handler handler, void* arg) {
int rc = ble_gap_event_listener_register(&m_listener, handler, arg);
bool NimBLEDevice::setCustomGapHandler(gap_event_handler handler) {
int rc = ble_gap_event_listener_register(&m_listener, handler, NULL);
if (rc == BLE_HS_EALREADY) {
NIMBLE_LOGI(LOG_TAG, "Already listening to GAP events.");
return true;
@@ -1326,7 +1325,7 @@ std::string NimBLEDevice::toString() {
return getAddress().toString();
} // toString
# if MYNEWT_VAL(NIMBLE_CPP_DEBUG_ASSERT_ENABLED) || __DOXYGEN__
# if CONFIG_NIMBLE_CPP_DEBUG_ASSERT_ENABLED || __DOXYGEN__
/**
* @brief Debug assert - weak function.
* @param [in] file The file where the assert occurred.
@@ -1337,7 +1336,7 @@ void nimble_cpp_assert(const char* file, unsigned line) {
ble_npl_time_delay(10);
abort();
}
# endif // MYNEWT_VAL(NIMBLE_CPP_DEBUG_ASSERT_ENABLED)
# endif // CONFIG_NIMBLE_CPP_DEBUG_ASSERT_ENABLED
void NimBLEDevice::setDeviceCallbacks(NimBLEDeviceCallbacks* cb) {
m_pDeviceCallbacks = cb ? cb : &defaultDeviceCallbacks;

View File

@@ -133,7 +133,7 @@ class NimBLEDevice {
static void setScanDuplicateCacheSize(uint16_t cacheSize);
static void setScanFilterMode(uint8_t type);
static void setScanDuplicateCacheResetTime(uint16_t time);
static bool setCustomGapHandler(gap_event_handler handler, void* arg = nullptr);
static bool setCustomGapHandler(gap_event_handler handler);
static void setSecurityAuth(bool bonding, bool mitm, bool sc);
static void setSecurityAuth(uint8_t auth);
static void setSecurityIOCap(uint8_t iocap);

View File

@@ -616,11 +616,6 @@ bool NimBLEExtAdvertisement::setFlags(uint8_t flag) {
* @return True if successful.
*/
bool NimBLEExtAdvertisement::setManufacturerData(const uint8_t* data, size_t length) {
if (length > 0xFF - 1) {
NIMBLE_LOGE(LOG_TAG, "Manufacturer data too long!");
return false;
}
uint8_t header[2];
header[0] = length + 1;
header[1] = BLE_HS_ADV_TYPE_MFG_DATA;
@@ -657,11 +652,6 @@ bool NimBLEExtAdvertisement::setManufacturerData(const std::vector<uint8_t>& dat
* @return True if successful.
*/
bool NimBLEExtAdvertisement::setURI(const std::string& uri) {
if (uri.length() > 0xFF - 1) {
NIMBLE_LOGE(LOG_TAG, "URI too long!");
return false;
}
uint8_t header[2];
header[0] = uri.length() + 1;
header[1] = BLE_HS_ADV_TYPE_URI;
@@ -680,11 +670,6 @@ bool NimBLEExtAdvertisement::setURI(const std::string& uri) {
* @return True if successful.
*/
bool NimBLEExtAdvertisement::setName(const std::string& name, bool isComplete) {
if (name.length() > 0xFF - 1) {
NIMBLE_LOGE(LOG_TAG, "Name too long!");
return false;
}
uint8_t header[2];
header[0] = name.length() + 1;
header[1] = isComplete ? BLE_HS_ADV_TYPE_COMP_NAME : BLE_HS_ADV_TYPE_INCOMP_NAME;
@@ -932,12 +917,8 @@ bool NimBLEExtAdvertisement::setServices(bool complete, uint8_t size, const std:
*/
bool NimBLEExtAdvertisement::setServiceData(const NimBLEUUID& uuid, const uint8_t* data, size_t length) {
uint8_t uuidBytes = uuid.bitSize() / 8;
if (length + uuidBytes + 2 > 0xFF) {
NIMBLE_LOGE(LOG_TAG, "Service data too long!");
return false;
}
uint8_t sDataLen = 2 + uuidBytes + length;
uint8_t sDataLen = 2 + uuidBytes + length;
if (m_payload.size() + sDataLen > MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)) {
return false;
}

View File

@@ -101,7 +101,7 @@ class NimBLELocalValueAttribute : public NimBLELocalAttribute, public NimBLEValu
NimBLELocalValueAttribute(const NimBLEUUID& uuid,
uint16_t handle,
uint16_t maxLen,
uint16_t initLen = MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_INIT_LENGTH))
uint16_t initLen = CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH)
: NimBLELocalAttribute(uuid, handle), NimBLEValueAttribute(maxLen, initLen) {}
/**
* @brief Destroy the NimBLELocalValueAttribute object.

View File

@@ -21,21 +21,12 @@
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED
# ifndef MYNEWT_VAL_NIMBLE_CPP_LOG_LEVEL
# ifndef CONFIG_NIMBLE_CPP_LOG_LEVEL
# if defined(ARDUINO_ARCH_ESP32) && defined(CORE_DEBUG_LEVEL)
# define MYNEWT_VAL_NIMBLE_CPP_LOG_LEVEL CORE_DEBUG_LEVEL
# else
# define MYNEWT_VAL_NIMBLE_CPP_LOG_LEVEL 0
# endif
# else
# define MYNEWT_VAL_NIMBLE_CPP_LOG_LEVEL CONFIG_NIMBLE_CPP_LOG_LEVEL
# endif
# endif
# if defined(CONFIG_NIMBLE_CPP_IDF)
# include "esp_log.h"
# include "console/console.h"
# ifndef CONFIG_NIMBLE_CPP_LOG_LEVEL
# define CONFIG_NIMBLE_CPP_LOG_LEVEL 0
# endif
# if defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR)
# if CONFIG_LOG_COLORS
@@ -129,13 +120,13 @@
# define NIMBLE_CPP_LOG_PRINT(level, tag, format, ...) \
do { \
if (MYNEWT_VAL(NIMBLE_CPP_LOG_LEVEL) >= level) NIMBLE_CPP_LOG_LEVEL_LOCAL(level, tag, format, ##__VA_ARGS__); \
if (CONFIG_NIMBLE_CPP_LOG_LEVEL >= level) NIMBLE_CPP_LOG_LEVEL_LOCAL(level, tag, format, ##__VA_ARGS__); \
} while (0)
# else
# define NIMBLE_CPP_LOG_PRINT(level, tag, format, ...) \
do { \
if (MYNEWT_VAL(NIMBLE_CPP_LOG_LEVEL) >= level) ESP_LOG_LEVEL_LOCAL(level, tag, format, ##__VA_ARGS__); \
if (CONFIG_NIMBLE_CPP_LOG_LEVEL >= level) ESP_LOG_LEVEL_LOCAL(level, tag, format, ##__VA_ARGS__); \
} while (0)
# endif /* CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR */
@@ -146,27 +137,35 @@
# define NIMBLE_LOGE(tag, format, ...) NIMBLE_CPP_LOG_PRINT(ESP_LOG_ERROR, tag, format, ##__VA_ARGS__)
# else
# include "syscfg/syscfg.h"
# include "nimble/console/console.h"
# ifndef CONFIG_NIMBLE_CPP_LOG_LEVEL
# if defined(ARDUINO_ARCH_ESP32) && defined(CORE_DEBUG_LEVEL)
# define CONFIG_NIMBLE_CPP_LOG_LEVEL CORE_DEBUG_LEVEL
# else
# define CONFIG_NIMBLE_CPP_LOG_LEVEL 0
# endif
# endif
# if MYNEWT_VAL(NIMBLE_CPP_LOG_LEVEL) >= 4
# if CONFIG_NIMBLE_CPP_LOG_LEVEL >= 4
# define NIMBLE_LOGD(tag, format, ...) console_printf("D %s: " format "\n", tag, ##__VA_ARGS__)
# else
# define NIMBLE_LOGD(tag, format, ...) (void)tag
# endif
# if MYNEWT_VAL(NIMBLE_CPP_LOG_LEVEL) >= 3
# if CONFIG_NIMBLE_CPP_LOG_LEVEL >= 3
# define NIMBLE_LOGI(tag, format, ...) console_printf("I %s: " format "\n", tag, ##__VA_ARGS__)
# else
# define NIMBLE_LOGI(tag, format, ...) (void)tag
# endif
# if MYNEWT_VAL(NIMBLE_CPP_LOG_LEVEL) >= 2
# if CONFIG_NIMBLE_CPP_LOG_LEVEL >= 2
# define NIMBLE_LOGW(tag, format, ...) console_printf("W %s: " format "\n", tag, ##__VA_ARGS__)
# else
# define NIMBLE_LOGW(tag, format, ...) (void)tag
# endif
# if MYNEWT_VAL(NIMBLE_CPP_LOG_LEVEL) >= 1
# if CONFIG_NIMBLE_CPP_LOG_LEVEL >= 1
# define NIMBLE_LOGE(tag, format, ...) console_printf("E %s: " format "\n", tag, ##__VA_ARGS__)
# else
# define NIMBLE_LOGE(tag, format, ...) (void)tag

View File

@@ -94,24 +94,8 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(
bool NimBLERemoteCharacteristic::retrieveDescriptors(NimBLEDescriptorFilter* pFilter) const {
NIMBLE_LOGD(LOG_TAG, ">> retrieveDescriptors() for characteristic: %s", getUUID().toString().c_str());
const auto pSvc = getRemoteService();
uint16_t endHandle = pSvc->getEndHandle();
// Find the handle of the next characteristic to limit the descriptor search range.
const auto& chars = pSvc->getCharacteristics(false);
for (auto it = chars.begin(); it != chars.end(); ++it) {
if ((*it)->getHandle() == this->getHandle()) {
auto next_it = std::next(it);
if (next_it != chars.end()) {
endHandle = (*next_it)->getHandle() - 1;
NIMBLE_LOGD(LOG_TAG, "Search range limited to handle 0x%04X", endHandle);
}
break;
}
}
// If this is the last handle then there are no descriptors
if (getHandle() == endHandle) {
if (getHandle() == getRemoteService()->getEndHandle()) {
NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): found 0 descriptors.");
return true;
}
@@ -124,7 +108,7 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(NimBLEDescriptorFilter* pFi
int rc = ble_gattc_disc_all_dscs(getClient()->getConnHandle(),
getHandle(),
endHandle,
getRemoteService()->getEndHandle(),
NimBLERemoteCharacteristic::descriptorDiscCB,
pFilter);
if (rc != 0) {

View File

@@ -109,34 +109,13 @@ class NimBLERemoteValueAttribute : public NimBLEValueAttribute, public NimBLEAtt
* @brief Template to set the remote characteristic value to <type\>val.
* @param [in] v The value to write.
* @param [in] response True == request write response.
* @details Only used if the <type\> has a `data()` and `size()` method with `value_type`.
* Correctly calculates byte size for containers with multi-byte element types.
* @details Only used if the <type\> has a `data()` and `size()` method.
*/
template <typename T>
# ifdef _DOXYGEN_
bool
# else
typename std::enable_if<Has_data_size<T>::value && Has_value_type<T>::value, bool>::type
# endif
writeValue(const T& v, bool response = false) const {
return writeValue(
reinterpret_cast<const uint8_t*>(v.data()),
v.size() * sizeof(typename T::value_type),
response
);
}
/**
* @brief Template to set the remote characteristic value to <type\>val.
* @param [in] v The value to write.
* @param [in] response True == request write response.
* @details Only used if the <type\> has a `data()` and `size()` method without `value_type`.
*/
template <typename T>
# ifdef _DOXYGEN_
bool
# else
typename std::enable_if<Has_data_size<T>::value && !Has_value_type<T>::value, bool>::type
typename std::enable_if<Has_data_size<T>::value, bool>::type
# endif
writeValue(const T& v, bool response = false) const {
return writeValue(reinterpret_cast<const uint8_t*>(v.data()), v.size(), response);
@@ -152,11 +131,7 @@ class NimBLERemoteValueAttribute : public NimBLEValueAttribute, public NimBLEAtt
template <typename T>
typename std::enable_if<!std::is_pointer<T>::value, bool>::type writeValue(const T& v, bool response = false) const {
if constexpr (Has_data_size<T>::value) {
if constexpr (Has_value_type<T>::value) {
return writeValue(reinterpret_cast<const uint8_t*>(v.data()), v.size() * sizeof(typename T::value_type), response);
} else {
return writeValue(reinterpret_cast<const uint8_t*>(v.data()), v.size(), response);
}
return writeValue(reinterpret_cast<const uint8_t*>(v.data()), v.size(), response);
} else if constexpr (Has_c_str_length<T>::value) {
return writeValue(reinterpret_cast<const uint8_t*>(v.c_str()), v.length(), response);
} else {

View File

@@ -117,22 +117,13 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
NIMBLE_LOGI(LOG_TAG, "New advertiser: %s", advertisedAddress.toString().c_str());
} else {
advertisedDevice->update(event, event_type);
if (isLegacyAdv) {
if (event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
NIMBLE_LOGI(LOG_TAG, "Scan response from: %s", advertisedAddress.toString().c_str());
} else {
NIMBLE_LOGI(LOG_TAG, "Duplicate; updated: %s", advertisedAddress.toString().c_str());
}
if (isLegacyAdv && event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
NIMBLE_LOGI(LOG_TAG, "Scan response from: %s", advertisedAddress.toString().c_str());
} else {
NIMBLE_LOGI(LOG_TAG, "Duplicate; updated: %s", advertisedAddress.toString().c_str());
}
}
# if MYNEWT_VAL(BLE_EXT_ADV)
if (advertisedDevice->getDataStatus() == BLE_GAP_EXT_ADV_DATA_STATUS_INCOMPLETE) {
NIMBLE_LOGD(LOG_TAG, "EXT ADV data incomplete, waiting for more");
return 0;
}
# endif
if (!advertisedDevice->m_callbackSent) {
advertisedDevice->m_callbackSent++;
pScan->m_pScanCallbacks->onDiscovered(advertisedDevice);
@@ -498,7 +489,7 @@ void NimBLEScan::clearResults() {
* @brief Dump the scan results to the log.
*/
void NimBLEScanResults::dump() const {
# if MYNEWT_VAL(NIMBLE_CPP_LOG_LEVEL) >= 3
# if CONFIG_NIMBLE_CPP_LOG_LEVEL >= 3
for (const auto& dev : m_deviceVec) {
NIMBLE_LOGI(LOG_TAG, "- %s", dev->toString().c_str());
}

View File

@@ -143,25 +143,10 @@ NimBLEService* NimBLEServer::getServiceByHandle(uint16_t handle) const {
return nullptr;
}
/**
* @brief Get a BLE Characteristic by its handle
* @param handle The handle of the characteristic.
* @return A pointer to the characteristic object or nullptr if not found.
*/
NimBLECharacteristic* NimBLEServer::getCharacteristicByHandle(uint16_t handle) const {
for (const auto& svc : m_svcVec) {
NimBLECharacteristic* pChr = svc->getCharacteristicByHandle(handle);
if (pChr != nullptr) {
return pChr;
}
}
return nullptr;
} // getCharacteristicByHandle
# if MYNEWT_VAL(BLE_EXT_ADV)
/**
* @brief Retrieve the advertising object that can be used to advertise the existence of the server.
* @return A pointer to an advertising object.
* @return A pinter to an advertising object.
*/
NimBLEExtAdvertising* NimBLEServer::getAdvertising() const {
return NimBLEDevice::getAdvertising();
@@ -204,7 +189,7 @@ void NimBLEServer::start() {
return;
}
# if MYNEWT_VAL(NIMBLE_CPP_LOG_LEVEL) >= 4
# if CONFIG_NIMBLE_CPP_LOG_LEVEL >= 4
ble_gatts_show_local();
# endif
@@ -320,7 +305,7 @@ NimBLEConnInfo NimBLEServer::getPeerInfo(uint8_t index) const {
for (const auto& peer : m_connectedPeers) {
if (peer != BLE_HS_CONN_HANDLE_NONE) {
if (count == index) {
return getPeerInfoByHandle(peer);
return getPeerInfoByHandle(m_connectedPeers[count]);
}
count++;
}
@@ -375,7 +360,9 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
}
if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "Connection failed rc = %d %s", rc, NimBLEUtils::returnCodeToString(rc));
NIMBLE_LOGE(LOG_TAG, "Connection failed rc = %d %s",
rc,
NimBLEUtils::returnCodeToString(rc));
# if !MYNEWT_VAL(BLE_EXT_ADV) && MYNEWT_VAL(BLE_ROLE_BROADCASTER)
NimBLEDevice::startAdvertising();
# endif
@@ -442,21 +429,33 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
} // BLE_GAP_EVENT_DISCONNECT
case BLE_GAP_EVENT_SUBSCRIBE: {
rc = ble_gap_conn_find(event->subscribe.conn_handle, &peerInfo.m_desc);
if (rc != 0) {
break;
NIMBLE_LOGI(LOG_TAG,
"subscribe event; attr_handle=%d, subscribed: %s",
event->subscribe.attr_handle,
((event->subscribe.cur_notify || event->subscribe.cur_indicate) ? "true" : "false"));
for (const auto& svc : pServer->m_svcVec) {
for (const auto& chr : svc->m_vChars) {
if (chr->getHandle() == event->subscribe.attr_handle) {
rc = ble_gap_conn_find(event->subscribe.conn_handle, &peerInfo.m_desc);
if (rc != 0) {
break;
}
auto chrProps = chr->getProperties();
if (!peerInfo.isEncrypted() &&
(chrProps & BLE_GATT_CHR_F_READ_AUTHEN || chrProps & BLE_GATT_CHR_F_READ_AUTHOR ||
chrProps & BLE_GATT_CHR_F_READ_ENC)) {
NimBLEDevice::startSecurity(event->subscribe.conn_handle);
}
chr->m_pCallbacks->onSubscribe(chr,
peerInfo,
event->subscribe.cur_notify + (event->subscribe.cur_indicate << 1));
}
}
}
uint8_t subVal = event->subscribe.cur_notify + (event->subscribe.cur_indicate << 1);
NIMBLE_LOGI(LOG_TAG, "subscribe event; attr_handle=%d, subscribed: %d", event->subscribe.attr_handle, subVal);
auto pChar = pServer->getCharacteristicByHandle(event->subscribe.attr_handle);
if (!pChar) {
NIMBLE_LOGE(LOG_TAG, "subscribe event; attr_handle=%d, not found", event->subscribe.attr_handle);
break;
}
pChar->processSubRequest(peerInfo, subVal);
break;
} // BLE_GAP_EVENT_SUBSCRIBE
@@ -470,14 +469,18 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
} // BLE_GAP_EVENT_MTU
case BLE_GAP_EVENT_NOTIFY_TX: {
rc = ble_gap_conn_find(event->notify_tx.conn_handle, &peerInfo.m_desc);
if (rc != 0) {
break;
NimBLECharacteristic* pChar = nullptr;
for (const auto& svc : pServer->m_svcVec) {
for (auto& chr : svc->m_vChars) {
if (chr->getHandle() == event->notify_tx.attr_handle) {
pChar = chr;
}
}
}
auto pChar = pServer->getCharacteristicByHandle(event->notify_tx.attr_handle);
if (pChar == nullptr) {
break;
return 0;
}
if (event->notify_tx.indication) {
@@ -487,19 +490,9 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
}
pChar->m_pCallbacks->onStatus(pChar, event->notify_tx.status);
pChar->m_pCallbacks->onStatus(pChar, peerInfo, event->notify_tx.status);
break;
} // BLE_GAP_EVENT_NOTIFY_TX
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
case BLE_GAP_EVENT_NOTIFY_RX: {
if (pServer->m_pClient && pServer->m_pClient->m_connHandle == event->notify_rx.conn_handle) {
NimBLEClient::handleGapEvent(event, pServer->m_pClient);
}
break;
} // BLE_GAP_EVENT_NOTIFY_RX
# endif
case BLE_GAP_EVENT_ADV_COMPLETE: {
# if MYNEWT_VAL(BLE_EXT_ADV) && MYNEWT_VAL(BLE_ROLE_BROADCASTER)
case BLE_GAP_EVENT_SCAN_REQ_RCVD:
@@ -549,13 +542,6 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
NimBLEClient::handleGapEvent(event, pServer->m_pClient);
}
# endif
// update the secured status of the peer in each characteristic's subscribed peers list
for (const auto& svc : pServer->m_svcVec) {
for (const auto& chr : svc->m_vChars) {
chr->updatePeerStatus(peerInfo);
}
}
break;
} // BLE_GAP_EVENT_ENC_CHANGE

View File

@@ -72,7 +72,6 @@ class NimBLEServer {
NimBLEService* getServiceByUUID(const char* uuid, uint16_t instanceId = 0) const;
NimBLEService* getServiceByUUID(const NimBLEUUID& uuid, uint16_t instanceId = 0) const;
NimBLEService* getServiceByHandle(uint16_t handle) const;
NimBLECharacteristic* getCharacteristicByHandle(uint16_t handle) const;
void removeService(NimBLEService* service, bool deleteSvc = false);
void addService(NimBLEService* service);
uint16_t getPeerMTU(uint16_t connHandle) const;
@@ -119,10 +118,6 @@ class NimBLEServer {
NimBLEServer();
~NimBLEServer();
static int handleGapEvent(struct ble_gap_event* event, void* arg);
static int handleGattEvent(uint16_t connHandle, uint16_t attrHandle, ble_gatt_access_ctxt* ctxt, void* arg);
void serviceChanged();
void resetGATT();
bool m_gattsStarted : 1;
bool m_svcChanged : 1;
@@ -130,13 +125,19 @@ class NimBLEServer {
# if !MYNEWT_VAL(BLE_EXT_ADV)
bool m_advertiseOnDisconnect : 1;
# endif
NimBLEServerCallbacks* m_pServerCallbacks;
std::vector<NimBLEService*> m_svcVec;
NimBLEServerCallbacks* m_pServerCallbacks;
std::vector<NimBLEService*> m_svcVec;
std::array<uint16_t, MYNEWT_VAL(BLE_MAX_CONNECTIONS)> m_connectedPeers;
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
NimBLEClient* m_pClient{nullptr};
# endif
static int handleGapEvent(struct ble_gap_event* event, void* arg);
static int handleGattEvent(uint16_t connHandle, uint16_t attrHandle, ble_gatt_access_ctxt* ctxt, void* arg);
void serviceChanged();
void resetGATT();
}; // NimBLEServer
/**

View File

@@ -35,42 +35,14 @@
# include <stdlib.h>
# include <climits>
# ifndef MYNEWT_VAL_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT
# ifdef CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT
# define MYNEWT_VAL_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT
# else
# define MYNEWT_VAL_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT (0)
# endif
# endif
# ifndef MYNEWT_VAL_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
# ifdef CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
# define MYNEWT_VAL_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
# else
# define MYNEWT_VAL_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT (0)
# endif
# endif
# ifndef MYNEWT_VAL_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT
# ifdef CONFIG_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT
# define MYNEWT_VAL_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT CONFIG_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT
# else
# define MYNEWT_VAL_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT (0)
# endif
# endif
# if defined INC_FREERTOS_H
# ifndef MYNEWT_VAL_NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT
# ifndef CONFIG_NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT
# define MYNEWT_VAL_NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT 31
# else
# define MYNEWT_VAL_NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT CONFIG_NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT
# endif
# 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
constexpr uint32_t TASK_BLOCK_BIT = (1 << MYNEWT_VAL(NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT));
static const char* LOG_TAG = "NimBLEUtils";
static const char* LOG_TAG = "NimBLEUtils";
/**
* @brief Construct a NimBLETaskData instance.
@@ -82,7 +54,7 @@ NimBLETaskData::NimBLETaskData(void* pInstance, int flags, void* buf)
: m_pInstance{pInstance},
m_flags{flags},
m_pBuf{buf}
# ifdef INC_FREERTOS_H
# if defined INC_FREERTOS_H
,
m_pHandle{xTaskGetCurrentTaskHandle()} {
}
@@ -103,7 +75,7 @@ NimBLETaskData::NimBLETaskData(void* pInstance, int flags, void* buf)
* @brief Destructor.
*/
NimBLETaskData::~NimBLETaskData() {
# ifndef INC_FREERTOS_H
# if !defined INC_FREERTOS_H
if (m_pHandle != nullptr) {
ble_npl_sem_deinit(static_cast<ble_npl_sem*>(m_pHandle));
delete static_cast<ble_npl_sem*>(m_pHandle);
@@ -125,7 +97,7 @@ bool NimBLEUtils::taskWait(const NimBLETaskData& taskData, uint32_t timeout) {
ble_npl_time_ms_to_ticks(timeout, &ticks);
}
# ifdef INC_FREERTOS_H
# if defined INC_FREERTOS_H
uint32_t notificationValue;
xTaskNotifyWait(0, TASK_BLOCK_BIT, &notificationValue, 0);
if (notificationValue & TASK_BLOCK_BIT) {
@@ -147,7 +119,7 @@ bool NimBLEUtils::taskWait(const NimBLETaskData& taskData, uint32_t timeout) {
void NimBLEUtils::taskRelease(const NimBLETaskData& taskData, int flags) {
taskData.m_flags = flags;
if (taskData.m_pHandle != nullptr) {
# ifdef INC_FREERTOS_H
# if defined INC_FREERTOS_H
xTaskNotify(static_cast<TaskHandle_t>(taskData.m_pHandle), TASK_BLOCK_BIT, eSetBits);
# else
ble_npl_sem_release(static_cast<ble_npl_sem*>(taskData.m_pHandle));
@@ -161,7 +133,7 @@ void NimBLEUtils::taskRelease(const NimBLETaskData& taskData, int flags) {
* @return A string representation of the return code.
*/
const char* NimBLEUtils::returnCodeToString(int rc) {
# if MYNEWT_VAL(NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
# if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
switch (rc) {
case 0:
return "SUCCESS";
@@ -444,10 +416,10 @@ const char* NimBLEUtils::returnCodeToString(int rc) {
default:
return "Unknown";
}
# else // MYNEWT_VAL(NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
# else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
(void)rc;
return "";
# endif // MYNEWT_VAL(NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
# endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
}
/**
@@ -456,7 +428,7 @@ const char* NimBLEUtils::returnCodeToString(int rc) {
* @return A string representation of the advertising flags.
*/
const char* NimBLEUtils::advTypeToString(uint8_t advType) {
# if MYNEWT_VAL(NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT)
# if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT)
switch (advType) {
case BLE_HCI_ADV_TYPE_ADV_IND: // 0
return "Undirected - Connectable / Scannable";
@@ -471,10 +443,10 @@ const char* NimBLEUtils::advTypeToString(uint8_t advType) {
default:
return "Unknown flag";
}
# else // MYNEWT_VAL(NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT)
# else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT)
(void)advType;
return "";
# endif // MYNEWT_VAL(NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT)
# endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT)
} // adFlagsToString
/**
@@ -483,7 +455,7 @@ const char* NimBLEUtils::advTypeToString(uint8_t advType) {
* @return A string representation of the event type.
*/
const char* NimBLEUtils::gapEventToString(uint8_t eventType) {
# if MYNEWT_VAL(NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
# if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
switch (eventType) {
case BLE_GAP_EVENT_CONNECT: // 0
return "BLE_GAP_EVENT_CONNECT ";
@@ -563,10 +535,10 @@ const char* NimBLEUtils::gapEventToString(uint8_t eventType) {
NIMBLE_LOGD(LOG_TAG, "Unknown event type %d 0x%.2x", eventType, eventType);
return "Unknown event type";
}
# else // MYNEWT_VAL(NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
# else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
(void)eventType;
return "";
# endif // MYNEWT_VAL(NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
# endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
} // gapEventToString
/**

View File

@@ -21,15 +21,7 @@
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED
# ifndef MYNEWT_VAL_NIMBLE_CPP_DEBUG_ASSERT_ENABLED
# if defined(CONFIG_NIMBLE_CPP_DEBUG_ASSERT_ENABLED)
# define MYNEWT_VAL_NIMBLE_CPP_DEBUG_ASSERT_ENABLED CONFIG_NIMBLE_CPP_DEBUG_ASSERT_ENABLED
# else
# define MYNEWT_VAL_NIMBLE_CPP_DEBUG_ASSERT_ENABLED (0)
# endif
# endif
#if MYNEWT_VAL(NIMBLE_CPP_DEBUG_ASSERT_ENABLED) && !defined NDEBUG
#if CONFIG_NIMBLE_CPP_DEBUG_ASSERT_ENABLED && !defined NDEBUG
void nimble_cpp_assert(const char *file, unsigned line) __attribute((weak, noreturn));
# define NIMBLE_ATT_VAL_FILE (__builtin_strrchr(__FILE__, '/') ? \
__builtin_strrchr (__FILE__, '/') + 1 : __FILE__)

View File

@@ -26,7 +26,7 @@
class NimBLEValueAttribute {
public:
NimBLEValueAttribute(uint16_t maxLen = BLE_ATT_ATTR_MAX_LEN, uint16_t initLen = MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_INIT_LENGTH))
NimBLEValueAttribute(uint16_t maxLen = BLE_ATT_ATTR_MAX_LEN, uint16_t initLen = CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH)
: m_value(initLen, maxLen) {}
/**