38 Commits

Author SHA1 Message Date
h2zero
0f5a184aa3 Add BLE stream classes. 2025-11-24 08:09:07 -07:00
h2zero
f216e95770 Add characteristic callbacks onStatus overload with conn info.
Adds a new overloaded callback to NimBLECharacteristicCallbacks for the notification/indication onStatus method that provides a NimBLEConnInfo reference.
2025-11-17 19:21:13 -07:00
h2zero
222f1590ed Refactor notify/indicate
This refactors the handling of sending notifications and indications for greater efficiency.
* Adds client subscription state tracking to NimBLECharacteristic rather than relying on the stack.
* Notifications/indications are now sent directly, no longer calling the callback to read the values.
  This avoids delays and flash writes in the stack, allowing for greater throughput.
2025-11-17 19:21:13 -07:00
srgg
149716a506 correct container byte size calculation to writeValue, notify, and indicate 2025-11-16 09:22:40 -07:00
srgg
4199c52af1 fix: correct byte size calculation for ATT values set from containers 2025-11-16 09:22:37 -07:00
h2zero
20158d62d0 [Bugfix] make sure the notify event is sent to server created clients 2025-10-24 13:19:42 -06:00
Quentin F
f6c8728ca3 Update 1.x_to2.x_migration_guide.md 2025-10-24 13:19:03 -06:00
h2zero
e0d3c4be39 Update workflows + add release publish 2025-10-24 13:09:46 -06:00
Guo-Rong
d163a9fdc6 Find client by handle during disconnect event.
If the peer has RPA enabled, searching by address fails due to address
resolution.
If this occurs, attempt to find the client by connection handle.
2025-10-23 11:55:24 -06:00
Chris Morgan
133c1a5da4 Usage_tips.md - Note that the library is threadsafe. 2025-10-23 11:54:37 -06:00
Chris Morgan
f622cdff0c README.md - Add a note about threadsafety 2025-10-23 11:54:37 -06:00
Chris Morgan
68068677ab Usage_tips.md - 'Device Local Name' information to help guide setting the GATT Device Name or Advertising name. 2025-09-28 19:31:04 -06:00
Chris Morgan
2c6ab706b3 Usage_tips.md - Detail persisted bonds limitations and considerations relative to CONFIG_BT_NIMBLE_MAX_CCCDS 2025-09-23 21:04:11 -06:00
h2zero
6f0b9ddf5d Convert NIMBLE_CPP macros to MYNEWT. 2025-09-06 16:59:55 -06:00
h2zero
8f9e85a46a Release 2.3.3 2025-09-05 16:11:11 -06:00
h2zero
7706f5a6b2 Support up to 1650 bytes of advertisement with extended advertising. 2025-09-05 15:44:47 -06:00
h2zero
1ffd013794 [Bugfix] Extended advertisements not reporting full data.
Extended advertisement reports would be truncated incorrectly as the handler was not checking the data status.

