6 Commits
2.3.2 ... 2.1.1

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

View File

@@ -17,8 +17,8 @@ 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", "release-v5.5"]
idf_target: ["esp32", "esp32s3", "esp32c2", "esp32c3", "esp32c5", "esp32c6", "esp32h2", "esp32p4"]
idf_ver: ["release-v4.4", "release-v5.1", "v5.3.2"]
idf_target: ["esp32", "esp32s3", "esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32p4"]
example:
- NimBLE_Client
- NimBLE_Server
@@ -31,8 +31,6 @@ jobs:
example: Bluetooth_5/NimBLE_extended_server
- idf_ver: release-v4.4
idf_target: "esp32c2"
- idf_ver: release-v4.4
idf_target: "esp32c5"
- idf_ver: release-v4.4
idf_target: "esp32c6"
- idf_ver: release-v4.4

View File

@@ -1,63 +1,6 @@
# Changelog
All notable changes to this project will be documented in this file.
## [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
- Incorrect `NimBLECharacteristic::onSubscribe` value when indications are set.
- `NimBLECharacteristic::onRead` callback not called in some cases.
- Clear attribute value when zero length value is written.
- Notify/Indicate incorrectly returning success with custom value.
- Corrected NimBLEClient array initialization.
- Prevent potential exception when scan is restarted.
- Attribute getValue failing with some data types
- Incorrectly passing a pointer to a function taking const reference.
## Added
- Support for esp32c5
- L2CAP infrastructure.
- Scan duplicate cache reset time.
## Changed
- Cleaned up examples.
- Allow PHY updates without enabling extended advertising.
## [2.2.1] 2025-02-28
## Fixed
- Added back `NimBLEClient::connect` overload with `NimBLEAdvertisedDevice` parameter to resolve connection error due to NULL address.
- Crash caused by returning invalid vector entry when retrieving remote descriptors.
## [2.2.0] 2025-02-24
## Fixed
- Crash when calling `NimBLEClient::DiscoverAttributes`.
## Added
- Conditional macros for logging.
- `NimBLEDeviceCallbacks` class with a callback for handling bond storage.
## [2.1.1] 2025-01-26
## Fixed

View File