Correct advertisement length and set status on update.
2025-09-05 15:39:46 -06:00
h2zero
e8f7147ac5 [Bugfix] NimBLEAdvertisedDevice::isConnectable incorrect result 2025-09-05 15:11:38 -06:00
h2zero
6ee2a951f5 Release 2.3.2 2025-09-02 14:54:24 -06:00
h2zero
4b74939b6d Improve macros for code enablement 2025-09-02 14:36:02 -06:00
h2zero
9f7b9042e0 Fix docs build 2025-09-02 14:36:02 -06:00
h2zero
2cd5dc2aa2 Fix build with idf v5.5+ and specific roles are defined. 2025-08-25 09:11:13 -06:00
h2zero
9df8cc7dd1 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-08-24 16:35:38 -06:00
iranl
88df909cfb 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-08-24 16:07:59 -06:00
h2zero
8cefc0a562 [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-08-01 17:08:44 -06:00
h2zero
8af38e7eb9 Change default security settings to BLE secure connections off.
Fixing some connection issues when enabled, users should enable if desired.
2025-06-27 18:08:42 -06:00
h2zero
e7fead903c [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-06-27 18:07:46 -06:00
h2zero
a57c45e1de Fix build with idf versions < 5.x 2025-06-27 18:07:41 -06:00
h2zero
edfc838bef [Bugfix] allow peripheral and central roles without broadcast/scan. 2025-06-20 10:41:28 -06:00
h2zero
f1ead9959d Bump idf_component version 2025-06-11 11:40:42 -06:00
h2zero
b30421c19d Fix library.json version 2025-06-11 11:34:10 -06:00
h2zero
bdb868d125 Release 2.3.1 2025-06-11 11:14:52 -06:00
h2zero
503939c66f Update docs 2025-06-11 11:11:58 -06:00
Larry Davis
2640c44b45 Support passing data directly from NimBLEBeacon.getData() to NimBLEAdvertisementData.setManufacturerData() 2025-06-11 11:11:11 -06:00
h2zero
fec2d7a279 [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-09 17:13:30 -06:00
h2zero
e2cee2d994 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-09 17:13:12 -06:00
h2zero
39f974625c Fix builds when exluding roles 2025-06-02 18:06:40 -06:00
John Boiles
169290f047 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-05-21 11:14:43 -06:00
74 changed files with 1819 additions and 828 deletions

View File

@@ -17,7 +17,7 @@ jobs:
# See https://hub.docker.com/r/espressif/idf/tags and
# 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"]
idf_ver: ["release-v4.4", "release-v5.4", "release-v5.5"]
idf_target: ["esp32", "esp32s3", "esp32c2", "esp32c3", "esp32c5", "esp32c6", "esp32h2", "esp32p4"]
example:
- NimBLE_Client
@@ -45,7 +45,7 @@ jobs:
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
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@v4
- uses: actions/checkout@v5
- name: Doxygen Action
uses: mattnotmitt/doxygen-action@v1.9.8
with:
@@ -17,4 +17,27 @@ jobs:
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/doxydocs/html
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 }}

1
.gitignore vendored
View File

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

View File

@@ -1,6 +1,36 @@
# 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
- Build failures with esp-idf versions 4.x.
- Workaround for upstream issue causing onConnectFail to not be called.
- Build failures with idf v5.5+ and specific roles are not enabled.
## Changed
- Allow peripheral and central roles to be used without broadcaster/observer roles.
- Where applicable, `MYNEWT_VAL_` macros are used to control feature availability instead of `CONFIG_`
## [2.3.1] 2025-06-11
## Fixed
- Build errors when disabling BLE roles.
- `NimBLEClient::readValue` call not returning when the instance was created with a`NimBLEServer` and reading a secured characteristic.
- `NimBLEScan` destructor potentially causing a crash.
## Added
- `NimBLEBeacon::BeaconData` `std::vector<uint8_t>` operator to allow it to be used as a parameter to `NimBLEAdvertisementData::setManufacturerData`.
## [2.3.0] 2025-05-19
## Fixed

View File

@@ -204,6 +204,10 @@ config NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT
Configure the bit to set in the task notification value when a task is blocked waiting for an event.
This should be set to a bit that is not used by other notifications in the system.
config NIMBLE_CPP_IDF
bool
default BT_NIMBLE_ENABLED
#
# BT config
#

View File

@@ -9,6 +9,8 @@
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

@@ -43,6 +43,7 @@ The changes listed here are only the required changes that must be made, and a s
Note: If setting a custom address, it should be set with `NimBLEDevice::setOwnAddr` first before calling `NimBLEDevice::setOwnAddrType`.
- `NimBLEDevice::getClientListSize` replaced with `NimBLEDevice::getCreatedClientCount`.
- `NimBLEDevice::getClientList` was removed and `NimBLEDevice::getConnectedClients` can be used instead which returns a `std::vector` of pointers to the connected client instances. This was done because internally the clients are managed in a `std::array` which replaced the 'std::list`.
- `NimBLEDevice::getClientByID(uint16_t conn_id);` has been changed to `NimBLEDevice::getClientByHandle(uint16_t connHandle)`
<br/>
## BLE Addresses
@@ -54,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.value` 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.val` and type is in `ble_addr_t.type`.
<br/>
## BLE UUID's
@@ -133,6 +134,7 @@ Have been removed, instead the application should use `NimBLERemoteCharacteristi
- - `NimBLEScanCallbacks::onResult`, functions the same as the old `NimBLEAdvertisedDeviceCallbacks::onResult` but now takes aa `const NimBLEAdvertisedDevice*` instead of non-const.
- - `NimBLEScanCallbacks::onScanEnd`, replaces the scanEnded callback passed to `NimBLEScan::start` and now takes a `const NimBLEScanResults&` and `int reason` parameter.
- - `NimBLEScanCallbacks::onDiscovered`, This is called immediately when a device is first scanned, before any scan response data is available and takes a `const NimBLEAdvertisedDevice*` parameter.
- `NimBLEScan::setAdvertisedDeviceCallbacks(NimBLEAdvertisedDeviceCallbacks* callbacks, bool wantDuplicates)` has been changed to `NimBLEScan::setScanCallbacks(NimBLEScanCallbacks* callbacks, bool wantDuplicates);`
<br/>
### Advertised Device

View File

@@ -48,8 +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.0
PROJECT_NUMBER = 2.3.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
# quick idea about the purpose of the project. Keep the description short.
@@ -2417,12 +2416,12 @@ INCLUDE_FILE_PATTERNS =
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED = _DOXYGEN_ \
CONFIG_BT_ENABLED \
CONFIG_BT_NIMBLE_ROLE_CENTRAL \
CONFIG_BT_NIMBLE_ROLE_OBSERVER \
CONFIG_BT_NIMBLE_ROLE_PERIPHERAL \
CONFIG_BT_NIMBLE_ROLE_BROADCASTER \
CONFIG_BT_NIMBLE_EXT_ADV
CONFIG_BT_NIMBLE_ENABLED=1 \
MYNEWT_VAL_BLE_ROLE_CENTRAL=1 \
MYNEWT_VAL_BLE_ROLE_OBSERVER=1 \
MYNEWT_VAL_BLE_ROLE_PERIPHERAL=1 \
MYNEWT_VAL_BLE_ROLE_BROADCASTER=1 \
MYNEWT_VAL_BLE_EXT_ADV=1
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The

View File

@@ -234,7 +234,7 @@ This can be changed to use passkey authentication or numeric comparison. See [Se
Advertising works the same as the original API except:
Calling `NimBLEAdvertising::setAdvertisementData` will entirely replace any data set with `NimBLEAdvertising::addServiceUUID`, or
`NimBLEAdvertising::setAppearance` or similar methods. You should set all the data you wish to advertise within the `NimBLEAdvertisementData` instead.
`NimBLEAdvertising::setAppearance` or similar methods. You should set all the data you wish to advertise within the `NimBLEAdvertisementData` instead if calling `NimBLEAdvertising::setAdvertisementData`.
<br/>
> BLEAdvertising::start (NimBLEAdvertising::start)

View File

@@ -1,11 +1,8 @@
# Usage Tips
## Put BLE functions in a task running on the NimBLE stack core
## Threadsafety
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/>
This library is threadsafe. Attribues can be manipulated freely.
## Do not delete client instances unless necessary or unused
@@ -32,6 +29,41 @@ 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

@@ -112,7 +112,7 @@ bool connectToServer() {
/** No client to reuse? Create a new one. */
if (!pClient) {
if (NimBLEDevice::getCreatedClientCount() >= NIMBLE_MAX_CONNECTIONS) {
if (NimBLEDevice::getCreatedClientCount() >= MYNEWT_VAL(BLE_MAX_CONNECTIONS)) {
printf("Max clients reached - no more connections available\n");
return false;
}
@@ -261,8 +261,7 @@ extern "C" void app_main(void) {
* These are the default values, only shown here for demonstration.
*/
// NimBLEDevice::setSecurityAuth(false, false, true);
NimBLEDevice::setSecurityAuth(/*BLE_SM_PAIR_AUTHREQ_BOND | BLE_SM_PAIR_AUTHREQ_MITM |*/ BLE_SM_PAIR_AUTHREQ_SC);
// NimBLEDevice::setSecurityAuth(BLE_SM_PAIR_AUTHREQ_BOND | BLE_SM_PAIR_AUTHREQ_MITM | BLE_SM_PAIR_AUTHREQ_SC);
/** Optional: set the transmit power */
NimBLEDevice::setPower(3); /** 3dbm */

View File

@@ -142,8 +142,8 @@ extern "C" void app_main(void) {
* These are the default values, only shown here for demonstration.
*/
// NimBLEDevice::setSecurityAuth(false, false, true);
// NimBLEDevice::setSecurityAuth(BLE_SM_PAIR_AUTHREQ_BOND | BLE_SM_PAIR_AUTHREQ_MITM | BLE_SM_PAIR_AUTHREQ_SC);
NimBLEDevice::setSecurityAuth(/*BLE_SM_PAIR_AUTHREQ_BOND | BLE_SM_PAIR_AUTHREQ_MITM |*/ BLE_SM_PAIR_AUTHREQ_SC);
pServer = NimBLEDevice::createServer();
pServer->setCallbacks(&serverCallbacks);

View File

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

View File

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

View File

@@ -15,10 +15,8 @@
* limitations under the License.
*/
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# include "NimBLE2904.h"
#include "NimBLE2904.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
NimBLE2904::NimBLE2904(NimBLECharacteristic* pChr)
: NimBLEDescriptor(NimBLEUUID((uint16_t)0x2904), BLE_GATT_CHR_F_READ, sizeof(NimBLE2904Data), pChr) {
@@ -71,4 +69,4 @@ void NimBLE2904::setUnit(uint16_t unit) {
setValue(m_data);
} // setUnit
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)

View File

@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_2904_H_
#define NIMBLE_CPP_2904_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# include "NimBLEDescriptor.h"
@@ -79,5 +79,5 @@ class NimBLE2904 : public NimBLEDescriptor {
NimBLE2904Data m_data{};
}; // NimBLE2904
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#endif // NIMBLE_CPP_2904_H_

View File

@@ -15,21 +15,36 @@
* limitations under the License.
*/
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "NimBLEAddress.h"
#if CONFIG_BT_NIMBLE_ENABLED
# include "NimBLEAddress.h"
# include "NimBLELog.h"
# include <algorithm>
# ifdef CONFIG_NIMBLE_CPP_ADDR_FMT_EXCLUDE_DELIMITER
# 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)
# define NIMBLE_CPP_ADDR_DELIMITER ""
# else
# define NIMBLE_CPP_ADDR_DELIMITER ":"
# endif
# ifdef CONFIG_NIMBLE_CPP_ADDR_FMT_UPPERCASE
# if MYNEWT_VAL(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"
@@ -224,11 +239,16 @@ NimBLEAddress::operator std::string() const {
snprintf(buffer,
sizeof(buffer),
NIMBLE_CPP_ADDR_FMT,
this->val[5], NIMBLE_CPP_ADDR_DELIMITER,
this->val[4], NIMBLE_CPP_ADDR_DELIMITER,
this->val[3], NIMBLE_CPP_ADDR_DELIMITER,
this->val[2], NIMBLE_CPP_ADDR_DELIMITER,
this->val[1], NIMBLE_CPP_ADDR_DELIMITER,
this->val[5],
NIMBLE_CPP_ADDR_DELIMITER,
this->val[4],
NIMBLE_CPP_ADDR_DELIMITER,
this->val[3],
NIMBLE_CPP_ADDR_DELIMITER,
this->val[2],
NIMBLE_CPP_ADDR_DELIMITER,
this->val[1],
NIMBLE_CPP_ADDR_DELIMITER,
this->val[0]);
return std::string{buffer};
} // operator std::string

View File

@@ -17,8 +17,9 @@
#ifndef NIMBLE_CPP_ADDRESS_H_
#define NIMBLE_CPP_ADDRESS_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED
# if defined(CONFIG_NIMBLE_CPP_IDF)
# include "nimble/ble.h"
@@ -66,5 +67,5 @@ class NimBLEAddress : private ble_addr_t {
operator uint64_t() const;
};
#endif /* CONFIG_BT_ENABLED */
#endif /* NIMBLE_CPP_ADDRESS_H_ */
#endif // CONFIG_BT_NIMBLE_ENABLED
#endif // NIMBLE_CPP_ADDRESS_H_

View File

@@ -15,11 +15,10 @@
* limitations under the License.
*/
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
#include "NimBLEAdvertisedDevice.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_OBSERVER)
# include "NimBLEDevice.h"
# include "NimBLEAdvertisedDevice.h"
# include "NimBLEUtils.h"
# include "NimBLELog.h"
@@ -32,13 +31,14 @@ static const char* LOG_TAG = "NimBLEAdvertisedDevice";
* @param [in] event The advertisement event data.
*/
NimBLEAdvertisedDevice::NimBLEAdvertisedDevice(const ble_gap_event* event, uint8_t eventType)
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_EXT_ADV)
: m_address{event->ext_disc.addr},
m_advType{eventType},
m_rssi{event->ext_disc.rssi},
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},
@@ -59,9 +59,18 @@ NimBLEAdvertisedDevice::NimBLEAdvertisedDevice(const ble_gap_event* event, uint8
* @param [in] event The advertisement event data.
*/
void NimBLEAdvertisedDevice::update(const ble_gap_event* event, uint8_t eventType) {
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_EXT_ADV)
const auto& disc = event->ext_disc;
m_isLegacyAdv = disc.props & BLE_HCI_ADV_LEGACY_MASK;
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;
# else
const auto& disc = event->disc;
# endif
@@ -87,11 +96,11 @@ const NimBLEAddress& NimBLEAdvertisedDevice::getAddress() const {
/**
* @brief Get the advertisement type.
* @return The advertising type the device is reporting:
* * 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
* * 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
*/
uint8_t NimBLEAdvertisedDevice::getAdvType() const {
return m_advType;
@@ -581,7 +590,7 @@ bool NimBLEAdvertisedDevice::haveTXPower() const {
return findAdvField(BLE_HS_ADV_TYPE_TX_PWR_LVL) > 0;
} // haveTXPower
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_EXT_ADV)
/**
* @brief Get the set ID of the extended advertisement.
* @return The set ID.
@@ -618,6 +627,18 @@ 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 {
@@ -731,7 +752,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.
*/
uint8_t NimBLEAdvertisedDevice::getAdvLength() const {
uint16_t NimBLEAdvertisedDevice::getAdvLength() const {
return m_advLength;
}
@@ -752,12 +773,13 @@ uint8_t NimBLEAdvertisedDevice::getAddressType() const {
* @return True if the device is connectable.
*/
bool NimBLEAdvertisedDevice::isConnectable() const {
# if CONFIG_BT_NIMBLE_EXT_ADV
if (m_isLegacyAdv) {
return m_advType == BLE_HCI_ADV_RPT_EVTYPE_ADV_IND || m_advType == BLE_HCI_ADV_RPT_EVTYPE_DIR_IND;
# if MYNEWT_VAL(BLE_EXT_ADV)
if (!m_isLegacyAdv) {
return (m_advType & BLE_HCI_ADV_CONN_MASK) || (m_advType & BLE_HCI_ADV_DIRECT_MASK);
}
# endif
return (m_advType & BLE_HCI_ADV_CONN_MASK) || (m_advType & BLE_HCI_ADV_DIRECT_MASK);
return m_advType == BLE_HCI_ADV_RPT_EVTYPE_ADV_IND || m_advType == BLE_HCI_ADV_RPT_EVTYPE_DIR_IND;
} // isConnectable
/**
@@ -773,7 +795,7 @@ bool NimBLEAdvertisedDevice::isScannable() const {
* @return True if legacy (Bluetooth 4.x), false if extended (bluetooth 5.x).
*/
bool NimBLEAdvertisedDevice::isLegacyAdvertisement() const {
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_EXT_ADV)
return m_isLegacyAdv;
# else
return true;
@@ -814,4 +836,4 @@ const std::vector<uint8_t>::const_iterator NimBLEAdvertisedDevice::end() const {
return m_payload.cend();
}
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_OBSERVER)

View File

@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_ADVERTISED_DEVICE_H_
#define NIMBLE_CPP_ADVERTISED_DEVICE_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_OBSERVER)
# include "NimBLEAddress.h"
# include "NimBLEScan.h"
@@ -69,7 +69,7 @@ class NimBLEAdvertisedDevice {
NimBLEAddress getTargetAddress(uint8_t index = 0) const;
uint8_t getTargetAddressCount() const;
int8_t getTXPower() const;
uint8_t getAdvLength() const;
uint16_t getAdvLength() const;
uint8_t getAddressType() const;
bool isAdvertisingService(const NimBLEUUID& uuid) const;
bool haveAppearance() const;
@@ -87,11 +87,12 @@ class NimBLEAdvertisedDevice {
bool isConnectable() const;
bool isScannable() const;
bool isLegacyAdvertisement() const;
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_EXT_ADV)
uint8_t getSetId() const;
uint8_t getPrimaryPhy() const;
uint8_t getSecondaryPhy() const;
uint16_t getPeriodicInterval() const;
uint8_t getDataStatus() const;
# endif
operator NimBLEAddress() const;
@@ -161,10 +162,11 @@ class NimBLEAdvertisedDevice {
uint8_t m_advType{};
int8_t m_rssi{};
uint8_t m_callbackSent{};
uint8_t m_advLength{};
uint16_t m_advLength{};
# if CONFIG_BT_NIMBLE_EXT_ADV
# 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{};
@@ -174,5 +176,5 @@ class NimBLEAdvertisedDevice {
std::vector<uint8_t> m_payload;
};
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_OBSERVER */
#endif /* CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_OBSERVER) */
#endif /* NIMBLE_CPP_ADVERTISED_DEVICE_H_ */

View File

@@ -15,11 +15,9 @@
* limitations under the License.
*/
#include "nimconfig.h"
#if (defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && !CONFIG_BT_NIMBLE_EXT_ADV) || \
defined(_DOXYGEN_)
#include "NimBLEAdvertisementData.h"
#if (CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && !MYNEWT_VAL(BLE_EXT_ADV)) || defined(_DOXYGEN_)
# include "NimBLEAdvertisementData.h"
# include "NimBLEDevice.h"
# include "NimBLEUtils.h"
# include "NimBLEUUID.h"
@@ -585,4 +583,4 @@ std::string NimBLEAdvertisementData::toString() const {
return str;
} // toString
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && !CONFIG_BT_NIMBLE_EXT_ADV
#endif // (CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && !MYNEWT_VAL(BLE_EXT_ADV)) || defined(_DOXYGEN_)

View File

@@ -18,9 +18,8 @@
#ifndef NIMBLE_CPP_ADVERTISEMENT_DATA_H_
#define NIMBLE_CPP_ADVERTISEMENT_DATA_H_
#include "nimconfig.h"
#if (defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && !CONFIG_BT_NIMBLE_EXT_ADV) || \
defined(_DOXYGEN_)
#include "syscfg/syscfg.h"
#if (CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && !MYNEWT_VAL(BLE_EXT_ADV)) || defined(_DOXYGEN_)
# include <cstdint>
# include <string>
@@ -75,5 +74,5 @@ class NimBLEAdvertisementData {
std::vector<uint8_t> m_payload{};
}; // NimBLEAdvertisementData
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && !CONFIG_BT_NIMBLE_EXT_ADV
#endif // (CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && !MYNEWT_VAL(BLE_EXT_ADV)) || defined(_DOXYGEN_)
#endif // NIMBLE_CPP_ADVERTISEMENT_DATA_H_

View File

@@ -15,16 +15,14 @@
* limitations under the License.
*/
#include "nimconfig.h"
#if (defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && !CONFIG_BT_NIMBLE_EXT_ADV) || \
defined(_DOXYGEN_)
#include "NimBLEAdvertising.h"
#if (CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && !MYNEWT_VAL(BLE_EXT_ADV)) || defined(_DOXYGEN_)
# if defined(CONFIG_NIMBLE_CPP_IDF)
# include "services/gap/ble_svc_gap.h"
# else
# include "nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h"
# endif
# include "NimBLEAdvertising.h"
# include "NimBLEDevice.h"
# include "NimBLEServer.h"
# include "NimBLEUtils.h"
@@ -44,7 +42,7 @@ NimBLEAdvertising::NimBLEAdvertising()
m_duration{BLE_HS_FOREVER},
m_scanResp{false},
m_advDataSet{false} {
# if !defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# if !MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
m_advParams.conn_mode = BLE_GAP_CONN_MODE_NON;
# else
m_advParams.conn_mode = BLE_GAP_CONN_MODE_UND;
@@ -197,7 +195,7 @@ bool NimBLEAdvertising::start(uint32_t duration, const NimBLEAddress* dirAddr) {
return true;
}
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
NimBLEServer* pServer = NimBLEDevice::getServer();
if (pServer != nullptr) {
pServer->start(); // make sure the GATT server is ready before advertising
@@ -222,7 +220,7 @@ bool NimBLEAdvertising::start(uint32_t duration, const NimBLEAddress* dirAddr) {
duration = BLE_HS_FOREVER;
}
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
int rc = ble_gap_adv_start(NimBLEDevice::m_ownAddrType,
(dirAddr != nullptr) ? dirAddr->getBase() : NULL,
duration,
@@ -622,4 +620,4 @@ bool NimBLEAdvertising::setServiceData(const NimBLEUUID& uuid, const std::string
return setServiceData(uuid, reinterpret_cast<const uint8_t*>(data.data()), data.length());
} // setServiceData
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && !CONFIG_BT_NIMBLE_EXT_ADV */
#endif // (CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && !MYNEWT_VAL(BLE_EXT_ADV)) || defined(_DOXYGEN_)

View File

@@ -18,9 +18,8 @@
#ifndef NIMBLE_CPP_ADVERTISING_H_
#define NIMBLE_CPP_ADVERTISING_H_
#include "nimconfig.h"
#if (defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && !CONFIG_BT_NIMBLE_EXT_ADV) || \
defined(_DOXYGEN_)
#include "syscfg/syscfg.h"
#if (CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && !MYNEWT_VAL(BLE_EXT_ADV)) || defined(_DOXYGEN_)
# if defined(CONFIG_NIMBLE_CPP_IDF)
# include "host/ble_gap.h"
@@ -106,5 +105,5 @@ class NimBLEAdvertising {
bool m_advDataSet : 1;
};
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && !CONFIG_BT_NIMBLE_EXT_ADV */
#endif /* NIMBLE_CPP_ADVERTISING_H_ */
#endif // (CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && !MYNEWT_VAL(BLE_EXT_ADV)) || defined(_DOXYGEN_)
#endif // NIMBLE_CPP_ADVERTISING_H_

View File

@@ -15,8 +15,8 @@
* limitations under the License.
*/
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "NimBLEAttValue.h"
#if CONFIG_BT_NIMBLE_ENABLED
# if defined(CONFIG_NIMBLE_CPP_IDF)
# include "nimble/nimble_npl.h"
@@ -24,7 +24,7 @@
# include "nimble/nimble/include/nimble/nimble_npl.h"
# endif
# include "NimBLEAttValue.h"
# include "NimBLEUtils.h"
# include "NimBLELog.h"
static const char* LOG_TAG = "NimBLEAttValue";
@@ -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 CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
# if MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED)
,
m_timestamp{}
# endif
@@ -105,7 +105,7 @@ void NimBLEAttValue::deepCopy(const NimBLEAttValue& source) {
// Set the value of the attribute.
bool NimBLEAttValue::setValue(const uint8_t* value, uint16_t len) {
m_attr_len = 0; // Just set the value length to 0 and append instead of repeating code.
m_attr_len = 0; // Just set the value length to 0 and append instead of repeating code.
m_attr_value[0] = '\0'; // Set the first byte to 0 incase the len of the new value is 0.
append(value, len);
return memcmp(m_attr_value, value, len) == 0 && m_attr_len == len;
@@ -134,7 +134,7 @@ NimBLEAttValue& NimBLEAttValue::append(const uint8_t* value, uint16_t len) {
return *this;
}
# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
# if MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED)
time_t t = time(nullptr);
# else
time_t t = 0;
@@ -160,4 +160,4 @@ uint8_t NimBLEAttValue::operator[](int pos) const {
return m_attr_value[pos];
}
#endif // CONFIG_BT_ENABLED
#endif // CONFIG_BT_NIMBLE_ENABLED

View File

@@ -17,8 +17,9 @@
#ifndef NIMBLE_CPP_ATTVALUE_H
#define NIMBLE_CPP_ATTVALUE_H
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED
# ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE
# include <Arduino.h>
@@ -30,20 +31,30 @@
# include <cstring>
# include <cstdint>
# ifndef CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
# define CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED 0
# 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
# endif
# ifndef BLE_ATT_ATTR_MAX_LEN
# define BLE_ATT_ATTR_MAX_LEN 512
# endif
# 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
# 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
# endif
/* Used to determine if the type passed to a template has a data() and size() method. */
@@ -62,6 +73,14 @@ 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
@@ -73,7 +92,7 @@ class NimBLEAttValue {
uint16_t m_attr_max_len{};
uint16_t m_attr_len{};
uint16_t m_capacity{};
# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
# if MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED)
time_t m_timestamp{};
# endif
void deepCopy(const NimBLEAttValue& source);
@@ -84,7 +103,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 = CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
NimBLEAttValue(uint16_t init_len = MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_INIT_LENGTH), uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
/**
* @brief Construct with an initial value from a buffer.
@@ -169,7 +188,7 @@ class NimBLEAttValue {
/** @brief Iterator end */
const uint8_t* end() const { return m_attr_value + m_attr_len; }
# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
# if MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED)
/** @brief Returns a timestamp of when the value was last updated */
time_t getTimeStamp() const { return m_timestamp; }
@@ -209,7 +228,7 @@ class NimBLEAttValue {
const NimBLEAttValue& getValue(time_t* timestamp = nullptr) const {
if (timestamp != nullptr) {
# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
# if MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED)
*timestamp = m_timestamp;
# else
*timestamp = 0;
@@ -263,13 +282,32 @@ 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.
* @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.
*/
template <typename T>
# ifdef _DOXYGEN_
bool
# else
typename std::enable_if<Has_data_size<T>::value, bool>::type
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
# endif
setValue(const T& v) {
return setValue(reinterpret_cast<const uint8_t*>(v.data()), v.size());
@@ -284,7 +322,11 @@ 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) {
return setValue(reinterpret_cast<const uint8_t*>(s.data()), s.size());
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());
}
} else if constexpr (Has_c_str_length<T>::value) {
return setValue(reinterpret_cast<const uint8_t*>(s.c_str()), s.length());
} else {
@@ -306,7 +348,7 @@ class NimBLEAttValue {
template <typename T>
T getValue(time_t* timestamp = nullptr, bool skipSizeCheck = false) const {
if (timestamp != nullptr) {
# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
# if MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED)
*timestamp = m_timestamp;
# else
*timestamp = 0;
@@ -362,5 +404,5 @@ class NimBLEAttValue {
# endif
};
#endif /*(CONFIG_BT_ENABLED) */
#endif /* NIMBLE_CPP_ATTVALUE_H_ */
#endif // CONFIG_BT_NIMBLE_ENABLED
#endif // NIMBLE_CPP_ATTVALUE_H_

View File

@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_ATTRIBUTE_H_
#define NIMBLE_CPP_ATTRIBUTE_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && (defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) || defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL))
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && (MYNEWT_VAL(BLE_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_ROLE_CENTRAL))
# include "NimBLEUUID.h"
@@ -56,5 +56,5 @@ class NimBLEAttribute {
uint16_t m_handle{0};
};
#endif // CONFIG_BT_ENABLED && (CONFIG_BT_NIMBLE_ROLE_PERIPHERAL || CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#endif // CONFIG_BT_NIMBLE_ENABLED && (MYNEWT_VAL(BLE_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_ROLE_CENTRAL))
#endif // NIMBLE_CPP_ATTRIBUTE_H_

View File

@@ -15,10 +15,9 @@
* limitations under the License.
*/
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
#include "NimBLEBeacon.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# include "NimBLEBeacon.h"
# include "NimBLEUUID.h"
# include "NimBLELog.h"
@@ -138,4 +137,4 @@ void NimBLEBeacon::setSignalPower(int8_t signalPower) {
m_beaconData.signalPower = signalPower;
} // setSignalPower
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER)

View File

@@ -18,12 +18,13 @@
#ifndef NIMBLE_CPP_BEACON_H_
#define NIMBLE_CPP_BEACON_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER)
class NimBLEUUID;
# include <cstdint>
# include <vector>
/**
* @brief Representation of a beacon.
@@ -40,6 +41,10 @@ class NimBLEBeacon {
uint16_t major{};
uint16_t minor{};
int8_t signalPower{};
operator std::vector<uint8_t> () const {
return std::vector<uint8_t>(reinterpret_cast<const uint8_t*>(this),
reinterpret_cast<const uint8_t*>(this) + sizeof(BeaconData));
}
} __attribute__((packed));
const BeaconData& getData();
@@ -60,5 +65,5 @@ class NimBLEBeacon {
BeaconData m_beaconData;
}; // NimBLEBeacon
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#endif // NIMBLE_CPP_BEACON_H_
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL

View File

@@ -15,10 +15,16 @@
* limitations under the License.
*/
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#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
# endif
# include "NimBLECharacteristic.h"
# include "NimBLE2904.h"
# include "NimBLEDevice.h"
# include "NimBLELog.h"
@@ -219,7 +225,8 @@ void NimBLECharacteristic::setService(NimBLEService* pService) {
* @return True if the indication was sent successfully, false otherwise.
*/
bool NimBLECharacteristic::indicate(uint16_t connHandle) const {
return sendValue(nullptr, 0, false, connHandle);
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);
} // indicate
/**
@@ -241,7 +248,8 @@ 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 {
return sendValue(nullptr, 0, true, connHandle);
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);
} // notify
/**
@@ -265,55 +273,50 @@ 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 {
int rc = 0;
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);
if (value != nullptr && length > 0) { // custom notification value
os_mbuf* om = nullptr;
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 (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_gattc_notify_custom(connHandle, m_handle, om);
} else {
rc = ble_gattc_indicate_custom(connHandle, m_handle, om);
}
goto done;
// 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;
}
// 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_gattc_notify_custom(ch, m_handle, om);
} else {
rc = ble_gattc_indicate_custom(ch, m_handle, om);
}
if (requireSecure && !entry.isSecured()) {
NIMBLE_LOGW(LOG_TAG, "skipping notify/indicate to connHandle=%d, link not secured", entry.getConnHandle());
continue;
}
} else if (connHandle != BLE_HS_CONN_HANDLE_NONE) {
// Null buffer will read the value from the characteristic
// 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));
om = ble_hs_mbuf_from_flat(value, length);
}
if (!om) {
rc = BLE_HS_ENOMEM;
break;
}
if (isNotification) {
rc = ble_gattc_notify_custom(connHandle, m_handle, nullptr);
rc = ble_gatts_notify_custom(ch, m_handle, om);
} else {
rc = ble_gattc_indicate_custom(connHandle, m_handle, nullptr);
rc = ble_gatts_indicate_custom(ch, m_handle, om);
}
if (rc != 0 || chSpecified) {
break;
}
} 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;
@@ -322,10 +325,107 @@ done:
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);
@@ -399,6 +499,18 @@ 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.
@@ -415,4 +527,4 @@ void NimBLECharacteristicCallbacks::onSubscribe(NimBLECharacteristic* pCharacter
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onSubscribe: default");
}
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)

View File

@@ -17,8 +17,9 @@
#ifndef NIMBLE_CPP_CHARACTERISTIC_H_
#define NIMBLE_CPP_CHARACTERISTIC_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
class NimBLECharacteristicCallbacks;
class NimBLEService;
@@ -30,6 +31,7 @@ class NimBLE2904;
# include <string>
# include <vector>
# include <array>
/**
* @brief The model of a BLE Characteristic.
@@ -111,7 +113,27 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
}
/**
* @brief Template to send a notification with a value from a class that has a data() and size() method.
* @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.
* @param [in] v The value to send.
* @param [in] connHandle Optional, a connection handle to send the notification to.
*/
@@ -119,7 +141,7 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
# ifdef _DOXYGEN_
bool
# else
typename std::enable_if<Has_data_size<T>::value, bool>::type
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(), connHandle);
@@ -159,7 +181,27 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
}
/**
* @brief Template to send a indication with a value from a class that has a data() and size() method.
* @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.
* @param [in] v The value to send.
* @param [in] connHandle Optional, a connection handle to send the notification to.
*/
@@ -167,7 +209,7 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
# ifdef _DOXYGEN_
bool
# else
typename std::enable_if<Has_data_size<T>::value, bool>::type
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(), connHandle);
@@ -189,7 +231,11 @@ 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) {
return notify(reinterpret_cast<const uint8_t*>(value.data()), value.size(), connHandle);
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);
}
} else if constexpr (Has_c_str_length<T>::value) {
return notify(reinterpret_cast<const uint8_t*>(value.c_str()), value.length(), connHandle);
} else {
@@ -211,7 +257,11 @@ 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) {
return indicate(reinterpret_cast<const uint8_t*>(value.data()), value.size(), connHandle);
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);
}
} else if constexpr (Has_c_str_length<T>::value) {
return indicate(reinterpret_cast<const uint8_t*>(value.c_str()), value.length(), connHandle);
} else {
@@ -232,9 +282,33 @@ 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
/**
@@ -249,9 +323,10 @@ 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);
virtual void onStatus(NimBLECharacteristic* pCharacteristic, int code); // deprecated
virtual void onStatus(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo, int code);
virtual void onSubscribe(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo, uint16_t subValue);
};
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
#endif /*NIMBLE_CPP_CHARACTERISTIC_H_*/
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#endif // NIMBLE_CPP_CHARACTERISTIC_H_

View File

@@ -15,10 +15,9 @@
* limitations under the License.
*/
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "NimBLEClient.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
# include "NimBLEClient.h"
# include "NimBLERemoteService.h"
# include "NimBLERemoteCharacteristic.h"
# include "NimBLEDevice.h"
@@ -69,7 +68,7 @@ NimBLEClient::NimBLEClient(const NimBLEAddress& peerAddress)
m_terminateFailCount{0},
m_asyncSecureAttempt{0},
m_config{},
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_EXT_ADV)
m_phyMask{BLE_GAP_LE_PHY_1M_MASK | BLE_GAP_LE_PHY_2M_MASK | BLE_GAP_LE_PHY_CODED_MASK},
# endif
m_connParams{16,
@@ -126,6 +125,7 @@ size_t NimBLEClient::deleteService(const NimBLEUUID& uuid) {
return m_svcVec.size();
} // deleteService
# if MYNEWT_VAL(BLE_ROLE_OBSERVER)
/**
* @brief Connect to an advertising device.
* @param [in] pDevice A pointer to the advertised device instance to connect to.
@@ -141,6 +141,7 @@ bool NimBLEClient::connect(const NimBLEAdvertisedDevice* pDevice, bool deleteAtt
NimBLEAddress address(pDevice->getAddress());
return connect(address, deleteAttributes, asyncConnect, exchangeMTU);
} // connect
# endif
/**
* @brief Connect to the BLE Server using the address of the last connected device, or the address\n
@@ -203,7 +204,7 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes,
m_config.exchangeMTU = exchangeMTU;
do {
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_EXT_ADV)
rc = ble_gap_ext_connect(NimBLEDevice::m_ownAddrType,
peerAddr,
m_connectTimeout,
@@ -227,10 +228,15 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes,
break;
case BLE_HS_EBUSY:
# if MYNEWT_VAL(BLE_ROLE_OBSERVER)
// Scan was active, stop it through the NimBLEScan API to release any tasks and call the callback.
if (!NimBLEDevice::getScan()->stop()) {
rc = BLE_HS_EUNKNOWN;
}
# else
rc = BLE_HS_EUNKNOWN;
# endif
break;
case BLE_HS_EDONE:
@@ -396,7 +402,7 @@ void NimBLEClient::setConfig(NimBLEClient::Config config) {
m_config = config;
} // setConfig
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_EXT_ADV)
/**
* @brief Set the PHY types to use when connecting to a server.
* @param [in] mask A bitmask indicating what PHYS to connect with.\n
@@ -927,9 +933,21 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) {
switch (event->type) {
case BLE_GAP_EVENT_DISCONNECT: {
// workaround for bug in NimBLE stack where disconnect event argument is not passed correctly
pClient = NimBLEDevice::getClientByHandle(event->disconnect.conn.conn_handle);
pClient = NimBLEDevice::getClientByPeerAddress(event->disconnect.conn.peer_ota_addr);
if (pClient == nullptr) {
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);
return 0;
}
@@ -954,7 +972,9 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) {
pClient->m_asyncSecureAttempt = 0;
// Don't call the disconnect callback if we are waiting for a connection to complete and it fails
if (rc != (BLE_HS_ERR_HCI_BASE + BLE_ERR_CONN_ESTABLISHMENT) || pClient->m_config.asyncConnect) {
if (rc == (BLE_HS_ERR_HCI_BASE + BLE_ERR_CONN_ESTABLISHMENT) && pClient->m_config.asyncConnect) {
pClient->m_pClientCallbacks->onConnectFail(pClient, rc);
} else {
pClient->m_pClientCallbacks->onDisconnect(pClient, rc);
}
@@ -982,6 +1002,10 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) {
}
rc = event->connect.status;
if (rc == BLE_ERR_UNSUPP_REM_FEATURE) {
rc = 0; // Workaround: Ignore unsupported remote feature error as it is not a real error.
}
if (rc == 0) {
pClient->m_connHandle = event->connect.conn_handle;
@@ -1301,4 +1325,4 @@ void NimBLEClientCallbacks::onPhyUpdate(NimBLEClient* pClient, uint8_t txPhy, ui
} // onPhyUpdate
#
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)

View File

@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_CLIENT_H_
#define NIMBLE_CPP_CLIENT_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
# if defined(CONFIG_NIMBLE_CPP_IDF)
# include "host/ble_gap.h"
@@ -48,10 +48,12 @@ struct NimBLETaskData;
*/
class NimBLEClient {
public:
# if MYNEWT_VAL(BLE_ROLE_OBSERVER)
bool connect(const NimBLEAdvertisedDevice* device,
bool deleteAttributes = true,
bool asyncConnect = false,
bool exchangeMTU = true);
# endif
bool connect(const NimBLEAddress& address, bool deleteAttributes = true, bool asyncConnect = false, bool exchangeMTU = true);
bool connect(bool deleteAttributes = true, bool asyncConnect = false, bool exchangeMTU = true);
bool disconnect(uint8_t reason = BLE_ERR_REM_USER_CONN_TERM);
@@ -93,7 +95,7 @@ class NimBLEClient {
const NimBLEAttValue& value,
bool response = false);
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_EXT_ADV)
void setConnectPhy(uint8_t phyMask);
# endif
bool updatePhy(uint8_t txPhysMask, uint8_t rxPhysMask, uint16_t phyOptions = 0);
@@ -135,7 +137,7 @@ class NimBLEClient {
mutable uint8_t m_asyncSecureAttempt;
Config m_config;
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_EXT_ADV)
uint8_t m_phyMask;
# endif
ble_gap_conn_params m_connParams;
@@ -227,5 +229,5 @@ class NimBLEClientCallbacks {
virtual void onPhyUpdate(NimBLEClient* pClient, uint8_t txPhy, uint8_t rxPhy);
};
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
#endif /* NIMBLE_CPP_CLIENT_H_ */
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
#endif // NIMBLE_CPP_CLIENT_H_

View File

@@ -15,8 +15,8 @@
* limitations under the License.
*/
#ifndef NIMBLECONNINFO_H_
#define NIMBLECONNINFO_H_
#ifndef NIMBLE_CPP_CONNINFO_H_
#define NIMBLE_CPP_CONNINFO_H_
#if defined(CONFIG_NIMBLE_CPP_IDF)
# include "host/ble_gap.h"
@@ -80,4 +80,5 @@ class NimBLEConnInfo {
NimBLEConnInfo() {};
NimBLEConnInfo(ble_gap_conn_desc desc) { m_desc = desc; }
};
#endif
#endif // NIMBLE_CPP_CONNINFO_H_

View File

@@ -15,11 +15,10 @@
* limitations under the License.
*/
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLEDescriptor.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# include "NimBLEService.h"
# include "NimBLEDescriptor.h"
# include "NimBLELog.h"
# include <string>
@@ -148,4 +147,4 @@ void NimBLEDescriptorCallbacks::onWrite(NimBLEDescriptor* pDescriptor, NimBLECon
NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onWrite: default");
} // onWrite
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)

View File

@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_DESCRIPTOR_H_
#define NIMBLE_CPP_DESCRIPTOR_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# include "NimBLELocalValueAttribute.h"
# include <string>
@@ -72,5 +72,5 @@ class NimBLEDescriptorCallbacks {
# include "NimBLE2904.h"
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
#endif /* NIMBLE_CPP_DESCRIPTOR_H_ */
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#endif // NIMBLE_CPP_DESCRIPTOR_H_

View File

@@ -15,11 +15,8 @@
* limitations under the License.
*/
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
# include "NimBLEDevice.h"
# include "NimBLEUtils.h"
#include "NimBLEDevice.h"
#if CONFIG_BT_NIMBLE_ENABLED
# ifdef ESP_PLATFORM
# include "esp_err.h"
@@ -59,17 +56,6 @@
# include "esp32-hal-bt.h"
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# include "NimBLEClient.h"
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# include "NimBLEServer.h"
# if CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM > 0
# include "NimBLEL2CAPServer.h"
# endif
# endif
# include "NimBLELog.h"
static const char* LOG_TAG = "NimBLEDevice";
@@ -82,27 +68,27 @@ extern "C" void ble_store_config_init(void);
NimBLEDeviceCallbacks NimBLEDevice::defaultDeviceCallbacks{};
NimBLEDeviceCallbacks* NimBLEDevice::m_pDeviceCallbacks = &defaultDeviceCallbacks;
# if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
# if MYNEWT_VAL(BLE_ROLE_OBSERVER)
NimBLEScan* NimBLEDevice::m_pScan = nullptr;
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
NimBLEServer* NimBLEDevice::m_pServer = nullptr;
# if CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM > 0
# if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
NimBLEL2CAPServer* NimBLEDevice::m_pL2CAPServer = nullptr;
# endif
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# if MYNEWT_VAL(BLE_EXT_ADV)
NimBLEExtAdvertising* NimBLEDevice::m_bleAdvertising = nullptr;
# else
NimBLEAdvertising* NimBLEDevice::m_bleAdvertising = nullptr;
# endif
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
std::array<NimBLEClient*, NIMBLE_MAX_CONNECTIONS> NimBLEDevice::m_pClients{};
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
std::array<NimBLEClient*, MYNEWT_VAL(BLE_MAX_CONNECTIONS)> NimBLEDevice::m_pClients{};
# endif
bool NimBLEDevice::m_initialized{false};
@@ -132,7 +118,7 @@ extern "C" int ble_vhci_disc_duplicate_mode_enable(int mode);
/* SERVER FUNCTIONS */
/* -------------------------------------------------------------------------- */
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
/**
* @brief Create an instance of a server.
* @return A pointer to the instance of the server.
@@ -156,7 +142,7 @@ NimBLEServer* NimBLEDevice::getServer() {
return m_pServer;
} // getServer
# if CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM > 0
# if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
/**
* @brief Create an instance of a L2CAP server.
* @return A pointer to the instance of the L2CAP server.
@@ -175,15 +161,15 @@ NimBLEL2CAPServer* NimBLEDevice::createL2CAPServer() {
NimBLEL2CAPServer* NimBLEDevice::getL2CAPServer() {
return m_pL2CAPServer;
} // getL2CAPServer
# endif
# endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# endif // #if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
# endif // #if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
/* -------------------------------------------------------------------------- */
/* ADVERTISING FUNCTIONS */
/* -------------------------------------------------------------------------- */
# if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# if MYNEWT_VAL(BLE_EXT_ADV)
/**
* @brief Get the instance of the extended advertising object.
* @return A pointer to the extended advertising object.
@@ -217,7 +203,7 @@ bool NimBLEDevice::stopAdvertising(uint8_t instId) {
} // stopAdvertising
# endif
# if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
# if !MYNEWT_VAL(BLE_EXT_ADV) || defined(_DOXYGEN_)
/**
* @brief Get the instance of the advertising object.
* @return A pointer to the advertising object.
@@ -246,7 +232,7 @@ bool NimBLEDevice::startAdvertising(uint32_t duration) {
bool NimBLEDevice::stopAdvertising() {
return getAdvertising()->stop();
} // stopAdvertising
# endif // #if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
# endif // #if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
/* -------------------------------------------------------------------------- */
/* SCAN FUNCTIONS */
@@ -257,7 +243,7 @@ bool NimBLEDevice::stopAdvertising() {
* @return The scanning object reference. This is a singleton object. The caller should not
* try and release/delete it.
*/
# if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
# if MYNEWT_VAL(BLE_ROLE_OBSERVER)
NimBLEScan* NimBLEDevice::getScan() {
if (m_pScan == nullptr) {
m_pScan = new NimBLEScan();
@@ -335,13 +321,13 @@ void NimBLEDevice::setScanDuplicateCacheResetTime(uint16_t time) {
}
# endif // CONFIG_BTDM_BLE_SCAN_DUPL || CONFIG_BT_LE_SCAN_DUPL
# endif // ESP_PLATFORM
# endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
# endif // MYNEWT_VAL(BLE_ROLE_OBSERVER)
/* -------------------------------------------------------------------------- */
/* CLIENT FUNCTIONS */
/* -------------------------------------------------------------------------- */
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
/**
* @brief Creates a new client object, each client can connect to 1 peripheral device.
* @return A pointer to the new client object, or nullptr on error.
@@ -364,7 +350,7 @@ NimBLEClient* NimBLEDevice::createClient(const NimBLEAddress& peerAddress) {
}
}
NIMBLE_LOGE(LOG_TAG, "Unable to create client; already at max: %d", NIMBLE_MAX_CONNECTIONS);
NIMBLE_LOGE(LOG_TAG, "Unable to create client; already at max: %d", MYNEWT_VAL(BLE_MAX_CONNECTIONS));
return nullptr;
} // createClient
@@ -476,7 +462,7 @@ std::vector<NimBLEClient*> NimBLEDevice::getConnectedClients() {
return clients;
} // getConnectedClients
# endif // #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# endif // MYNEWT_VAL(BLE_ROLE_CENTRAL)
/* -------------------------------------------------------------------------- */
/* TRANSMIT POWER */
@@ -627,7 +613,7 @@ uint16_t NimBLEDevice::getMTU() {
/* BOND MANAGEMENT */
/* -------------------------------------------------------------------------- */
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) || defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# if MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
/**
* @brief Gets the number of bonded peers stored
*/
@@ -864,13 +850,13 @@ void NimBLEDevice::onSync(void) {
m_synced = true;
if (m_initialized) {
# if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
# if MYNEWT_VAL(BLE_ROLE_OBSERVER)
if (m_pScan != nullptr) {
m_pScan->onHostSync();
}
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
if (m_bleAdvertising != nullptr) {
m_bleAdvertising->onHostSync();
}
@@ -921,17 +907,19 @@ bool NimBLEDevice::init(const std::string& deviceName) {
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
# if defined(CONFIG_IDF_TARGET_ESP32)
bt_cfg.mode = ESP_BT_MODE_BLE;
bt_cfg.ble_max_conn = CONFIG_BT_NIMBLE_MAX_CONNECTIONS;
bt_cfg.ble_max_conn = MYNEWT_VAL(BLE_MAX_CONNECTIONS);
# elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3)
bt_cfg.ble_max_act = CONFIG_BT_NIMBLE_MAX_CONNECTIONS;
bt_cfg.ble_max_act = MYNEWT_VAL(BLE_MAX_CONNECTIONS) + MYNEWT_VAL(BLE_ROLE_BROADCASTER) + MYNEWT_VAL(BLE_ROLE_OBSERVER);
# else
bt_cfg.nimble_max_connections = CONFIG_BT_NIMBLE_MAX_CONNECTIONS;
bt_cfg.nimble_max_connections = MYNEWT_VAL(BLE_MAX_CONNECTIONS);
# endif
# if CONFIG_BTDM_BLE_SCAN_DUPL
bt_cfg.normal_adv_size = m_scanDuplicateSize;
bt_cfg.scan_duplicate_type = m_scanFilterMode;
bt_cfg.normal_adv_size = m_scanDuplicateSize;
bt_cfg.scan_duplicate_type = m_scanFilterMode;
# if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
bt_cfg.dup_list_refresh_period = m_scanDuplicateResetTime;
# endif
# elif CONFIG_BT_LE_SCAN_DUPL
bt_cfg.ble_ll_rsp_dup_list_count = m_scanDuplicateSize;
bt_cfg.ble_ll_adv_dup_list_count = m_scanDuplicateSize;
@@ -989,7 +977,7 @@ bool NimBLEDevice::init(const std::string& deviceName) {
ble_hs_cfg.sm_io_cap = BLE_HS_IO_NO_INPUT_OUTPUT;
ble_hs_cfg.sm_bonding = 0;
ble_hs_cfg.sm_mitm = 0;
ble_hs_cfg.sm_sc = 1;
ble_hs_cfg.sm_sc = 0;
ble_hs_cfg.sm_our_key_dist = BLE_SM_PAIR_KEY_DIST_ENC;
ble_hs_cfg.sm_their_key_dist = BLE_SM_PAIR_KEY_DIST_ENC;
# if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
@@ -1038,12 +1026,12 @@ bool NimBLEDevice::deinit(bool clearAll) {
}
if (clearAll) {
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
if (NimBLEDevice::m_pServer != nullptr) {
delete NimBLEDevice::m_pServer;
NimBLEDevice::m_pServer = nullptr;
}
# if CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM > 0
# if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
if (NimBLEDevice::m_pL2CAPServer != nullptr) {
delete NimBLEDevice::m_pL2CAPServer;
NimBLEDevice::m_pL2CAPServer = nullptr;
@@ -1051,21 +1039,21 @@ bool NimBLEDevice::deinit(bool clearAll) {
# endif
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
if (NimBLEDevice::m_bleAdvertising != nullptr) {
delete NimBLEDevice::m_bleAdvertising;
NimBLEDevice::m_bleAdvertising = nullptr;
}
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
# if MYNEWT_VAL(BLE_ROLE_OBSERVER)
if (NimBLEDevice::m_pScan != nullptr) {
delete NimBLEDevice::m_pScan;
NimBLEDevice::m_pScan = nullptr;
}
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
for (auto clt : m_pClients) {
deleteClient(clt);
}
@@ -1266,7 +1254,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)
# if MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
/**
* @brief Inject the provided passkey into the Security Manager.
* @param [in] peerInfo Connection information for the peer.
@@ -1291,7 +1279,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
# endif // MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
/* -------------------------------------------------------------------------- */
/* UTILITIES */
@@ -1302,12 +1290,13 @@ bool NimBLEDevice::injectConfirmPasskey(const NimBLEConnInfo& peerInfo, bool acc
* @param [in] deviceName The name to set.
*/
bool NimBLEDevice::setDeviceName(const std::string& deviceName) {
#if !defined(MYNEWT_VAL_BLE_GATTS) || MYNEWT_VAL(BLE_GATTS) > 0
int rc = ble_svc_gap_device_name_set(deviceName.c_str());
if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "Device name not set - too long");
return false;
}
#endif
return true;
} // setDeviceName
@@ -1336,7 +1325,7 @@ std::string NimBLEDevice::toString() {
return getAddress().toString();
} // toString
# if CONFIG_NIMBLE_CPP_DEBUG_ASSERT_ENABLED || __DOXYGEN__
# if MYNEWT_VAL(NIMBLE_CPP_DEBUG_ASSERT_ENABLED) || __DOXYGEN__
/**
* @brief Debug assert - weak function.
* @param [in] file The file where the assert occurred.
@@ -1347,7 +1336,7 @@ void nimble_cpp_assert(const char* file, unsigned line) {
ble_npl_time_delay(10);
abort();
}
# endif // CONFIG_NIMBLE_CPP_DEBUG_ASSERT_ENABLED
# endif // MYNEWT_VAL(NIMBLE_CPP_DEBUG_ASSERT_ENABLED)
void NimBLEDevice::setDeviceCallbacks(NimBLEDeviceCallbacks* cb) {
m_pDeviceCallbacks = cb ? cb : &defaultDeviceCallbacks;
@@ -1358,4 +1347,4 @@ int NimBLEDeviceCallbacks::onStoreStatus(struct ble_store_status_event* event, v
return ble_store_util_status_rr(event, arg);
}
#endif // CONFIG_BT_ENABLED
#endif // CONFIG_BT_NIMBLE_ENABLED

View File

@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_DEVICE_H_
#define NIMBLE_CPP_DEVICE_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED
# ifdef ESP_PLATFORM
# ifndef CONFIG_IDF_TARGET_ESP32P4
# include <esp_bt.h>
@@ -40,31 +40,31 @@
# include <string>
# include <vector>
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
# include <array>
class NimBLEClient;
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
# if MYNEWT_VAL(BLE_ROLE_OBSERVER)
class NimBLEScan;
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# if MYNEWT_VAL(BLE_EXT_ADV)
class NimBLEExtAdvertising;
# else
class NimBLEAdvertising;
# endif
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
class NimBLEServer;
# if CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM > 0
# if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
class NimBLEL2CAPServer;
# endif
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) || defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_ROLE_CENTRAL)
class NimBLEConnInfo;
# endif
@@ -106,12 +106,6 @@ class NimBLEDeviceCallbacks;
# define BLEL2CAPChannel NimBLEL2CAPChannel
# define BLEL2CAPChannelCallbacks NimBLEL2CAPChannelCallbacks
# ifdef CONFIG_BT_NIMBLE_MAX_CONNECTIONS
# define NIMBLE_MAX_CONNECTIONS CONFIG_BT_NIMBLE_MAX_CONNECTIONS
# else
# define NIMBLE_MAX_CONNECTIONS CONFIG_NIMBLE_MAX_CONNECTIONS
# endif
enum class NimBLETxPowerType { All = 0, Advertise = 1, Scan = 2, Connection = 3 };
typedef int (*gap_event_handler)(ble_gap_event* event, void* arg);
@@ -164,39 +158,39 @@ class NimBLEDevice {
# endif
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
# if MYNEWT_VAL(BLE_ROLE_OBSERVER)
static NimBLEScan* getScan();
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
static NimBLEServer* createServer();
static NimBLEServer* getServer();
# if CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM > 0
# if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
static NimBLEL2CAPServer* createL2CAPServer();
static NimBLEL2CAPServer* getL2CAPServer();
# endif
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) || defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_ROLE_CENTRAL)
static bool injectConfirmPasskey(const NimBLEConnInfo& peerInfo, bool accept);
static bool injectPassKey(const NimBLEConnInfo& peerInfo, uint32_t pin);
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# if MYNEWT_VAL(BLE_EXT_ADV)
static NimBLEExtAdvertising* getAdvertising();
static bool startAdvertising(uint8_t instId, int duration = 0, int maxEvents = 0);
static bool stopAdvertising(uint8_t instId);
static bool stopAdvertising();
# endif
# if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
# if !MYNEWT_VAL(BLE_EXT_ADV) || defined(_DOXYGEN_)
static NimBLEAdvertising* getAdvertising();
static bool startAdvertising(uint32_t duration = 0);
static bool stopAdvertising();
# endif
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
static NimBLEClient* createClient();
static NimBLEClient* createClient(const NimBLEAddress& peerAddress);
static bool deleteClient(NimBLEClient* pClient);
@@ -207,7 +201,7 @@ class NimBLEDevice {
static std::vector<NimBLEClient*> getConnectedClients();
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) || defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# if MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
static bool deleteBond(const NimBLEAddress& address);
static int getNumBonds();
static bool isBonded(const NimBLEAddress& address);
@@ -225,27 +219,27 @@ class NimBLEDevice {
static NimBLEDeviceCallbacks* m_pDeviceCallbacks;
static NimBLEDeviceCallbacks defaultDeviceCallbacks;
# if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
# if MYNEWT_VAL(BLE_ROLE_OBSERVER)
static NimBLEScan* m_pScan;
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
static NimBLEServer* m_pServer;
# if CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM > 0
# if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
static NimBLEL2CAPServer* m_pL2CAPServer;
# endif
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# if MYNEWT_VAL(BLE_EXT_ADV)
static NimBLEExtAdvertising* m_bleAdvertising;
# else
static NimBLEAdvertising* m_bleAdvertising;
# endif
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
static std::array<NimBLEClient*, NIMBLE_MAX_CONNECTIONS> m_pClients;
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
static std::array<NimBLEClient*, MYNEWT_VAL(BLE_MAX_CONNECTIONS)> m_pClients;
# endif
# ifdef ESP_PLATFORM
@@ -256,62 +250,63 @@ class NimBLEDevice {
# endif
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
friend class NimBLEClient;
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
# if MYNEWT_VAL(BLE_ROLE_OBSERVER)
friend class NimBLEScan;
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
friend class NimBLEServer;
friend class NimBLECharacteristic;
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
friend class NimBLEAdvertising;
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_EXT_ADV)
friend class NimBLEExtAdvertising;
friend class NimBLEExtAdvertisement;
# endif
# endif
};
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
# include "NimBLEClient.h"
# include "NimBLERemoteService.h"
# include "NimBLERemoteCharacteristic.h"
# include "NimBLERemoteDescriptor.h"
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
# if MYNEWT_VAL(BLE_ROLE_OBSERVER)
# include "NimBLEScan.h"
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# include "NimBLEServer.h"
# include "NimBLEService.h"
# include "NimBLECharacteristic.h"
# include "NimBLEDescriptor.h"
# if CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM > 0
# if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
# include "NimBLEL2CAPServer.h"
# include "NimBLEL2CAPChannel.h"
# endif
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# if MYNEWT_VAL(BLE_EXT_ADV)
# include "NimBLEExtAdvertising.h"
# else
# include "NimBLEAdvertising.h"
# endif
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) || defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# if MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# include "NimBLEConnInfo.h"
# endif
# include "NimBLEAddress.h"
# include "NimBLEUtils.h"
/**
@@ -336,5 +331,5 @@ class NimBLEDeviceCallbacks {
virtual int onStoreStatus(struct ble_store_status_event* event, void* arg);
};
#endif // CONFIG_BT_ENABLED
#endif // CONFIG_BT_NIMBLE_ENABLED
#endif // NIMBLE_CPP_DEVICE_H_

View File

@@ -15,10 +15,9 @@
* limitations under the License.
*/
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
#include "NimBLEEddystoneTLM.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# include "NimBLEEddystoneTLM.h"
# include "NimBLEUUID.h"
# include "NimBLELog.h"
@@ -216,4 +215,4 @@ void NimBLEEddystoneTLM::setTime(uint32_t tmil) {
m_eddystoneData.tmil = tmil;
} // setTime
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER)

View File

@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_EDDYSTONETLM_H_
#define NIMBLE_CPP_EDDYSTONETLM_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER)
class NimBLEUUID;
@@ -66,5 +66,5 @@ class NimBLEEddystoneTLM {
}; // NimBLEEddystoneTLM
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER)
#endif // NIMBLE_CPP_EDDYSTONETLM_H_

View File

@@ -15,8 +15,8 @@
* limitations under the License.
*/
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && CONFIG_BT_NIMBLE_EXT_ADV
#include "NimBLEExtAdvertising.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && MYNEWT_VAL(BLE_EXT_ADV)
# if defined(CONFIG_NIMBLE_CPP_IDF)
# include "services/gap/ble_svc_gap.h"
@@ -24,7 +24,6 @@
# include "nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h"
# endif
# include "NimBLEExtAdvertising.h"
# include "NimBLEDevice.h"
# include "NimBLEServer.h"
# include "NimBLEUtils.h"
@@ -39,7 +38,7 @@ static const char* LOG_TAG = "NimBLEExtAdvertising";
NimBLEExtAdvertising::NimBLEExtAdvertising()
: m_deleteCallbacks{false},
m_pCallbacks{&defaultCallbacks},
m_advStatus(CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES + 1, false) {}
m_advStatus(MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES) + 1, false) {}
/**
* @brief Destructor: deletes callback instances if requested.
@@ -69,7 +68,7 @@ bool NimBLEExtAdvertising::setInstanceData(uint8_t instId, NimBLEExtAdvertisemen
adv.m_params.scan_req_notif = false;
}
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
NimBLEServer* pServer = NimBLEDevice::getServer();
if (pServer != nullptr) {
pServer->start(); // make sure the GATT server is ready before advertising
@@ -392,7 +391,7 @@ void NimBLEExtAdvertisement::setTxPower(int8_t dbm) {
* @param [in] enable True = connectable.
*/
void NimBLEExtAdvertisement::setConnectable(bool enable) {
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
m_params.connectable = enable;
# endif
} // setConnectable
@@ -532,7 +531,7 @@ void NimBLEExtAdvertisement::clearData() {
* @details This will completely replace any data that was previously set.
*/
bool NimBLEExtAdvertisement::setData(const uint8_t* data, size_t length) {
if (length > CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN) {
if (length > MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)) {
return false;
}
@@ -547,7 +546,7 @@ bool NimBLEExtAdvertisement::setData(const uint8_t* data, size_t length) {
* @return True if successful, false if the data is too large.
*/
bool NimBLEExtAdvertisement::addData(const uint8_t* data, size_t length) {
if (m_payload.size() + length > CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN) {
if (m_payload.size() + length > MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)) {
return false;
}
@@ -561,7 +560,7 @@ bool NimBLEExtAdvertisement::addData(const uint8_t* data, size_t length) {
* @return True if successful, false if the data is too large.
*/
bool NimBLEExtAdvertisement::addData(const std::string& data) {
if (m_payload.size() + data.length() > CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN) {
if (m_payload.size() + data.length() > MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)) {
return false;
}
@@ -617,6 +616,11 @@ 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;
@@ -653,6 +657,11 @@ 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;
@@ -671,6 +680,11 @@ 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;
@@ -711,7 +725,7 @@ bool NimBLEExtAdvertisement::addServiceUUID(const NimBLEUUID& serviceUUID) {
length += 2;
}
if (length + getDataSize() > CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN) {
if (length + getDataSize() > MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)) {
NIMBLE_LOGE(LOG_TAG, "Cannot add UUID, data length exceeded!");
return false;
}
@@ -918,9 +932,13 @@ 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;
uint8_t sDataLen = 2 + uuidBytes + length;
if (length + uuidBytes + 2 > 0xFF) {
NIMBLE_LOGE(LOG_TAG, "Service data too long!");
return false;
}
if (m_payload.size() + sDataLen > CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN) {
uint8_t sDataLen = 2 + uuidBytes + length;
if (m_payload.size() + sDataLen > MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)) {
return false;
}
@@ -1091,4 +1109,4 @@ std::string NimBLEExtAdvertisement::toString() const {
return str;
} // toString
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && CONFIG_BT_NIMBLE_EXT_ADV */
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && MYNEWT_VAL(BLE_EXT_ADV)

View File

@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_EXTADVERTISING_H_
#define NIMBLE_CPP_EXTADVERTISING_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && CONFIG_BT_NIMBLE_EXT_ADV
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && MYNEWT_VAL(BLE_EXT_ADV)
# if defined(CONFIG_NIMBLE_CPP_IDF)
# include "host/ble_gap.h"
@@ -159,5 +159,5 @@ class NimBLEExtAdvertisingCallbacks {
virtual void onScanRequest(NimBLEExtAdvertising* pAdv, uint8_t instId, NimBLEAddress addr);
}; // NimBLEExtAdvertisingCallbacks
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && CONFIG_BT_NIMBLE_EXT_ADV
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && MYNEWT_VAL(BLE_EXT_ADV)
#endif // NIMBLE_CPP_EXTADVERTISING_H_

View File

@@ -15,10 +15,9 @@
* limitations under the License.
*/
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLEHIDDevice.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# include "NimBLEHIDDevice.h"
# include "NimBLEServer.h"
# include "NimBLEService.h"
# include "NimBLE2904.h"
@@ -341,4 +340,4 @@ NimBLEService* NimBLEHIDDevice::getBatteryService() {
return m_batterySvc;
} // getBatteryService
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)

View File

@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_HIDDEVICE_H_
#define NIMBLE_CPP_HIDDEVICE_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# include <stdint.h>
# include <string>
@@ -85,5 +85,5 @@ class NimBLEHIDDevice {
NimBLECharacteristic* locateReportCharacteristicByIdAndType(uint8_t reportId, uint8_t reportType);
};
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#endif // NIMBLE_CPP_HIDDEVICE_H_

View File

@@ -1,21 +1,29 @@
//
// (C) Dr. Michael 'Mickey' Lauer <mickey@vanille-media.de>
//
#include "NimBLEL2CAPChannel.h"
#include "NimBLEClient.h"
#include "NimBLELog.h"
#include "NimBLEUtils.h"
#include "NimBLEL2CAPChannel.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
# include "NimBLEClient.h"
# include "NimBLELog.h"
# include "NimBLEUtils.h"
# if defined(CONFIG_NIMBLE_CPP_IDF)
# include "host/ble_gap.h"
# else
# include "nimble/nimble/host/include/host/ble_gap.h"
# endif
// L2CAP buffer block size
#define L2CAP_BUF_BLOCK_SIZE (250)
#define L2CAP_BUF_SIZE_MTUS_PER_CHANNEL (3)
# define L2CAP_BUF_BLOCK_SIZE (250)
# define L2CAP_BUF_SIZE_MTUS_PER_CHANNEL (3)
// Round-up integer division
#define CEIL_DIVIDE(a, b) (((a) + (b) - 1) / (b))
#define ROUND_DIVIDE(a, b) (((a) + (b) / 2) / (b))
# define CEIL_DIVIDE(a, b) (((a) + (b) - 1) / (b))
# define ROUND_DIVIDE(a, b) (((a) + (b) / 2) / (b))
// Retry
constexpr uint32_t RetryTimeout = 50;
constexpr int RetryCounter = 3;
constexpr int RetryCounter = 3;
NimBLEL2CAPChannel::NimBLEL2CAPChannel(uint16_t psm, uint16_t mtu, NimBLEL2CAPChannelCallbacks* callbacks)
: psm(psm), mtu(mtu), callbacks(callbacks) {
@@ -84,7 +92,7 @@ int NimBLEL2CAPChannel::writeFragment(std::vector<uint8_t>::const_iterator begin
m_pTaskData = &taskData;
NimBLEUtils::taskWait(taskData, BLE_NPL_TIME_FOREVER);
m_pTaskData = nullptr;
stalled = false;
stalled = false;
NIMBLE_LOGD(LOG_TAG, "L2CAP Channel unstalled!");
}
@@ -141,7 +149,7 @@ int NimBLEL2CAPChannel::writeFragment(std::vector<uint8_t>::const_iterator begin
return -BLE_HS_EREJECT;
}
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
NimBLEL2CAPChannel* NimBLEL2CAPChannel::connect(NimBLEClient* client,
uint16_t psm,
uint16_t mtu,
@@ -166,7 +174,7 @@ NimBLEL2CAPChannel* NimBLEL2CAPChannel::connect(NimBLEClient* cli
}
return channel;
}
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL
# endif // MYNEWT_VAL(BLE_ROLE_CENTRAL)
bool NimBLEL2CAPChannel::write(const std::vector<uint8_t>& bytes) {
if (!this->channel) {
@@ -302,3 +310,5 @@ int NimBLEL2CAPChannel::handleL2capEvent(struct ble_l2cap_event* event, void* ar
return returnValue;
}
#endif // #if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)

View File

@@ -1,11 +1,12 @@
//
// (C) Dr. Michael 'Mickey' Lauer <mickey@vanille-media.de>
//
#pragma once
#ifndef NIMBLEL2CAPCHANNEL_H
# define NIMBLEL2CAPCHANNEL_H
# include "nimconfig.h"
#ifndef NIMBLE_CPP_L2CAPCHANNEL_H_
#define NIMBLE_CPP_L2CAPCHANNEL_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
# include "inttypes.h"
# if defined(CONFIG_NIMBLE_CPP_IDF)
@@ -85,7 +86,7 @@ class NimBLEL2CAPChannel {
// Runtime handling
std::atomic<bool> stalled{false};
NimBLETaskData* m_pTaskData{nullptr};
NimBLETaskData* m_pTaskData{nullptr};
// Allocate / deallocate NimBLE memory pool
bool setupMemPool();
@@ -121,4 +122,5 @@ class NimBLEL2CAPChannelCallbacks {
virtual void onDisconnect(NimBLEL2CAPChannel* channel) {};
};
#endif
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
#endif // NIMBLE_CPP_L2CAPCHANNEL_H_

View File

@@ -1,10 +1,13 @@
//
// (C) Dr. Michael 'Mickey' Lauer <mickey@vanille-media.de>
//
#include "NimBLEL2CAPServer.h"
#include "NimBLEL2CAPChannel.h"
#include "NimBLEDevice.h"
#include "NimBLELog.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
# include "NimBLEL2CAPChannel.h"
# include "NimBLEDevice.h"
# include "NimBLELog.h"
static const char* LOG_TAG = "NimBLEL2CAPServer";
@@ -33,3 +36,5 @@ NimBLEL2CAPChannel* NimBLEL2CAPServer::createService(const uint16_t
this->services.push_back(service);
return service;
}
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)

View File

@@ -1,12 +1,14 @@
//
// (C) Dr. Michael 'Mickey' Lauer <mickey@vanille-media.de>
//
#ifndef NIMBLEL2CAPSERVER_H
#define NIMBLEL2CAPSERVER_H
#pragma once
#include "inttypes.h"
#include <vector>
#ifndef NIMBLE_CPP_L2CAPSERVER_H_
#define NIMBLE_CPP_L2CAPSERVER_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
# include "inttypes.h"
# include <vector>
class NimBLEL2CAPChannel;
class NimBLEL2CAPChannelCallbacks;
@@ -35,4 +37,5 @@ class NimBLEL2CAPServer {
friend class NimBLEDevice;
};
#endif
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
#endif // NIMBLE_CPP_L2CAPSERVER_H_

View File

@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_LOCAL_ATTRIBUTE_H_
#define NIMBLE_CPP_LOCAL_ATTRIBUTE_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# include "NimBLEAttribute.h"
@@ -54,5 +54,5 @@ class NimBLELocalAttribute : public NimBLEAttribute {
uint8_t m_removed{0};
};
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#endif // NIMBLE_CPP_LOCAL_ATTRIBUTE_H_

View File

@@ -18,8 +18,8 @@
#ifndef NIMBLE_LOCAL_VALUE_ATTRIBUTE_H_
#define NIMBLE_LOCAL_VALUE_ATTRIBUTE_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# if defined(CONFIG_NIMBLE_CPP_IDF)
# include "host/ble_hs.h"
@@ -101,7 +101,7 @@ class NimBLELocalValueAttribute : public NimBLELocalAttribute, public NimBLEValu
NimBLELocalValueAttribute(const NimBLEUUID& uuid,
uint16_t handle,
uint16_t maxLen,
uint16_t initLen = CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH)
uint16_t initLen = MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_INIT_LENGTH))
: NimBLELocalAttribute(uuid, handle), NimBLEValueAttribute(maxLen, initLen) {}
/**
* @brief Destroy the NimBLELocalValueAttribute object.
@@ -140,5 +140,5 @@ class NimBLELocalValueAttribute : public NimBLELocalAttribute, public NimBLEValu
uint16_t m_properties{0};
};
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#endif // NIMBLE_LOCAL_VALUE_ATTRIBUTE_H_

View File

@@ -18,15 +18,24 @@
#ifndef NIMBLE_CPP_LOG_H_
#define NIMBLE_CPP_LOG_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
#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
@@ -120,13 +129,13 @@
# define NIMBLE_CPP_LOG_PRINT(level, tag, format, ...) \
do { \
if (CONFIG_NIMBLE_CPP_LOG_LEVEL >= level) NIMBLE_CPP_LOG_LEVEL_LOCAL(level, tag, format, ##__VA_ARGS__); \
if (MYNEWT_VAL(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 (CONFIG_NIMBLE_CPP_LOG_LEVEL >= level) ESP_LOG_LEVEL_LOCAL(level, tag, format, ##__VA_ARGS__); \
if (MYNEWT_VAL(NIMBLE_CPP_LOG_LEVEL) >= level) ESP_LOG_LEVEL_LOCAL(level, tag, format, ##__VA_ARGS__); \
} while (0)
# endif /* CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR */
@@ -137,35 +146,27 @@
# define NIMBLE_LOGE(tag, format, ...) NIMBLE_CPP_LOG_PRINT(ESP_LOG_ERROR, tag, format, ##__VA_ARGS__)
# else
# include "nimble/porting/nimble/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 CONFIG_NIMBLE_CPP_LOG_LEVEL >= 4
# if MYNEWT_VAL(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 CONFIG_NIMBLE_CPP_LOG_LEVEL >= 3
# if MYNEWT_VAL(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 CONFIG_NIMBLE_CPP_LOG_LEVEL >= 2
# if MYNEWT_VAL(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 CONFIG_NIMBLE_CPP_LOG_LEVEL >= 1
# if MYNEWT_VAL(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
@@ -179,5 +180,5 @@
# define NIMBLE_LOGE_IF(cond, tag, format, ...) { if (cond) { NIMBLE_LOGE(tag, format, ##__VA_ARGS__); }}
# define NIMBLE_LOGE_RC(rc, tag, format, ...) { if (rc) { NIMBLE_LOGE(tag, format "; rc=%d %s", ##__VA_ARGS__, rc, NimBLEUtils::returnCodeToString(rc)); }}
#endif /* CONFIG_BT_ENABLED */
#endif /* CONFIG_BT_NIMBLE_ENABLED */
#endif /* NIMBLE_CPP_LOG_H_ */

View File

@@ -15,10 +15,9 @@
* limitations under the License.
*/
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "NimBLERemoteCharacteristic.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
# include "NimBLERemoteCharacteristic.h"
# include "NimBLERemoteDescriptor.h"
# include "NimBLERemoteService.h"
# include "NimBLEClient.h"
@@ -388,4 +387,4 @@ NimBLEClient* NimBLERemoteCharacteristic::getClient() const {
return getRemoteService()->getClient();
} // getClient
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)

View File

@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_REMOTE_CHARACTERISTIC_H_
#define NIMBLE_CPP_REMOTE_CHARACTERISTIC_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
# include "NimBLERemoteValueAttribute.h"
# include <vector>
@@ -79,5 +79,5 @@ class NimBLERemoteCharacteristic : public NimBLERemoteValueAttribute {
}; // NimBLERemoteCharacteristic
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
#endif /* CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL) */
#endif /* NIMBLE_CPP_REMOTE_CHARACTERISTIC_H_ */

View File

@@ -15,10 +15,9 @@
* limitations under the License.
*/
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "NimBLERemoteDescriptor.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
# include "NimBLERemoteDescriptor.h"
# include "NimBLERemoteCharacteristic.h"
/**
@@ -57,4 +56,4 @@ NimBLEClient* NimBLERemoteDescriptor::getClient() const {
return m_pRemoteCharacteristic->getClient();
}
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)

View File

@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_REMOTE_DESCRIPTOR_H_
#define NIMBLE_CPP_REMOTE_DESCRIPTOR_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
# include "NimBLERemoteValueAttribute.h"
@@ -44,5 +44,5 @@ class NimBLERemoteDescriptor : public NimBLERemoteValueAttribute {
const NimBLERemoteCharacteristic* m_pRemoteCharacteristic;
};
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
#endif /* NIMBLE_CPP_REMOTE_DESCRIPTOR_H_ */
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
#endif // NIMBLE_CPP_REMOTE_DESCRIPTOR_H_

View File

@@ -15,10 +15,9 @@
* limitations under the License.
*/
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "NimBLERemoteService.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
# include "NimBLERemoteService.h"
# include "NimBLERemoteCharacteristic.h"
# include "NimBLEClient.h"
# include "NimBLEAttValue.h"
@@ -303,4 +302,4 @@ std::string NimBLERemoteService::toString() const {
return res;
} // toString
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)

View File

@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_REMOTE_SERVICE_H_
#define NIMBLE_CPP_REMOTE_SERVICE_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
# include "NimBLEAttribute.h"
# include <vector>
@@ -64,5 +64,5 @@ class NimBLERemoteService : public NimBLEAttribute {
uint16_t m_endHandle{0};
}; // NimBLERemoteService
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
#endif /* NIMBLE_CPP_REMOTE_SERVICE_H_*/
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
#endif // NIMBLE_CPP_REMOTE_SERVICE_H_

View File

@@ -15,10 +15,9 @@
* limitations under the License.
*/
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "NimBLERemoteValueAttribute.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
# include "NimBLERemoteValueAttribute.h"
# include "NimBLEClient.h"
# include "NimBLEUtils.h"
# include "NimBLELog.h"
@@ -218,4 +217,4 @@ int NimBLERemoteValueAttribute::onReadCB(uint16_t conn_handle, const ble_gatt_er
return rc;
} // onReadCB
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)

View File

@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_REMOTE_VALUE_ATTRIBUTE_H_
#define NIMBLE_CPP_REMOTE_VALUE_ATTRIBUTE_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
# if defined(CONFIG_NIMBLE_CPP_IDF)
# include <host/ble_gatt.h>
@@ -109,13 +109,34 @@ 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.
* @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.
*/
template <typename T>
# ifdef _DOXYGEN_
bool
# else
typename std::enable_if<Has_data_size<T>::value, bool>::type
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
# endif
writeValue(const T& v, bool response = false) const {
return writeValue(reinterpret_cast<const uint8_t*>(v.data()), v.size(), response);
@@ -131,7 +152,11 @@ 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) {
return writeValue(reinterpret_cast<const uint8_t*>(v.data()), v.size(), response);
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);
}
} else if constexpr (Has_c_str_length<T>::value) {
return writeValue(reinterpret_cast<const uint8_t*>(v.c_str()), v.length(), response);
} else {
@@ -170,5 +195,5 @@ class NimBLERemoteValueAttribute : public NimBLEValueAttribute, public NimBLEAtt
static int onWriteCB(uint16_t conn_handle, const ble_gatt_error* error, ble_gatt_attr* attr, void* arg);
};
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
#endif // NIMBLE_CPP_REMOTE_VALUE_ATTRIBUTE_H_

View File

@@ -15,10 +15,9 @@
* limitations under the License.
*/
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
#include "NimBLEScan.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_OBSERVER)
# include "NimBLEScan.h"
# include "NimBLEDevice.h"
# include "NimBLELog.h"
@@ -42,7 +41,9 @@ NimBLEScan::NimBLEScan()
* @brief Scan destructor, release any allocated resources.
*/
NimBLEScan::~NimBLEScan() {
clearResults();
for (const auto& dev : m_scanResults.m_deviceVec) {
delete dev;
}
}
/**
@@ -62,7 +63,7 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
return 0;
}
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_EXT_ADV)
const auto& disc = event->ext_disc;
const bool isLegacyAdv = disc.props & BLE_HCI_ADV_LEGACY_MASK;
const auto event_type = isLegacyAdv ? disc.legacy_event_type : disc.props;
@@ -73,7 +74,7 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
# endif
NimBLEAddress advertisedAddress(disc.addr);
# ifdef CONFIG_BT_NIMBLE_ROLE_CENTRAL
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
// stop processing if already connected
NimBLEClient* pClient = NimBLEDevice::getClientByPeerAddress(advertisedAddress);
if (pClient != nullptr && pClient->isConnected()) {
@@ -85,7 +86,7 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
// If we've seen this device before get a pointer to it from the vector
for (const auto& dev : pScan->m_scanResults.m_deviceVec) {
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_EXT_ADV)
// Same address but different set ID should create a new advertised device.
if (dev->getAddress() == advertisedAddress && dev->getSetId() == disc.sid)
# else
@@ -116,13 +117,22 @@ 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 && 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) {
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 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);
@@ -271,7 +281,7 @@ bool NimBLEScan::isScanning() {
return ble_gap_disc_active();
}
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_EXT_ADV)
/**
* @brief Set the PHYs to scan.
* @param [in] phyMask The PHYs to scan, a bit mask of:
@@ -323,7 +333,7 @@ bool NimBLEScan::start(uint32_t duration, bool isContinue, bool restart) {
// If scanning is already active, call the functions anyway as the parameters can be changed.
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_EXT_ADV)
ble_gap_ext_disc_params scan_params;
scan_params.passive = m_scanParams.passive;
scan_params.itvl = m_scanParams.itvl;
@@ -488,7 +498,7 @@ void NimBLEScan::clearResults() {
* @brief Dump the scan results to the log.
*/
void NimBLEScanResults::dump() const {
# if CONFIG_NIMBLE_CPP_LOG_LEVEL >= 3
# if MYNEWT_VAL(NIMBLE_CPP_LOG_LEVEL) >= 3
for (const auto& dev : m_deviceVec) {
NIMBLE_LOGI(LOG_TAG, "- %s", dev->toString().c_str());
}
@@ -559,4 +569,4 @@ void NimBLEScanCallbacks::onScanEnd(const NimBLEScanResults& results, int reason
NIMBLE_LOGD(CB_TAG, "Scan ended; reason %d, num results: %d", reason, results.getCount());
}
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_OBSERVER */
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_OBSERVER)

View File

@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_SCAN_H_
#define NIMBLE_CPP_SCAN_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_OBSERVER)
# include "NimBLEAdvertisedDevice.h"
# include "NimBLEUtils.h"
@@ -83,7 +83,7 @@ class NimBLEScan {
void erase(const NimBLEAddress& address);
void erase(const NimBLEAdvertisedDevice* device);
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_EXT_ADV)
enum Phy { SCAN_1M = 0x01, SCAN_CODED = 0x02, SCAN_ALL = 0x03 };
void setPhy(Phy phyMask);
void setPeriod(uint32_t periodMs);
@@ -103,7 +103,7 @@ class NimBLEScan {
NimBLETaskData* m_pTaskData;
uint8_t m_maxResults;
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_EXT_ADV)
uint8_t m_phy{SCAN_ALL};
uint16_t m_period{0};
# endif
@@ -136,5 +136,5 @@ class NimBLEScanCallbacks {
virtual void onScanEnd(const NimBLEScanResults& scanResults, int reason);
};
#endif // CONFIG_BT_ENABLED CONFIG_BT_NIMBLE_ROLE_OBSERVER
#endif // CONFIG_BT_NIMBLE_ENABLED MYNEWT_VAL(BLE_ROLE_OBSERVER)
#endif // NIMBLE_CPP_SCAN_H_

View File

@@ -15,14 +15,13 @@
* limitations under the License.
*/
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLEServer.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# include "NimBLEServer.h"
# include "NimBLEDevice.h"
# include "NimBLELog.h"
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
# include "NimBLEClient.h"
# endif
@@ -50,7 +49,7 @@ NimBLEServer::NimBLEServer()
: m_gattsStarted{false},
m_svcChanged{false},
m_deleteCallbacks{false},
# if !CONFIG_BT_NIMBLE_EXT_ADV
# if !MYNEWT_VAL(BLE_EXT_ADV)
m_advertiseOnDisconnect{false},
# endif
m_pServerCallbacks{&defaultCallbacks},
@@ -70,7 +69,7 @@ NimBLEServer::~NimBLEServer() {
delete m_pServerCallbacks;
}
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
if (m_pClient != nullptr) {
delete m_pClient;
}
@@ -144,17 +143,32 @@ NimBLEService* NimBLEServer::getServiceByHandle(uint16_t handle) const {
return nullptr;
}
# if CONFIG_BT_NIMBLE_EXT_ADV
/**
* @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 pinter to an advertising object.
* @return A pointer to an advertising object.
*/
NimBLEExtAdvertising* NimBLEServer::getAdvertising() const {
return NimBLEDevice::getAdvertising();
} // getAdvertising
# endif
# if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
# if (!MYNEWT_VAL(BLE_EXT_ADV) && MYNEWT_VAL(BLE_ROLE_BROADCASTER)) || defined(_DOXYGEN_)
/**
* @brief Retrieve the advertising object that can be used to advertise the existence of the server.
* @return A pointer to an advertising object.
@@ -190,7 +204,7 @@ void NimBLEServer::start() {
return;
}
# if CONFIG_NIMBLE_CPP_LOG_LEVEL >= 4
# if MYNEWT_VAL(NIMBLE_CPP_LOG_LEVEL) >= 4
ble_gatts_show_local();
# endif
@@ -251,7 +265,7 @@ bool NimBLEServer::disconnect(const NimBLEConnInfo& connInfo, uint8_t reason) co
return disconnect(connInfo.getConnHandle(), reason);
} // disconnect
# if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
# if !MYNEWT_VAL(BLE_EXT_ADV) || defined(_DOXYGEN_)
/**
* @brief Set the server to automatically start advertising when a client disconnects.
* @param [in] enable true == advertise, false == don't advertise.
@@ -306,7 +320,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(m_connectedPeers[count]);
return getPeerInfoByHandle(peer);
}
count++;
}
@@ -355,9 +369,14 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
switch (event->type) {
case BLE_GAP_EVENT_CONNECT: {
if (event->connect.status != 0) {
NIMBLE_LOGE(LOG_TAG, "Connection failed");
# if !CONFIG_BT_NIMBLE_EXT_ADV
rc = event->connect.status;
if (rc == BLE_ERR_UNSUPP_REM_FEATURE) {
rc = 0; // Workaround: Ignore unsupported remote feature error as it is not a real error.
}
if (rc != 0) {
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
} else {
@@ -401,7 +420,7 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
}
}
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# if MYNEWT_VAL(BLE_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;
@@ -414,7 +433,7 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
peerInfo.m_desc = event->disconnect.conn;
pServer->m_pServerCallbacks->onDisconnect(pServer, peerInfo, event->disconnect.reason);
# if !CONFIG_BT_NIMBLE_EXT_ADV
# if !MYNEWT_VAL(BLE_EXT_ADV)
if (pServer->m_advertiseOnDisconnect) {
pServer->startAdvertising();
}
@@ -423,33 +442,21 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
} // BLE_GAP_EVENT_DISCONNECT
case BLE_GAP_EVENT_SUBSCRIBE: {
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));
}
}
rc = ble_gap_conn_find(event->subscribe.conn_handle, &peerInfo.m_desc);
if (rc != 0) {
break;
}
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
@@ -463,18 +470,14 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
} // BLE_GAP_EVENT_MTU
case BLE_GAP_EVENT_NOTIFY_TX: {
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;
}
}
rc = ble_gap_conn_find(event->notify_tx.conn_handle, &peerInfo.m_desc);
if (rc != 0) {
break;
}
auto pChar = pServer->getCharacteristicByHandle(event->notify_tx.attr_handle);
if (pChar == nullptr) {
return 0;
break;
}
if (event->notify_tx.indication) {
@@ -484,14 +487,24 @@ 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 CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_EXT_ADV) && MYNEWT_VAL(BLE_ROLE_BROADCASTER)
case BLE_GAP_EVENT_SCAN_REQ_RCVD:
return NimBLEExtAdvertising::handleGapEvent(event, arg);
# else
# elif MYNEWT_VAL(BLE_ROLE_BROADCASTER)
return NimBLEAdvertising::handleGapEvent(event, arg);
# endif
} // BLE_GAP_EVENT_ADV_COMPLETE | BLE_GAP_EVENT_SCAN_REQ_RCVD
@@ -531,6 +544,18 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
}
pServer->m_pServerCallbacks->onAuthenticationComplete(peerInfo);
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
if (pServer->m_pClient && pServer->m_pClient->m_connHandle == event->enc_change.conn_handle) {
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
@@ -726,7 +751,7 @@ void NimBLEServer::removeService(NimBLEService* service, bool deleteSvc) {
service->setRemoved(deleteSvc ? NIMBLE_ATT_REMOVE_DELETE : NIMBLE_ATT_REMOVE_HIDE);
serviceChanged();
# if !CONFIG_BT_NIMBLE_EXT_ADV
# if !MYNEWT_VAL(BLE_EXT_ADV) && MYNEWT_VAL(BLE_ROLE_BROADCASTER)
NimBLEDevice::getAdvertising()->removeServiceUUID(service->getUUID());
# endif
} // removeService
@@ -763,7 +788,9 @@ void NimBLEServer::resetGATT() {
return;
}
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
NimBLEDevice::stopAdvertising();
# endif
ble_gatts_reset();
ble_svc_gap_init();
ble_svc_gatt_init();
@@ -830,7 +857,7 @@ bool NimBLEServer::getPhy(uint16_t connHandle, uint8_t* txPhy, uint8_t* rxPhy) {
return rc == 0;
} // getPhy
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_EXT_ADV)
/**
* @brief Start advertising.
* @param [in] instId The extended advertisement instance ID to start.
@@ -855,7 +882,7 @@ bool NimBLEServer::stopAdvertising(uint8_t instId) const {
# endif
# if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
# if (!MYNEWT_VAL(BLE_EXT_ADV) && MYNEWT_VAL(BLE_ROLE_BROADCASTER)) || defined(_DOXYGEN_)
/**
* @brief Start advertising.
* @param [in] duration The duration in milliseconds to advertise for, default = forever.
@@ -932,7 +959,7 @@ void NimBLEServer::setDataLen(uint16_t connHandle, uint16_t octets) const {
# endif
} // setDataLen
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
/**
* @brief Create a client instance from the connection handle.
* @param [in] connHandle The connection handle to create a client instance from.
@@ -1019,4 +1046,4 @@ void NimBLEServerCallbacks::onPhyUpdate(NimBLEConnInfo& connInfo, uint8_t txPhy,
NIMBLE_LOGD("NimBLEServerCallbacks", "onPhyUpdate: default, txPhy: %d, rxPhy: %d", txPhy, rxPhy);
} // onPhyUpdate
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)

View File

@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_SERVER_H_
#define NIMBLE_CPP_SERVER_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# if defined(CONFIG_NIMBLE_CPP_IDF)
# include "host/ble_gap.h"
@@ -45,12 +45,14 @@ class NimBLEConnInfo;
class NimBLEAddress;
class NimBLEService;
class NimBLECharacteristic;
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# if MYNEWT_VAL(BLE_EXT_ADV)
class NimBLEExtAdvertising;
# else
# else
class NimBLEAdvertising;
# endif
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
class NimBLEClient;
# endif
@@ -70,6 +72,7 @@ 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;
@@ -82,56 +85,58 @@ class NimBLEServer {
bool updatePhy(uint16_t connHandle, uint8_t txPhysMask, uint8_t rxPhysMask, uint16_t phyOptions);
bool getPhy(uint16_t connHandle, uint8_t* txPhy, uint8_t* rxPhy);
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
NimBLEClient* getClient(uint16_t connHandle);
NimBLEClient* getClient(const NimBLEConnInfo& connInfo);
void deleteClient();
# endif
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# if MYNEWT_VAL(BLE_EXT_ADV)
NimBLEExtAdvertising* getAdvertising() const;
bool startAdvertising(uint8_t instanceId, int duration = 0, int maxEvents = 0) const;
bool stopAdvertising(uint8_t instanceId) const;
# endif
# endif
# if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
# if !MYNEWT_VAL(BLE_EXT_ADV) || defined(_DOXYGEN_)
NimBLEAdvertising* getAdvertising() const;
bool startAdvertising(uint32_t duration = 0) const;
bool stopAdvertising() const;
# endif
# endif
private:
friend class NimBLEDevice;
friend class NimBLEService;
friend class NimBLECharacteristic;
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# if MYNEWT_VAL(BLE_EXT_ADV)
friend class NimBLEExtAdvertising;
# else
# else
friend class NimBLEAdvertising;
# endif
# endif
NimBLEServer();
~NimBLEServer();
bool m_gattsStarted : 1;
bool m_svcChanged : 1;
bool m_deleteCallbacks : 1;
# if !CONFIG_BT_NIMBLE_EXT_ADV
bool m_advertiseOnDisconnect : 1;
# endif
NimBLEServerCallbacks* m_pServerCallbacks;
std::vector<NimBLEService*> m_svcVec;
std::array<uint16_t, CONFIG_BT_NIMBLE_MAX_CONNECTIONS> m_connectedPeers;
# if defined(CONFIG_BT_NIMBLE_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();
bool m_gattsStarted : 1;
bool m_svcChanged : 1;
bool m_deleteCallbacks : 1;
# if !MYNEWT_VAL(BLE_EXT_ADV)
bool m_advertiseOnDisconnect : 1;
# endif
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
}; // NimBLEServer
/**
@@ -217,5 +222,5 @@ class NimBLEServerCallbacks {
virtual void onPhyUpdate(NimBLEConnInfo& connInfo, uint8_t txPhy, uint8_t rxPhy);
}; // NimBLEServerCallbacks
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#endif // NIMBLE_CPP_SERVER_H_

View File

@@ -15,11 +15,10 @@
* limitations under the License.
*/
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLEService.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# include "NimBLEService.h"
# if CONFIG_BT_NIMBLE_EXT_ADV
# if MYNEWT_VAL(BLE_EXT_ADV)
# include "NimBLEExtAdvertising.h"
# else
# include "NimBLEAdvertising.h"
@@ -376,4 +375,4 @@ bool NimBLEService::isStarted() const {
return m_pSvcDef->type > 0;
} // isStarted
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)

View File

@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_SERVICE_H_
#define NIMBLE_CPP_SERVICE_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
class NimBLEService;
@@ -69,5 +69,5 @@ class NimBLEService : public NimBLELocalAttribute {
ble_gatt_svc_def m_pSvcDef[2]{};
}; // NimBLEService
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
#endif /* NIMBLE_CPP_SERVICE_H_ */
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#endif // NIMBLE_CPP_SERVICE_H_

498
src/NimBLEStream.cpp Normal file
View File

@@ -0,0 +1,498 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef ESP_PLATFORM
# include "NimBLEStream.h"
# if CONFIG_BT_NIMBLE_ENABLED && (MYNEWT_VAL(BLE_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_ROLE_CENTRAL))
# include "NimBLEDevice.h"
# include "rom/uart.h"
static const char* LOG_TAG = "NimBLEStream";
// Stub Print/Stream implementations when Arduino not available
# if !NIMBLE_CPP_ARDUINO_STRING_AVAILABLE
size_t Print::print(const char* s) {
if (!s) return 0;
return write(reinterpret_cast<const uint8_t*>(s), strlen(s));
}
size_t Print::println(const char* s) {
size_t n = print(s);
static const char crlf[] = "\r\n";
n += write(reinterpret_cast<const uint8_t*>(crlf), 2);
return n;
}
size_t Print::printf(const char* fmt, ...) {
if (!fmt) {
return 0;
}
char stackBuf[128];
va_list ap;
va_start(ap, fmt);
int n = vsnprintf(stackBuf, sizeof(stackBuf), fmt, ap);
va_end(ap);
if (n < 0) {
return 0;
}
if (static_cast<size_t>(n) < sizeof(stackBuf)) {
return write(reinterpret_cast<const uint8_t*>(stackBuf), static_cast<size_t>(n));
}
// allocate for larger output
size_t needed = static_cast<size_t>(n) + 1;
char* buf = static_cast<char*>(malloc(needed));
if (!buf) {
return 0;
}
va_start(ap, fmt);
vsnprintf(buf, needed, fmt, ap);
va_end(ap);
size_t ret = write(reinterpret_cast<const uint8_t*>(buf), static_cast<size_t>(n));
free(buf);
return ret;
}
# endif
void NimBLEStream::txTask(void* arg) {
NimBLEStream* pStream = static_cast<NimBLEStream*>(arg);
for (;;) {
size_t itemSize = 0;
void* item = xRingbufferReceive(pStream->m_txBuf, &itemSize, portMAX_DELAY);
if (item) {
pStream->send(reinterpret_cast<uint8_t*>(item), itemSize);
vRingbufferReturnItem(pStream->m_txBuf, item);
}
}
}
bool NimBLEStream::begin() {
if (m_txBuf || m_rxBuf || m_txTask) {
NIMBLE_UART_LOGW(LOG_TAG, "Already initialized");
return true;
}
if (m_txBufSize) {
m_txBuf = xRingbufferCreate(m_txBufSize, RINGBUF_TYPE_BYTEBUF);
if (!m_txBuf) {
NIMBLE_UART_LOGE(LOG_TAG, "Failed to create TX ringbuffer");
return false;
}
}
if (m_rxBufSize) {
m_rxBuf = xRingbufferCreate(m_rxBufSize, RINGBUF_TYPE_BYTEBUF);
if (!m_rxBuf) {
NIMBLE_UART_LOGE(LOG_TAG, "Failed to create RX ringbuffer");
if (m_txBuf) {
vRingbufferDelete(m_txBuf);
m_txBuf = nullptr;
}
return false;
}
}
if (xTaskCreate(txTask, "NimBLEStreamTx", m_txTaskStackSize, this, m_txTaskPriority, &m_txTask) != pdPASS) {
NIMBLE_UART_LOGE(LOG_TAG, "Failed to create stream tx task");
if (m_rxBuf) {
vRingbufferDelete(m_rxBuf);
m_rxBuf = nullptr;
}
if (m_txBuf) {
vRingbufferDelete(m_txBuf);
m_txBuf = nullptr;
}
return false;
}
return true;
}
bool NimBLEStream::end() {
if (m_txTask) {
vTaskDelete(m_txTask);
m_txTask = nullptr;
}
if (m_txBuf) {
vRingbufferDelete(m_txBuf);
m_txBuf = nullptr;
}
if (m_rxBuf) {
vRingbufferDelete(m_rxBuf);
m_rxBuf = nullptr;
}
m_hasPeek = false;
return true;
}
size_t NimBLEStream::write(const uint8_t* data, size_t len) {
if (!m_txBuf || !data || len == 0) {
return 0;
}
ble_npl_time_t timeout = 0;
ble_npl_time_ms_to_ticks(getTimeout(), &timeout);
size_t chunk = std::min(len, xRingbufferGetCurFreeSize(m_txBuf));
if (xRingbufferSend(m_txBuf, data, chunk, static_cast<TickType_t>(timeout)) != pdTRUE) {
return 0;
}
return chunk;
}
size_t NimBLEStream::availableForWrite() const {
return m_txBuf ? xRingbufferGetCurFreeSize(m_txBuf) : 0;
}
void NimBLEStream::flush() {
// Wait until TX ring is drained
while (m_txBuf && xRingbufferGetCurFreeSize(m_txBuf) < m_txBufSize) {
ble_npl_time_delay(ble_npl_time_ms_to_ticks32(1));
}
}
int NimBLEStream::available() {
if (!m_rxBuf) {
NIMBLE_UART_LOGE(LOG_TAG, "Invalid RX buffer");
return 0;
}
if (m_hasPeek) {
return 1; // at least the peeked byte
}
// Query items in RX ring
UBaseType_t waiting = 0;
vRingbufferGetInfo(m_rxBuf, nullptr, nullptr, nullptr, nullptr, &waiting);
return static_cast<int>(waiting);
}
int NimBLEStream::read() {
if (!m_rxBuf) {
return -1;
}
// Return peeked byte if available
if (m_hasPeek) {
m_hasPeek = false;
return static_cast<int>(m_peekByte);
}
size_t itemSize = 0;
uint8_t* item = static_cast<uint8_t*>(xRingbufferReceive(m_rxBuf, &itemSize, 0));
if (!item || itemSize == 0) return -1;
uint8_t byte = item[0];
// If item has more bytes, put the rest back
if (itemSize > 1) {
xRingbufferSend(m_rxBuf, item + 1, itemSize - 1, 0);
}
vRingbufferReturnItem(m_rxBuf, item);
return static_cast<int>(byte);
}
int NimBLEStream::peek() {
if (!m_rxBuf) {
return -1;
}
if (m_hasPeek) {
return static_cast<int>(m_peekByte);
}
size_t itemSize = 0;
uint8_t* item = static_cast<uint8_t*>(xRingbufferReceive(m_rxBuf, &itemSize, 0));
if (!item || itemSize == 0) {
return -1;
}
m_peekByte = item[0];
m_hasPeek = true;
// Put the entire item back
xRingbufferSend(m_rxBuf, item, itemSize, 0);
vRingbufferReturnItem(m_rxBuf, item);
return static_cast<int>(m_peekByte);
}
size_t NimBLEStream::pushRx(const uint8_t* data, size_t len) {
if (!m_rxBuf || !data || len == 0) {
NIMBLE_UART_LOGE(LOG_TAG, "Invalid RX buffer or data");
return 0;
}
// Clear peek state when new data arrives
m_hasPeek = false;
if (xRingbufferSend(m_rxBuf, data, len, 0) != pdTRUE) {
NIMBLE_UART_LOGE(LOG_TAG, "RX buffer full, dropping %u bytes", len);
return 0;
}
return len;
}
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
bool NimBLEStreamServer::init(const NimBLEUUID& svcUuid, const NimBLEUUID& chrUuid, bool canWrite, bool secure) {
if (!NimBLEDevice::isInitialized()) {
NIMBLE_UART_LOGE(LOG_TAG, "NimBLEDevice not initialized");
return false;
}
NimBLEServer* pServer = NimBLEDevice::getServer();
if (!pServer) {
pServer = NimBLEDevice::createServer();
}
NimBLEService* pSvc = pServer->getServiceByUUID(svcUuid);
if (!pSvc) {
pSvc = pServer->createService(svcUuid);
}
if (!pSvc) {
NIMBLE_UART_LOGE(LOG_TAG, "Failed to create service");
return false;
}
// Create characteristic with notify + write properties for bidirectional stream
uint32_t props = NIMBLE_PROPERTY::NOTIFY;
if (secure) {
props |= NIMBLE_PROPERTY::READ_ENC;
}
if (canWrite) {
props |= NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_NR;
if (secure) {
props |= NIMBLE_PROPERTY::WRITE_ENC;
}
} else {
m_rxBufSize = 0; // disable RX if not writable
}
m_pChr = pSvc->getCharacteristic(chrUuid);
if (!m_pChr) {
m_pChr = pSvc->createCharacteristic(chrUuid, props);
}
if (!m_pChr) {
NIMBLE_UART_LOGE(LOG_TAG, "Failed to create characteristic");
return false;
}
m_pChr->setCallbacks(&m_charCallbacks);
return pSvc->start();
}
void NimBLEStreamServer::deinit() {
if (m_pChr) {
NimBLEService* pSvc = m_pChr->getService();
if (pSvc) {
pSvc->removeCharacteristic(m_pChr, true);
}
m_pChr = nullptr;
}
NimBLEStream::end();
}
size_t NimBLEStreamServer::write(const uint8_t* data, size_t len) {
if (!m_pChr || len == 0 || !hasSubscriber()) {
return 0;
}
# if MYNEWT_VAL(NIMBLE_CPP_LOG_LEVEL) >= 4
// Skip server gap events to avoid log recursion
static const char filterStr[] = "handleGapEvent";
constexpr size_t filterLen = sizeof(filterStr) - 1;
if (len >= filterLen + 3) {
for (size_t i = 3; i <= len - filterLen; i++) {
if (memcmp(data + i, filterStr, filterLen) == 0) {
return len; // drop to avoid recursion
}
}
}
# endif
return NimBLEStream::write(data, len);
}
bool NimBLEStreamServer::send(const uint8_t* data, size_t len) {
if (!m_pChr || !len || !hasSubscriber()) {
return false;
}
size_t offset = 0;
while (offset < len) {
size_t chunkLen = std::min(len - offset, getMaxLength());
while (!m_pChr->notify(data + offset, chunkLen, getPeerHandle())) {
// Retry on ENOMEM (mbuf shortage)
if (m_rc == BLE_HS_ENOMEM || os_msys_num_free() <= 2) {
ble_npl_time_delay(ble_npl_time_ms_to_ticks32(8)); // wait for a minimum connection event time
continue;
}
return false;
}
offset += chunkLen;
}
return true;
}
void NimBLEStreamServer::ChrCallbacks::onWrite(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo) {
// Push received data into RX buffer
auto val = pCharacteristic->getValue();
if (val.size() > 0) {
m_parent->pushRx(val.data(), val.size());
}
if (m_userCallbacks) {
m_userCallbacks->onWrite(pCharacteristic, connInfo);
}
}
void NimBLEStreamServer::ChrCallbacks::onSubscribe(NimBLECharacteristic* pCharacteristic,
NimBLEConnInfo& connInfo,
uint16_t subValue) {
// only one subscriber supported
if (m_peerHandle != BLE_HS_CONN_HANDLE_NONE && subValue) {
return;
}
m_peerHandle = subValue ? connInfo.getConnHandle() : BLE_HS_CONN_HANDLE_NONE;
if (m_peerHandle != BLE_HS_CONN_HANDLE_NONE) {
m_maxLen = ble_att_mtu(m_peerHandle) - 3;
if (!m_parent->begin()) {
NIMBLE_UART_LOGE(LOG_TAG, "NimBLEStreamServer failed to begin");
}
return;
}
m_parent->end();
if (m_userCallbacks) {
m_userCallbacks->onSubscribe(pCharacteristic, connInfo, subValue);
}
}
void NimBLEStreamServer::ChrCallbacks::onStatus(NimBLECharacteristic* pCharacteristic, int code) {
m_parent->m_rc = code;
if (m_userCallbacks) {
m_userCallbacks->onStatus(pCharacteristic, code);
}
}
# endif // MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
bool NimBLEStreamClient::init(NimBLERemoteCharacteristic* pChr, bool subscribe) {
if (!pChr) {
return false;
}
m_pChr = pChr;
m_writeWithRsp = !pChr->canWriteNoResponse();
// Subscribe to notifications/indications for RX if requested
if (subscribe && (pChr->canNotify() || pChr->canIndicate())) {
using namespace std::placeholders;
if (!pChr->subscribe(pChr->canNotify(), std::bind(&NimBLEStreamClient::notifyCallback, this, _1, _2, _3, _4))) {
NIMBLE_UART_LOGE(LOG_TAG, "Failed to subscribe for notifications");
}
}
if (!subscribe) {
m_rxBufSize = 0; // disable RX if not subscribing
}
return true;
}
void NimBLEStreamClient::deinit() {
if (m_pChr && (m_pChr->canNotify() || m_pChr->canIndicate())) {
m_pChr->unsubscribe();
}
NimBLEStream::end();
m_pChr = nullptr;
}
size_t NimBLEStreamClient::write(const uint8_t* data, size_t len) {
if (!m_pChr || !data || len == 0) {
return 0;
}
return NimBLEStream::write(data, len);
}
bool NimBLEStreamClient::send(const uint8_t* data, size_t len) {
if (!m_pChr || !data || len == 0) {
return false;
}
return m_pChr->writeValue(data, len, m_writeWithRsp);
}
void NimBLEStreamClient::notifyCallback(NimBLERemoteCharacteristic* pChar, uint8_t* pData, size_t len, bool isNotify) {
if (pData && len > 0) {
pushRx(pData, len);
}
if (m_userNotifyCallback) {
m_userNotifyCallback(pChar, pData, len, isNotify);
}
}
// UART logging support
int uart_log_printfv(const char* format, va_list arg) {
static char loc_buf[64];
char* temp = loc_buf;
uint32_t len;
va_list copy;
va_copy(copy, arg);
len = vsnprintf(NULL, 0, format, copy);
va_end(copy);
if (len >= sizeof(loc_buf)) {
temp = (char*)malloc(len + 1);
if (temp == NULL) {
return 0;
}
}
int wlen = vsnprintf(temp, len + 1, format, arg);
for (int i = 0; i < wlen; i++) {
uart_tx_one_char(temp[i]);
}
if (len >= sizeof(loc_buf)) {
free(temp);
}
return len;
}
int uart_log_printf(const char* format, ...) {
int len;
va_list arg;
va_start(arg, format);
len = uart_log_printfv(format, arg);
va_end(arg);
return len;
}
# endif // MYNEWT_VAL(BLE_ROLE_CENTRAL)
# endif // CONFIG_BT_NIMBLE_ENABLED && (MYNEWT_VAL(BLE_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_ROLE_CENTRAL))
#endif // ESP_PLATFORM

220
src/NimBLEStream.h Normal file
View File

@@ -0,0 +1,220 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef ESP_PLATFORM
# ifndef NIMBLE_CPP_STREAM_H
# define NIMBLE_CPP_STREAM_H
# include "syscfg/syscfg.h"
# if CONFIG_BT_NIMBLE_ENABLED && (MYNEWT_VAL(BLE_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_ROLE_CENTRAL))
# include "NimBLEUUID.h"
# include <freertos/FreeRTOS.h>
# include <freertos/ringbuf.h>
# if NIMBLE_CPP_ARDUINO_STRING_AVAILABLE
# include <Stream.h>
# else
// Minimal Stream/Print stubs when Arduino not available
class Print {
public:
virtual ~Print() {}
virtual size_t write(uint8_t) = 0;
virtual size_t write(const uint8_t* buffer, size_t size) = 0;
size_t print(const char* s);
size_t println(const char* s);
size_t printf(const char* format, ...) __attribute__((format(printf, 2, 3)));
};
class Stream : public Print {
public:
virtual int available() = 0;
virtual int read() = 0;
virtual int peek() = 0;
void setTimeout(unsigned long timeout) { m_timeout = timeout; }
unsigned long getTimeout() const { return m_timeout; }
protected:
unsigned long m_timeout{0};
};
# endif
class NimBLEStream : public Stream {
public:
NimBLEStream() = default;
virtual ~NimBLEStream() { end(); }
bool begin();
bool end();
// Configure TX/RX buffer sizes and task parameters before begin()
void setTxBufSize(uint32_t size) { m_txBufSize = size; }
void setRxBufSize(uint32_t size) { m_rxBufSize = size; }
void setTxTaskStackSize(uint32_t size) { m_txTaskStackSize = size; }
void setTxTaskPriority(uint32_t priority) { m_txTaskPriority = priority; }
// Print/Stream TX methods
virtual size_t write(const uint8_t* data, size_t len) override;
virtual size_t write(uint8_t data) override { return write(&data, 1); }
size_t availableForWrite() const;
void flush() override;
// Stream RX methods
virtual int available() override;
virtual int read() override;
virtual int peek() override;
// Serial-like helpers
bool ready() const { return isReady(); }
operator bool() const { return ready(); }
using Print::write;
protected:
static void txTask(void* arg);
virtual bool send(const uint8_t* data, size_t len) = 0;
virtual bool isReady() const = 0;
// Push received data into RX ring (called by subclass callbacks)
size_t pushRx(const uint8_t* data, size_t len);
RingbufHandle_t m_txBuf{nullptr};
RingbufHandle_t m_rxBuf{nullptr};
TaskHandle_t m_txTask{nullptr};
uint32_t m_txTaskStackSize{4096};
uint32_t m_txTaskPriority{tskIDLE_PRIORITY + 1};
uint32_t m_txBufSize{1024};
uint32_t m_rxBufSize{1024};
// RX peek state
mutable uint8_t m_peekByte{0};
mutable bool m_hasPeek{false};
};
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# include "NimBLECharacteristic.h"
class NimBLEStreamServer : public NimBLEStream {
public:
NimBLEStreamServer() : m_charCallbacks(this) {}
~NimBLEStreamServer() = default;
// non-copyable
NimBLEStreamServer(const NimBLEStreamServer&) = delete;
NimBLEStreamServer& operator=(const NimBLEStreamServer&) = delete;
bool init(const NimBLEUUID& svcUuid = NimBLEUUID(uint16_t(0xc0de)),
const NimBLEUUID& chrUuid = NimBLEUUID(uint16_t(0xfeed)),
bool canWrite = false,
bool secure = false);
void deinit();
size_t write(const uint8_t* data, size_t len) override;
uint16_t getPeerHandle() const { return m_charCallbacks.m_peerHandle; }
bool hasSubscriber() const { return m_charCallbacks.m_peerHandle != BLE_HS_CONN_HANDLE_NONE; }
size_t getMaxLength() const { return m_charCallbacks.m_maxLen; }
void setCallbacks(NimBLECharacteristicCallbacks* pCallbacks) { m_charCallbacks.m_userCallbacks = pCallbacks; }
private:
bool send(const uint8_t* data, size_t len) override;
bool isReady() const override { return hasSubscriber(); }
struct ChrCallbacks : public NimBLECharacteristicCallbacks {
ChrCallbacks(NimBLEStreamServer* parent)
: m_parent(parent), m_userCallbacks(nullptr), m_peerHandle(BLE_HS_CONN_HANDLE_NONE), m_maxLen(0) {}
void onWrite(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo) override;
void onSubscribe(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo, uint16_t subValue) override;
void onStatus(NimBLECharacteristic* pCharacteristic, int code) override;
// override this to avoid recursion when debug logs are enabled
void onStatus(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo, int code) {
if (m_userCallbacks) {
m_userCallbacks->onStatus(pCharacteristic, connInfo, code);
}
}
NimBLEStreamServer* m_parent;
NimBLECharacteristicCallbacks* m_userCallbacks;
uint16_t m_peerHandle;
uint16_t m_maxLen;
} m_charCallbacks;
NimBLECharacteristic* m_pChr{nullptr};
int m_rc{0};
};
# endif // BLE_ROLE_PERIPHERAL
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
# include "NimBLERemoteCharacteristic.h"
class NimBLEStreamClient : public NimBLEStream {
public:
NimBLEStreamClient() = default;
~NimBLEStreamClient() = default;
// non-copyable
NimBLEStreamClient(const NimBLEStreamClient&) = delete;
NimBLEStreamClient& operator=(const NimBLEStreamClient&) = delete;
// Attach a discovered remote characteristic; app owns discovery/connection.
// Set subscribeNotify=true to receive notifications into RX buffer.
bool init(NimBLERemoteCharacteristic* pChr, bool subscribeNotify = false);
void deinit();
size_t write(const uint8_t* data, size_t len) override;
void setWriteWithResponse(bool useWithRsp) { m_writeWithRsp = useWithRsp; }
void setNotifyCallback(NimBLERemoteCharacteristic::notify_callback cb) { m_userNotifyCallback = cb; }
private:
bool send(const uint8_t* data, size_t len) override;
bool isReady() const override { return m_pChr != nullptr; }
void notifyCallback(NimBLERemoteCharacteristic* pChar, uint8_t* pData, size_t len, bool isNotify);
NimBLERemoteCharacteristic* m_pChr{nullptr};
bool m_writeWithRsp{false};
NimBLERemoteCharacteristic::notify_callback m_userNotifyCallback{nullptr};
};
# endif // BLE_ROLE_CENTRAL
# endif // CONFIG_BT_NIMBLE_ENABLED && (MYNEWT_VAL(BLE_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_ROLE_CENTRAL))
// These logging macros exist to provide log output over UART so that it stream classes can
// be used to redirect logs without causing recursion issues.
static int uart_log_printfv(const char* format, va_list arg);
static int uart_log_printf(const char* format, ...);
# if MYNEWT_VAL(NIMBLE_CPP_LOG_LEVEL) >= 4
# define NIMBLE_UART_LOGD(tag, format, ...) uart_log_printf("D %s: " format "\n", tag, ##__VA_ARGS__)
# else
# define NIMBLE_UART_LOGD(tag, format, ...) (void)tag
# endif
# if MYNEWT_VAL(NIMBLE_CPP_LOG_LEVEL) >= 3
# define NIMBLE_UART_LOGI(tag, format, ...) uart_log_printf("I %s: " format "\n", tag, ##__VA_ARGS__)
# else
# define NIMBLE_UART_LOGI(tag, format, ...) (void)tag
# endif
# if MYNEWT_VAL(NIMBLE_CPP_LOG_LEVEL) >= 2
# define NIMBLE_UART_LOGW(tag, format, ...) uart_log_printf("W %s: " format "\n", tag, ##__VA_ARGS__)
# else
# define NIMBLE_UART_LOGW(tag, format, ...) (void)tag
# endif
# if MYNEWT_VAL(NIMBLE_CPP_LOG_LEVEL) >= 1
# define NIMBLE_UART_LOGE(tag, format, ...) uart_log_printf("E %s: " format "\n", tag, ##__VA_ARGS__)
# else
# define NIMBLE_UART_LOGE(tag, format, ...) (void)tag
# endif
# endif // NIMBLE_CPP_STREAM_H
#endif // ESP_PLATFORM

View File

@@ -15,11 +15,10 @@
* limitations under the License.
*/
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "NimBLEUUID.h"
#if CONFIG_BT_NIMBLE_ENABLED
# include "NimBLEUtils.h"
# include "NimBLEUUID.h"
# include "NimBLELog.h"
/**** FIX COMPILATION ****/
@@ -337,4 +336,4 @@ NimBLEUUID::operator std::string() const {
return ble_uuid_to_str(&m_uuid.u, buf);
} // operator std::string
#endif /* CONFIG_BT_ENABLED */
#endif /* CONFIG_BT_NIMBLE_ENABLED */

View File

@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_UUID_H_
#define NIMBLE_CPP_UUID_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED
# if defined(CONFIG_NIMBLE_CPP_IDF)
# include "host/ble_uuid.h"
@@ -70,5 +70,5 @@ class NimBLEUUID {
ble_uuid_any_t m_uuid{};
}; // NimBLEUUID
#endif /* CONFIG_BT_ENABLED */
#endif /* NIMBLE_CPP_UUID_H_ */
#endif // CONFIG_BT_NIMBLE_ENABLED
#endif // NIMBLE_CPP_UUID_H_

View File

@@ -15,10 +15,9 @@
* limitations under the License.
*/
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "NimBLEUtils.h"
#if CONFIG_BT_NIMBLE_ENABLED
# include "NimBLEUtils.h"
# include "NimBLEAddress.h"
# include "NimBLELog.h"
@@ -36,14 +35,42 @@
# include <stdlib.h>
# include <climits>
# if defined INC_FREERTOS_H
# ifndef CONFIG_NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT
# define CONFIG_NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT 31
# 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
constexpr uint32_t TASK_BLOCK_BIT = (1 << CONFIG_NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT);
# endif
static const char* LOG_TAG = "NimBLEUtils";
# 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
# endif
# endif
constexpr uint32_t TASK_BLOCK_BIT = (1 << MYNEWT_VAL(NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT));
static const char* LOG_TAG = "NimBLEUtils";
/**
* @brief Construct a NimBLETaskData instance.
@@ -55,7 +82,7 @@ NimBLETaskData::NimBLETaskData(void* pInstance, int flags, void* buf)
: m_pInstance{pInstance},
m_flags{flags},
m_pBuf{buf}
# if defined INC_FREERTOS_H
# ifdef INC_FREERTOS_H
,
m_pHandle{xTaskGetCurrentTaskHandle()} {
}
@@ -76,7 +103,7 @@ NimBLETaskData::NimBLETaskData(void* pInstance, int flags, void* buf)
* @brief Destructor.
*/
NimBLETaskData::~NimBLETaskData() {
# if !defined INC_FREERTOS_H
# ifndef 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);
@@ -98,7 +125,7 @@ bool NimBLEUtils::taskWait(const NimBLETaskData& taskData, uint32_t timeout) {
ble_npl_time_ms_to_ticks(timeout, &ticks);
}
# if defined INC_FREERTOS_H
# ifdef INC_FREERTOS_H
uint32_t notificationValue;
xTaskNotifyWait(0, TASK_BLOCK_BIT, &notificationValue, 0);
if (notificationValue & TASK_BLOCK_BIT) {
@@ -120,7 +147,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) {
# if defined INC_FREERTOS_H
# ifdef 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));
@@ -134,7 +161,7 @@ void NimBLEUtils::taskRelease(const NimBLETaskData& taskData, int flags) {
* @return A string representation of the return code.
*/
const char* NimBLEUtils::returnCodeToString(int rc) {
# if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
# if MYNEWT_VAL(NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
switch (rc) {
case 0:
return "SUCCESS";
@@ -417,10 +444,10 @@ const char* NimBLEUtils::returnCodeToString(int rc) {
default:
return "Unknown";
}
# else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
# else // MYNEWT_VAL(NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
(void)rc;
return "";
# endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
# endif // MYNEWT_VAL(NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
}
/**
@@ -429,7 +456,7 @@ const char* NimBLEUtils::returnCodeToString(int rc) {
* @return A string representation of the advertising flags.
*/
const char* NimBLEUtils::advTypeToString(uint8_t advType) {
# if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT)
# if MYNEWT_VAL(NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT)
switch (advType) {
case BLE_HCI_ADV_TYPE_ADV_IND: // 0
return "Undirected - Connectable / Scannable";
@@ -444,10 +471,10 @@ const char* NimBLEUtils::advTypeToString(uint8_t advType) {
default:
return "Unknown flag";
}
# else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT)
# else // MYNEWT_VAL(NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT)
(void)advType;
return "";
# endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT)
# endif // MYNEWT_VAL(NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT)
} // adFlagsToString
/**
@@ -456,7 +483,7 @@ const char* NimBLEUtils::advTypeToString(uint8_t advType) {
* @return A string representation of the event type.
*/
const char* NimBLEUtils::gapEventToString(uint8_t eventType) {
# if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
# if MYNEWT_VAL(NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
switch (eventType) {
case BLE_GAP_EVENT_CONNECT: // 0
return "BLE_GAP_EVENT_CONNECT ";
@@ -536,10 +563,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 // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
# else // MYNEWT_VAL(NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
(void)eventType;
return "";
# endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
# endif // MYNEWT_VAL(NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
} // gapEventToString
/**
@@ -577,4 +604,4 @@ NimBLEAddress NimBLEUtils::generateAddr(bool nrpa) {
return NimBLEAddress{addr};
} // generateAddr
#endif // CONFIG_BT_ENABLED
#endif // CONFIG_BT_NIMBLE_ENABLED

View File

@@ -18,8 +18,29 @@
#ifndef NIMBLE_CPP_UTILS_H_
#define NIMBLE_CPP_UTILS_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
#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
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__)
# define NIMBLE_CPP_DEBUG_ASSERT(cond) \
if (!(cond)) { \
nimble_cpp_assert(NIMBLE_ATT_VAL_FILE, __LINE__); \
}
#else
# define NIMBLE_CPP_DEBUG_ASSERT(cond) (void(0))
#endif
# include <string>
class NimBLEAddress;
@@ -55,5 +76,5 @@ class NimBLEUtils {
static void taskRelease(const NimBLETaskData& taskData, int rc = 0);
};
#endif // CONFIG_BT_ENABLED
#endif // CONFIG_BT_NIMBLE_ENABLED
#endif // NIMBLE_CPP_UTILS_H_

View File

@@ -18,15 +18,15 @@
#ifndef NIMBLE_CPP_VALUE_ATTRIBUTE_H_
#define NIMBLE_CPP_VALUE_ATTRIBUTE_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && (defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) || defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL))
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && (MYNEWT_VAL(BLE_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_ROLE_CENTRAL))
# include "NimBLEAttribute.h"
# include "NimBLEAttValue.h"
class NimBLEValueAttribute {
public:
NimBLEValueAttribute(uint16_t maxLen = BLE_ATT_ATTR_MAX_LEN, uint16_t initLen = CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH)
NimBLEValueAttribute(uint16_t maxLen = BLE_ATT_ATTR_MAX_LEN, uint16_t initLen = MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_INIT_LENGTH))
: m_value(initLen, maxLen) {}
/**
@@ -82,5 +82,5 @@ class NimBLEValueAttribute {
NimBLEAttValue m_value{};
};
#endif // CONFIG_BT_ENABLED && (CONFIG_BT_NIMBLE_ROLE_PERIPHERAL || CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#endif // CONFIG_BT_NIMBLE_ENABLED && (MYNEWT_VAL(BLE_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_ROLE_CENTRAL))
#endif // NIMBLE_CPP_ATTRIBUTE_H_

View File

@@ -1,152 +0,0 @@
/** @file
*
* IGNORE THIS FILE IF USING ESP-IDF, USE MENUCONFIG TO SET NIMBLE OPTIONS.
*
* The config options here are for doxygen documentation only.
*/
#pragma once
#include "sdkconfig.h"
#include "nimconfig_rename.h"
#if defined(CONFIG_BT_ENABLED)
// Allows cpp wrapper to select the correct include paths when using esp-idf
#define CONFIG_NIMBLE_CPP_IDF
/* Cannot use client without scan */
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) && !defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER
#endif
/* Cannot use server without advertise */
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) && !defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER
#endif
/* Enables the use of Arduino String class for attribute values */
#if defined __has_include
# if __has_include (<Arduino.h>)
# define NIMBLE_CPP_ARDUINO_STRING_AVAILABLE
# endif
#endif
#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__)
# define NIMBLE_CPP_DEBUG_ASSERT(cond) \
if (!(cond)) { \
nimble_cpp_assert(NIMBLE_ATT_VAL_FILE, __LINE__); \
}
#else
# define NIMBLE_CPP_DEBUG_ASSERT(cond) (void(0))
#endif
#endif /* CONFIG_BT_ENABLED */
#ifdef _DOXYGEN_
/** @brief Un-comment to change the number of simultaneous connections (esp controller max is 9) */
#define CONFIG_BT_NIMBLE_MAX_CONNECTIONS 3
/** @brief Un-comment to enable storing the timestamp when an attribute value is updated\n
* This allows for checking the last update time using getTimeStamp() or getValue(time_t*)\n
* If disabled, the timestamp returned from these functions will be 0.\n
* Disabling timestamps will reduce the memory used for each value.\n
* 1 = Enabled, 0 = Disabled; Default = Disabled
*/
#define CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED 0
/** @brief Uncomment to set the default allocation size (bytes) for each attribute if\n
* not specified when the constructor is called. This is also the size used when a remote\n
* characteristic or descriptor is constructed before a value is read/notifed.\n
* Increasing this will reduce reallocations but increase memory footprint.\n
* Default value is 20. Range: 1 : 512 (BLE_ATT_ATTR_MAX_LEN)
*/
#define CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH 20
/** @brief Un-comment to change the default MTU size */
#define CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU 255
/** @brief Un-comment to change default device name */
#define CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME "nimble"
/** @brief Un-comment to set the debug log messages level from the NimBLE host stack.\n
* Values: 0 = DEBUG, 1 = INFO, 2 = WARNING, 3 = ERROR, 4 = CRITICAL, 5+ = NONE\n
* Uses approx. 32kB of flash memory.
*/
#define CONFIG_BT_NIMBLE_LOG_LEVEL 5
/** @brief Un-comment to set the debug log messages level from the NimBLE CPP Wrapper.\n
* Values: 0 = NONE, 1 = ERROR, 2 = WARNING, 3 = INFO, 4+ = DEBUG\n
* Uses approx. 32kB of flash memory.
*/
#define CONFIG_NIMBLE_CPP_LOG_LEVEL 0
/** @brief Un-comment to see NimBLE host return codes as text debug log messages.
* Uses approx. 7kB of flash memory.
*/
#define CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT
/** @brief Un-comment to see GAP event codes as text in debug log messages.
* Uses approx. 1kB of flash memory.
*/
#define CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
/** @brief Un-comment to see advertisment types as text while scanning in debug log messages.
* Uses approx. 250 bytes of flash memory.
*/
#define CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT
/** @brief Un-comment to change the default GAP appearance */
#define CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE 0x0
/** @brief Un-comment if not using NimBLE Client functions \n
* Reduces flash size by approx. 7kB.
*/
#define CONFIG_BT_NIMBLE_ROLE_CENTRAL_DISABLED
/** @brief Un-comment if not using NimBLE Scan functions \n
* Reduces flash size by approx. 26kB.
*/
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER_DISABLED
/** @brief Un-comment if not using NimBLE Server functions \n
* Reduces flash size by approx. 16kB.
*/
#define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL_DISABLED
/** @brief Un-comment if not using NimBLE Advertising functions \n
* Reduces flash size by approx. 5kB.
*/
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER_DISABLED
/** @brief Un-comment to change the number of devices allowed to store/bond with */
#define CONFIG_BT_NIMBLE_MAX_BONDS 3
/** @brief Un-comment to change the maximum number of CCCD subscriptions to store */
#define CONFIG_BT_NIMBLE_MAX_CCCDS 8
/** @brief Un-comment to change the random address refresh time (in seconds) */
#define CONFIG_BT_NIMBLE_RPA_TIMEOUT 900
/**
* @brief Un-comment to change the number of MSYS buffers available.
* @details MSYS is a system level mbuf registry. For prepare write & prepare \n
* responses MBUFs are allocated out of msys_1 pool. This may need to be increased if\n
* you are sending large blocks of data with a low MTU. E.g: 512 bytes with 23 MTU will fail.
*/
#define CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT 12
/** @brief Un-comment to use external PSRAM for the NimBLE host */
#define CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL 1
/** @brief Un-comment to change the core NimBLE host runs on */
#define CONFIG_BT_NIMBLE_PINNED_TO_CORE 0
/** @brief Un-comment to change the stack size for the NimBLE host task */
#define CONFIG_BT_NIMBLE_TASK_STACK_SIZE 4096
#endif // _DOXYGEN_

View File

@@ -1,93 +0,0 @@
/*
* For ESP-IDF compatibility
* Some versions of ESP-IDF used the config name format "CONFIG_NIMBLE_".
* This converts them to "CONFIG_BT_NIMBLE_" format used in the latest IDF.
*/
#if defined(CONFIG_NIMBLE_ENABLED) && !defined(CONFIG_BT_NIMBLE_ENABLED)
#define CONFIG_BT_NIMBLE_ENABLED
#endif
#if defined(CONFIG_NIMBLE_ROLE_OBSERVER) && !defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER
#endif
#if defined(CONFIG_NIMBLE_ROLE_BROADCASTER) && !defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER
#endif
#if defined(CONFIG_NIMBLE_ROLE_CENTRAL) && !defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#define CONFIG_BT_NIMBLE_ROLE_CENTRAL
#endif
#if defined(CONFIG_NIMBLE_ROLE_PERIPHERAL) && !defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
#endif
#if defined(CONFIG_NIMBLE_DEBUG) && !defined(CONFIG_BT_NIMBLE_DEBUG)
#define CONFIG_BT_NIMBLE_DEBUG
#endif
#if defined(CONFIG_SCAN_DUPLICATE_BY_DEVICE_ADDR) && !defined(CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE)
#define CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE CONFIG_SCAN_DUPLICATE_BY_DEVICE_ADDR
#endif
#if defined(CONFIG_SCAN_DUPLICATE_BY_ADV_DATA ) && !defined(CONFIG_BTDM_SCAN_DUPL_TYPE_DATA)
#define CONFIG_BTDM_SCAN_DUPL_TYPE_DATA CONFIG_SCAN_DUPLICATE_BY_ADV_DATA
#endif
#if defined(CONFIG_SCAN_DUPLICATE_BY_ADV_DATA_AND_DEVICE_ADDR) && !defined(CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE)
#define CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE CONFIG_SCAN_DUPLICATE_BY_ADV_DATA_AND_DEVICE_ADDR
#endif
#if defined(CONFIG_SCAN_DUPLICATE_TYPE) && !defined(CONFIG_BTDM_SCAN_DUPL_TYPE)
#define CONFIG_BTDM_SCAN_DUPL_TYPE CONFIG_SCAN_DUPLICATE_TYPE
#endif
#if defined(CONFIG_BT_CTRL_SCAN_DUPL_TYPE) && !defined(CONFIG_BTDM_SCAN_DUPL_TYPE)
#define CONFIG_BTDM_SCAN_DUPL_TYPE CONFIG_BT_CTRL_SCAN_DUPL_TYPE
#endif
#if defined(CONFIG_DUPLICATE_SCAN_CACHE_SIZE) && !defined(CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE)
#define CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE CONFIG_DUPLICATE_SCAN_CACHE_SIZE
#endif
#if defined(CONFIG_BT_CTRL_SCAN_DUPL_CACHE_SIZE) && !defined(CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE)
#define CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE CONFIG_BT_CTRL_SCAN_DUPL_CACHE_SIZE
#endif
#if defined(CONFIG_NIMBLE_MAX_CONNECTIONS ) && !defined(CONFIG_BT_NIMBLE_MAX_CONNECTIONS)
#define CONFIG_BT_NIMBLE_MAX_CONNECTIONS CONFIG_NIMBLE_MAX_CONNECTIONS
#endif
#if defined(CONFIG_BT_NIMBLE_EXT_ADV_MAX_SIZE) && !defined(CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN)
#define CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN CONFIG_BT_NIMBLE_EXT_ADV_MAX_SIZE
#endif
#if !defined(CONFIG_BTDM_BLE_SCAN_DUPL) && defined(CONFIG_BT_CTRL_BLE_SCAN_DUPL)
#define CONFIG_BTDM_BLE_SCAN_DUPL CONFIG_BT_CTRL_BLE_SCAN_DUPL
#endif
#if !defined(CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE) && defined(CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DEVICE)
#define CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DEVICE
#endif
#if !defined(CONFIG_BTDM_SCAN_DUPL_TYPE_DATA) && defined(CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA)
#define CONFIG_BTDM_SCAN_DUPL_TYPE_DATA CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA
#endif
#if !defined(CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE) && defined(CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE)
#define CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE
#endif
#ifdef CONFIG_BT_LE_LL_CFG_FEAT_LE_CODED_PHY
#define CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_CODED_PHY CONFIG_BT_LE_LL_CFG_FEAT_LE_CODED_PHY
#endif
#ifdef CONFIG_BT_LE_LL_CFG_FEAT_LE_2M_PHY
#define CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_2M_PHY CONFIG_BT_LE_LL_CFG_FEAT_LE_2M_PHY
#endif
#ifdef CONFIG_BT_LE_50_FEATURE_SUPPORT
#define CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT CONFIG_BT_LE_50_FEATURE_SUPPORT
#endif