@@ -35,7 +35,6 @@ idf_component_register(
"esp32s3"
"esp32c2"
"esp32c3"
"esp32c5"
"esp32c6"
"esp32h2"
"esp32p4"
@@ -56,8 +55,6 @@ idf_component_register(
"src/NimBLEEddystoneTLM.cpp"
"src/NimBLEExtAdvertising.cpp"
"src/NimBLEHIDDevice.cpp"
"src/NimBLEL2CAPChannel.cpp"
"src/NimBLEL2CAPServer.cpp"
"src/NimBLERemoteCharacteristic.cpp"
"src/NimBLERemoteDescriptor.cpp"
"src/NimBLERemoteService.cpp"

View File

@@ -204,10 +204,6 @@ 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
#

2
NOTICE
View File

@@ -1,6 +1,6 @@
esp-nimble-cpp
NimBLE-Arduino
Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
esp-nimble-cpp, NimBLE-Arduino contributors.
The Initial Developer of some parts of this library, which are copied from,

View File

@@ -43,7 +43,6 @@ 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
@@ -134,7 +133,6 @@ 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,7 +48,8 @@ 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.2
PROJECT_NUMBER = 2.1.1
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
# quick idea about the purpose of the project. Keep the description short.
@@ -2416,12 +2417,12 @@ INCLUDE_FILE_PATTERNS =
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED = _DOXYGEN_ \
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
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
# 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 if calling `NimBLEAdvertising::setAdvertisementData`.
`NimBLEAdvertising::setAppearance` or similar methods. You should set all the data you wish to advertise within the `NimBLEAdvertisementData` instead.
<br/>
> BLEAdvertising::start (NimBLEAdvertising::start)

View File

@@ -65,7 +65,8 @@ class AdvertisingCallbacks : public NimBLEExtAdvertisingCallbacks {
}
} advertisingCallbacks;
extern "C" void app_main(void) {
extern "C"
void app_main(void) {
/** Initialize NimBLE and set the device name */
NimBLEDevice::init("Extended advertiser");
@@ -104,6 +105,7 @@ extern "C" void app_main(void) {
"This example message is 226 bytes long "
"and is using CODED_PHY for long range."));
extAdv.setCompleteServices16({NimBLEUUID(SERVICE_UUID)});
extAdv.setName("Extended advertiser");
/** When extended advertising is enabled `NimBLEDevice::getAdvertising` returns a pointer to `NimBLEExtAdvertising */

View File

@@ -1,5 +0,0 @@
.vscode
build
sdkconfig
sdkconfig.old
dependencies.lock

View File

@@ -1,7 +0,0 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(SUPPORTED_TARGETS esp32 esp32s3 esp32c3 esp32c6)
project(L2CAP_client)

View File

@@ -1,3 +0,0 @@
PROJECT_NAME := L2CAP_client
include $(IDF_PATH)/make/project.mk

View File

@@ -1,4 +0,0 @@
set(COMPONENT_SRCS "main.cpp")
set(COMPONENT_ADD_INCLUDEDIRS ".")
register_component()

View File

@@ -1,4 +0,0 @@
#
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

View File

@@ -1,3 +0,0 @@
dependencies:
local/esp-nimble-cpp:
path: ../../../../../esp-nimble-cpp/

View File

@@ -1,165 +0,0 @@
#include <NimBLEDevice.h>
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
// The remote service we wish to connect to.
static BLEUUID serviceUUID("dcbc7255-1e9e-49a0-a360-b0430b6c6905");
// The characteristic of the remote service we are interested in.
static BLEUUID charUUID("371a55c8-f251-4ad2-90b3-c7c195b049be");
#define L2CAP_CHANNEL 150
#define L2CAP_MTU 5000
const BLEAdvertisedDevice* theDevice = NULL;
BLEClient* theClient = NULL;
BLEL2CAPChannel* theChannel = NULL;
size_t bytesSent = 0;
size_t bytesReceived = 0;
class L2CAPChannelCallbacks: public BLEL2CAPChannelCallbacks {
public:
void onConnect(NimBLEL2CAPChannel* channel) {
printf("L2CAP connection established\n");
}
void onMTUChange(NimBLEL2CAPChannel* channel, uint16_t mtu) {
printf("L2CAP MTU changed to %d\n", mtu);
}
void onRead(NimBLEL2CAPChannel* channel, std::vector<uint8_t>& data) {
printf("L2CAP read %d bytes\n", data.size());
}
void onDisconnect(NimBLEL2CAPChannel* channel) {
printf("L2CAP disconnected\n");
}
};
class MyClientCallbacks: public BLEClientCallbacks {
void onConnect(BLEClient* pClient) {
printf("GAP connected\n");
pClient->setDataLen(251);
theChannel = BLEL2CAPChannel::connect(pClient, L2CAP_CHANNEL, L2CAP_MTU, new L2CAPChannelCallbacks());
}
void onDisconnect(BLEClient* pClient, int reason) {
printf("GAP disconnected (reason: %d)\n", reason);
theDevice = NULL;
theChannel = NULL;
vTaskDelay(1000 / portTICK_PERIOD_MS);
BLEDevice::getScan()->start(5 * 1000, true);
}
};
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(const BLEAdvertisedDevice* advertisedDevice) {
if (theDevice) { return; }
printf("BLE Advertised Device found: %s\n", advertisedDevice->toString().c_str());
if (!advertisedDevice->haveServiceUUID()) { return; }
if (!advertisedDevice->isAdvertisingService(serviceUUID)) { return; }
printf("Found the device we're interested in!\n");
BLEDevice::getScan()->stop();
// Hand over the device to the other task
theDevice = advertisedDevice;
}
};
void connectTask(void *pvParameters) {
uint8_t sequenceNumber = 0;
while (true) {
if (!theDevice) {
vTaskDelay(1000 / portTICK_PERIOD_MS);
continue;
}
if (!theClient) {
theClient = BLEDevice::createClient();
theClient->setConnectionParams(6, 6, 0, 42);
auto callbacks = new MyClientCallbacks();
theClient->setClientCallbacks(callbacks);
auto success = theClient->connect(theDevice);
if (!success) {
printf("Error: Could not connect to device\n");
break;
}
vTaskDelay(2000 / portTICK_PERIOD_MS);
continue;
}
if (!theChannel) {
printf("l2cap channel not initialized\n");
vTaskDelay(2000 / portTICK_PERIOD_MS);
continue;
}
if (!theChannel->isConnected()) {
printf("l2cap channel not connected\n");
vTaskDelay(2000 / portTICK_PERIOD_MS);
continue;
}
while (theChannel->isConnected()) {
/*
static auto initialDelay = true;
if (initialDelay) {
printf("Waiting gracefully 3 seconds before sending data\n");
vTaskDelay(3000 / portTICK_PERIOD_MS);
initialDelay = false;
};
*/
std::vector<uint8_t> data(5000, sequenceNumber++);
if (theChannel->write(data)) {
bytesSent += data.size();
} else {
printf("failed to send!\n");
abort();
}
}
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
extern "C"
void app_main(void) {
printf("Starting L2CAP client example\n");
xTaskCreate(connectTask, "connectTask", 5000, NULL, 1, NULL);
BLEDevice::init("L2CAP-Client");
BLEDevice::setMTU(BLE_ATT_MTU_MAX);
auto scan = BLEDevice::getScan();
auto callbacks = new MyAdvertisedDeviceCallbacks();
scan->setScanCallbacks(callbacks);
scan->setInterval(1349);
scan->setWindow(449);
scan->setActiveScan(true);
scan->start(25 * 1000, false);
int numberOfSeconds = 0;
while (bytesSent == 0) {
vTaskDelay(10 / portTICK_PERIOD_MS);
}
while (true) {
vTaskDelay(1000 / portTICK_PERIOD_MS);
int bytesSentPerSeconds = bytesSent / ++numberOfSeconds;
printf("Bandwidth: %d b/sec = %d KB/sec\n", bytesSentPerSeconds, bytesSentPerSeconds / 1024);
}
}

View File

@@ -1,13 +0,0 @@
# Override some defaults so BT stack is enabled
# in this example
#
# BT config
#
CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM=1

View File

@@ -1,7 +0,0 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(SUPPORTED_TARGETS esp32 esp32s3 esp32c3 esp32c6)
project(L2CAP_server)

View File

@@ -1,3 +0,0 @@
PROJECT_NAME := L2CAP_server
include $(IDF_PATH)/make/project.mk

View File

@@ -1,4 +0,0 @@
set(COMPONENT_SRCS "main.cpp")
set(COMPONENT_ADD_INCLUDEDIRS ".")
register_component()

View File

@@ -1,4 +0,0 @@
#
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

View File

@@ -1,3 +0,0 @@
dependencies:
local/esp-nimble-cpp:
path: ../../../../../esp-nimble-cpp/

View File

@@ -1,90 +0,0 @@
#include <NimBLEDevice.h>
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "dcbc7255-1e9e-49a0-a360-b0430b6c6905"
#define CHARACTERISTIC_UUID "371a55c8-f251-4ad2-90b3-c7c195b049be"
#define L2CAP_CHANNEL 150
#define L2CAP_MTU 5000
class GATTCallbacks: public BLEServerCallbacks {
public:
void onConnect(BLEServer* pServer, BLEConnInfo& info) {
/// Booster #1
pServer->setDataLen(info.getConnHandle(), 251);
/// Booster #2 (especially for Apple devices)
BLEDevice::getServer()->updateConnParams(info.getConnHandle(), 12, 12, 0, 200);
}
};
class L2CAPChannelCallbacks: public BLEL2CAPChannelCallbacks {
public:
bool connected = false;
size_t numberOfReceivedBytes;
uint8_t nextSequenceNumber;
public:
void onConnect(NimBLEL2CAPChannel* channel) {
printf("L2CAP connection established\n");
connected = true;
numberOfReceivedBytes = nextSequenceNumber = 0;
}
void onRead(NimBLEL2CAPChannel* channel, std::vector<uint8_t>& data) {
numberOfReceivedBytes += data.size();
size_t sequenceNumber = data[0];
printf("L2CAP read %d bytes w/ sequence number %d", data.size(), sequenceNumber);
if (sequenceNumber != nextSequenceNumber) {
printf("(wrong sequence number %d, expected %d)\n", sequenceNumber, nextSequenceNumber);
} else {
printf("\n");
nextSequenceNumber++;
}
}
void onDisconnect(NimBLEL2CAPChannel* channel) {
printf("L2CAP disconnected\n");
connected = false;
}
};
extern "C"
void app_main(void) {
printf("Starting L2CAP server example [%lu free] [%lu min]\n", esp_get_free_heap_size(), esp_get_minimum_free_heap_size());
BLEDevice::init("L2CAP-Server");
BLEDevice::setMTU(BLE_ATT_MTU_MAX);
auto cocServer = BLEDevice::createL2CAPServer();
auto l2capChannelCallbacks = new L2CAPChannelCallbacks();
auto channel = cocServer->createService(L2CAP_CHANNEL, L2CAP_MTU, l2capChannelCallbacks);
auto server = BLEDevice::createServer();
server->setCallbacks(new GATTCallbacks());
auto service = server->createService(SERVICE_UUID);
auto characteristic = service->createCharacteristic(CHARACTERISTIC_UUID, NIMBLE_PROPERTY::READ);
characteristic->setValue(L2CAP_CHANNEL);
service->start();
auto advertising = BLEDevice::getAdvertising();
advertising->addServiceUUID(SERVICE_UUID);
advertising->enableScanResponse(true);
BLEDevice::startAdvertising();
printf("Server waiting for connection requests [%lu free] [%lu min]\n", esp_get_free_heap_size(), esp_get_minimum_free_heap_size());
// Wait until transfer actually starts...
while (!l2capChannelCallbacks->numberOfReceivedBytes) {
vTaskDelay(10 / portTICK_PERIOD_MS);
}
printf("\n\n\n");
int numberOfSeconds = 0;
while (true) {
vTaskDelay(1000 / portTICK_PERIOD_MS);
if (!l2capChannelCallbacks->connected) { continue; }
int bps = l2capChannelCallbacks->numberOfReceivedBytes / ++numberOfSeconds;
printf("Bandwidth: %d b/sec = %d KB/sec [%lu free] [%lu min]\n", bps, bps / 1024, esp_get_free_heap_size(), esp_get_minimum_free_heap_size());
}
}

View File

@@ -1,13 +0,0 @@
# Override some defaults so BT stack is enabled
# in this example
#
# BT config
#
CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM=1

View File

@@ -112,7 +112,7 @@ bool connectToServer() {
/** No client to reuse? Create a new one. */
if (!pClient) {
if (NimBLEDevice::getCreatedClientCount() >= MYNEWT_VAL(BLE_MAX_CONNECTIONS)) {
if (NimBLEDevice::getCreatedClientCount() >= NIMBLE_MAX_CONNECTIONS) {
printf("Max clients reached - no more connections available\n");
return false;
}
@@ -261,7 +261,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);
/** 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.2"
version: "2.1.1"
license: "Apache-2.0"
description: "C++ wrapper for the NimBLE BLE stack"
url: "https://github.com/h2zero/esp-nimble-cpp"
@@ -16,7 +16,7 @@ dependencies:
rules:
- if: "target in [esp32p4]"
espressif/esp_wifi_remote:
version: ">=0.5.3"
version: "<0.5.4"
rules:
- if: "target in [esp32p4]"
idf:

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,8 +15,10 @@
* limitations under the License.
*/
#include "NimBLE2904.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# include "NimBLE2904.h"
NimBLE2904::NimBLE2904(NimBLECharacteristic* pChr)
: NimBLEDescriptor(NimBLEUUID((uint16_t)0x2904), BLE_GATT_CHR_F_READ, sizeof(NimBLE2904Data), pChr) {
@@ -69,4 +71,4 @@ void NimBLE2904::setUnit(uint16_t unit) {
setValue(m_data);
} // setUnit
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_2904_H_
#define NIMBLE_CPP_2904_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# include "NimBLEDescriptor.h"
@@ -68,7 +68,7 @@ class NimBLE2904 : public NimBLEDescriptor {
static const uint8_t FORMAT_OPAQUE = 27;
static const uint8_t FORMAT_MEDASN1 = 28;
void setDescription(uint16_t description);
void setDescription(uint16_t);
void setExponent(int8_t exponent);
void setFormat(uint8_t format);
void setNamespace(uint8_t namespace_value);
@@ -79,5 +79,5 @@ class NimBLE2904 : public NimBLEDescriptor {
NimBLE2904Data m_data{};
}; // NimBLE2904
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
#endif // NIMBLE_CPP_2904_H_

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,9 +15,10 @@
* limitations under the License.
*/
#include "NimBLEAddress.h"
#if CONFIG_BT_NIMBLE_ENABLED
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
# include "NimBLEAddress.h"
# include "NimBLELog.h"
# include <algorithm>
@@ -223,16 +224,11 @@ 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

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,9 +17,8 @@
#ifndef NIMBLE_CPP_ADDRESS_H_
#define NIMBLE_CPP_ADDRESS_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
# if defined(CONFIG_NIMBLE_CPP_IDF)
# include "nimble/ble.h"
@@ -67,5 +66,5 @@ class NimBLEAddress : private ble_addr_t {
operator uint64_t() const;
};
#endif // CONFIG_BT_NIMBLE_ENABLED
#endif // NIMBLE_CPP_ADDRESS_H_
#endif /* CONFIG_BT_ENABLED */
#endif /* NIMBLE_CPP_ADDRESS_H_ */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,10 +15,11 @@
* limitations under the License.
*/
#include "NimBLEAdvertisedDevice.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_OBSERVER)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
# include "NimBLEDevice.h"
# include "NimBLEAdvertisedDevice.h"
# include "NimBLEUtils.h"
# include "NimBLELog.h"
@@ -31,7 +32,7 @@ static const char* LOG_TAG = "NimBLEAdvertisedDevice";
* @param [in] event The advertisement event data.
*/
NimBLEAdvertisedDevice::NimBLEAdvertisedDevice(const ble_gap_event* event, uint8_t eventType)
# if MYNEWT_VAL(BLE_EXT_ADV)
# if CONFIG_BT_NIMBLE_EXT_ADV
: m_address{event->ext_disc.addr},
m_advType{eventType},
m_rssi{event->ext_disc.rssi},
@@ -58,7 +59,7 @@ 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 MYNEWT_VAL(BLE_EXT_ADV)
# if CONFIG_BT_NIMBLE_EXT_ADV
const auto& disc = event->ext_disc;
m_isLegacyAdv = disc.props & BLE_HCI_ADV_LEGACY_MASK;
# else
@@ -580,7 +581,7 @@ bool NimBLEAdvertisedDevice::haveTXPower() const {
return findAdvField(BLE_HS_ADV_TYPE_TX_PWR_LVL) > 0;
} // haveTXPower
# if MYNEWT_VAL(BLE_EXT_ADV)
# if CONFIG_BT_NIMBLE_EXT_ADV
/**
* @brief Get the set ID of the extended advertisement.
* @return The set ID.
@@ -751,7 +752,7 @@ uint8_t NimBLEAdvertisedDevice::getAddressType() const {
* @return True if the device is connectable.
*/
bool NimBLEAdvertisedDevice::isConnectable() const {
# if MYNEWT_VAL(BLE_EXT_ADV)
# 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;
}
@@ -772,23 +773,13 @@ bool NimBLEAdvertisedDevice::isScannable() const {
* @return True if legacy (Bluetooth 4.x), false if extended (bluetooth 5.x).
*/
bool NimBLEAdvertisedDevice::isLegacyAdvertisement() const {
# if MYNEWT_VAL(BLE_EXT_ADV)
# if CONFIG_BT_NIMBLE_EXT_ADV
return m_isLegacyAdv;
# else
return true;
# endif
} // isLegacyAdvertisement
/**
* @brief Convenience operator to convert this NimBLEAdvertisedDevice to NimBLEAddress representation.
* @details This allows passing NimBLEAdvertisedDevice to functions
* that accept NimBLEAddress and/or or it's methods as a parameter.
*/
NimBLEAdvertisedDevice::operator NimBLEAddress() const {
NimBLEAddress address(getAddress());
return address;
} // operator NimBLEAddress
/**
* @brief Get the payload advertised by the device.
* @return The advertisement payload.
@@ -813,4 +804,4 @@ const std::vector<uint8_t>::const_iterator NimBLEAdvertisedDevice::end() const {
return m_payload.cend();
}
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_OBSERVER)
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_ADVERTISED_DEVICE_H_
#define NIMBLE_CPP_ADVERTISED_DEVICE_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_OBSERVER)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
# include "NimBLEAddress.h"
# include "NimBLEScan.h"
@@ -87,13 +87,12 @@ class NimBLEAdvertisedDevice {
bool isConnectable() const;
bool isScannable() const;
bool isLegacyAdvertisement() const;
# if MYNEWT_VAL(BLE_EXT_ADV)
# if CONFIG_BT_NIMBLE_EXT_ADV
uint8_t getSetId() const;
uint8_t getPrimaryPhy() const;
uint8_t getSecondaryPhy() const;
uint16_t getPeriodicInterval() const;
# endif
operator NimBLEAddress() const;
const std::vector<uint8_t>& getPayload() const;
const std::vector<uint8_t>::const_iterator begin() const;
@@ -163,7 +162,7 @@ class NimBLEAdvertisedDevice {
uint8_t m_callbackSent{};
uint8_t m_advLength{};
# if MYNEWT_VAL(BLE_EXT_ADV)
# if CONFIG_BT_NIMBLE_EXT_ADV
bool m_isLegacyAdv{};
uint8_t m_sid{};
uint8_t m_primPhy{};
@@ -174,5 +173,5 @@ class NimBLEAdvertisedDevice {
std::vector<uint8_t> m_payload;
};
#endif /* CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_OBSERVER) */
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_OBSERVER */
#endif /* NIMBLE_CPP_ADVERTISED_DEVICE_H_ */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,9 +15,11 @@
* limitations under the License.
*/
#include "NimBLEAdvertisementData.h"
#if (CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && !MYNEWT_VAL(BLE_EXT_ADV)) || defined(_DOXYGEN_)
#include "nimconfig.h"
#if (defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && !CONFIG_BT_NIMBLE_EXT_ADV) || \
defined(_DOXYGEN_)
# include "NimBLEAdvertisementData.h"
# include "NimBLEDevice.h"
# include "NimBLEUtils.h"
# include "NimBLEUUID.h"
@@ -583,4 +585,4 @@ std::string NimBLEAdvertisementData::toString() const {
return str;
} // toString
#endif // (CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && !MYNEWT_VAL(BLE_EXT_ADV)) || defined(_DOXYGEN_)
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && !CONFIG_BT_NIMBLE_EXT_ADV

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +18,9 @@
#ifndef NIMBLE_CPP_ADVERTISEMENT_DATA_H_
#define NIMBLE_CPP_ADVERTISEMENT_DATA_H_
#include "syscfg/syscfg.h"
#if (CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && !MYNEWT_VAL(BLE_EXT_ADV)) || defined(_DOXYGEN_)
#include "nimconfig.h"
#if (defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && !CONFIG_BT_NIMBLE_EXT_ADV) || \
defined(_DOXYGEN_)
# include <cstdint>
# include <string>
@@ -37,7 +38,7 @@ class NimBLEAdvertisementData {
bool addData(const uint8_t* data, size_t length);
bool addData(const std::vector<uint8_t>& data);
bool setAppearance(uint16_t appearance);
bool setFlags(uint8_t flag);
bool setFlags(uint8_t);
bool addTxPower();
bool setPreferredParams(uint16_t minInterval, uint16_t maxInterval);
bool addServiceUUID(const NimBLEUUID& serviceUUID);
@@ -74,5 +75,5 @@ class NimBLEAdvertisementData {
std::vector<uint8_t> m_payload{};
}; // NimBLEAdvertisementData
#endif // (CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && !MYNEWT_VAL(BLE_EXT_ADV)) || defined(_DOXYGEN_)
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && !CONFIG_BT_NIMBLE_EXT_ADV
#endif // NIMBLE_CPP_ADVERTISEMENT_DATA_H_

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,14 +15,16 @@
* limitations under the License.
*/
#include "NimBLEAdvertising.h"
#if (CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && !MYNEWT_VAL(BLE_EXT_ADV)) || defined(_DOXYGEN_)
#include "nimconfig.h"
#if (defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && !CONFIG_BT_NIMBLE_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"
@@ -42,7 +44,7 @@ NimBLEAdvertising::NimBLEAdvertising()
m_duration{BLE_HS_FOREVER},
m_scanResp{false},
m_advDataSet{false} {
# if !MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# if !defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
m_advParams.conn_mode = BLE_GAP_CONN_MODE_NON;
# else
m_advParams.conn_mode = BLE_GAP_CONN_MODE_UND;
@@ -195,7 +197,7 @@ bool NimBLEAdvertising::start(uint32_t duration, const NimBLEAddress* dirAddr) {
return true;
}
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
NimBLEServer* pServer = NimBLEDevice::getServer();
if (pServer != nullptr) {
pServer->start(); // make sure the GATT server is ready before advertising
@@ -220,7 +222,7 @@ bool NimBLEAdvertising::start(uint32_t duration, const NimBLEAddress* dirAddr) {
duration = BLE_HS_FOREVER;
}
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
int rc = ble_gap_adv_start(NimBLEDevice::m_ownAddrType,
(dirAddr != nullptr) ? dirAddr->getBase() : NULL,
duration,
@@ -620,4 +622,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_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && !MYNEWT_VAL(BLE_EXT_ADV)) || defined(_DOXYGEN_)
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && !CONFIG_BT_NIMBLE_EXT_ADV */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +18,9 @@
#ifndef NIMBLE_CPP_ADVERTISING_H_
#define NIMBLE_CPP_ADVERTISING_H_
#include "syscfg/syscfg.h"
#if (CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && !MYNEWT_VAL(BLE_EXT_ADV)) || defined(_DOXYGEN_)
#include "nimconfig.h"
#if (defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && !CONFIG_BT_NIMBLE_EXT_ADV) || \
defined(_DOXYGEN_)
# if defined(CONFIG_NIMBLE_CPP_IDF)
# include "host/ble_gap.h"
@@ -105,5 +106,5 @@ class NimBLEAdvertising {
bool m_advDataSet : 1;
};
#endif // (CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && !MYNEWT_VAL(BLE_EXT_ADV)) || defined(_DOXYGEN_)
#endif // NIMBLE_CPP_ADVERTISING_H_
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && !CONFIG_BT_NIMBLE_EXT_ADV */
#endif /* NIMBLE_CPP_ADVERTISING_H_ */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,8 +15,8 @@
* limitations under the License.
*/
#include "NimBLEAttValue.h"
#if CONFIG_BT_NIMBLE_ENABLED
#include "nimconfig.h"
#if defined(CONFIG_BT_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 "NimBLEUtils.h"
# include "NimBLEAttValue.h"
# include "NimBLELog.h"
static const char* LOG_TAG = "NimBLEAttValue";
@@ -105,8 +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_value[0] = '\0'; // Set the first byte to 0 incase the len of the new value is 0.
m_attr_len = 0; // Just set the value length to 0 and append instead of repeating code.
append(value, len);
return memcmp(m_attr_value, value, len) == 0 && m_attr_len == len;
}
@@ -160,4 +159,4 @@ uint8_t NimBLEAttValue::operator[](int pos) const {
return m_attr_value[pos];
}
#endif // CONFIG_BT_NIMBLE_ENABLED
#endif // CONFIG_BT_ENABLED

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,9 +17,8 @@
#ifndef NIMBLE_CPP_ATTVALUE_H
#define NIMBLE_CPP_ATTVALUE_H
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
# ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE
# include <Arduino.h>
@@ -306,6 +305,9 @@ class NimBLEAttValue {
*/
template <typename T>
T getValue(time_t* timestamp = nullptr, bool skipSizeCheck = false) const {
if (!skipSizeCheck && size() < sizeof(T)) {
return T();
}
if (timestamp != nullptr) {
# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
*timestamp = m_timestamp;
@@ -314,9 +316,6 @@ class NimBLEAttValue {
# endif
}
if (!skipSizeCheck && size() < sizeof(T)) {
return T();
}
return *(reinterpret_cast<const T*>(m_attr_value));
}
@@ -363,5 +362,5 @@ class NimBLEAttValue {
# endif
};
#endif // CONFIG_BT_NIMBLE_ENABLED
#endif // NIMBLE_CPP_ATTVALUE_H_
#endif /*(CONFIG_BT_ENABLED) */
#endif /* NIMBLE_CPP_ATTVALUE_H_ */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_ATTRIBUTE_H_
#define NIMBLE_CPP_ATTRIBUTE_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && (MYNEWT_VAL(BLE_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_ROLE_CENTRAL))
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && (defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) || defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL))
# include "NimBLEUUID.h"
@@ -56,5 +56,5 @@ class NimBLEAttribute {
uint16_t m_handle{0};
};
#endif // CONFIG_BT_NIMBLE_ENABLED && (MYNEWT_VAL(BLE_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_ROLE_CENTRAL))
#endif // CONFIG_BT_ENABLED && (CONFIG_BT_NIMBLE_ROLE_PERIPHERAL || CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#endif // NIMBLE_CPP_ATTRIBUTE_H_

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,9 +15,10 @@
* limitations under the License.
*/
#include "NimBLEBeacon.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
# include "NimBLEBeacon.h"
# include "NimBLEUUID.h"
# include "NimBLELog.h"
@@ -137,4 +138,4 @@ void NimBLEBeacon::setSignalPower(int8_t signalPower) {
m_beaconData.signalPower = signalPower;
} // setSignalPower
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER)
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,13 +18,12 @@
#ifndef NIMBLE_CPP_BEACON_H_
#define NIMBLE_CPP_BEACON_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
class NimBLEUUID;
# include <cstdint>
# include <vector>
/**
* @brief Representation of a beacon.
@@ -41,10 +40,6 @@ 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();
@@ -65,5 +60,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

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,16 +15,10 @@
* 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 "NimBLE2904.h"
# include "NimBLEDevice.h"
# include "NimBLELog.h"
@@ -274,58 +268,42 @@ bool NimBLECharacteristic::sendValue(const uint8_t* value, size_t length, bool i
int rc = 0;
if (value != nullptr && length > 0) { // custom notification value
os_mbuf* om = nullptr;
if (connHandle != BLE_HS_CONN_HANDLE_NONE) { // only sending to specific peer
om = ble_hs_mbuf_from_flat(value, length);
if (!om) {
rc = BLE_HS_ENOMEM;
goto done;
}
// Null buffer will read the value from the characteristic
if (isNotification) {
rc = ble_gatts_notify_custom(connHandle, m_handle, om);
} else {
rc = ble_gatts_indicate_custom(connHandle, m_handle, om);
}
goto done;
}
// Notify all connected peers unless a specific handle is provided
for (const auto& ch : NimBLEDevice::getServer()->getPeerDevices()) {
if (connHandle != BLE_HS_CONN_HANDLE_NONE && ch != connHandle) {
continue; // only send to the specific handle, minor inefficiency but saves code.
}
// 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);
os_mbuf* om = ble_hs_mbuf_from_flat(value, length);
if (!om) {
rc = BLE_HS_ENOMEM;
goto done;
NIMBLE_LOGE(LOG_TAG, "<< sendValue: failed to allocate mbuf");
return false;
}
if (isNotification) {
rc = ble_gatts_notify_custom(ch, m_handle, om);
rc = ble_gattc_notify_custom(ch, m_handle, om);
} else {
rc = ble_gatts_indicate_custom(ch, m_handle, om);
rc = ble_gattc_indicate_custom(ch, m_handle, om);
}
if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "<< sendValue: failed to send value, rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
break;
}
}
} else if (connHandle != BLE_HS_CONN_HANDLE_NONE) {
} else if (connHandle != BLE_HS_CONN_HANDLE_NONE) { // only sending to specific peer
// Null buffer will read the value from the characteristic
if (isNotification) {
rc = ble_gatts_notify_custom(connHandle, m_handle, nullptr);
rc = ble_gattc_notify_custom(connHandle, m_handle, NULL);
} else {
rc = ble_gatts_indicate_custom(connHandle, m_handle, nullptr);
rc = ble_gattc_indicate_custom(connHandle, m_handle, NULL);
}
} 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;
}
return true;
return rc == 0;
} // sendValue
void NimBLECharacteristic::readEvent(NimBLEConnInfo& connInfo) {
@@ -421,4 +399,4 @@ void NimBLECharacteristicCallbacks::onSubscribe(NimBLECharacteristic* pCharacter
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onSubscribe: default");
}
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,9 +17,8 @@
#ifndef NIMBLE_CPP_CHARACTERISTIC_H_
#define NIMBLE_CPP_CHARACTERISTIC_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
class NimBLECharacteristicCallbacks;
class NimBLEService;
@@ -88,9 +87,7 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
# ifdef _DOXYGEN_
bool
# else
typename std::enable_if<!std::is_pointer<T>::value && !std::is_array<T>::value && !Has_c_str_length<T>::value &&
!Has_data_size<T>::value,
bool>::type
typename std::enable_if<!std::is_pointer<T>::value && !Has_c_str_length<T>::value && !Has_data_size<T>::value, bool>::type
# endif
notify(const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const {
return notify(reinterpret_cast<const uint8_t*>(&v), sizeof(T), connHandle);
@@ -136,9 +133,7 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
# ifdef _DOXYGEN_
bool
# else
typename std::enable_if<!std::is_pointer<T>::value && !std::is_array<T>::value && !Has_c_str_length<T>::value &&
!Has_data_size<T>::value,
bool>::type
typename std::enable_if<!std::is_pointer<T>::value && !Has_c_str_length<T>::value && !Has_data_size<T>::value, bool>::type
# endif
indicate(const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const {
return indicate(reinterpret_cast<const uint8_t*>(&v), sizeof(T), connHandle);
@@ -187,8 +182,8 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
* @note This function is only available if the type T is not a pointer.
*/
template <typename T>
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 {
typename std::enable_if<!std::is_pointer<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);
} else if constexpr (Has_c_str_length<T>::value) {
@@ -209,7 +204,7 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
* @note This function is only available if the type T is not a pointer.
*/
template <typename T>
typename std::enable_if<!std::is_pointer<T>::value && !std::is_array<T>::value, bool>::type indicate(
typename std::enable_if<!std::is_pointer<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);
@@ -254,5 +249,5 @@ class NimBLECharacteristicCallbacks {
virtual void onSubscribe(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo, uint16_t subValue);
};
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#endif // NIMBLE_CPP_CHARACTERISTIC_H_
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
#endif /*NIMBLE_CPP_CHARACTERISTIC_H_*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,9 +15,10 @@
* limitations under the License.
*/
#include "NimBLEClient.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# include "NimBLEClient.h"
# include "NimBLERemoteService.h"
# include "NimBLERemoteCharacteristic.h"
# include "NimBLEDevice.h"
@@ -68,7 +69,7 @@ NimBLEClient::NimBLEClient(const NimBLEAddress& peerAddress)
m_terminateFailCount{0},
m_asyncSecureAttempt{0},
m_config{},
# if MYNEWT_VAL(BLE_EXT_ADV)
# if CONFIG_BT_NIMBLE_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,
@@ -125,24 +126,6 @@ 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.
* @param [in] deleteAttributes If true this will delete any attribute objects this client may already\n
* have created when last connected.
* @param [in] asyncConnect If true, the connection will be made asynchronously and this function will return immediately.\n
* If false, this function will block until the connection is established or the connection attempt times out.
* @param [in] exchangeMTU If true, the client will attempt to exchange MTU with the server after connection.\n
* If false, the client will use the default MTU size and the application will need to call exchangeMTU() later.
* @return true on success.
*/
bool NimBLEClient::connect(const NimBLEAdvertisedDevice* pDevice, bool deleteAttributes, bool asyncConnect, bool exchangeMTU) {
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
* passed to the constructor.
@@ -158,6 +141,22 @@ bool NimBLEClient::connect(bool deleteAttributes, bool asyncConnect, bool exchan
return connect(m_peerAddress, deleteAttributes, asyncConnect, exchangeMTU);
} // connect
/**
* @brief Connect to an advertising device.
* @param [in] device The device to connect to.
* @param [in] deleteAttributes If true this will delete any attribute objects this client may already\n
* have created when last connected.
* @param [in] asyncConnect If true, the connection will be made asynchronously and this function will return immediately.\n
* If false, this function will block until the connection is established or the connection attempt times out.
* @param [in] exchangeMTU If true, the client will attempt to exchange MTU with the server after connection.\n
* If false, the client will use the default MTU size and the application will need to call exchangeMTU() later.
* @return true on success.
*/
bool NimBLEClient::connect(const NimBLEAdvertisedDevice* device, bool deleteAttributes, bool asyncConnect, bool exchangeMTU) {
NimBLEAddress address(device->getAddress());
return connect(address, deleteAttributes, asyncConnect, exchangeMTU);
} // connect
/**
* @brief Connect to a BLE Server by address.
* @param [in] address The address of the server.
@@ -204,7 +203,7 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes,
m_config.exchangeMTU = exchangeMTU;
do {
# if MYNEWT_VAL(BLE_EXT_ADV)
# if CONFIG_BT_NIMBLE_EXT_ADV
rc = ble_gap_ext_connect(NimBLEDevice::m_ownAddrType,
peerAddr,
m_connectTimeout,
@@ -228,15 +227,10 @@ 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:
@@ -402,7 +396,7 @@ void NimBLEClient::setConfig(NimBLEClient::Config config) {
m_config = config;
} // setConfig
# if MYNEWT_VAL(BLE_EXT_ADV)
# if CONFIG_BT_NIMBLE_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
@@ -414,7 +408,6 @@ void NimBLEClient::setConfig(NimBLEClient::Config config) {
void NimBLEClient::setConnectPhy(uint8_t mask) {
m_phyMask = mask;
} // setConnectPhy
# endif
/**
* @brief Request a change to the PHY used for this peer connection.
@@ -457,6 +450,7 @@ bool NimBLEClient::getPhy(uint8_t* txPhy, uint8_t* rxPhy) {
return rc == 0;
} // getPhy
# endif
/**
* @brief Set the connection parameters to use when connecting to a server.
@@ -933,16 +927,9 @@ 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::getClientByPeerAddress(event->disconnect.conn.peer_ota_addr);
pClient = NimBLEDevice::getClientByHandle(event->disconnect.conn.conn_handle);
if (pClient == nullptr) {
pClient = NimBLEDevice::getClientByPeerAddress(event->disconnect.conn.peer_id_addr);
}
if (pClient == nullptr) {
NIMBLE_LOGE(LOG_TAG, "Disconnected client not found, conn_handle=%d",
event->disconnect.conn.conn_handle);
return 0;
}
@@ -967,9 +954,7 @@ 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) {
pClient->m_pClientCallbacks->onConnectFail(pClient, rc);
} else {
if (rc != (BLE_HS_ERR_HCI_BASE + BLE_ERR_CONN_ESTABLISHMENT) || pClient->m_config.asyncConnect) {
pClient->m_pClientCallbacks->onDisconnect(pClient, rc);
}
@@ -997,10 +982,6 @@ 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;
@@ -1160,6 +1141,7 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) {
break;
} // BLE_GAP_EVENT_IDENTITY_RESOLVED
# if CONFIG_BT_NIMBLE_EXT_ADV
case BLE_GAP_EVENT_PHY_UPDATE_COMPLETE: {
NimBLEConnInfo peerInfo;
rc = ble_gap_conn_find(event->phy_updated.conn_handle, &peerInfo.m_desc);
@@ -1170,6 +1152,7 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) {
pClient->m_pClientCallbacks->onPhyUpdate(pClient, event->phy_updated.tx_phy, event->phy_updated.rx_phy);
return 0;
} // BLE_GAP_EVENT_PHY_UPDATE_COMPLETE
# endif
case BLE_GAP_EVENT_MTU: {
if (pClient->m_connHandle != event->mtu.conn_handle) {
@@ -1315,9 +1298,10 @@ void NimBLEClientCallbacks::onMTUChange(NimBLEClient* pClient, uint16_t mtu) {
NIMBLE_LOGD(CB_TAG, "onMTUChange: default");
} // onMTUChange
# if CONFIG_BT_NIMBLE_EXT_ADV
void NimBLEClientCallbacks::onPhyUpdate(NimBLEClient* pClient, uint8_t txPhy, uint8_t rxPhy) {
NIMBLE_LOGD(CB_TAG, "onPhyUpdate: default, txPhy: %d, rxPhy: %d", txPhy, rxPhy);
} // onPhyUpdate
#
# endif
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_CLIENT_H_
#define NIMBLE_CPP_CLIENT_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# if defined(CONFIG_NIMBLE_CPP_IDF)
# include "host/ble_gap.h"
@@ -48,12 +48,10 @@ 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);
@@ -95,11 +93,11 @@ class NimBLEClient {
const NimBLEAttValue& value,
bool response = false);
# if MYNEWT_VAL(BLE_EXT_ADV)
# if CONFIG_BT_NIMBLE_EXT_ADV
void setConnectPhy(uint8_t phyMask);
# endif
bool updatePhy(uint8_t txPhysMask, uint8_t rxPhysMask, uint16_t phyOptions = 0);
bool getPhy(uint8_t* txPhy, uint8_t* rxPhy);
# endif
struct Config {
uint8_t deleteCallbacks : 1; // Delete the callback object when the client is deleted.
@@ -137,7 +135,7 @@ class NimBLEClient {
mutable uint8_t m_asyncSecureAttempt;
Config m_config;
# if MYNEWT_VAL(BLE_EXT_ADV)
# if CONFIG_BT_NIMBLE_EXT_ADV
uint8_t m_phyMask;
# endif
ble_gap_conn_params m_connParams;
@@ -215,6 +213,7 @@ class NimBLEClientCallbacks {
*/
virtual void onMTUChange(NimBLEClient* pClient, uint16_t MTU);
# if CONFIG_BT_NIMBLE_EXT_ADV
/**
* @brief Called when the PHY update procedure is complete.
* @param [in] pClient A pointer to the client whose PHY was updated.
@@ -227,7 +226,8 @@ class NimBLEClientCallbacks {
* * BLE_GAP_LE_PHY_CODED
*/
virtual void onPhyUpdate(NimBLEClient* pClient, uint8_t txPhy, uint8_t rxPhy);
# endif
};
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
#endif // NIMBLE_CPP_CLIENT_H_
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
#endif /* NIMBLE_CPP_CLIENT_H_ */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,8 +15,8 @@
* limitations under the License.
*/
#ifndef NIMBLE_CPP_CONNINFO_H_
#define NIMBLE_CPP_CONNINFO_H_
#ifndef NIMBLECONNINFO_H_
#define NIMBLECONNINFO_H_
#if defined(CONFIG_NIMBLE_CPP_IDF)
# include "host/ble_gap.h"
@@ -80,5 +80,4 @@ class NimBLEConnInfo {
NimBLEConnInfo() {};
NimBLEConnInfo(ble_gap_conn_desc desc) { m_desc = desc; }
};
#endif // NIMBLE_CPP_CONNINFO_H_
#endif

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,10 +15,11 @@
* limitations under the License.
*/
#include "NimBLEDescriptor.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# include "NimBLEService.h"
# include "NimBLEDescriptor.h"
# include "NimBLELog.h"
# include <string>
@@ -147,4 +148,4 @@ void NimBLEDescriptorCallbacks::onWrite(NimBLEDescriptor* pDescriptor, NimBLECon
NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onWrite: default");
} // onWrite
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_DESCRIPTOR_H_
#define NIMBLE_CPP_DESCRIPTOR_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# include "NimBLELocalValueAttribute.h"
# include <string>
@@ -72,5 +72,5 @@ class NimBLEDescriptorCallbacks {
# include "NimBLE2904.h"
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#endif // NIMBLE_CPP_DESCRIPTOR_H_
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
#endif /* NIMBLE_CPP_DESCRIPTOR_H_ */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,8 +15,11 @@
* limitations under the License.
*/
#include "NimBLEDevice.h"
#if CONFIG_BT_NIMBLE_ENABLED
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
# include "NimBLEDevice.h"
# include "NimBLEUtils.h"
# ifdef ESP_PLATFORM
# include "esp_err.h"
@@ -56,6 +59,14 @@
# 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"
# endif
# include "NimBLELog.h"
static const char* LOG_TAG = "NimBLEDevice";
@@ -65,30 +76,24 @@ extern "C" void ble_store_config_init(void);
/**
* Singletons for the NimBLEDevice.
*/
NimBLEDeviceCallbacks NimBLEDevice::defaultDeviceCallbacks{};
NimBLEDeviceCallbacks* NimBLEDevice::m_pDeviceCallbacks = &defaultDeviceCallbacks;
# if MYNEWT_VAL(BLE_ROLE_OBSERVER)
# if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
NimBLEScan* NimBLEDevice::m_pScan = nullptr;
# endif
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
NimBLEServer* NimBLEDevice::m_pServer = nullptr;
# if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
NimBLEL2CAPServer* NimBLEDevice::m_pL2CAPServer = nullptr;
# endif
# endif
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# if MYNEWT_VAL(BLE_EXT_ADV)
# if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
# if CONFIG_BT_NIMBLE_EXT_ADV
NimBLEExtAdvertising* NimBLEDevice::m_bleAdvertising = nullptr;
# else
NimBLEAdvertising* NimBLEDevice::m_bleAdvertising = nullptr;
# endif
# endif
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
std::array<NimBLEClient*, MYNEWT_VAL(BLE_MAX_CONNECTIONS)> NimBLEDevice::m_pClients{};
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
std::array<NimBLEClient*, NIMBLE_MAX_CONNECTIONS> NimBLEDevice::m_pClients{nullptr};
# endif
bool NimBLEDevice::m_initialized{false};
@@ -99,18 +104,9 @@ std::vector<NimBLEAddress> NimBLEDevice::m_whiteList{};
uint8_t NimBLEDevice::m_ownAddrType{BLE_OWN_ADDR_PUBLIC};
# ifdef ESP_PLATFORM
# if CONFIG_BTDM_BLE_SCAN_DUPL
# ifdef CONFIG_BTDM_BLE_SCAN_DUPL
uint16_t NimBLEDevice::m_scanDuplicateSize{CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE};
uint8_t NimBLEDevice::m_scanFilterMode{CONFIG_BTDM_SCAN_DUPL_TYPE};
uint16_t NimBLEDevice::m_scanDuplicateResetTime{0};
# elif CONFIG_BT_LE_SCAN_DUPL
uint16_t NimBLEDevice::m_scanDuplicateSize{CONFIG_BT_LE_LL_DUP_SCAN_LIST_COUNT};
uint8_t NimBLEDevice::m_scanFilterMode{CONFIG_BT_LE_SCAN_DUPL_TYPE};
uint16_t NimBLEDevice::m_scanDuplicateResetTime{0};
extern "C" int ble_vhci_disc_duplicate_set_max_cache_size(int max_cache_size);
extern "C" int ble_vhci_disc_duplicate_set_period_refresh_time(int refresh_period_time);
extern "C" int ble_vhci_disc_duplicate_mode_disable(int mode);
extern "C" int ble_vhci_disc_duplicate_mode_enable(int mode);
# endif
# endif
@@ -118,7 +114,7 @@ extern "C" int ble_vhci_disc_duplicate_mode_enable(int mode);
/* SERVER FUNCTIONS */
/* -------------------------------------------------------------------------- */
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
/**
* @brief Create an instance of a server.
* @return A pointer to the instance of the server.
@@ -141,35 +137,14 @@ NimBLEServer* NimBLEDevice::createServer() {
NimBLEServer* NimBLEDevice::getServer() {
return m_pServer;
} // getServer
# 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.
*/
NimBLEL2CAPServer* NimBLEDevice::createL2CAPServer() {
if (NimBLEDevice::m_pL2CAPServer == nullptr) {
NimBLEDevice::m_pL2CAPServer = new NimBLEL2CAPServer();
}
return m_pL2CAPServer;
} // createL2CAPServer
/**
* @brief Get the instance of the L2CAP server.
* @return A pointer to the L2CAP server instance or nullptr if none have been created.
*/
NimBLEL2CAPServer* NimBLEDevice::getL2CAPServer() {
return m_pL2CAPServer;
} // getL2CAPServer
# endif // #if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
# endif // #if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
/* -------------------------------------------------------------------------- */
/* ADVERTISING FUNCTIONS */
/* -------------------------------------------------------------------------- */
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# if MYNEWT_VAL(BLE_EXT_ADV)
# if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
# if CONFIG_BT_NIMBLE_EXT_ADV
/**
* @brief Get the instance of the extended advertising object.
* @return A pointer to the extended advertising object.
@@ -203,7 +178,7 @@ bool NimBLEDevice::stopAdvertising(uint8_t instId) {
} // stopAdvertising
# endif
# if !MYNEWT_VAL(BLE_EXT_ADV) || defined(_DOXYGEN_)
# if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
/**
* @brief Get the instance of the advertising object.
* @return A pointer to the advertising object.
@@ -232,7 +207,7 @@ bool NimBLEDevice::startAdvertising(uint32_t duration) {
bool NimBLEDevice::stopAdvertising() {
return getAdvertising()->stop();
} // stopAdvertising
# endif // #if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# endif // #if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
/* -------------------------------------------------------------------------- */
/* SCAN FUNCTIONS */
@@ -243,7 +218,7 @@ bool NimBLEDevice::stopAdvertising() {
* @return The scanning object reference. This is a singleton object. The caller should not
* try and release/delete it.
*/
# if MYNEWT_VAL(BLE_ROLE_OBSERVER)
# if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
NimBLEScan* NimBLEDevice::getScan() {
if (m_pScan == nullptr) {
m_pScan = new NimBLEScan();
@@ -253,7 +228,7 @@ NimBLEScan* NimBLEDevice::getScan() {
} // getScan
# ifdef ESP_PLATFORM
# if CONFIG_BTDM_BLE_SCAN_DUPL || CONFIG_BT_LE_SCAN_DUPL
# ifdef CONFIG_BTDM_BLE_SCAN_DUPL
/**
* @brief Set the duplicate filter cache size for filtering scanned devices.
* @param [in] size The number of advertisements filtered before the cache is reset.\n
@@ -300,34 +275,15 @@ void NimBLEDevice::setScanFilterMode(uint8_t mode) {
m_scanFilterMode = mode;
}
/**
* @brief Set the time in seconds to reset the duplicate cache.
* @param [in] time The time in seconds to reset the cache.
* @details When the cache is reset all scanned devices will be reported again
* even if already seen in the current scan. If set to 0 the cache will never be reset.
*/
void NimBLEDevice::setScanDuplicateCacheResetTime(uint16_t time) {
if (m_initialized) {
NIMBLE_LOGE(LOG_TAG, "Cannot change scan cache reset time while initialized");
return;
} else if (time > 1000) {
NIMBLE_LOGE(LOG_TAG, "Invalid scan cache reset time");
return;
}
NIMBLE_LOGD(LOG_TAG, "Set duplicate cache reset time to: %u", time);
m_scanDuplicateResetTime = time;
}
# endif // CONFIG_BTDM_BLE_SCAN_DUPL || CONFIG_BT_LE_SCAN_DUPL
# endif // CONFIG_BTDM_BLE_SCAN_DUPL
# endif // ESP_PLATFORM
# endif // MYNEWT_VAL(BLE_ROLE_OBSERVER)
# endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
/* -------------------------------------------------------------------------- */
/* CLIENT FUNCTIONS */
/* -------------------------------------------------------------------------- */
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
# if defined(CONFIG_BT_NIMBLE_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.
@@ -350,7 +306,7 @@ NimBLEClient* NimBLEDevice::createClient(const NimBLEAddress& peerAddress) {
}
}
NIMBLE_LOGE(LOG_TAG, "Unable to create client; already at max: %d", MYNEWT_VAL(BLE_MAX_CONNECTIONS));
NIMBLE_LOGE(LOG_TAG, "Unable to create client; already at max: %d", NIMBLE_MAX_CONNECTIONS);
return nullptr;
} // createClient
@@ -462,7 +418,7 @@ std::vector<NimBLEClient*> NimBLEDevice::getConnectedClients() {
return clients;
} // getConnectedClients
# endif // MYNEWT_VAL(BLE_ROLE_CENTRAL)
# endif // #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
/* -------------------------------------------------------------------------- */
/* TRANSMIT POWER */
@@ -517,14 +473,14 @@ bool NimBLEDevice::setPower(int8_t dbm, NimBLETxPowerType type) {
dbm++; // round up to the next multiple of 3 to be able to target 20dbm
}
bool success = false;
esp_power_level_t espPwr = static_cast<esp_power_level_t>(dbm / 3 + ESP_PWR_LVL_N0);
bool success = false;
esp_power_level_t espPwr = static_cast<esp_power_level_t>(dbm / 3 + ESP_PWR_LVL_N0);
if (type == NimBLETxPowerType::All) {
success = setPowerLevel(espPwr, ESP_BLE_PWR_TYPE_ADV);
success &= setPowerLevel(espPwr, ESP_BLE_PWR_TYPE_SCAN);
success &= setPowerLevel(espPwr, ESP_BLE_PWR_TYPE_DEFAULT);
} else if (type == NimBLETxPowerType::Advertise) {
success = setPowerLevel(espPwr, ESP_BLE_PWR_TYPE_ADV);
success = setPowerLevel(espPwr, ESP_BLE_PWR_TYPE_ADV);
} else if (type == NimBLETxPowerType::Scan) {
success = setPowerLevel(espPwr, ESP_BLE_PWR_TYPE_SCAN);
} else if (type == NimBLETxPowerType::Connection) {
@@ -536,13 +492,15 @@ bool NimBLEDevice::setPower(int8_t dbm, NimBLETxPowerType type) {
# else
(void)type; // unused
NIMBLE_LOGD(LOG_TAG, ">> setPower: %d", dbm);
int rc = ble_phy_tx_power_set(dbm);
ble_hci_vs_set_tx_pwr_cp cmd{dbm};
ble_hci_vs_set_tx_pwr_rp rsp{0};
int rc = ble_hs_hci_send_vs_cmd(BLE_HCI_OCF_VS_SET_TX_PWR, &cmd, sizeof(cmd), &rsp, sizeof(rsp));
if (rc) {
NIMBLE_LOGE(LOG_TAG, "failed to set TX power, rc: %04x\n", rc);
return false;
}
NIMBLE_LOGD(LOG_TAG, "TX power set to %d dBm\n", dbm);
NIMBLE_LOGD(LOG_TAG, "TX power set to %d dBm\n", rsp.tx_power);
return true;
# endif
} // setPower
@@ -578,7 +536,7 @@ int NimBLEDevice::getPower(NimBLETxPowerType type) {
# endif
# else
(void)type; // unused
return ble_phy_tx_power_get();
return ble_phy_txpwr_get();
# endif
} // getPower
@@ -613,7 +571,7 @@ uint16_t NimBLEDevice::getMTU() {
/* BOND MANAGEMENT */
/* -------------------------------------------------------------------------- */
# if MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) || defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
/**
* @brief Gets the number of bonded peers stored
*/
@@ -778,6 +736,7 @@ NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) {
/* STACK FUNCTIONS */
/* -------------------------------------------------------------------------- */
# if CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
/**
* @brief Set the preferred default phy to use for connections.
* @param [in] txPhyMask TX PHY. Can be mask of following:
@@ -800,6 +759,7 @@ bool NimBLEDevice::setDefaultPhy(uint8_t txPhyMask, uint8_t rxPhyMask) {
return rc == 0;
}
# endif
/**
* @brief Host reset, we pass the message so we don't make calls until re-synced.
@@ -850,13 +810,13 @@ void NimBLEDevice::onSync(void) {
m_synced = true;
if (m_initialized) {
# if MYNEWT_VAL(BLE_ROLE_OBSERVER)
# if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
if (m_pScan != nullptr) {
m_pScan->onHostSync();
}
# endif
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
if (m_bleAdvertising != nullptr) {
m_bleAdvertising->onHostSync();
}
@@ -881,7 +841,7 @@ bool NimBLEDevice::init(const std::string& deviceName) {
if (!m_initialized) {
# ifdef ESP_PLATFORM
# if defined(CONFIG_ENABLE_ARDUINO_DEPENDS) && SOC_BT_SUPPORTED
# ifdef CONFIG_ENABLE_ARDUINO_DEPENDS
// make sure the linker includes esp32-hal-bt.c so Arduino init doesn't release BLE memory.
btStarted();
# endif
@@ -903,26 +863,18 @@ bool NimBLEDevice::init(const std::string& deviceName) {
esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
# endif
# if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) || !defined(CONFIG_NIMBLE_CPP_IDF)
# if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) | !defined(CONFIG_NIMBLE_CPP_IDF)
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 = MYNEWT_VAL(BLE_MAX_CONNECTIONS);
# elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3)
bt_cfg.ble_max_act = MYNEWT_VAL(BLE_MAX_CONNECTIONS) + MYNEWT_VAL(BLE_ROLE_BROADCASTER) + MYNEWT_VAL(BLE_ROLE_OBSERVER);
# if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3)
bt_cfg.bluetooth_mode = ESP_BT_MODE_BLE;
# else
bt_cfg.nimble_max_connections = MYNEWT_VAL(BLE_MAX_CONNECTIONS);
bt_cfg.mode = ESP_BT_MODE_BLE;
bt_cfg.ble_max_conn = CONFIG_BT_NIMBLE_MAX_CONNECTIONS;
# endif
# if CONFIG_BTDM_BLE_SCAN_DUPL
# ifdef CONFIG_BTDM_BLE_SCAN_DUPL
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;
# endif
err = esp_bt_controller_init(&bt_cfg);
if (err != ESP_OK) {
@@ -930,38 +882,17 @@ bool NimBLEDevice::init(const std::string& deviceName) {
return false;
}
# if CONFIG_BT_LE_SCAN_DUPL
int mode = (1UL << 4); // FILTER_DUPLICATE_EXCEPTION_FOR_MESH
switch (m_scanFilterMode) {
case 1:
mode |= (1UL << 3); // FILTER_DUPLICATE_ADVDATA
break;
case 2:
mode |= ((1UL << 2) | (1UL << 3)); // FILTER_DUPLICATE_ADDRESS | FILTER_DUPLICATE_ADVDATA
break;
default:
mode |= (1UL << 0) | (1UL << 2); // FILTER_DUPLICATE_PDUTYPE | FILTER_DUPLICATE_ADDRESS
}
ble_vhci_disc_duplicate_mode_disable(0xFFFFFFFF);
ble_vhci_disc_duplicate_mode_enable(mode);
ble_vhci_disc_duplicate_set_max_cache_size(m_scanDuplicateSize);
ble_vhci_disc_duplicate_set_period_refresh_time(m_scanDuplicateResetTime);
# endif
err = esp_bt_controller_enable(ESP_BT_MODE_BLE);
if (err != ESP_OK) {
NIMBLE_LOGE(LOG_TAG, "esp_bt_controller_enable() failed; err=%d", err);
return false;
}
# if CONFIG_BT_NIMBLE_LEGACY_VHCI_ENABLE
err = esp_nimble_hci_init();
if (err != ESP_OK) {
NIMBLE_LOGE(LOG_TAG, "esp_nimble_hci_init() failed; err=%d", err);
return false;
}
# endif
# endif
# endif
nimble_port_init();
@@ -969,15 +900,13 @@ bool NimBLEDevice::init(const std::string& deviceName) {
// Setup callbacks for host events
ble_hs_cfg.reset_cb = NimBLEDevice::onReset;
ble_hs_cfg.sync_cb = NimBLEDevice::onSync;
ble_hs_cfg.store_status_cb = [](struct ble_store_status_event* event, void* arg) {
return m_pDeviceCallbacks->onStoreStatus(event, arg);
};
ble_hs_cfg.store_status_cb = ble_store_util_status_rr; /*TODO: Implement handler for this*/
// Set initial security capabilities
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 = 0;
ble_hs_cfg.sm_sc = 1;
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)
@@ -1026,34 +955,28 @@ bool NimBLEDevice::deinit(bool clearAll) {
}
if (clearAll) {
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
if (NimBLEDevice::m_pServer != nullptr) {
delete NimBLEDevice::m_pServer;
NimBLEDevice::m_pServer = nullptr;
}
# if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
if (NimBLEDevice::m_pL2CAPServer != nullptr) {
delete NimBLEDevice::m_pL2CAPServer;
NimBLEDevice::m_pL2CAPServer = nullptr;
}
# endif
# endif
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
if (NimBLEDevice::m_bleAdvertising != nullptr) {
delete NimBLEDevice::m_bleAdvertising;
NimBLEDevice::m_bleAdvertising = nullptr;
}
# endif
# if MYNEWT_VAL(BLE_ROLE_OBSERVER)
# if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
if (NimBLEDevice::m_pScan != nullptr) {
delete NimBLEDevice::m_pScan;
NimBLEDevice::m_pScan = nullptr;
}
# endif
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
for (auto clt : m_pClients) {
deleteClient(clt);
}
@@ -1110,16 +1033,18 @@ bool NimBLEDevice::setOwnAddrType(uint8_t type) {
m_ownAddrType = type;
# if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
if (type == BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT || type == BLE_OWN_ADDR_RPA_RANDOM_DEFAULT) {
# ifdef CONFIG_IDF_TARGET_ESP32
// esp32 controller does not support RPA so we must use the random static for calls to the stack
// the host will take care of the random private address generation/setting.
m_ownAddrType = BLE_OWN_ADDR_RANDOM;
rc = ble_hs_pvcy_rpa_config(NIMBLE_HOST_ENABLE_RPA);
} else {
rc = ble_hs_pvcy_rpa_config(NIMBLE_HOST_DISABLE_PRIVACY);
}
# endif
} else {
# ifdef CONFIG_IDF_TARGET_ESP32
rc = ble_hs_pvcy_rpa_config(NIMBLE_HOST_DISABLE_PRIVACY);
# endif
}
return rc == 0;
} // setOwnAddrType
@@ -1254,7 +1179,7 @@ bool NimBLEDevice::startSecurity(uint16_t connHandle, int* rcPtr) {
return rc == 0 || rc == BLE_HS_EALREADY;
} // startSecurity
# if MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) || defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
/**
* @brief Inject the provided passkey into the Security Manager.
* @param [in] peerInfo Connection information for the peer.
@@ -1279,7 +1204,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 // MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# endif // CONFIG_BT_NIMBLE_ROLE_CENTRAL || CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
/* -------------------------------------------------------------------------- */
/* UTILITIES */
@@ -1290,13 +1215,12 @@ 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
@@ -1338,13 +1262,4 @@ void nimble_cpp_assert(const char* file, unsigned line) {
}
# endif // CONFIG_NIMBLE_CPP_DEBUG_ASSERT_ENABLED
void NimBLEDevice::setDeviceCallbacks(NimBLEDeviceCallbacks* cb) {
m_pDeviceCallbacks = cb ? cb : &defaultDeviceCallbacks;
}
int NimBLEDeviceCallbacks::onStoreStatus(struct ble_store_status_event* event, void* arg) {
NIMBLE_LOGD("NimBLEDeviceCallbacks", "onStoreStatus: default");
return ble_store_util_status_rr(event, arg);
}
#endif // CONFIG_BT_NIMBLE_ENABLED
#endif // CONFIG_BT_ENABLED

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_DEVICE_H_
#define NIMBLE_CPP_DEVICE_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
# ifdef ESP_PLATFORM
# ifndef CONFIG_IDF_TARGET_ESP32P4
# include <esp_bt.h>
@@ -40,36 +40,32 @@
# include <string>
# include <vector>
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# include <array>
class NimBLEClient;
# endif
# if MYNEWT_VAL(BLE_ROLE_OBSERVER)
# if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
class NimBLEScan;
# endif
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# if MYNEWT_VAL(BLE_EXT_ADV)
# if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
# if CONFIG_BT_NIMBLE_EXT_ADV
class NimBLEExtAdvertising;
# else
class NimBLEAdvertising;
# endif
# endif
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
class NimBLEServer;
# if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
class NimBLEL2CAPServer;
# endif
# endif
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_ROLE_CENTRAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) || defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
class NimBLEConnInfo;
# endif
class NimBLEAddress;
class NimBLEDeviceCallbacks;
# define BLEDevice NimBLEDevice
# define BLEClient NimBLEClient
@@ -98,15 +94,19 @@ class NimBLEDeviceCallbacks;
# define BLEEddystoneTLM NimBLEEddystoneTLM
# define BLEEddystoneURL NimBLEEddystoneURL
# define BLEConnInfo NimBLEConnInfo
# define BLEL2CAPServer NimBLEL2CAPServer
# define BLEL2CAPService NimBLEL2CAPService
# define BLEL2CAPServiceCallbacks NimBLEL2CAPServiceCallbacks
# define BLEL2CAPClient NimBLEL2CAPClient
# define BLEL2CAPClientCallbacks NimBLEL2CAPClientCallbacks
# define BLEL2CAPChannel NimBLEL2CAPChannel
# define BLEL2CAPChannelCallbacks NimBLEL2CAPChannelCallbacks
enum class NimBLETxPowerType { All = 0, Advertise = 1, Scan = 2, Connection = 3 };
# 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);
@@ -129,10 +129,8 @@ class NimBLEDevice {
static bool setOwnAddrType(uint8_t type);
static bool setOwnAddr(const NimBLEAddress& addr);
static bool setOwnAddr(const uint8_t* addr);
static void setDeviceCallbacks(NimBLEDeviceCallbacks* cb);
static void setScanDuplicateCacheSize(uint16_t cacheSize);
static void setScanFilterMode(uint8_t type);
static void setScanDuplicateCacheResetTime(uint16_t time);
static bool setCustomGapHandler(gap_event_handler handler);
static void setSecurityAuth(bool bonding, bool mitm, bool sc);
static void setSecurityAuth(uint8_t auth);
@@ -149,7 +147,6 @@ class NimBLEDevice {
static void host_task(void* param);
static int getPower(NimBLETxPowerType type = NimBLETxPowerType::All);
static bool setPower(int8_t dbm, NimBLETxPowerType type = NimBLETxPowerType::All);
static bool setDefaultPhy(uint8_t txPhyMask, uint8_t rxPhyMask);
# ifdef ESP_PLATFORM
# ifndef CONFIG_IDF_TARGET_ESP32P4
@@ -158,39 +155,39 @@ class NimBLEDevice {
# endif
# endif
# if MYNEWT_VAL(BLE_ROLE_OBSERVER)
# if CONFIG_BT_NIMBLE_EXT_ADV
static bool setDefaultPhy(uint8_t txPhyMask, uint8_t rxPhyMask);
# endif
# if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
static NimBLEScan* getScan();
# endif
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
static NimBLEServer* createServer();
static NimBLEServer* getServer();
# if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
static NimBLEL2CAPServer* createL2CAPServer();
static NimBLEL2CAPServer* getL2CAPServer();
# endif
# endif
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_ROLE_CENTRAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) || defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
static bool injectConfirmPasskey(const NimBLEConnInfo& peerInfo, bool accept);
static bool injectPassKey(const NimBLEConnInfo& peerInfo, uint32_t pin);
# endif
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# if MYNEWT_VAL(BLE_EXT_ADV)
# if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
# if CONFIG_BT_NIMBLE_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 !MYNEWT_VAL(BLE_EXT_ADV) || defined(_DOXYGEN_)
# if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
static NimBLEAdvertising* getAdvertising();
static bool startAdvertising(uint32_t duration = 0);
static bool stopAdvertising();
# endif
# endif
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
static NimBLEClient* createClient();
static NimBLEClient* createClient(const NimBLEAddress& peerAddress);
static bool deleteClient(NimBLEClient* pClient);
@@ -201,7 +198,7 @@ class NimBLEDevice {
static std::vector<NimBLEClient*> getConnectedClients();
# endif
# if MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) || defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
static bool deleteBond(const NimBLEAddress& address);
static int getNumBonds();
static bool isBonded(const NimBLEAddress& address);
@@ -216,120 +213,87 @@ class NimBLEDevice {
static ble_gap_event_listener m_listener;
static uint8_t m_ownAddrType;
static std::vector<NimBLEAddress> m_whiteList;
static NimBLEDeviceCallbacks* m_pDeviceCallbacks;
static NimBLEDeviceCallbacks defaultDeviceCallbacks;
# if MYNEWT_VAL(BLE_ROLE_OBSERVER)
# if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
static NimBLEScan* m_pScan;
# endif
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
static NimBLEServer* m_pServer;
# if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
static NimBLEL2CAPServer* m_pL2CAPServer;
# endif
# endif
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# if MYNEWT_VAL(BLE_EXT_ADV)
# if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
# if CONFIG_BT_NIMBLE_EXT_ADV
static NimBLEExtAdvertising* m_bleAdvertising;
# else
static NimBLEAdvertising* m_bleAdvertising;
# endif
# endif
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
static std::array<NimBLEClient*, MYNEWT_VAL(BLE_MAX_CONNECTIONS)> m_pClients;
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
static std::array<NimBLEClient*, NIMBLE_MAX_CONNECTIONS> m_pClients;
# endif
# ifdef ESP_PLATFORM
# if CONFIG_BTDM_BLE_SCAN_DUPL || CONFIG_BT_LE_SCAN_DUPL
# ifdef CONFIG_BTDM_BLE_SCAN_DUPL
static uint16_t m_scanDuplicateSize;
static uint8_t m_scanFilterMode;
static uint16_t m_scanDuplicateResetTime;
# endif
# endif
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
friend class NimBLEClient;
# endif
# if MYNEWT_VAL(BLE_ROLE_OBSERVER)
# if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
friend class NimBLEScan;
# endif
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
friend class NimBLEServer;
friend class NimBLECharacteristic;
# endif
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
friend class NimBLEAdvertising;
# if MYNEWT_VAL(BLE_EXT_ADV)
# if CONFIG_BT_NIMBLE_EXT_ADV
friend class NimBLEExtAdvertising;
friend class NimBLEExtAdvertisement;
# endif
# endif
};
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# include "NimBLEClient.h"
# include "NimBLERemoteService.h"
# include "NimBLERemoteCharacteristic.h"
# include "NimBLERemoteDescriptor.h"
# endif
# if MYNEWT_VAL(BLE_ROLE_OBSERVER)
# if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
# include "NimBLEScan.h"
# endif
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# include "NimBLEServer.h"
# include "NimBLEService.h"
# include "NimBLECharacteristic.h"
# include "NimBLEDescriptor.h"
# if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
# include "NimBLEL2CAPServer.h"
# include "NimBLEL2CAPChannel.h"
# endif
# endif
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# if MYNEWT_VAL(BLE_EXT_ADV)
# if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
# if CONFIG_BT_NIMBLE_EXT_ADV
# include "NimBLEExtAdvertising.h"
# else
# include "NimBLEAdvertising.h"
# endif
# endif
# if MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) || defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# include "NimBLEConnInfo.h"
# endif
# include "NimBLEAddress.h"
# include "NimBLEUtils.h"
/**
* @brief Callbacks associated with a BLE device.
*/
class NimBLEDeviceCallbacks {
public:
virtual ~NimBLEDeviceCallbacks() {};
/**
* @brief Indicates an inability to perform a store operation.
* This callback should do one of two things:
* -Address the problem and return 0, indicating that the store operation
* should proceed.
* -Return nonzero to indicate that the store operation should be aborted.
* @param event Describes the store event being reported.
* BLE_STORE_EVENT_FULL; or
* BLE_STORE_EVENT_OVERFLOW
* @return 0 if the store operation should proceed;
* nonzero if the store operation should be aborted.
*/
virtual int onStoreStatus(struct ble_store_status_event* event, void* arg);
};
#endif // CONFIG_BT_NIMBLE_ENABLED
#endif // CONFIG_BT_ENABLED
#endif // NIMBLE_CPP_DEVICE_H_

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,9 +15,10 @@
* limitations under the License.
*/
#include "NimBLEEddystoneTLM.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
# include "NimBLEEddystoneTLM.h"
# include "NimBLEUUID.h"
# include "NimBLELog.h"
@@ -215,4 +216,4 @@ void NimBLEEddystoneTLM::setTime(uint32_t tmil) {
m_eddystoneData.tmil = tmil;
} // setTime
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER)
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_EDDYSTONETLM_H_
#define NIMBLE_CPP_EDDYSTONETLM_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
class NimBLEUUID;
@@ -66,5 +66,5 @@ class NimBLEEddystoneTLM {
}; // NimBLEEddystoneTLM
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER)
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER
#endif // NIMBLE_CPP_EDDYSTONETLM_H_

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,8 +15,8 @@
* limitations under the License.
*/
#include "NimBLEExtAdvertising.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && MYNEWT_VAL(BLE_EXT_ADV)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && CONFIG_BT_NIMBLE_EXT_ADV
# if defined(CONFIG_NIMBLE_CPP_IDF)
# include "services/gap/ble_svc_gap.h"
@@ -24,6 +24,7 @@
# 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"
@@ -38,7 +39,7 @@ static const char* LOG_TAG = "NimBLEExtAdvertising";
NimBLEExtAdvertising::NimBLEExtAdvertising()
: m_deleteCallbacks{false},
m_pCallbacks{&defaultCallbacks},
m_advStatus(MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES) + 1, false) {}
m_advStatus(CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES + 1, false) {}
/**
* @brief Destructor: deletes callback instances if requested.
@@ -68,7 +69,7 @@ bool NimBLEExtAdvertising::setInstanceData(uint8_t instId, NimBLEExtAdvertisemen
adv.m_params.scan_req_notif = false;
}
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
NimBLEServer* pServer = NimBLEDevice::getServer();
if (pServer != nullptr) {
pServer->start(); // make sure the GATT server is ready before advertising
@@ -391,7 +392,7 @@ void NimBLEExtAdvertisement::setTxPower(int8_t dbm) {
* @param [in] enable True = connectable.
*/
void NimBLEExtAdvertisement::setConnectable(bool enable) {
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
m_params.connectable = enable;
# endif
} // setConnectable
@@ -531,7 +532,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 > MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)) {
if (length > CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN) {
return false;
}
@@ -546,7 +547,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 > MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)) {
if (m_payload.size() + length > CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN) {
return false;
}
@@ -560,7 +561,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() > MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)) {
if (m_payload.size() + data.length() > CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN) {
return false;
}
@@ -710,7 +711,7 @@ bool NimBLEExtAdvertisement::addServiceUUID(const NimBLEUUID& serviceUUID) {
length += 2;
}
if (length + getDataSize() > MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)) {
if (length + getDataSize() > CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN) {
NIMBLE_LOGE(LOG_TAG, "Cannot add UUID, data length exceeded!");
return false;
}
@@ -919,7 +920,7 @@ bool NimBLEExtAdvertisement::setServiceData(const NimBLEUUID& uuid, const uint8_
uint8_t uuidBytes = uuid.bitSize() / 8;
uint8_t sDataLen = 2 + uuidBytes + length;
if (m_payload.size() + sDataLen > MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)) {
if (m_payload.size() + sDataLen > CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN) {
return false;
}
@@ -1090,4 +1091,4 @@ std::string NimBLEExtAdvertisement::toString() const {
return str;
} // toString
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && MYNEWT_VAL(BLE_EXT_ADV)
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && CONFIG_BT_NIMBLE_EXT_ADV */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_EXTADVERTISING_H_
#define NIMBLE_CPP_EXTADVERTISING_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && MYNEWT_VAL(BLE_EXT_ADV)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && CONFIG_BT_NIMBLE_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_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && MYNEWT_VAL(BLE_EXT_ADV)
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && CONFIG_BT_NIMBLE_EXT_ADV
#endif // NIMBLE_CPP_EXTADVERTISING_H_

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,9 +15,10 @@
* limitations under the License.
*/
#include "NimBLEHIDDevice.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# include "NimBLEHIDDevice.h"
# include "NimBLEServer.h"
# include "NimBLEService.h"
# include "NimBLE2904.h"
@@ -340,4 +341,4 @@ NimBLEService* NimBLEHIDDevice::getBatteryService() {
return m_batterySvc;
} // getBatteryService
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_HIDDEVICE_H_
#define NIMBLE_CPP_HIDDEVICE_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# include <stdint.h>
# include <string>
@@ -85,5 +85,5 @@ class NimBLEHIDDevice {
NimBLECharacteristic* locateReportCharacteristicByIdAndType(uint8_t reportId, uint8_t reportType);
};
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif // NIMBLE_CPP_HIDDEVICE_H_

View File

@@ -1,314 +0,0 @@
//
// (C) Dr. Michael 'Mickey' Lauer <mickey@vanille-media.de>
//
#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)
// Round-up integer division
# 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;
NimBLEL2CAPChannel::NimBLEL2CAPChannel(uint16_t psm, uint16_t mtu, NimBLEL2CAPChannelCallbacks* callbacks)
: psm(psm), mtu(mtu), callbacks(callbacks) {
assert(mtu); // fail here, if MTU is too little
assert(callbacks); // fail here, if no callbacks are given
assert(setupMemPool()); // fail here, if the memory pool could not be setup
NIMBLE_LOGI(LOG_TAG, "L2CAP COC 0x%04X initialized w/ L2CAP MTU %i", this->psm, this->mtu);
};
NimBLEL2CAPChannel::~NimBLEL2CAPChannel() {
teardownMemPool();
NIMBLE_LOGI(LOG_TAG, "L2CAP COC 0x%04X shutdown and freed.", this->psm);
}
bool NimBLEL2CAPChannel::setupMemPool() {
const size_t buf_blocks = CEIL_DIVIDE(mtu, L2CAP_BUF_BLOCK_SIZE) * L2CAP_BUF_SIZE_MTUS_PER_CHANNEL;
NIMBLE_LOGD(LOG_TAG, "Computed number of buf_blocks = %d", buf_blocks);
_coc_memory = malloc(OS_MEMPOOL_SIZE(buf_blocks, L2CAP_BUF_BLOCK_SIZE) * sizeof(os_membuf_t));
if (_coc_memory == 0) {
NIMBLE_LOGE(LOG_TAG, "Can't allocate _coc_memory: %d", errno);
return false;
}
auto rc = os_mempool_init(&_coc_mempool, buf_blocks, L2CAP_BUF_BLOCK_SIZE, _coc_memory, "appbuf");
if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "Can't os_mempool_init: %d", rc);
return false;
}
auto rc2 = os_mbuf_pool_init(&_coc_mbuf_pool, &_coc_mempool, L2CAP_BUF_BLOCK_SIZE, buf_blocks);
if (rc2 != 0) {
NIMBLE_LOGE(LOG_TAG, "Can't os_mbuf_pool_init: %d", rc);
return false;
}
this->receiveBuffer = (uint8_t*)malloc(mtu);
if (!this->receiveBuffer) {
NIMBLE_LOGE(LOG_TAG, "Can't malloc receive buffer: %d, %s", errno, strerror(errno));
return false;
}
return true;
}
void NimBLEL2CAPChannel::teardownMemPool() {
if (this->callbacks) {
delete this->callbacks;
}
if (this->receiveBuffer) {
free(this->receiveBuffer);
}
if (_coc_memory) {
free(_coc_memory);
}
}
int NimBLEL2CAPChannel::writeFragment(std::vector<uint8_t>::const_iterator begin, std::vector<uint8_t>::const_iterator end) {
auto toSend = end - begin;
if (stalled) {
NIMBLE_LOGD(LOG_TAG, "L2CAP Channel waiting for unstall...");
NimBLETaskData taskData;
m_pTaskData = &taskData;
NimBLEUtils::taskWait(taskData, BLE_NPL_TIME_FOREVER);
m_pTaskData = nullptr;
stalled = false;
NIMBLE_LOGD(LOG_TAG, "L2CAP Channel unstalled!");
}
struct ble_l2cap_chan_info info;
ble_l2cap_get_chan_info(channel, &info);
// Take the minimum of our and peer MTU
auto mtu = info.peer_coc_mtu < info.our_coc_mtu ? info.peer_coc_mtu : info.our_coc_mtu;
if (toSend > mtu) {
return -BLE_HS_EBADDATA;
}
auto retries = RetryCounter;
while (retries--) {
auto txd = os_mbuf_get_pkthdr(&_coc_mbuf_pool, 0);
if (!txd) {
NIMBLE_LOGE(LOG_TAG, "Can't os_mbuf_get_pkthdr.");
return -BLE_HS_ENOMEM;
}
auto append = os_mbuf_append(txd, &(*begin), toSend);
if (append != 0) {
NIMBLE_LOGE(LOG_TAG, "Can't os_mbuf_append: %d", append);
return append;
}
auto res = ble_l2cap_send(channel, txd);
switch (res) {
case 0:
NIMBLE_LOGD(LOG_TAG, "L2CAP COC 0x%04X sent %d bytes.", this->psm, toSend);
return 0;
case BLE_HS_ESTALLED:
stalled = true;
NIMBLE_LOGD(LOG_TAG, "L2CAP COC 0x%04X sent %d bytes.", this->psm, toSend);
NIMBLE_LOGW(LOG_TAG,
"ble_l2cap_send returned BLE_HS_ESTALLED. Next send will wait for unstalled event...");
return 0;
case BLE_HS_ENOMEM:
case BLE_HS_EAGAIN:
case BLE_HS_EBUSY:
NIMBLE_LOGD(LOG_TAG, "ble_l2cap_send returned %d. Retrying shortly...", res);
os_mbuf_free_chain(txd);
ble_npl_time_delay(ble_npl_time_ms_to_ticks32(RetryTimeout));
continue;
default:
NIMBLE_LOGE(LOG_TAG, "ble_l2cap_send failed: %d", res);
return res;
}
}
NIMBLE_LOGE(LOG_TAG, "Retries exhausted, dropping %d bytes to send.", toSend);
return -BLE_HS_EREJECT;
}
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
NimBLEL2CAPChannel* NimBLEL2CAPChannel::connect(NimBLEClient* client,
uint16_t psm,
uint16_t mtu,
NimBLEL2CAPChannelCallbacks* callbacks) {
if (!client->isConnected()) {
NIMBLE_LOGE(
LOG_TAG,
"Client is not connected. Before connecting via L2CAP, a GAP connection must have been established");
return nullptr;
};
auto channel = new NimBLEL2CAPChannel(psm, mtu, callbacks);
auto sdu_rx = os_mbuf_get_pkthdr(&channel->_coc_mbuf_pool, 0);
if (!sdu_rx) {
NIMBLE_LOGE(LOG_TAG, "Can't allocate SDU buffer: %d, %s", errno, strerror(errno));
return nullptr;
}
auto rc = ble_l2cap_connect(client->getConnHandle(), psm, mtu, sdu_rx, NimBLEL2CAPChannel::handleL2capEvent, channel);
if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "ble_l2cap_connect failed: %d", rc);
}
return channel;
}
# endif // MYNEWT_VAL(BLE_ROLE_CENTRAL)
bool NimBLEL2CAPChannel::write(const std::vector<uint8_t>& bytes) {
if (!this->channel) {
NIMBLE_LOGW(LOG_TAG, "L2CAP Channel not open");
return false;
}
struct ble_l2cap_chan_info info;
ble_l2cap_get_chan_info(channel, &info);
auto mtu = info.peer_coc_mtu < info.our_coc_mtu ? info.peer_coc_mtu : info.our_coc_mtu;
auto start = bytes.begin();
while (start != bytes.end()) {
auto end = start + mtu < bytes.end() ? start + mtu : bytes.end();
if (writeFragment(start, end) < 0) {
return false;
}
start = end;
}
return true;
}
// private
int NimBLEL2CAPChannel::handleConnectionEvent(struct ble_l2cap_event* event) {
channel = event->connect.chan;
struct ble_l2cap_chan_info info;
ble_l2cap_get_chan_info(channel, &info);
NIMBLE_LOGI(LOG_TAG,
"L2CAP COC 0x%04X connected. Local MTU = %d [%d], remote MTU = %d [%d].",
psm,
info.our_coc_mtu,
info.our_l2cap_mtu,
info.peer_coc_mtu,
info.peer_l2cap_mtu);
if (info.our_coc_mtu > info.peer_coc_mtu) {
NIMBLE_LOGW(LOG_TAG, "L2CAP COC 0x%04X connected, but local MTU is bigger than remote MTU.", psm);
}
auto mtu = info.peer_coc_mtu < info.our_coc_mtu ? info.peer_coc_mtu : info.our_coc_mtu;
callbacks->onConnect(this, mtu);
return 0;
}
int NimBLEL2CAPChannel::handleAcceptEvent(struct ble_l2cap_event* event) {
NIMBLE_LOGI(LOG_TAG, "L2CAP COC 0x%04X accept.", psm);
if (!callbacks->shouldAcceptConnection(this)) {
NIMBLE_LOGI(LOG_TAG, "L2CAP COC 0x%04X refused by delegate.", psm);
return -1;
}
struct os_mbuf* sdu_rx = os_mbuf_get_pkthdr(&_coc_mbuf_pool, 0);
assert(sdu_rx != NULL);
ble_l2cap_recv_ready(event->accept.chan, sdu_rx);
return 0;
}
int NimBLEL2CAPChannel::handleDataReceivedEvent(struct ble_l2cap_event* event) {
NIMBLE_LOGD(LOG_TAG, "L2CAP COC 0x%04X data received.", psm);
struct os_mbuf* rxd = event->receive.sdu_rx;
assert(rxd != NULL);
int rx_len = (int)OS_MBUF_PKTLEN(rxd);
assert(rx_len <= (int)mtu);
int res = os_mbuf_copydata(rxd, 0, rx_len, receiveBuffer);
assert(res == 0);
NIMBLE_LOGD(LOG_TAG, "L2CAP COC 0x%04X received %d bytes.", psm, rx_len);
res = os_mbuf_free_chain(rxd);
assert(res == 0);
std::vector<uint8_t> incomingData(receiveBuffer, receiveBuffer + rx_len);
callbacks->onRead(this, incomingData);
struct os_mbuf* next = os_mbuf_get_pkthdr(&_coc_mbuf_pool, 0);
assert(next != NULL);
res = ble_l2cap_recv_ready(channel, next);
assert(res == 0);
return 0;
}
int NimBLEL2CAPChannel::handleTxUnstalledEvent(struct ble_l2cap_event* event) {
if (m_pTaskData != nullptr) {
NimBLEUtils::taskRelease(*m_pTaskData, event->tx_unstalled.status);
}
NIMBLE_LOGI(LOG_TAG, "L2CAP COC 0x%04X transmit unstalled.", psm);
return 0;
}
int NimBLEL2CAPChannel::handleDisconnectionEvent(struct ble_l2cap_event* event) {
NIMBLE_LOGI(LOG_TAG, "L2CAP COC 0x%04X disconnected.", psm);
channel = NULL;
callbacks->onDisconnect(this);
return 0;
}
/* STATIC */
int NimBLEL2CAPChannel::handleL2capEvent(struct ble_l2cap_event* event, void* arg) {
NIMBLE_LOGD(LOG_TAG, "handleL2capEvent: handling l2cap event %d", event->type);
NimBLEL2CAPChannel* self = reinterpret_cast<NimBLEL2CAPChannel*>(arg);
int returnValue = 0;
switch (event->type) {
case BLE_L2CAP_EVENT_COC_CONNECTED:
returnValue = self->handleConnectionEvent(event);
break;
case BLE_L2CAP_EVENT_COC_DISCONNECTED:
returnValue = self->handleDisconnectionEvent(event);
break;
case BLE_L2CAP_EVENT_COC_ACCEPT:
returnValue = self->handleAcceptEvent(event);
break;
case BLE_L2CAP_EVENT_COC_DATA_RECEIVED:
returnValue = self->handleDataReceivedEvent(event);
break;
case BLE_L2CAP_EVENT_COC_TX_UNSTALLED:
returnValue = self->handleTxUnstalledEvent(event);
break;
default:
NIMBLE_LOGW(LOG_TAG, "Unhandled l2cap event %d", event->type);
break;
}
return returnValue;
}
#endif // #if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)

View File

@@ -1,126 +0,0 @@
//
// (C) Dr. Michael 'Mickey' Lauer <mickey@vanille-media.de>
//
#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)
# include "host/ble_l2cap.h"
# include "os/os_mbuf.h"
# else
# include "nimble/nimble/host/include/host/ble_l2cap.h"
# include "nimble/porting/nimble/include/os/os_mbuf.h"
# endif
/**** FIX COMPILATION ****/
# undef min
# undef max
/**************************/
# include <vector>
# include <atomic>
class NimBLEClient;
class NimBLEL2CAPChannelCallbacks;
struct NimBLETaskData;
/**
* @brief Encapsulates a L2CAP channel.
*
* This class is used to encapsulate a L2CAP connection oriented channel, both
* from the "server" (which waits for the connection to be opened) and the "client"
* (which opens the connection) point of view.
*/
class NimBLEL2CAPChannel {
public:
/// @brief Open an L2CAP channel via the specified PSM and MTU.
/// @param[in] psm The PSM to use.
/// @param[in] mtu The MTU to use. Note that this is the local MTU. Upon opening the channel,
/// the final MTU will be negotiated to be the minimum of local and remote.
/// @param[in] callbacks The callbacks to use. NOTE that these callbacks are called from the
/// context of the NimBLE bluetooth task (`nimble_host`) and MUST be handled as fast as possible.
/// @return True if the channel was opened successfully, false otherwise.
static NimBLEL2CAPChannel* connect(NimBLEClient* client, uint16_t psm, uint16_t mtu, NimBLEL2CAPChannelCallbacks* callbacks);
/// @brief Write data to the channel.
///
/// If the size of the data exceeds the MTU, the data will be split into multiple fragments.
/// @return true on success, after the data has been sent.
/// @return false, if the data can't be sent.
///
/// NOTE: This function will block until the data has been sent or an error occurred.
bool write(const std::vector<uint8_t>& bytes);
/// @return True, if the channel is connected. False, otherwise.
bool isConnected() const { return !!channel; }
protected:
NimBLEL2CAPChannel(uint16_t psm, uint16_t mtu, NimBLEL2CAPChannelCallbacks* callbacks);
~NimBLEL2CAPChannel();
int handleConnectionEvent(struct ble_l2cap_event* event);
int handleAcceptEvent(struct ble_l2cap_event* event);
int handleDataReceivedEvent(struct ble_l2cap_event* event);
int handleTxUnstalledEvent(struct ble_l2cap_event* event);
int handleDisconnectionEvent(struct ble_l2cap_event* event);
private:
friend class NimBLEL2CAPServer;
static constexpr const char* LOG_TAG = "NimBLEL2CAPChannel";
const uint16_t psm; // PSM of the channel
const uint16_t mtu; // The requested (local) MTU of the channel, might be larger than negotiated MTU
struct ble_l2cap_chan* channel = nullptr;
NimBLEL2CAPChannelCallbacks* callbacks;
uint8_t* receiveBuffer = nullptr; // buffers a full (local) MTU
// NimBLE memory pool
void* _coc_memory = nullptr;
struct os_mempool _coc_mempool;
struct os_mbuf_pool _coc_mbuf_pool;
// Runtime handling
std::atomic<bool> stalled{false};
NimBLETaskData* m_pTaskData{nullptr};
// Allocate / deallocate NimBLE memory pool
bool setupMemPool();
void teardownMemPool();
// Writes data up to the size of the negotiated MTU to the channel.
int writeFragment(std::vector<uint8_t>::const_iterator begin, std::vector<uint8_t>::const_iterator end);
// L2CAP event handler
static int handleL2capEvent(struct ble_l2cap_event* event, void* arg);
};
/**
* @brief Callbacks base class for the L2CAP channel.
*/
class NimBLEL2CAPChannelCallbacks {
public:
NimBLEL2CAPChannelCallbacks() = default;
virtual ~NimBLEL2CAPChannelCallbacks() = default;
/// Called when the client attempts to open a channel on the server.
/// You can choose to accept or deny the connection.
/// Default implementation returns true.
virtual bool shouldAcceptConnection(NimBLEL2CAPChannel* channel) { return true; }
/// Called after a connection has been made.
/// Default implementation does nothing.
virtual void onConnect(NimBLEL2CAPChannel* channel, uint16_t negotiatedMTU) {};
/// Called when data has been read from the channel.
/// Default implementation does nothing.
virtual void onRead(NimBLEL2CAPChannel* channel, std::vector<uint8_t>& data) {};
/// Called after the channel has been disconnected.
/// Default implementation does nothing.
virtual void onDisconnect(NimBLEL2CAPChannel* channel) {};
};
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
#endif // NIMBLE_CPP_L2CAPCHANNEL_H_

View File

@@ -1,40 +0,0 @@
//
// (C) Dr. Michael 'Mickey' Lauer <mickey@vanille-media.de>
//
#include "NimBLEL2CAPServer.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";
NimBLEL2CAPServer::NimBLEL2CAPServer() {
// Nothing to do here...
}
NimBLEL2CAPServer::~NimBLEL2CAPServer() {
// Delete all services
for (auto service : this->services) {
delete service;
}
}
NimBLEL2CAPChannel* NimBLEL2CAPServer::createService(const uint16_t psm,
const uint16_t mtu,
NimBLEL2CAPChannelCallbacks* callbacks) {
auto service = new NimBLEL2CAPChannel(psm, mtu, callbacks);
auto rc = ble_l2cap_create_server(psm, mtu, NimBLEL2CAPChannel::handleL2capEvent, service);
if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "Could not ble_l2cap_create_server: %d", rc);
return nullptr;
}
this->services.push_back(service);
return service;
}
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)

View File

@@ -1,41 +0,0 @@
//
// (C) Dr. Michael 'Mickey' Lauer <mickey@vanille-media.de>
//
#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;
/**
* @brief L2CAP server class.
*
* Encapsulates a L2CAP server that can hold multiple services. Every service is represented by a channel object
* and an assorted set of callbacks.
*/
class NimBLEL2CAPServer {
public:
/// @brief Register a new L2CAP service instance.
/// @param psm The port multiplexor service number.
/// @param mtu The maximum transmission unit.
/// @param callbacks The callbacks for this service.
/// @return the newly created object, if the server registration was successful.
NimBLEL2CAPChannel* createService(const uint16_t psm, const uint16_t mtu, NimBLEL2CAPChannelCallbacks* callbacks);
private:
NimBLEL2CAPServer();
~NimBLEL2CAPServer();
std::vector<NimBLEL2CAPChannel*> services;
friend class NimBLEL2CAPChannel;
friend class NimBLEDevice;
};
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
#endif // NIMBLE_CPP_L2CAPSERVER_H_

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_LOCAL_ATTRIBUTE_H_
#define NIMBLE_CPP_LOCAL_ATTRIBUTE_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# include "NimBLEAttribute.h"
@@ -54,5 +54,5 @@ class NimBLELocalAttribute : public NimBLEAttribute {
uint8_t m_removed{0};
};
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
#endif // NIMBLE_CPP_LOCAL_ATTRIBUTE_H_

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +18,8 @@
#ifndef NIMBLE_LOCAL_VALUE_ATTRIBUTE_H_
#define NIMBLE_LOCAL_VALUE_ATTRIBUTE_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# if defined(CONFIG_NIMBLE_CPP_IDF)
# include "host/ble_hs.h"
@@ -48,18 +48,30 @@ typedef enum {
} NIMBLE_PROPERTY;
# include "NimBLELocalAttribute.h"
# include "NimBLEValueAttribute.h"
# include "NimBLEAttValue.h"
# include <vector>
class NimBLEConnInfo;
class NimBLELocalValueAttribute : public NimBLELocalAttribute, public NimBLEValueAttribute {
class NimBLELocalValueAttribute : public NimBLELocalAttribute {
public:
/**
* @brief Get the properties of the attribute.
*/
uint16_t getProperties() const { return m_properties; }
/**
* @brief Get the length of the attribute value.
* @return The length of the attribute value.
*/
size_t getLength() const { return m_value.size(); }
/**
* @brief Get a copy of the value of the attribute value.
* @param [in] timestamp (Optional) A pointer to a time_t struct to get the time the value set.
* @return A copy of the attribute value.
*/
NimBLEAttValue getValue(time_t* timestamp = nullptr) const { return m_value; }
/**
* @brief Set the value of the attribute value.
* @param [in] data The data to set the value to.
@@ -88,6 +100,19 @@ class NimBLELocalValueAttribute : public NimBLELocalAttribute, public NimBLEValu
m_value.setValue<T>(val);
}
/**
* @brief Template to convert the data to <type\>.
* @tparam T The type to convert the data to.
* @param [in] timestamp (Optional) A pointer to a time_t struct to get the time the value set.
* @param [in] skipSizeCheck (Optional) If true it will skip checking if the data size is less than <tt>sizeof(<type\>)</tt>.
* @return The data converted to <type\> or NULL if skipSizeCheck is false and the data is less than <tt>sizeof(<type\>)</tt>.
* @details <b>Use:</b> <tt>getValue<type>(&timestamp, skipSizeCheck);</tt>
*/
template <typename T>
T getValue(time_t* timestamp = nullptr, bool skipSizeCheck = false) const {
return m_value.getValue<T>(timestamp, skipSizeCheck);
}
protected:
friend class NimBLEServer;
@@ -102,7 +127,8 @@ class NimBLELocalValueAttribute : public NimBLELocalAttribute, public NimBLEValu
uint16_t handle,
uint16_t maxLen,
uint16_t initLen = CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH)
: NimBLELocalAttribute(uuid, handle), NimBLEValueAttribute(maxLen, initLen) {}
: NimBLELocalAttribute(uuid, handle), m_value(initLen, maxLen) {}
/**
* @brief Destroy the NimBLELocalValueAttribute object.
*/
@@ -137,8 +163,9 @@ class NimBLELocalValueAttribute : public NimBLELocalAttribute, public NimBLEValu
*/
void setProperties(uint16_t properties) { m_properties = properties; }
uint16_t m_properties{0};
NimBLEAttValue m_value{};
uint16_t m_properties{0};
};
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
#endif // NIMBLE_LOCAL_VALUE_ATTRIBUTE_H_

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_LOG_H_
#define NIMBLE_CPP_LOG_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
# if defined(CONFIG_NIMBLE_CPP_IDF)
# include "esp_log.h"
@@ -110,16 +110,16 @@
# define NIMBLE_CPP_LOG_FORMAT(letter, format) NIMBLE_CPP_LOG_COLOR_##letter #letter " (%lu) %s: " format LOG_RESET_COLOR "\n"
# define NIMBLE_CPP_LOG_LEVEL_LOCAL(level, tag, format, ...) \
do { \
if (level==ESP_LOG_ERROR) { esp_log_write(ESP_LOG_ERROR, tag, NIMBLE_CPP_LOG_FORMAT(E, format), esp_log_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
# define NIMBLE_CPP_LOG_LEVEL_LOCAL(level, tag, format, ...) \
do { \
if (level==ESP_LOG_ERROR) { esp_log_write(ESP_LOG_ERROR, tag, NIMBLE_CPP_LOG_FORMAT(E, format), esp_log_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
else if (level==ESP_LOG_WARN) { esp_log_write(ESP_LOG_WARN, tag, NIMBLE_CPP_LOG_FORMAT(W, format), esp_log_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
else if (level==ESP_LOG_INFO) { esp_log_write(ESP_LOG_INFO, tag, NIMBLE_CPP_LOG_FORMAT(I, format), esp_log_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
else { esp_log_write(ESP_LOG_DEBUG, tag, NIMBLE_CPP_LOG_FORMAT(D, format), esp_log_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
} while(0)
# define NIMBLE_CPP_LOG_PRINT(level, tag, format, ...) \
do { \
# 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__); \
} while (0)
@@ -137,7 +137,7 @@
# define NIMBLE_LOGE(tag, format, ...) NIMBLE_CPP_LOG_PRINT(ESP_LOG_ERROR, tag, format, ##__VA_ARGS__)
# else
# include "syscfg/syscfg.h"
# 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)
@@ -172,12 +172,5 @@
# endif
# endif /* CONFIG_NIMBLE_CPP_IDF */
# define NIMBLE_LOGD_IF(cond, tag, format, ...) { if (cond) { NIMBLE_LOGD(tag, format, ##__VA_ARGS__); }}
# define NIMBLE_LOGI_IF(cond, tag, format, ...) { if (cond) { NIMBLE_LOGI(tag, format, ##__VA_ARGS__); }}
# define NIMBLE_LOGW_IF(cond, tag, format, ...) { if (cond) { NIMBLE_LOGW(tag, format, ##__VA_ARGS__); }}
# 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_NIMBLE_ENABLED */
#endif /* CONFIG_BT_ENABLED */
#endif /* NIMBLE_CPP_LOG_H_ */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,9 +15,10 @@
* limitations under the License.
*/
#include "NimBLERemoteCharacteristic.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# include "NimBLERemoteCharacteristic.h"
# include "NimBLERemoteDescriptor.h"
# include "NimBLERemoteService.h"
# include "NimBLEClient.h"
@@ -62,8 +63,11 @@ NimBLERemoteCharacteristic::~NimBLERemoteCharacteristic() {
/**
* @brief Callback used by the API when a descriptor is discovered or search complete.
*/
int NimBLERemoteCharacteristic::descriptorDiscCB(
uint16_t connHandle, const ble_gatt_error* error, uint16_t chrHandle, const ble_gatt_dsc* dsc, void* arg) {
int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t connHandle,
const ble_gatt_error* error,
uint16_t chrHandle,
const ble_gatt_dsc* dsc,
void* arg) {
int rc = error->status;
auto filter = (NimBLEDescriptorFilter*)arg;
auto pTaskData = (NimBLETaskData*)filter->taskData;
@@ -73,7 +77,8 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(
// Results for chrHandle added until rc != 0
// Must find specified UUID if filter is used
if (rc == 0 && pChr->getHandle() == chrHandle && (!uuid || 0 == ble_uuid_cmp(uuid->getBase(), &dsc->uuid.u))) {
if (rc == 0 && pChr->getHandle() == chrHandle
&& (!uuid || 0 == ble_uuid_cmp(uuid->getBase(), &dsc->uuid.u))) {
// Return BLE_HS_EDONE if the descriptor was found, stop the search
pChr->m_vDescriptors.push_back(new NimBLERemoteDescriptor(pChr, dsc));
rc = !!uuid * BLE_HS_EDONE;
@@ -88,10 +93,10 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(
/**
* @brief Populate the descriptors (if any) for this characteristic.
* @param [in] pFilter Pointer to a filter containing pointers to descriptor, UUID, and task data.
* @param [in] filter Structure containing pointers to descriptor, UUID, and task data.
* @return True if successfully retrieved, success = BLE_HS_EDONE.
*/
bool NimBLERemoteCharacteristic::retrieveDescriptors(NimBLEDescriptorFilter* pFilter) const {
bool NimBLERemoteCharacteristic::retrieveDescriptors(NimBLEDescriptorFilter* filter) const {
NIMBLE_LOGD(LOG_TAG, ">> retrieveDescriptors() for characteristic: %s", getUUID().toString().c_str());
// If this is the last handle then there are no descriptors
@@ -100,35 +105,25 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(NimBLEDescriptorFilter* pFi
return true;
}
NimBLETaskData taskData(const_cast<NimBLERemoteCharacteristic*>(this));
NimBLEDescriptorFilter defaultFilter{nullptr, nullptr, &taskData};
if (pFilter == nullptr) {
pFilter = &defaultFilter;
}
int rc = ble_gattc_disc_all_dscs(getClient()->getConnHandle(),
getHandle(),
getRemoteService()->getEndHandle(),
NimBLERemoteCharacteristic::descriptorDiscCB,
pFilter);
filter);
if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_dscs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
return false;
}
auto prevDscCount = m_vDescriptors.size();
NimBLEUtils::taskWait(taskData, BLE_NPL_TIME_FOREVER);
rc = ((NimBLETaskData*)pFilter->taskData)->m_flags;
NimBLEUtils::taskWait(filter->taskData, BLE_NPL_TIME_FOREVER);
rc = ((NimBLETaskData*)filter->taskData)->m_flags;
if (rc != BLE_HS_EDONE) {
NIMBLE_LOGE(LOG_TAG, "<< retrieveDescriptors(): failed: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
return false;
}
if (m_vDescriptors.size() > prevDscCount) {
pFilter->dsc = m_vDescriptors.back();
}
NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): found %d descriptors.", m_vDescriptors.size() - prevDscCount);
filter->dsc = m_vDescriptors.back();
NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): found %d descriptors.", m_vDescriptors.size());
return true;
} // retrieveDescriptors
@@ -139,9 +134,9 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(NimBLEDescriptorFilter* pFi
*/
NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUUID& uuid) const {
NIMBLE_LOGD(LOG_TAG, ">> getDescriptor: uuid: %s", uuid.toString().c_str());
NimBLEUUID uuidTmp{uuid};
NimBLETaskData taskData(const_cast<NimBLERemoteCharacteristic*>(this));
NimBLEDescriptorFilter filter{nullptr, &uuidTmp, &taskData};
NimBLEDescriptorFilter filter = {nullptr, &uuid, &taskData};
NimBLEUUID uuidTmp;
for (const auto& dsc : m_vDescriptors) {
if (dsc->getUUID() == uuid) {
@@ -153,18 +148,16 @@ NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUU
if (!retrieveDescriptors(&filter) || filter.dsc) {
goto Done;
}
// Try again with 128 bit uuid if request succeeded but no descriptor found.
if (uuid.bitSize() != BLE_UUID_TYPE_128) {
uuidTmp.to128();
// Try again with 128 bit uuid if request succeeded with no uuid found.
if (uuid.bitSize() == BLE_UUID_TYPE_16 || uuid.bitSize() == BLE_UUID_TYPE_32) {
uuidTmp = NimBLEUUID(uuid).to128();
retrieveDescriptors(&filter);
goto Done;
}
// If the uuid was 128 bit, try again with 16 bit uuid.
uuidTmp.to16();
// Try again with 16 bit uuid if request succeeded with no uuid found.
// If the uuid was 128 bit but not of the BLE base type this check will fail.
uuidTmp = NimBLEUUID(uuid).to16();
if (uuidTmp.bitSize() == BLE_UUID_TYPE_16) {
filter.uuid = &uuidTmp;
retrieveDescriptors(&filter);
}
@@ -387,4 +380,4 @@ NimBLEClient* NimBLERemoteCharacteristic::getClient() const {
return getRemoteService()->getClient();
} // getClient
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_REMOTE_CHARACTERISTIC_H_
#define NIMBLE_CPP_REMOTE_CHARACTERISTIC_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# include "NimBLERemoteValueAttribute.h"
# include <vector>
@@ -67,7 +67,7 @@ class NimBLERemoteCharacteristic : public NimBLERemoteValueAttribute {
~NimBLERemoteCharacteristic();
bool setNotify(uint16_t val, notify_callback notifyCallback = nullptr, bool response = true) const;
bool retrieveDescriptors(NimBLEDescriptorFilter* pFilter = nullptr) const;
bool retrieveDescriptors(NimBLEDescriptorFilter* filter = nullptr) const;
static int descriptorDiscCB(
uint16_t connHandle, const ble_gatt_error* error, uint16_t chrHandle, const ble_gatt_dsc* dsc, void* arg);
@@ -79,5 +79,5 @@ class NimBLERemoteCharacteristic : public NimBLERemoteValueAttribute {
}; // NimBLERemoteCharacteristic
#endif /* CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL) */
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
#endif /* NIMBLE_CPP_REMOTE_CHARACTERISTIC_H_ */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,9 +15,10 @@
* limitations under the License.
*/
#include "NimBLERemoteDescriptor.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# include "NimBLERemoteDescriptor.h"
# include "NimBLERemoteCharacteristic.h"
/**
@@ -56,4 +57,4 @@ NimBLEClient* NimBLERemoteDescriptor::getClient() const {
return m_pRemoteCharacteristic->getClient();
}
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_REMOTE_DESCRIPTOR_H_
#define NIMBLE_CPP_REMOTE_DESCRIPTOR_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# include "NimBLERemoteValueAttribute.h"
@@ -44,5 +44,5 @@ class NimBLERemoteDescriptor : public NimBLERemoteValueAttribute {
const NimBLERemoteCharacteristic* m_pRemoteCharacteristic;
};
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
#endif // NIMBLE_CPP_REMOTE_DESCRIPTOR_H_
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
#endif /* NIMBLE_CPP_REMOTE_DESCRIPTOR_H_ */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,9 +15,10 @@
* limitations under the License.
*/
#include "NimBLERemoteService.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# include "NimBLERemoteService.h"
# include "NimBLERemoteCharacteristic.h"
# include "NimBLEClient.h"
# include "NimBLEAttValue.h"
@@ -302,4 +303,4 @@ std::string NimBLERemoteService::toString() const {
return res;
} // toString
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_REMOTE_SERVICE_H_
#define NIMBLE_CPP_REMOTE_SERVICE_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# include "NimBLEAttribute.h"
# include <vector>
@@ -64,5 +64,5 @@ class NimBLERemoteService : public NimBLEAttribute {
uint16_t m_endHandle{0};
}; // NimBLERemoteService
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
#endif // NIMBLE_CPP_REMOTE_SERVICE_H_
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
#endif /* NIMBLE_CPP_REMOTE_SERVICE_H_*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,9 +15,10 @@
* limitations under the License.
*/
#include "NimBLERemoteValueAttribute.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# include "NimBLERemoteValueAttribute.h"
# include "NimBLEClient.h"
# include "NimBLEUtils.h"
# include "NimBLELog.h"
@@ -121,7 +122,7 @@ int NimBLERemoteValueAttribute::onWriteCB(uint16_t conn_handle, const ble_gatt_e
* @param [in] timestamp A pointer to a time_t struct to store the time the value was read.
* @return The value of the remote characteristic.
*/
NimBLEAttValue NimBLERemoteValueAttribute::readValue(time_t* timestamp) {
NimBLEAttValue NimBLERemoteValueAttribute::readValue(time_t* timestamp) const {
NIMBLE_LOGD(LOG_TAG, ">> readValue()");
NimBLEAttValue value{};
@@ -217,4 +218,4 @@ int NimBLERemoteValueAttribute::onReadCB(uint16_t conn_handle, const ble_gatt_er
return rc;
} // onReadCB
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_REMOTE_VALUE_ATTRIBUTE_H_
#define NIMBLE_CPP_REMOTE_VALUE_ATTRIBUTE_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# if defined(CONFIG_NIMBLE_CPP_IDF)
# include <host/ble_gatt.h>
@@ -32,19 +32,32 @@
# undef max
/**************************/
# include "NimBLEValueAttribute.h"
# include "NimBLEAttribute.h"
# include "NimBLEAttValue.h"
class NimBLEClient;
class NimBLERemoteValueAttribute : public NimBLEValueAttribute, public NimBLEAttribute {
class NimBLERemoteValueAttribute : public NimBLEAttribute {
public:
/**
* @brief Read the value of the remote attribute.
* @param [in] timestamp A pointer to a time_t struct to store the time the value was read.
* @return The value of the remote attribute.
*/
NimBLEAttValue readValue(time_t* timestamp = nullptr);
NimBLEAttValue readValue(time_t* timestamp = nullptr) const;
/**
* @brief Get the length of the remote attribute value.
* @return The length of the remote attribute value.
*/
size_t getLength() const { return m_value.size(); }
/**
* @brief Get the value of the remote attribute.
* @return The value of the remote attribute.
* @details This returns a copy of the value to avoid potential race conditions.
*/
NimBLEAttValue getValue() const { return m_value; }
/**
* Get the client instance that owns this attribute.
@@ -140,6 +153,20 @@ class NimBLERemoteValueAttribute : public NimBLEValueAttribute, public NimBLEAtt
}
# endif
/**
* @brief Template to convert the remote characteristic data to <type\>.
* @tparam T The type to convert the data to.
* @param [in] timestamp A pointer to a time_t struct to store the time the value was read.
* @param [in] skipSizeCheck If true it will skip checking if the data size is less than <tt>sizeof(<type\>)</tt>.
* @return The data converted to <type\> or NULL if skipSizeCheck is false and the data is
* less than <tt>sizeof(<type\>)</tt>.
* @details <b>Use:</b> <tt>getValue<type>(&timestamp, skipSizeCheck);</tt>
*/
template <typename T>
T getValue(time_t* timestamp = nullptr, bool skipSizeCheck = false) const {
return m_value.getValue<T>(timestamp, skipSizeCheck);
}
/**
* @brief Template to convert the remote characteristic data to <type\>.
* @tparam T The type to convert the data to.
@@ -150,16 +177,16 @@ class NimBLERemoteValueAttribute : public NimBLEValueAttribute, public NimBLEAtt
* @details <b>Use:</b> <tt>readValue<type>(&timestamp, skipSizeCheck);</tt>
*/
template <typename T>
T readValue(time_t* timestamp = nullptr, bool skipSizeCheck = false) {
T readValue(time_t* timestamp = nullptr, bool skipSizeCheck = false) const {
readValue();
return getValue<T>(timestamp, skipSizeCheck);
return m_value.getValue<T>(timestamp, skipSizeCheck);
}
protected:
/**
* @brief Construct a new NimBLERemoteValueAttribute object.
*/
NimBLERemoteValueAttribute(const ble_uuid_any_t& uuid, uint16_t handle) : NimBLEAttribute{uuid, handle} {}
NimBLERemoteValueAttribute(const ble_uuid_any_t& uuid, uint16_t handle) : NimBLEAttribute(uuid, handle) {}
/**
* @brief Destroy the NimBLERemoteValueAttribute object.
@@ -168,7 +195,9 @@ class NimBLERemoteValueAttribute : public NimBLEValueAttribute, public NimBLEAtt
static int onReadCB(uint16_t conn_handle, const ble_gatt_error* error, ble_gatt_attr* attr, void* arg);
static int onWriteCB(uint16_t conn_handle, const ble_gatt_error* error, ble_gatt_attr* attr, void* arg);
mutable NimBLEAttValue m_value{};
};
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
#endif // NIMBLE_CPP_REMOTE_VALUE_ATTRIBUTE_H_

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,9 +15,10 @@
* limitations under the License.
*/
#include "NimBLEScan.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_OBSERVER)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
# include "NimBLEScan.h"
# include "NimBLEDevice.h"
# include "NimBLELog.h"
@@ -41,9 +42,7 @@ NimBLEScan::NimBLEScan()
* @brief Scan destructor, release any allocated resources.
*/
NimBLEScan::~NimBLEScan() {
for (const auto& dev : m_scanResults.m_deviceVec) {
delete dev;
}
clearResults();
}
/**
@@ -58,12 +57,7 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
switch (event->type) {
case BLE_GAP_EVENT_EXT_DISC:
case BLE_GAP_EVENT_DISC: {
if (!pScan->isScanning()) {
NIMBLE_LOGI(LOG_TAG, "Scan stopped, ignoring event");
return 0;
}
# if MYNEWT_VAL(BLE_EXT_ADV)
# if CONFIG_BT_NIMBLE_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;
@@ -74,7 +68,7 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
# endif
NimBLEAddress advertisedAddress(disc.addr);
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
# ifdef CONFIG_BT_NIMBLE_ROLE_CENTRAL
// stop processing if already connected
NimBLEClient* pClient = NimBLEDevice::getClientByPeerAddress(advertisedAddress);
if (pClient != nullptr && pClient->isConnected()) {
@@ -86,7 +80,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 MYNEWT_VAL(BLE_EXT_ADV)
# if CONFIG_BT_NIMBLE_EXT_ADV
// Same address but different set ID should create a new advertised device.
if (dev->getAddress() == advertisedAddress && dev->getSetId() == disc.sid)
# else
@@ -272,7 +266,7 @@ bool NimBLEScan::isScanning() {
return ble_gap_disc_active();
}
# if MYNEWT_VAL(BLE_EXT_ADV)
# if CONFIG_BT_NIMBLE_EXT_ADV
/**
* @brief Set the PHYs to scan.
* @param [in] phyMask The PHYs to scan, a bit mask of:
@@ -324,7 +318,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 MYNEWT_VAL(BLE_EXT_ADV)
# if CONFIG_BT_NIMBLE_EXT_ADV
ble_gap_ext_disc_params scan_params;
scan_params.passive = m_scanParams.passive;
scan_params.itvl = m_scanParams.itvl;
@@ -489,11 +483,11 @@ void NimBLEScan::clearResults() {
* @brief Dump the scan results to the log.
*/
void NimBLEScanResults::dump() const {
# if CONFIG_NIMBLE_CPP_LOG_LEVEL >= 3
#if CONFIG_NIMBLE_CPP_LOG_LEVEL >=3
for (const auto& dev : m_deviceVec) {
NIMBLE_LOGI(LOG_TAG, "- %s", dev->toString().c_str());
}
# endif
#endif
} // dump
/**
@@ -560,4 +554,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_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_OBSERVER)
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_OBSERVER */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_SCAN_H_
#define NIMBLE_CPP_SCAN_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_OBSERVER)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_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 MYNEWT_VAL(BLE_EXT_ADV)
# if CONFIG_BT_NIMBLE_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 MYNEWT_VAL(BLE_EXT_ADV)
# if CONFIG_BT_NIMBLE_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_NIMBLE_ENABLED MYNEWT_VAL(BLE_ROLE_OBSERVER)
#endif // CONFIG_BT_ENABLED CONFIG_BT_NIMBLE_ROLE_OBSERVER
#endif // NIMBLE_CPP_SCAN_H_

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,13 +15,14 @@
* limitations under the License.
*/
#include "NimBLEServer.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# include "NimBLEServer.h"
# include "NimBLEDevice.h"
# include "NimBLELog.h"
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
# include "NimBLEClient.h"
# endif
@@ -49,7 +50,7 @@ NimBLEServer::NimBLEServer()
: m_gattsStarted{false},
m_svcChanged{false},
m_deleteCallbacks{false},
# if !MYNEWT_VAL(BLE_EXT_ADV)
# if !CONFIG_BT_NIMBLE_EXT_ADV
m_advertiseOnDisconnect{false},
# endif
m_pServerCallbacks{&defaultCallbacks},
@@ -69,7 +70,7 @@ NimBLEServer::~NimBLEServer() {
delete m_pServerCallbacks;
}
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
if (m_pClient != nullptr) {
delete m_pClient;
}
@@ -143,7 +144,7 @@ NimBLEService* NimBLEServer::getServiceByHandle(uint16_t handle) const {
return nullptr;
}
# if MYNEWT_VAL(BLE_EXT_ADV)
# if CONFIG_BT_NIMBLE_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.
@@ -153,7 +154,7 @@ NimBLEExtAdvertising* NimBLEServer::getAdvertising() const {
} // getAdvertising
# endif
# if (!MYNEWT_VAL(BLE_EXT_ADV) && MYNEWT_VAL(BLE_ROLE_BROADCASTER)) || defined(_DOXYGEN_)
# if !CONFIG_BT_NIMBLE_EXT_ADV || 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.
@@ -250,7 +251,7 @@ bool NimBLEServer::disconnect(const NimBLEConnInfo& connInfo, uint8_t reason) co
return disconnect(connInfo.getConnHandle(), reason);
} // disconnect
# if !MYNEWT_VAL(BLE_EXT_ADV) || defined(_DOXYGEN_)
# if !CONFIG_BT_NIMBLE_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.
@@ -354,16 +355,9 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
switch (event->type) {
case BLE_GAP_EVENT_CONNECT: {
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)
if (event->connect.status != 0) {
NIMBLE_LOGE(LOG_TAG, "Connection failed");
# if !CONFIG_BT_NIMBLE_EXT_ADV
NimBLEDevice::startAdvertising();
# endif
} else {
@@ -407,7 +401,7 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
}
}
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
if (pServer->m_pClient && pServer->m_pClient->m_connHandle == event->disconnect.conn.conn_handle) {
// If this was also the client make sure it's flagged as disconnected.
pServer->m_pClient->m_connHandle = BLE_HS_CONN_HANDLE_NONE;
@@ -420,7 +414,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 !MYNEWT_VAL(BLE_EXT_ADV)
# if !CONFIG_BT_NIMBLE_EXT_ADV
if (pServer->m_advertiseOnDisconnect) {
pServer->startAdvertising();
}
@@ -451,7 +445,7 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
chr->m_pCallbacks->onSubscribe(chr,
peerInfo,
event->subscribe.cur_notify + (event->subscribe.cur_indicate << 1));
event->subscribe.cur_notify + event->subscribe.cur_indicate);
}
}
}
@@ -494,10 +488,10 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
} // BLE_GAP_EVENT_NOTIFY_TX
case BLE_GAP_EVENT_ADV_COMPLETE: {
# if MYNEWT_VAL(BLE_EXT_ADV) && MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# if CONFIG_BT_NIMBLE_EXT_ADV
case BLE_GAP_EVENT_SCAN_REQ_RCVD:
return NimBLEExtAdvertising::handleGapEvent(event, arg);
# elif MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# else
return NimBLEAdvertising::handleGapEvent(event, arg);
# endif
} // BLE_GAP_EVENT_ADV_COMPLETE | BLE_GAP_EVENT_SCAN_REQ_RCVD
@@ -537,11 +531,6 @@ 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
break;
} // BLE_GAP_EVENT_ENC_CHANGE
@@ -555,6 +544,7 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
break;
} // BLE_GAP_EVENT_IDENTITY_RESOLVED
# if CONFIG_BT_NIMBLE_EXT_ADV
case BLE_GAP_EVENT_PHY_UPDATE_COMPLETE: {
rc = ble_gap_conn_find(event->phy_updated.conn_handle, &peerInfo.m_desc);
if (rc != 0) {
@@ -564,6 +554,7 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
pServer->m_pServerCallbacks->onPhyUpdate(peerInfo, event->phy_updated.tx_phy, event->phy_updated.rx_phy);
return 0;
} // BLE_GAP_EVENT_PHY_UPDATE_COMPLETE
# endif
case BLE_GAP_EVENT_PASSKEY_ACTION: {
struct ble_sm_io pkey = {0, 0};
@@ -629,10 +620,13 @@ int NimBLEServer::handleGattEvent(uint16_t connHandle, uint16_t attrHandle, ble_
switch (ctxt->op) {
case BLE_GATT_ACCESS_OP_READ_DSC:
case BLE_GATT_ACCESS_OP_READ_CHR: {
// Don't call readEvent if the buffer len is 0 (this is a follow up to a previous read),
// or if this is an internal read (handle is NONE)
if (ctxt->om->om_len > 0 && connHandle != BLE_HS_CONN_HANDLE_NONE) {
pAtt->readEvent(peerInfo);
// Don't call readEvent if this is an internal read (handle is NONE)
if (connHandle != BLE_HS_CONN_HANDLE_NONE) {
// If the packet header is only 8 bytes then this is a follow up of a long read
// so we don't want to call the onRead() callback again.
if (ctxt->om->om_pkthdr_len > 8 || val.size() <= (ble_att_mtu(connHandle) - 3)) {
pAtt->readEvent(peerInfo);
}
}
ble_npl_hw_enter_critical();
@@ -644,12 +638,12 @@ int NimBLEServer::handleGattEvent(uint16_t connHandle, uint16_t attrHandle, ble_
case BLE_GATT_ACCESS_OP_WRITE_DSC:
case BLE_GATT_ACCESS_OP_WRITE_CHR: {
uint16_t maxLen = val.max_size();
uint16_t len = ctxt->om->om_len;
if (len > maxLen) {
if (ctxt->om->om_len > maxLen) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
uint8_t buf[maxLen];
uint8_t buf[maxLen];
uint16_t len = ctxt->om->om_len;
memcpy(buf, ctxt->om->om_data, len);
os_mbuf* next;
@@ -737,7 +731,7 @@ void NimBLEServer::removeService(NimBLEService* service, bool deleteSvc) {
service->setRemoved(deleteSvc ? NIMBLE_ATT_REMOVE_DELETE : NIMBLE_ATT_REMOVE_HIDE);
serviceChanged();
# if !MYNEWT_VAL(BLE_EXT_ADV) && MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# if !CONFIG_BT_NIMBLE_EXT_ADV
NimBLEDevice::getAdvertising()->removeServiceUUID(service->getUUID());
# endif
} // removeService
@@ -774,9 +768,7 @@ void NimBLEServer::resetGATT() {
return;
}
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
NimBLEDevice::stopAdvertising();
# endif
ble_gatts_reset();
ble_svc_gap_init();
ble_svc_gatt_init();
@@ -799,6 +791,29 @@ void NimBLEServer::resetGATT() {
m_gattsStarted = false;
} // resetGATT
# if CONFIG_BT_NIMBLE_EXT_ADV
/**
* @brief Start advertising.
* @param [in] instId The extended advertisement instance ID to start.
* @param [in] duration How long to advertise for in milliseconds, 0 = forever (default).
* @param [in] maxEvents Maximum number of advertisement events to send, 0 = no limit (default).
* @return True if advertising started successfully.
* @details Start the server advertising its existence. This is a convenience function and is equivalent to
* retrieving the advertising object and invoking start upon it.
*/
bool NimBLEServer::startAdvertising(uint8_t instId, int duration, int maxEvents) const {
return getAdvertising()->start(instId, duration, maxEvents);
} // startAdvertising
/**
* @brief Convenience function to stop advertising a data set.
* @param [in] instId The extended advertisement instance ID to stop advertising.
* @return True if advertising stopped successfully.
*/
bool NimBLEServer::stopAdvertising(uint8_t instId) const {
return getAdvertising()->stop(instId);
} // stopAdvertising
/**
* @brief Request an update to the PHY used for a peer connection.
* @param [in] connHandle the connection handle to the update the PHY for.
@@ -842,33 +857,9 @@ bool NimBLEServer::getPhy(uint16_t connHandle, uint8_t* txPhy, uint8_t* rxPhy) {
return rc == 0;
} // getPhy
# if MYNEWT_VAL(BLE_EXT_ADV)
/**
* @brief Start advertising.
* @param [in] instId The extended advertisement instance ID to start.
* @param [in] duration How long to advertise for in milliseconds, 0 = forever (default).
* @param [in] maxEvents Maximum number of advertisement events to send, 0 = no limit (default).
* @return True if advertising started successfully.
* @details Start the server advertising its existence. This is a convenience function and is equivalent to
* retrieving the advertising object and invoking start upon it.
*/
bool NimBLEServer::startAdvertising(uint8_t instId, int duration, int maxEvents) const {
return getAdvertising()->start(instId, duration, maxEvents);
} // startAdvertising
/**
* @brief Convenience function to stop advertising a data set.
* @param [in] instId The extended advertisement instance ID to stop advertising.
* @return True if advertising stopped successfully.
*/
bool NimBLEServer::stopAdvertising(uint8_t instId) const {
return getAdvertising()->stop(instId);
} // stopAdvertising
# endif
# if (!MYNEWT_VAL(BLE_EXT_ADV) && MYNEWT_VAL(BLE_ROLE_BROADCASTER)) || defined(_DOXYGEN_)
# if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
/**
* @brief Start advertising.
* @param [in] duration The duration in milliseconds to advertise for, default = forever.
@@ -945,7 +936,7 @@ void NimBLEServer::setDataLen(uint16_t connHandle, uint16_t octets) const {
# endif
} // setDataLen
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
/**
* @brief Create a client instance from the connection handle.
* @param [in] connHandle The connection handle to create a client instance from.
@@ -1028,8 +1019,10 @@ void NimBLEServerCallbacks::onConnParamsUpdate(NimBLEConnInfo& connInfo) {
NIMBLE_LOGD("NimBLEServerCallbacks", "onConnParamsUpdate: default");
} // onConnParamsUpdate
# if CONFIG_BT_NIMBLE_EXT_ADV
void NimBLEServerCallbacks::onPhyUpdate(NimBLEConnInfo& connInfo, uint8_t txPhy, uint8_t rxPhy) {
NIMBLE_LOGD("NimBLEServerCallbacks", "onPhyUpdate: default, txPhy: %d, rxPhy: %d", txPhy, rxPhy);
} // onPhyUpdate
# endif
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_SERVER_H_
#define NIMBLE_CPP_SERVER_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# if defined(CONFIG_NIMBLE_CPP_IDF)
# include "host/ble_gap.h"
@@ -45,14 +45,12 @@ class NimBLEConnInfo;
class NimBLEAddress;
class NimBLEService;
class NimBLECharacteristic;
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# if MYNEWT_VAL(BLE_EXT_ADV)
# if CONFIG_BT_NIMBLE_EXT_ADV
class NimBLEExtAdvertising;
# else
# else
class NimBLEAdvertising;
# endif
# endif
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
class NimBLEClient;
# endif
@@ -81,39 +79,35 @@ class NimBLEServer {
NimBLEConnInfo getPeerInfoByHandle(uint16_t connHandle) const;
void advertiseOnDisconnect(bool enable);
void setDataLen(uint16_t connHandle, uint16_t tx_octets) const;
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 MYNEWT_VAL(BLE_ROLE_CENTRAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
NimBLEClient* getClient(uint16_t connHandle);
NimBLEClient* getClient(const NimBLEConnInfo& connInfo);
void deleteClient();
# endif
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# if MYNEWT_VAL(BLE_EXT_ADV)
# if CONFIG_BT_NIMBLE_EXT_ADV
NimBLEExtAdvertising* getAdvertising() const;
bool startAdvertising(uint8_t instanceId, int duration = 0, int maxEvents = 0) const;
bool stopAdvertising(uint8_t instanceId) const;
# endif
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);
# endif
# if !MYNEWT_VAL(BLE_EXT_ADV) || defined(_DOXYGEN_)
# if !CONFIG_BT_NIMBLE_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 MYNEWT_VAL(BLE_ROLE_BROADCASTER)
# if MYNEWT_VAL(BLE_EXT_ADV)
# if CONFIG_BT_NIMBLE_EXT_ADV
friend class NimBLEExtAdvertising;
# else
# else
friend class NimBLEAdvertising;
# endif
# endif
NimBLEServer();
@@ -122,14 +116,14 @@ class NimBLEServer {
bool m_gattsStarted : 1;
bool m_svcChanged : 1;
bool m_deleteCallbacks : 1;
# if !MYNEWT_VAL(BLE_EXT_ADV)
# if !CONFIG_BT_NIMBLE_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;
std::array<uint16_t, CONFIG_BT_NIMBLE_MAX_CONNECTIONS> m_connectedPeers;
# if MYNEWT_VAL(BLE_ROLE_CENTRAL)
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
NimBLEClient* m_pClient{nullptr};
# endif
@@ -209,6 +203,7 @@ class NimBLEServerCallbacks {
*/
virtual void onConnParamsUpdate(NimBLEConnInfo& connInfo);
# if CONFIG_BT_NIMBLE_EXT_ADV
/**
* @brief Called when the PHY update procedure is complete.
* @param [in] connInfo A reference to a NimBLEConnInfo instance with information
@@ -221,7 +216,8 @@ class NimBLEServerCallbacks {
* * BLE_GAP_LE_PHY_CODED
*/
virtual void onPhyUpdate(NimBLEConnInfo& connInfo, uint8_t txPhy, uint8_t rxPhy);
# endif
}; // NimBLEServerCallbacks
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
#endif // NIMBLE_CPP_SERVER_H_

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,10 +15,11 @@
* limitations under the License.
*/
#include "NimBLEService.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# if MYNEWT_VAL(BLE_EXT_ADV)
# include "NimBLEService.h"
# if CONFIG_BT_NIMBLE_EXT_ADV
# include "NimBLEExtAdvertising.h"
# else
# include "NimBLEAdvertising.h"
@@ -375,4 +376,4 @@ bool NimBLEService::isStarted() const {
return m_pSvcDef->type > 0;
} // isStarted
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_SERVICE_H_
#define NIMBLE_CPP_SERVICE_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
class NimBLEService;
@@ -69,5 +69,5 @@ class NimBLEService : public NimBLELocalAttribute {
ble_gatt_svc_def m_pSvcDef[2]{};
}; // NimBLEService
#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#endif // NIMBLE_CPP_SERVICE_H_
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
#endif /* NIMBLE_CPP_SERVICE_H_ */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,10 +15,11 @@
* limitations under the License.
*/
#include "NimBLEUUID.h"
#if CONFIG_BT_NIMBLE_ENABLED
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
# include "NimBLEUtils.h"
# include "NimBLEUUID.h"
# include "NimBLELog.h"
/**** FIX COMPILATION ****/
@@ -336,4 +337,4 @@ NimBLEUUID::operator std::string() const {
return ble_uuid_to_str(&m_uuid.u, buf);
} // operator std::string
#endif /* CONFIG_BT_NIMBLE_ENABLED */
#endif /* CONFIG_BT_ENABLED */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +18,8 @@
#ifndef NIMBLE_CPP_UUID_H_
#define NIMBLE_CPP_UUID_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED
#include "nimconfig.h"
#if defined(CONFIG_BT_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_NIMBLE_ENABLED
#endif // NIMBLE_CPP_UUID_H_
#endif /* CONFIG_BT_ENABLED */
#endif /* NIMBLE_CPP_UUID_H_ */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,9 +15,10 @@
* limitations under the License.
*/
#include "NimBLEUtils.h"
#if CONFIG_BT_NIMBLE_ENABLED
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
# include "NimBLEUtils.h"
# include "NimBLEAddress.h"
# include "NimBLELog.h"
@@ -510,24 +511,22 @@ const char* NimBLEUtils::gapEventToString(uint8_t eventType) {
return "BLE_GAP_EVENT_PATHLOSS_THRESHOLD";
case BLE_GAP_EVENT_TRANSMIT_POWER: // 26
return "BLE_GAP_EVENT_TRANSMIT_POWER";
case BLE_GAP_EVENT_PARING_COMPLETE: // 27
return "BLE_GAP_EVENT_PARING_COMPLETE";
case BLE_GAP_EVENT_SUBRATE_CHANGE: // 28
case BLE_GAP_EVENT_SUBRATE_CHANGE: // 27
return "BLE_GAP_EVENT_SUBRATE_CHANGE";
case BLE_GAP_EVENT_VS_HCI: // 29
case BLE_GAP_EVENT_VS_HCI: // 28
return "BLE_GAP_EVENT_VS_HCI";
case BLE_GAP_EVENT_REATTEMPT_COUNT: // 31
case BLE_GAP_EVENT_REATTEMPT_COUNT: // 29
return "BLE_GAP_EVENT_REATTEMPT_COUNT";
case BLE_GAP_EVENT_AUTHORIZE: // 32
case BLE_GAP_EVENT_AUTHORIZE: // 30
return "BLE_GAP_EVENT_AUTHORIZE";
case BLE_GAP_EVENT_TEST_UPDATE: // 33
case BLE_GAP_EVENT_TEST_UPDATE: // 31
return "BLE_GAP_EVENT_TEST_UPDATE";
# ifdef BLE_GAP_EVENT_DATA_LEN_CHG
case BLE_GAP_EVENT_DATA_LEN_CHG: // 34
case BLE_GAP_EVENT_DATA_LEN_CHG: // 32
return "BLE_GAP_EVENT_DATA_LEN_CHG";
# endif
# ifdef BLE_GAP_EVENT_LINK_ESTAB
case BLE_GAP_EVENT_LINK_ESTAB: // 38
case BLE_GAP_EVENT_LINK_ESTAB: // 33
return "BLE_GAP_EVENT_LINK_ESTAB";
# endif
# endif
@@ -576,4 +575,4 @@ NimBLEAddress NimBLEUtils::generateAddr(bool nrpa) {
return NimBLEAddress{addr};
} // generateAddr
#endif // CONFIG_BT_NIMBLE_ENABLED
#endif // CONFIG_BT_ENABLED

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
* esp-nimble-cpp, NimBLE-Arduino contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,21 +18,8 @@
#ifndef NIMBLE_CPP_UTILS_H_
#define NIMBLE_CPP_UTILS_H_
#include "syscfg/syscfg.h"
#if CONFIG_BT_NIMBLE_ENABLED
#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
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
# include <string>
class NimBLEAddress;
@@ -68,5 +55,5 @@ class NimBLEUtils {
static void taskRelease(const NimBLETaskData& taskData, int rc = 0);
};
#endif // CONFIG_BT_NIMBLE_ENABLED
#endif // CONFIG_BT_ENABLED
#endif // NIMBLE_CPP_UTILS_H_

View File

@@ -1,86 +0,0 @@
/*
* 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.
*/
#ifndef NIMBLE_CPP_VALUE_ATTRIBUTE_H_
#define NIMBLE_CPP_VALUE_ATTRIBUTE_H_
#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)
: m_value(initLen, maxLen) {}
/**
* @brief Get a copy of the value of the attribute value.
* @param [in] timestamp (Optional) A pointer to a time_t struct to get the time the value set.
* @return A copy of the attribute value.
*/
NimBLEAttValue getValue(time_t* timestamp) const { return m_value.getValue(timestamp); }
/**
* @brief Get a copy of the value of the attribute value.
* @return A copy of the attribute value.
*/
NimBLEAttValue getValue() const { return m_value; }
/**
* @brief Get the length of the attribute value.
* @return The length of the attribute value.
*/
size_t getLength() const { return m_value.size(); }
/**
* @brief Template to convert the data to <type\>.
* @tparam T The type to convert the data to.
* @param [in] timestamp (Optional) A pointer to a time_t struct to get the time the value set.
* @param [in] skipSizeCheck (Optional) If true it will skip checking if the data size is less than <tt>sizeof(<type\>)</tt>.
* @return The data converted to <type\> or NULL if skipSizeCheck is false and the data is less than <tt>sizeof(<type\>)</tt>.
* @details <b>Use:</b> <tt>getValue<type>(&timestamp, skipSizeCheck);</tt>
* Used for types that are trivially copyable and convertible to NimBLEAttValue.
*/
template <typename T>
typename std::enable_if<std::is_trivially_copyable<T>::value, T>::type
getValue(time_t* timestamp = nullptr, bool skipSizeCheck = false) const {
return m_value.getValue<T>(timestamp, skipSizeCheck);
}
/**
* @brief Template to convert the data to <type\>.
* @tparam T The type to convert the data to.
* @param [in] timestamp (Optional) A pointer to a time_t struct to get the time the value set.
* @param [in] skipSizeCheck (Optional) If true it will skip checking if the data size is less than <tt>sizeof(<type\>)</tt>.
* @return The data converted to <type\> or NULL if skipSizeCheck is false and the data is less than <tt>sizeof(<type\>)</tt>.
* @details <b>Use:</b> <tt>getValue<type>(&timestamp, skipSizeCheck);</tt>
* Used for types that are not trivially copyable and convertible to NimBLEAttValue via it's operators.
*/
template <typename T>
typename std::enable_if<!std::is_trivially_copyable<T>::value && std::is_convertible<T, NimBLEAttValue>::value, T>::type
getValue(time_t* timestamp = nullptr, bool skipSizeCheck = false) const {
return m_value;
}
protected:
NimBLEAttValue m_value{};
};
#endif // CONFIG_BT_NIMBLE_ENABLED && (MYNEWT_VAL(BLE_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_ROLE_CENTRAL))
#endif // NIMBLE_CPP_ATTRIBUTE_H_

152
src/nimconfig.h Normal file
View File

@@ -0,0 +1,152 @@
/** @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_

81
src/nimconfig_rename.h Normal file
View File

@@ -0,0 +1,81 @@
/*
* 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