mirror of
https://github.com/h2zero/esp-nimble-cpp.git
synced 2026-04-16 14:46:07 +02:00
Compare commits
72 Commits
2.5.0
...
err-on-blo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24a89199a1 | ||
|
|
dd32365625 | ||
|
|
8bb9578b41 | ||
|
|
28d49a0d28 | ||
|
|
b11d34ee06 | ||
|
|
67fa4776f4 | ||
|
|
0db2215c2f | ||
|
|
182796d756 | ||
|
|
afe12212ff | ||
|
|
5d48f9479b | ||
|
|
0dbca80bcf | ||
|
|
74443d93ee | ||
|
|
7b897b1551 | ||
|
|
bc6bb9836d | ||
|
|
2cb68e242d | ||
|
|
6f16880c25 | ||
|
|
a672ecd86b | ||
|
|
3aace03f54 | ||
|
|
494f647e1f | ||
|
|
22e7d6fe8d | ||
|
|
c731adc441 | ||
|
|
42c33fcdb5 | ||
|
|
59ef15a218 | ||
|
|
a0a8db992c | ||
|
|
c64ca74c34 | ||
|
|
4cb427ef51 | ||
|
|
04a7a792ac | ||
|
|
540ebfcb64 | ||
|
|
437e651e0c | ||
|
|
ea7075a2f7 | ||
|
|
002abf91e9 | ||
|
|
3266951aee | ||
|
|
4c07a1d892 | ||
|
|
9a7db6a16e | ||
|
|
25af28bcad | ||
|
|
f216e95770 | ||
|
|
222f1590ed | ||
|
|
149716a506 | ||
|
|
4199c52af1 | ||
|
|
20158d62d0 | ||
|
|
f6c8728ca3 | ||
|
|
e0d3c4be39 | ||
|
|
d163a9fdc6 | ||
|
|
133c1a5da4 | ||
|
|
f622cdff0c | ||
|
|
68068677ab | ||
|
|
2c6ab706b3 | ||
|
|
6f0b9ddf5d | ||
|
|
8f9e85a46a | ||
|
|
7706f5a6b2 | ||
|
|
1ffd013794 | ||
|
|
e8f7147ac5 | ||
|
|
6ee2a951f5 | ||
|
|
4b74939b6d | ||
|
|
9f7b9042e0 | ||
|
|
2cd5dc2aa2 | ||
|
|
9df8cc7dd1 | ||
|
|
88df909cfb | ||
|
|
8cefc0a562 | ||
|
|
8af38e7eb9 | ||
|
|
e7fead903c | ||
|
|
a57c45e1de | ||
|
|
edfc838bef | ||
|
|
f1ead9959d | ||
|
|
b30421c19d | ||
|
|
bdb868d125 | ||
|
|
503939c66f | ||
|
|
2640c44b45 | ||
|
|
fec2d7a279 | ||
|
|
e2cee2d994 | ||
|
|
39f974625c | ||
|
|
169290f047 |
43
CHANGELOG.md
43
CHANGELOG.md
@@ -1,49 +1,6 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [2.5.0] 2026-04-01
|
||||
|
||||
## Fixed
|
||||
- `NimBLEClient` connection state tracking.
|
||||
- Calling disconnect will no longer return false if the HCI response is "Unknown ID".
|
||||
- Remote descriptors not found when characteristic vector handles out of order.
|
||||
- `setValue` with char inputs now calculates the data length correctly.
|
||||
|
||||
## Added
|
||||
- `NimBLEServer::sendServiceChangedIndication` Sends the service changed indication to peers so they refresh their database.
|
||||
- `NimBLEScan` user configuarable scan response timer added to prevent unreported devices on long duration scans.
|
||||
- `NimBLEClient` Connection retry on connection establishment failure, retry count configurable by app, default 2.
|
||||
- ANCS Example
|
||||
- `l2Cap` Disconnect API
|
||||
|
||||
|
||||
## [2.4.0] 2026-03-20
|
||||
|
||||
## Fixed
|
||||
- GATT attribute handles are now assigned from the registration callback so duplicate UUID attributes are identified correctly.
|
||||
- Dynamic service changes now properly remove characteristics/descriptors and reset the GATT database when advertising starts.
|
||||
- Missing notification/indication payload data when the value spans multiple mbufs, such as values larger than 255 bytes with small ACL buffers.
|
||||
- `NimBLEDevice::createServer` will longer crash when called before the stack is initialized.
|
||||
- Re-pairing after deleting all bonds now works by unpairing each stored bond instead of only deleting NVS data.
|
||||
- Whitelist bounds checks.
|
||||
- `NimBLEDevice::getBondedAddress` index bounds validation.
|
||||
- Compiler warnings when bonds are disabled.
|
||||
- kconfig warnings, redefined macros.
|
||||
|
||||
## Added
|
||||
- `NimBLEStream`, `NimBLEStreamClient`, and `NimBLEStreamServer` classes and examples.
|
||||
- `NimBLECppVersion.h` with compile-time version macros.
|
||||
- `NimBLEDevice::getVersion` runtime version string helper.
|
||||
- Matching passkey callbacks for both roles: `NimBLEServerCallbacks::onPassKeyEntry` and `NimBLEClientCallbacks::onPassKeyDisplay`.
|
||||
- Bond migration helpers to convert bond storage between v1 and current formats while preserving existing bonds.
|
||||
- `NimBLEUUID` constructor overload for `ble_uuid_t*`.
|
||||
- Optional `index` parameter for `NimBLECharacteristic::getDescriptorByUUID` to access multiple descriptors with the same UUID.
|
||||
- `NimBLEConnInfo::toString` method to get a string representation of the connection info.
|
||||
|
||||
## Changed
|
||||
- `NimBLEService::start` is deprecated; services are now added when the server starts.
|
||||
- `NimBLEHIDDevice::startServices()` is deprecated; services are now added when the server starts.
|
||||
|
||||
## [2.3.4] 2025-12-27
|
||||
|
||||
## Fixed
|
||||
|
||||
4
Kconfig
4
Kconfig
@@ -204,4 +204,8 @@ 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
|
||||
|
||||
endmenu
|
||||
@@ -48,7 +48,7 @@ PROJECT_NAME = esp-nimble-cpp
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = 2.5.0
|
||||
PROJECT_NUMBER = 2.3.3
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
# quick idea about the purpose of the project. Keep the description short.
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
dependencies:
|
||||
local/esp-nimble-cpp:
|
||||
path: ../../../../../esp-nimble-cpp/
|
||||
mickeyl/esp-hpl:
|
||||
git: https://github.com/mickeyl/esp-hpl.git
|
||||
version: "1.1.0"
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
#include <NimBLEDevice.h>
|
||||
#include <esp_hpl.hpp>
|
||||
#include <esp_timer.h>
|
||||
|
||||
#define L2CAP_PSM 192
|
||||
// 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
|
||||
#define INITIAL_PAYLOAD_SIZE 64
|
||||
#define BLOCKS_BEFORE_DOUBLE 50
|
||||
#define MAX_PAYLOAD_SIZE 4900
|
||||
|
||||
const BLEAdvertisedDevice* theDevice = NULL;
|
||||
BLEClient* theClient = NULL;
|
||||
@@ -14,15 +17,6 @@ BLEL2CAPChannel* theChannel = NULL;
|
||||
|
||||
size_t bytesSent = 0;
|
||||
size_t bytesReceived = 0;
|
||||
size_t currentPayloadSize = INITIAL_PAYLOAD_SIZE;
|
||||
uint32_t blocksSent = 0;
|
||||
uint64_t startTime = 0;
|
||||
|
||||
// Heap monitoring
|
||||
size_t initialHeap = 0;
|
||||
size_t lastHeap = 0;
|
||||
size_t heapDecreaseCount = 0;
|
||||
const size_t HEAP_LEAK_THRESHOLD = 10; // Warn after 10 consecutive decreases
|
||||
|
||||
class L2CAPChannelCallbacks: public BLEL2CAPChannelCallbacks {
|
||||
|
||||
@@ -49,7 +43,7 @@ class MyClientCallbacks: public BLEClientCallbacks {
|
||||
printf("GAP connected\n");
|
||||
pClient->setDataLen(251);
|
||||
|
||||
theChannel = BLEL2CAPChannel::connect(pClient, L2CAP_PSM, L2CAP_MTU, new L2CAPChannelCallbacks());
|
||||
theChannel = BLEL2CAPChannel::connect(pClient, L2CAP_CHANNEL, L2CAP_MTU, new L2CAPChannelCallbacks());
|
||||
}
|
||||
|
||||
void onDisconnect(BLEClient* pClient, int reason) {
|
||||
@@ -67,72 +61,23 @@ class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
|
||||
if (theDevice) { return; }
|
||||
printf("BLE Advertised Device found: %s\n", advertisedDevice->toString().c_str());
|
||||
|
||||
// Look for device named "l2cap"
|
||||
if (advertisedDevice->haveName() && advertisedDevice->getName() == "l2cap") {
|
||||
printf("Found l2cap device!\n");
|
||||
BLEDevice::getScan()->stop();
|
||||
theDevice = advertisedDevice;
|
||||
}
|
||||
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 statusTask(void *pvParameters) {
|
||||
while (true) {
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
|
||||
if (startTime > 0 && blocksSent > 0) {
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
double elapsedSeconds = (currentTime - startTime) / 1000000.0;
|
||||
double bytesPerSecond = 0.0;
|
||||
double kbPerSecond = 0.0;
|
||||
if (elapsedSeconds > 0.0) {
|
||||
bytesPerSecond = bytesSent / elapsedSeconds;
|
||||
kbPerSecond = bytesPerSecond / 1024.0;
|
||||
}
|
||||
|
||||
// Heap monitoring
|
||||
size_t currentHeap = esp_get_free_heap_size();
|
||||
size_t minHeap = esp_get_minimum_free_heap_size();
|
||||
|
||||
// Track heap for leak detection
|
||||
if (initialHeap == 0) {
|
||||
initialHeap = currentHeap;
|
||||
lastHeap = currentHeap;
|
||||
}
|
||||
|
||||
// Check for consistent heap decrease
|
||||
if (currentHeap < lastHeap) {
|
||||
heapDecreaseCount++;
|
||||
if (heapDecreaseCount >= HEAP_LEAK_THRESHOLD) {
|
||||
printf("\n⚠️ WARNING: POSSIBLE MEMORY LEAK DETECTED! ⚠️\n");
|
||||
printf("Heap has decreased %zu times in a row\n", heapDecreaseCount);
|
||||
printf("Initial heap: %zu, Current heap: %zu, Lost: %zu bytes\n",
|
||||
initialHeap, currentHeap, initialHeap - currentHeap);
|
||||
}
|
||||
} else if (currentHeap >= lastHeap) {
|
||||
heapDecreaseCount = 0; // Reset counter if heap stabilizes or increases
|
||||
}
|
||||
lastHeap = currentHeap;
|
||||
|
||||
printf("\n=== STATUS UPDATE ===\n");
|
||||
printf("Blocks sent: %lu\n", (unsigned long)blocksSent);
|
||||
printf("Total bytes sent: %zu\n", bytesSent);
|
||||
printf("Current payload size: %zu bytes\n", currentPayloadSize);
|
||||
printf("Elapsed time: %.1f seconds\n", elapsedSeconds);
|
||||
printf("Bandwidth: %.2f KB/s (%.2f Mbps)\n", kbPerSecond, (bytesPerSecond * 8) / 1000000.0);
|
||||
printf("Heap: %zu free (min: %zu), Used since start: %zu\n",
|
||||
currentHeap, minHeap, initialHeap > 0 ? initialHeap - currentHeap : 0);
|
||||
printf("==================\n\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void connectTask(void *pvParameters) {
|
||||
|
||||
uint8_t sequenceNumber = 0;
|
||||
|
||||
while (true) {
|
||||
|
||||
|
||||
if (!theDevice) {
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
continue;
|
||||
@@ -151,7 +96,7 @@ void connectTask(void *pvParameters) {
|
||||
break;
|
||||
}
|
||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!theChannel) {
|
||||
@@ -167,58 +112,22 @@ void connectTask(void *pvParameters) {
|
||||
}
|
||||
|
||||
while (theChannel->isConnected()) {
|
||||
// Create framed packet: [seqno 8bit] [16bit payload length] [payload]
|
||||
std::vector<uint8_t> packet;
|
||||
packet.reserve(3 + currentPayloadSize);
|
||||
|
||||
// Add sequence number (8 bits)
|
||||
packet.push_back(sequenceNumber);
|
||||
|
||||
// Add payload length (16 bits, big endian - network byte order)
|
||||
uint16_t payloadLen = currentPayloadSize;
|
||||
packet.push_back((payloadLen >> 8) & 0xFF); // High byte first
|
||||
packet.push_back(payloadLen & 0xFF); // Low byte second
|
||||
|
||||
// Add payload
|
||||
for (size_t i = 0; i < currentPayloadSize; i++) {
|
||||
packet.push_back(i & 0xFF);
|
||||
}
|
||||
|
||||
if (theChannel->write(packet)) {
|
||||
if (startTime == 0) {
|
||||
startTime = esp_timer_get_time();
|
||||
}
|
||||
bytesSent += packet.size();
|
||||
blocksSent++;
|
||||
|
||||
// Print every block since we're sending slowly now
|
||||
printf("Sent block %lu (seq=%d, payload=%zu bytes, frame_size=%zu)\n",
|
||||
(unsigned long)blocksSent, sequenceNumber, currentPayloadSize, packet.size());
|
||||
|
||||
sequenceNumber++;
|
||||
|
||||
// After every 50 blocks, double payload size
|
||||
if (blocksSent % BLOCKS_BEFORE_DOUBLE == 0) {
|
||||
size_t newSize = currentPayloadSize * 2;
|
||||
|
||||
// Cap at maximum safe payload size
|
||||
if (newSize > MAX_PAYLOAD_SIZE) {
|
||||
if (currentPayloadSize < MAX_PAYLOAD_SIZE) {
|
||||
currentPayloadSize = MAX_PAYLOAD_SIZE;
|
||||
printf("\n=== Reached maximum payload size of %zu bytes after %lu blocks ===\n", currentPayloadSize, (unsigned long)blocksSent);
|
||||
}
|
||||
// Already at max, don't increase further
|
||||
} else {
|
||||
currentPayloadSize = newSize;
|
||||
printf("\n=== Doubling payload size to %zu bytes after %lu blocks ===\n", currentPayloadSize, (unsigned long)blocksSent);
|
||||
}
|
||||
}
|
||||
/*
|
||||
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();
|
||||
abort();
|
||||
}
|
||||
|
||||
// No delay - send as fast as possible
|
||||
}
|
||||
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
@@ -227,13 +136,9 @@ void connectTask(void *pvParameters) {
|
||||
|
||||
extern "C"
|
||||
void app_main(void) {
|
||||
// Install high performance logging before any output
|
||||
esp_hpl::HighPerformanceLogger::init();
|
||||
|
||||
printf("Starting L2CAP client example\n");
|
||||
|
||||
xTaskCreate(connectTask, "connectTask", 5000, NULL, 1, NULL);
|
||||
xTaskCreate(statusTask, "statusTask", 3000, NULL, 1, NULL);
|
||||
|
||||
BLEDevice::init("L2CAP-Client");
|
||||
BLEDevice::setMTU(BLE_ATT_MTU_MAX);
|
||||
@@ -246,8 +151,15 @@ void app_main(void) {
|
||||
scan->setActiveScan(true);
|
||||
scan->start(25 * 1000, false);
|
||||
|
||||
// Main task just waits
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
dependencies:
|
||||
local/esp-nimble-cpp:
|
||||
path: ../../../../../esp-nimble-cpp/
|
||||
mickeyl/esp-hpl:
|
||||
git: https://github.com/mickeyl/esp-hpl.git
|
||||
version: "1.1.0"
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
#include <NimBLEDevice.h>
|
||||
#include <esp_hpl.hpp>
|
||||
#include <esp_timer.h>
|
||||
|
||||
#define L2CAP_PSM 192
|
||||
// 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
|
||||
|
||||
// Heap monitoring
|
||||
size_t initialHeap = 0;
|
||||
size_t lastHeap = 0;
|
||||
size_t heapDecreaseCount = 0;
|
||||
const size_t HEAP_LEAK_THRESHOLD = 10; // Warn after 10 consecutive decreases
|
||||
|
||||
class GATTCallbacks: public BLEServerCallbacks {
|
||||
|
||||
public:
|
||||
@@ -26,179 +23,68 @@ class L2CAPChannelCallbacks: public BLEL2CAPChannelCallbacks {
|
||||
|
||||
public:
|
||||
bool connected = false;
|
||||
size_t totalBytesReceived = 0;
|
||||
size_t totalFramesReceived = 0;
|
||||
size_t totalPayloadBytes = 0;
|
||||
uint8_t expectedSequenceNumber = 0;
|
||||
size_t sequenceErrors = 0;
|
||||
size_t frameErrors = 0;
|
||||
uint64_t startTime = 0;
|
||||
std::vector<uint8_t> buffer; // Buffer for incomplete frames
|
||||
size_t numberOfReceivedBytes;
|
||||
uint8_t nextSequenceNumber;
|
||||
|
||||
public:
|
||||
void onConnect(NimBLEL2CAPChannel* channel) {
|
||||
printf("L2CAP connection established on PSM %d\n", L2CAP_PSM);
|
||||
printf("L2CAP connection established\n");
|
||||
connected = true;
|
||||
totalBytesReceived = 0;
|
||||
totalFramesReceived = 0;
|
||||
totalPayloadBytes = 0;
|
||||
expectedSequenceNumber = 0;
|
||||
sequenceErrors = 0;
|
||||
frameErrors = 0;
|
||||
startTime = esp_timer_get_time();
|
||||
buffer.clear();
|
||||
numberOfReceivedBytes = nextSequenceNumber = 0;
|
||||
}
|
||||
|
||||
void onRead(NimBLEL2CAPChannel* channel, std::vector<uint8_t>& data) {
|
||||
// Append new data to buffer
|
||||
buffer.insert(buffer.end(), data.begin(), data.end());
|
||||
totalBytesReceived += data.size();
|
||||
if (startTime == 0) {
|
||||
startTime = esp_timer_get_time(); // start measuring once data flows
|
||||
}
|
||||
|
||||
// Process complete frames from buffer
|
||||
while (buffer.size() >= 3) { // Minimum frame size: seqno(1) + len(2)
|
||||
// Parse frame header
|
||||
uint8_t seqno = buffer[0];
|
||||
uint16_t payloadLen = (buffer[1] << 8) | buffer[2]; // Big-endian
|
||||
|
||||
size_t frameSize = 3 + payloadLen;
|
||||
|
||||
// Check if we have complete frame
|
||||
if (buffer.size() < frameSize) {
|
||||
break; // Wait for more data
|
||||
}
|
||||
|
||||
// Validate and process frame
|
||||
totalFramesReceived++;
|
||||
totalPayloadBytes += payloadLen;
|
||||
|
||||
// Check sequence number
|
||||
if (seqno != expectedSequenceNumber) {
|
||||
sequenceErrors++;
|
||||
printf("Frame %zu: Sequence error - got %d, expected %d (payload=%d bytes)\n",
|
||||
totalFramesReceived, seqno, expectedSequenceNumber, payloadLen);
|
||||
}
|
||||
|
||||
// Update expected sequence number (wraps at 256)
|
||||
expectedSequenceNumber = (seqno + 1) & 0xFF;
|
||||
|
||||
// Remove processed frame from buffer
|
||||
buffer.erase(buffer.begin(), buffer.begin() + frameSize);
|
||||
|
||||
// Print progress every 100 frames
|
||||
if (totalFramesReceived % 100 == 0) {
|
||||
double elapsedSeconds = (esp_timer_get_time() - startTime) / 1000000.0;
|
||||
double bytesPerSecond = elapsedSeconds > 0 ? totalBytesReceived / elapsedSeconds : 0.0;
|
||||
printf("Received %zu frames (%zu payload bytes) - Bandwidth: %.2f KB/s (%.2f Mbps)\n",
|
||||
totalFramesReceived, totalPayloadBytes,
|
||||
bytesPerSecond / 1024.0, (bytesPerSecond * 8) / 1000000.0);
|
||||
}
|
||||
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("\nL2CAP disconnected\n");
|
||||
double elapsedSeconds = startTime > 0 ? (esp_timer_get_time() - startTime) / 1000000.0 : 0.0;
|
||||
double bytesPerSecond = elapsedSeconds > 0 ? totalBytesReceived / elapsedSeconds : 0.0;
|
||||
|
||||
printf("Final statistics:\n");
|
||||
printf(" Total frames: %zu\n", totalFramesReceived);
|
||||
printf(" Total bytes: %zu\n", totalBytesReceived);
|
||||
printf(" Payload bytes: %zu\n", totalPayloadBytes);
|
||||
printf(" Sequence errors: %zu\n", sequenceErrors);
|
||||
printf(" Frame errors: %zu\n", frameErrors);
|
||||
printf(" Bandwidth: %.2f KB/s (%.2f Mbps)\n", bytesPerSecond / 1024.0, (bytesPerSecond * 8) / 1000000.0);
|
||||
|
||||
// Reset state for the next connection
|
||||
buffer.clear();
|
||||
totalBytesReceived = 0;
|
||||
totalFramesReceived = 0;
|
||||
totalPayloadBytes = 0;
|
||||
expectedSequenceNumber = 0;
|
||||
sequenceErrors = 0;
|
||||
frameErrors = 0;
|
||||
startTime = 0;
|
||||
printf("L2CAP disconnected\n");
|
||||
connected = false;
|
||||
|
||||
// Restart advertising so another client can connect
|
||||
BLEDevice::startAdvertising();
|
||||
}
|
||||
};
|
||||
|
||||
extern "C"
|
||||
void app_main(void) {
|
||||
// Install high performance logging before any other output
|
||||
esp_hpl::HighPerformanceLogger::init();
|
||||
|
||||
printf("Starting L2CAP server example [%lu free] [%lu min]\n", esp_get_free_heap_size(), esp_get_minimum_free_heap_size());
|
||||
|
||||
BLEDevice::init("l2cap"); // Match the name the client is looking for
|
||||
BLEDevice::init("L2CAP-Server");
|
||||
BLEDevice::setMTU(BLE_ATT_MTU_MAX);
|
||||
|
||||
auto cocServer = BLEDevice::createL2CAPServer();
|
||||
auto l2capChannelCallbacks = new L2CAPChannelCallbacks();
|
||||
auto channel = cocServer->createService(L2CAP_PSM, L2CAP_MTU, l2capChannelCallbacks);
|
||||
(void)channel; // prevent unused warning
|
||||
|
||||
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();
|
||||
NimBLEAdvertisementData scanData;
|
||||
scanData.setName("l2cap");
|
||||
advertising->setScanResponseData(scanData);
|
||||
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());
|
||||
|
||||
// Status reporting loop
|
||||
// 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 && l2capChannelCallbacks->totalBytesReceived > 0) {
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
double elapsedSeconds = (currentTime - l2capChannelCallbacks->startTime) / 1000000.0;
|
||||
|
||||
if (elapsedSeconds > 0) {
|
||||
double bytesPerSecond = l2capChannelCallbacks->totalBytesReceived / elapsedSeconds;
|
||||
double framesPerSecond = l2capChannelCallbacks->totalFramesReceived / elapsedSeconds;
|
||||
|
||||
// Heap monitoring
|
||||
size_t currentHeap = esp_get_free_heap_size();
|
||||
size_t minHeap = esp_get_minimum_free_heap_size();
|
||||
|
||||
// Track heap for leak detection
|
||||
if (initialHeap == 0) {
|
||||
initialHeap = currentHeap;
|
||||
lastHeap = currentHeap;
|
||||
}
|
||||
|
||||
// Check for consistent heap decrease
|
||||
if (currentHeap < lastHeap) {
|
||||
heapDecreaseCount++;
|
||||
if (heapDecreaseCount >= HEAP_LEAK_THRESHOLD) {
|
||||
printf("\n⚠️ WARNING: POSSIBLE MEMORY LEAK DETECTED! ⚠️\n");
|
||||
printf("Heap has decreased %zu times in a row\n", heapDecreaseCount);
|
||||
printf("Initial heap: %zu, Current heap: %zu, Lost: %zu bytes\n",
|
||||
initialHeap, currentHeap, initialHeap - currentHeap);
|
||||
}
|
||||
} else if (currentHeap >= lastHeap) {
|
||||
heapDecreaseCount = 0; // Reset counter if heap stabilizes or increases
|
||||
}
|
||||
lastHeap = currentHeap;
|
||||
|
||||
printf("\n=== STATUS UPDATE ===\n");
|
||||
printf("Frames received: %zu (%.1f fps)\n", l2capChannelCallbacks->totalFramesReceived, framesPerSecond);
|
||||
printf("Total bytes: %zu\n", l2capChannelCallbacks->totalBytesReceived);
|
||||
printf("Payload bytes: %zu\n", l2capChannelCallbacks->totalPayloadBytes);
|
||||
printf("Bandwidth: %.2f KB/s (%.2f Mbps)\n", bytesPerSecond / 1024.0, (bytesPerSecond * 8) / 1000000.0);
|
||||
printf("Sequence errors: %zu\n", l2capChannelCallbacks->sequenceErrors);
|
||||
printf("Heap: %zu free (min: %zu), Used since start: %zu\n",
|
||||
currentHeap, minHeap, initialHeap > 0 ? initialHeap - currentHeap : 0);
|
||||
printf("==================\n");
|
||||
}
|
||||
}
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
## IDF Component Manager Manifest File
|
||||
version: "2.5.0"
|
||||
version: "2.3.4"
|
||||
license: "Apache-2.0"
|
||||
description: "C++ wrapper for the NimBLE BLE stack"
|
||||
url: "https://github.com/h2zero/esp-nimble-cpp"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "esp-nimble-cpp",
|
||||
"version": "2.5.0",
|
||||
"version": "2.3.4",
|
||||
"description": "C++ wrapper for the NimBLE BLE stack",
|
||||
"keywords": [
|
||||
"BLE",
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
#include "syscfg/syscfg.h"
|
||||
#if CONFIG_BT_NIMBLE_ENABLED
|
||||
|
||||
# ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# include "nimble/nimble/include/nimble/ble.h"
|
||||
# else
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# include "nimble/ble.h"
|
||||
# else
|
||||
# include "nimble/nimble/include/nimble/ble.h"
|
||||
# endif
|
||||
|
||||
/**** FIX COMPILATION ****/
|
||||
@@ -63,8 +63,8 @@ class NimBLEAddress : private ble_addr_t {
|
||||
const NimBLEAddress& reverseByteOrder();
|
||||
bool operator==(const NimBLEAddress& rhs) const;
|
||||
bool operator!=(const NimBLEAddress& rhs) const;
|
||||
operator std::string() const;
|
||||
operator uint64_t() const;
|
||||
operator std::string() const;
|
||||
operator uint64_t() const;
|
||||
};
|
||||
|
||||
#endif // CONFIG_BT_NIMBLE_ENABLED
|
||||
|
||||
@@ -25,12 +25,12 @@
|
||||
# include "NimBLEScan.h"
|
||||
# include "NimBLEUUID.h"
|
||||
|
||||
# ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# include "nimble/nimble/host/include/host/ble_hs_adv.h"
|
||||
# include "nimble/nimble/host/include/host/ble_gap.h"
|
||||
# else
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# include "host/ble_hs_adv.h"
|
||||
# include "host/ble_gap.h"
|
||||
# else
|
||||
# include "nimble/nimble/host/include/host/ble_hs_adv.h"
|
||||
# include "nimble/nimble/host/include/host/ble_gap.h"
|
||||
# endif
|
||||
|
||||
# include <vector>
|
||||
@@ -158,13 +158,13 @@ class NimBLEAdvertisedDevice {
|
||||
uint8_t findAdvField(uint8_t type, uint8_t index = 0, size_t* data_loc = nullptr) const;
|
||||
size_t findServiceData(uint8_t index, uint8_t* bytes) const;
|
||||
|
||||
NimBLEAddress m_address{};
|
||||
uint8_t m_advType{};
|
||||
int8_t m_rssi{};
|
||||
uint8_t m_callbackSent{};
|
||||
uint16_t m_advLength{};
|
||||
ble_npl_time_t m_time{};
|
||||
NimBLEAdvertisedDevice* m_pNextWaiting{}; // intrusive list node; self-pointer means "not in list", set in ctor
|
||||
NimBLEAddress m_address{};
|
||||
uint8_t m_advType{};
|
||||
int8_t m_rssi{};
|
||||
uint8_t m_callbackSent{};
|
||||
uint16_t m_advLength{};
|
||||
ble_npl_time_t m_time{};
|
||||
NimBLEAdvertisedDevice* m_pNextWaiting{}; // intrusive list node; self-pointer means "not in list", set in ctor
|
||||
|
||||
# if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
bool m_isLegacyAdv{};
|
||||
|
||||
@@ -23,10 +23,10 @@
|
||||
# include "NimBLEUUID.h"
|
||||
# include "NimBLELog.h"
|
||||
|
||||
#ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# include "nimble/nimble/host/include/host/ble_hs_adv.h"
|
||||
# else
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# include "host/ble_hs_adv.h"
|
||||
# else
|
||||
# include "nimble/nimble/host/include/host/ble_hs_adv.h"
|
||||
# endif
|
||||
|
||||
static const char* LOG_TAG = "NimBLEAdvertisementData";
|
||||
|
||||
@@ -18,12 +18,11 @@
|
||||
#include "NimBLEAdvertising.h"
|
||||
#if (CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && !MYNEWT_VAL(BLE_EXT_ADV)) || defined(_DOXYGEN_)
|
||||
|
||||
#ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# include "nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h"
|
||||
# else
|
||||
# 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 "NimBLEDevice.h"
|
||||
# include "NimBLEServer.h"
|
||||
# include "NimBLEUtils.h"
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
#include "syscfg/syscfg.h"
|
||||
#if (CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && !MYNEWT_VAL(BLE_EXT_ADV)) || defined(_DOXYGEN_)
|
||||
|
||||
#ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# include "nimble/nimble/host/include/host/ble_gap.h"
|
||||
# else
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# include "host/ble_gap.h"
|
||||
# else
|
||||
# include "nimble/nimble/host/include/host/ble_gap.h"
|
||||
# endif
|
||||
|
||||
/**** FIX COMPILATION ****/
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
#include "NimBLEAttValue.h"
|
||||
#if CONFIG_BT_NIMBLE_ENABLED
|
||||
|
||||
# ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# include "nimble/nimble/include/nimble/nimble_npl.h"
|
||||
# else
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# include "nimble/nimble_npl.h"
|
||||
# else
|
||||
# include "nimble/nimble/include/nimble/nimble_npl.h"
|
||||
# endif
|
||||
|
||||
# include "NimBLEUtils.h"
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "NimBLECharacteristic.h"
|
||||
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
|
||||
|
||||
# ifndef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# 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
|
||||
|
||||
@@ -23,10 +23,10 @@
|
||||
# include "NimBLEDevice.h"
|
||||
# include "NimBLELog.h"
|
||||
|
||||
# ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# include "nimble/porting/nimble/include/nimble/nimble_port.h"
|
||||
# else
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# include "nimble/nimble_port.h"
|
||||
# else
|
||||
# include "nimble/porting/nimble/include/nimble/nimble_port.h"
|
||||
# endif
|
||||
|
||||
# include <climits>
|
||||
@@ -270,6 +270,12 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes,
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!asyncConnect && NimBLEUtils::inHostTask()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot connect synchronously from host task");
|
||||
rc = BLE_HS_EREJECT;
|
||||
goto error;
|
||||
}
|
||||
|
||||
m_connStatus = CONNECTING;
|
||||
m_peerAddress = address;
|
||||
m_config.asyncConnect = asyncConnect;
|
||||
@@ -334,6 +340,11 @@ error:
|
||||
*/
|
||||
bool NimBLEClient::secureConnection(bool async) const {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> secureConnection()");
|
||||
if (!async && NimBLEUtils::inHostTask()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot secure connection synchronously from host task");
|
||||
m_lastErr = BLE_HS_EREJECT;
|
||||
return false;
|
||||
}
|
||||
|
||||
int rc = 0;
|
||||
if (async && !NimBLEDevice::startSecurity(m_connHandle, &rc)) {
|
||||
@@ -550,7 +561,7 @@ bool NimBLEClient::updateConnParams(uint16_t minInterval, uint16_t maxInterval,
|
||||
* @param [in] txOctets The preferred number of payload octets to use (Range 0x001B-0x00FB).
|
||||
*/
|
||||
bool NimBLEClient::setDataLen(uint16_t txOctets) {
|
||||
# if !defined(USING_NIMBLE_ARDUINO_HEADERS) && !defined(ESP_IDF_VERSION) || \
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF) && !defined(ESP_IDF_VERSION) || \
|
||||
(ESP_IDF_VERSION_MAJOR * 100 + ESP_IDF_VERSION_MINOR * 10 + ESP_IDF_VERSION_PATCH) < 432
|
||||
return false;
|
||||
# else
|
||||
@@ -669,6 +680,10 @@ NimBLERemoteService* NimBLEClient::getService(const char* uuid) {
|
||||
*/
|
||||
NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID& uuid) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> getService: uuid: %s", uuid.toString().c_str());
|
||||
if (NimBLEUtils::inHostTask()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "getService cannot be called from host task");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (auto& it : m_svcVec) {
|
||||
if (it->getUUID() == uuid) {
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
#include "syscfg/syscfg.h"
|
||||
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
|
||||
|
||||
# ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# include "nimble/nimble/host/include/host/ble_gap.h"
|
||||
# else
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# include "host/ble_gap.h"
|
||||
# else
|
||||
# include "nimble/nimble/host/include/host/ble_gap.h"
|
||||
# endif
|
||||
|
||||
# include "NimBLEAddress.h"
|
||||
@@ -118,7 +118,7 @@ class NimBLEClient {
|
||||
* - deleteOnConnectFail: false
|
||||
* - asyncConnect: false
|
||||
* - exchangeMTU: true
|
||||
* - connectFailRetries: 2
|
||||
* - connectFailRetries: 2
|
||||
*/
|
||||
Config()
|
||||
: deleteCallbacks(0),
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
#ifndef NIMBLE_CPP_CONNINFO_H_
|
||||
#define NIMBLE_CPP_CONNINFO_H_
|
||||
|
||||
#ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# include "nimble/nimble/host/include/host/ble_gap.h"
|
||||
#else
|
||||
#if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# include "host/ble_gap.h"
|
||||
#else
|
||||
# include "nimble/nimble/host/include/host/ble_gap.h"
|
||||
#endif
|
||||
|
||||
#include "NimBLEAddress.h"
|
||||
|
||||
@@ -22,10 +22,10 @@
|
||||
#define NIMBLE_CPP_VERSION_MAJOR 2
|
||||
|
||||
/** @brief NimBLE-Arduino library minor version number. */
|
||||
#define NIMBLE_CPP_VERSION_MINOR 5
|
||||
#define NIMBLE_CPP_VERSION_MINOR 3
|
||||
|
||||
/** @brief NimBLE-Arduino library patch version number. */
|
||||
#define NIMBLE_CPP_VERSION_PATCH 0
|
||||
#define NIMBLE_CPP_VERSION_PATCH 9
|
||||
|
||||
/**
|
||||
* @brief Macro to create a version number for comparison.
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
# include "esp_bt.h"
|
||||
# endif
|
||||
# include "nvs_flash.h"
|
||||
# ifndef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) || CONFIG_BT_NIMBLE_LEGACY_VHCI_ENABLE)
|
||||
# include "esp_nimble_hci.h"
|
||||
# endif
|
||||
@@ -35,14 +35,14 @@
|
||||
# include "host/util/util.h"
|
||||
# include "services/gap/ble_svc_gap.h"
|
||||
# include "services/gatt/ble_svc_gatt.h"
|
||||
# else // USING_NIMBLE_ARDUINO_HEADERS
|
||||
# else
|
||||
# include "nimble/esp_port/esp-hci/include/esp_nimble_hci.h"
|
||||
# endif
|
||||
# else
|
||||
# include "nimble/nimble/controller/include/controller/ble_phy.h"
|
||||
# endif
|
||||
|
||||
# ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# ifndef CONFIG_NIMBLE_CPP_IDF
|
||||
# include "nimble/porting/nimble/include/nimble/nimble_port.h"
|
||||
# include "nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h"
|
||||
# include "nimble/nimble/host/include/host/ble_hs.h"
|
||||
@@ -876,6 +876,7 @@ void NimBLEDevice::onSync(void) {
|
||||
*/
|
||||
void NimBLEDevice::host_task(void* param) {
|
||||
NIMBLE_LOGI(LOG_TAG, "NimBLE Started!");
|
||||
NimBLEUtils::m_hostTaskHandle = ble_npl_get_current_task_id();
|
||||
nimble_port_run(); // This function will return only when nimble_port_stop() is executed
|
||||
nimble_port_freertos_deinit();
|
||||
} // host_task
|
||||
@@ -911,7 +912,7 @@ 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(USING_NIMBLE_ARDUINO_HEADERS)
|
||||
# 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;
|
||||
@@ -1025,7 +1026,7 @@ bool NimBLEDevice::deinit(bool clearAll) {
|
||||
rc = nimble_port_stop();
|
||||
if (rc == 0) {
|
||||
nimble_port_deinit();
|
||||
# ifndef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# ifdef CONFIG_NIMBLE_CPP_IDF
|
||||
# if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
rc = esp_nimble_hci_and_controller_deinit();
|
||||
if (rc != ESP_OK) {
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
(CONFIG_BTDM_BLE_SCAN_DUPL || CONFIG_BT_LE_SCAN_DUPL || CONFIG_BT_CTRL_BLE_SCAN_DUPL)
|
||||
# endif
|
||||
|
||||
# ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# include "nimble/nimble/host/include/host/ble_gap.h"
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# include <host/ble_gap.h>
|
||||
# else
|
||||
# include "host/ble_gap.h"
|
||||
# include <nimble/nimble/host/include/host/ble_gap.h>
|
||||
# endif
|
||||
|
||||
/**** FIX COMPILATION ****/
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
#include "NimBLEExtAdvertising.h"
|
||||
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && MYNEWT_VAL(BLE_EXT_ADV)
|
||||
|
||||
#ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# include "nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h"
|
||||
#else
|
||||
# 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 "NimBLEDevice.h"
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
#include "syscfg/syscfg.h"
|
||||
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && MYNEWT_VAL(BLE_EXT_ADV)
|
||||
|
||||
# ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# include "nimble/nimble/host/include/host/ble_gap.h"
|
||||
# else
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# include "host/ble_gap.h"
|
||||
# else
|
||||
# include "nimble/nimble/host/include/host/ble_gap.h"
|
||||
# endif
|
||||
|
||||
/**** FIX COMPILATION ****/
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
# include "NimBLELog.h"
|
||||
# include "NimBLEUtils.h"
|
||||
|
||||
# ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# include "nimble/nimble/host/include/host/ble_gap.h"
|
||||
# else
|
||||
# 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
|
||||
@@ -134,14 +134,8 @@ int NimBLEL2CAPChannel::writeFragment(std::vector<uint8_t>::const_iterator begin
|
||||
|
||||
case BLE_HS_ENOMEM:
|
||||
case BLE_HS_EAGAIN:
|
||||
/* ble_l2cap_send already consumed and freed txd on these errors */
|
||||
NIMBLE_LOGD(LOG_TAG, "ble_l2cap_send returned %d (consumed buffer). Retrying shortly...", res);
|
||||
ble_npl_time_delay(ble_npl_time_ms_to_ticks32(RetryTimeout));
|
||||
continue;
|
||||
|
||||
case BLE_HS_EBUSY:
|
||||
/* Channel busy; txd not consumed */
|
||||
NIMBLE_LOGD(LOG_TAG, "ble_l2cap_send returned %d (busy). Retrying shortly...", res);
|
||||
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;
|
||||
@@ -203,28 +197,6 @@ bool NimBLEL2CAPChannel::write(const std::vector<uint8_t>& bytes) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NimBLEL2CAPChannel::disconnect() {
|
||||
if (!this->channel) {
|
||||
NIMBLE_LOGW(LOG_TAG, "L2CAP Channel not open");
|
||||
return false;
|
||||
}
|
||||
|
||||
int rc = ble_l2cap_disconnect(this->channel);
|
||||
if (rc != 0 && rc != BLE_HS_ENOTCONN && rc != BLE_HS_EALREADY) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_l2cap_disconnect failed: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t NimBLEL2CAPChannel::getConnHandle() const {
|
||||
if (!this->channel) {
|
||||
return BLE_HS_CONN_HANDLE_NONE;
|
||||
}
|
||||
return ble_l2cap_get_conn_handle(this->channel);
|
||||
}
|
||||
|
||||
// private
|
||||
int NimBLEL2CAPChannel::handleConnectionEvent(struct ble_l2cap_event* event) {
|
||||
channel = event->connect.chan;
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
|
||||
|
||||
# include "inttypes.h"
|
||||
# ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# include "nimble/nimble/host/include/host/ble_l2cap.h"
|
||||
# include "nimble/porting/nimble/include/os/os_mbuf.h"
|
||||
# else
|
||||
# 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 ****/
|
||||
@@ -56,14 +56,6 @@ class NimBLEL2CAPChannel {
|
||||
/// NOTE: This function will block until the data has been sent or an error occurred.
|
||||
bool write(const std::vector<uint8_t>& bytes);
|
||||
|
||||
/// @brief Disconnect this L2CAP channel.
|
||||
/// @return true on success, false on failure.
|
||||
bool disconnect();
|
||||
|
||||
/// @brief Get the connection handle associated with this channel.
|
||||
/// @return Connection handle, or BLE_HS_CONN_HANDLE_NONE if not connected.
|
||||
uint16_t getConnHandle() const;
|
||||
|
||||
/// @return True, if the channel is connected. False, otherwise.
|
||||
bool isConnected() const { return !!channel; }
|
||||
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
#include "syscfg/syscfg.h"
|
||||
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
|
||||
|
||||
#ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# include "nimble/nimble/host/include/host/ble_hs.h"
|
||||
# else
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# include "host/ble_hs.h"
|
||||
# else
|
||||
# include "nimble/nimble/host/include/host/ble_hs.h"
|
||||
# endif
|
||||
|
||||
/**** FIX COMPILATION ****/
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# include "esp_log.h"
|
||||
# include "console/console.h"
|
||||
|
||||
@@ -172,7 +172,7 @@
|
||||
# define NIMBLE_LOGE(tag, format, ...) (void)tag
|
||||
# endif
|
||||
|
||||
# endif /* !USING_NIMBLE_ARDUINO_HEADERS */
|
||||
# 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__); }}
|
||||
|
||||
@@ -155,6 +155,11 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(NimBLEDescriptorFilter* pFi
|
||||
*/
|
||||
NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUUID& uuid) const {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> getDescriptor: uuid: %s", uuid.toString().c_str());
|
||||
if (NimBLEUtils::inHostTask()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "getDescriptor cannot be called from host task");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NimBLEUUID uuidTmp{uuid};
|
||||
NimBLETaskData taskData(const_cast<NimBLERemoteCharacteristic*>(this));
|
||||
NimBLEDescriptorFilter filter{nullptr, &uuidTmp, &taskData};
|
||||
|
||||
@@ -75,6 +75,11 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const char* u
|
||||
*/
|
||||
NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEUUID& uuid) const {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> getCharacteristic: uuid: %s", uuid.toString().c_str());
|
||||
if (NimBLEUtils::inHostTask()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "getCharacteristic cannot be called from host task");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NimBLERemoteCharacteristic* pChar = nullptr;
|
||||
|
||||
for (const auto& it : m_vChars) {
|
||||
@@ -116,6 +121,11 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEU
|
||||
* @return A read-only reference to the vector of characteristics retrieved for this service.
|
||||
*/
|
||||
const std::vector<NimBLERemoteCharacteristic*>& NimBLERemoteService::getCharacteristics(bool refresh) const {
|
||||
if (refresh && NimBLEUtils::inHostTask()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "cannot refresh characteristics from host task");
|
||||
return m_vChars;
|
||||
}
|
||||
|
||||
if (refresh) {
|
||||
deleteCharacteristics();
|
||||
retrieveCharacteristics();
|
||||
|
||||
@@ -42,6 +42,11 @@ bool NimBLERemoteValueAttribute::writeValue(const uint8_t* data, size_t length,
|
||||
goto Done;
|
||||
}
|
||||
|
||||
if (NimBLEUtils::inHostTask()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "writeValue cannot be called from the host task");
|
||||
return false;
|
||||
}
|
||||
|
||||
do {
|
||||
if (length > mtu) {
|
||||
NIMBLE_LOGI(LOG_TAG, "writeValue: long write");
|
||||
@@ -123,6 +128,10 @@ int NimBLERemoteValueAttribute::onWriteCB(uint16_t conn_handle, const ble_gatt_e
|
||||
*/
|
||||
NimBLEAttValue NimBLERemoteValueAttribute::readValue(time_t* timestamp) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> readValue()");
|
||||
if (NimBLEUtils::inHostTask()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "readValue cannot be called from the host task");
|
||||
return NimBLEAttValue();
|
||||
}
|
||||
|
||||
NimBLEAttValue value{};
|
||||
const NimBLEClient* pClient = getClient();
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
#include "syscfg/syscfg.h"
|
||||
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_CENTRAL)
|
||||
|
||||
#ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# include "nimble/nimble/host/include/host/ble_gatt.h"
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# include <host/ble_gatt.h>
|
||||
# else
|
||||
# include "host/ble_gatt.h"
|
||||
# include <nimble/nimble/host/include/host/ble_gatt.h>
|
||||
# endif
|
||||
|
||||
/**** FIX COMPILATION ****/
|
||||
|
||||
@@ -20,10 +20,10 @@
|
||||
|
||||
# include "NimBLEDevice.h"
|
||||
# include "NimBLELog.h"
|
||||
# ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# include "nimble/porting/nimble/include/nimble/nimble_port.h"
|
||||
# else
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# include "nimble/nimble_port.h"
|
||||
# else
|
||||
# include "nimble/porting/nimble/include/nimble/nimble_port.h"
|
||||
# endif
|
||||
|
||||
# include <string>
|
||||
@@ -564,15 +564,15 @@ bool NimBLEScan::start(uint32_t duration, bool isContinue, bool restart) {
|
||||
scan_params.itvl = m_scanParams.itvl;
|
||||
scan_params.window = m_scanParams.window;
|
||||
int rc = ble_gap_ext_disc(NimBLEDevice::m_ownAddrType,
|
||||
duration / 10, // 10ms units
|
||||
m_period,
|
||||
m_scanParams.filter_duplicates,
|
||||
m_scanParams.filter_policy,
|
||||
m_scanParams.limited,
|
||||
m_phy & SCAN_1M ? &scan_params : NULL,
|
||||
m_phy & SCAN_CODED ? &scan_params : NULL,
|
||||
NimBLEScan::handleGapEvent,
|
||||
NULL);
|
||||
duration / 10, // 10ms units
|
||||
m_period,
|
||||
m_scanParams.filter_duplicates,
|
||||
m_scanParams.filter_policy,
|
||||
m_scanParams.limited,
|
||||
m_phy & SCAN_1M ? &scan_params : NULL,
|
||||
m_phy & SCAN_CODED ? &scan_params : NULL,
|
||||
NimBLEScan::handleGapEvent,
|
||||
NULL);
|
||||
# else
|
||||
int rc = ble_gap_disc(NimBLEDevice::m_ownAddrType,
|
||||
duration ? duration : BLE_HS_FOREVER,
|
||||
@@ -689,6 +689,11 @@ NimBLEScanResults NimBLEScan::getResults(uint32_t duration, bool is_continue) {
|
||||
return m_scanResults;
|
||||
}
|
||||
|
||||
if (NimBLEUtils::inHostTask()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot call blocking getResults from NimBLE host task");
|
||||
return m_scanResults;
|
||||
}
|
||||
|
||||
NimBLETaskData taskData;
|
||||
m_pTaskData = &taskData;
|
||||
|
||||
|
||||
@@ -24,10 +24,10 @@
|
||||
# include "NimBLEAdvertisedDevice.h"
|
||||
# include "NimBLEUtils.h"
|
||||
|
||||
# ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# include "nimble/nimble/host/include/host/ble_gap.h"
|
||||
# else
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# include "host/ble_gap.h"
|
||||
# else
|
||||
# include "nimble/nimble/host/include/host/ble_gap.h"
|
||||
# endif
|
||||
|
||||
# include <vector>
|
||||
|
||||
@@ -25,12 +25,12 @@
|
||||
# include "NimBLEClient.h"
|
||||
# endif
|
||||
|
||||
# ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# include "nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h"
|
||||
# include "nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h"
|
||||
# else
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# include "services/gap/ble_svc_gap.h"
|
||||
# include "services/gatt/ble_svc_gatt.h"
|
||||
# else
|
||||
# include "nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h"
|
||||
# include "nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h"
|
||||
# endif
|
||||
|
||||
# define NIMBLE_SERVER_GET_PEER_NAME_ON_CONNECT_CB 0
|
||||
@@ -1072,7 +1072,7 @@ void NimBLEServer::updateConnParams(
|
||||
* @param [in] octets The preferred number of payload octets to use (Range 0x001B-0x00FB).
|
||||
*/
|
||||
void NimBLEServer::setDataLen(uint16_t connHandle, uint16_t octets) const {
|
||||
# if !defined(USING_NIMBLE_ARDUINO_HEADERS) && !defined(ESP_IDF_VERSION) || \
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF) && !defined(ESP_IDF_VERSION) || \
|
||||
(ESP_IDF_VERSION_MAJOR * 100 + ESP_IDF_VERSION_MINOR * 10 + ESP_IDF_VERSION_PATCH) < 432
|
||||
return;
|
||||
# else
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
#include "syscfg/syscfg.h"
|
||||
#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
|
||||
|
||||
# ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# include "nimble/nimble/host/include/host/ble_gap.h"
|
||||
# else
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# include "host/ble_gap.h"
|
||||
# else
|
||||
# include "nimble/nimble/host/include/host/ble_gap.h"
|
||||
# endif
|
||||
|
||||
/**** FIX COMPILATION ****/
|
||||
|
||||
@@ -20,12 +20,12 @@
|
||||
|
||||
# include "NimBLEDevice.h"
|
||||
# include "NimBLELog.h"
|
||||
# ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# include "nimble/porting/nimble/include/os/os_mbuf.h"
|
||||
# include "nimble/porting/nimble/include/nimble/nimble_port.h"
|
||||
# else
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# include "os/os_mbuf.h"
|
||||
# include "nimble/nimble_port.h"
|
||||
# else
|
||||
# include "nimble/porting/nimble/include/os/os_mbuf.h"
|
||||
# include "nimble/porting/nimble/include/nimble/nimble_port.h"
|
||||
# endif
|
||||
# include <algorithm>
|
||||
# include <cstdio>
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
#include "syscfg/syscfg.h"
|
||||
#if CONFIG_BT_NIMBLE_ENABLED && (MYNEWT_VAL(BLE_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_ROLE_CENTRAL))
|
||||
|
||||
# ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# include "nimble/nimble/include/nimble/nimble_npl.h"
|
||||
# else
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# include "nimble/nimble_npl.h"
|
||||
# else
|
||||
# include "nimble/nimble/include/nimble/nimble_npl.h"
|
||||
# endif
|
||||
|
||||
# include <functional>
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
#include "syscfg/syscfg.h"
|
||||
#if CONFIG_BT_NIMBLE_ENABLED
|
||||
|
||||
# ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# include "nimble/nimble/host/include/host/ble_uuid.h"
|
||||
# else
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# include "host/ble_uuid.h"
|
||||
# else
|
||||
# include "nimble/nimble/host/include/host/ble_uuid.h"
|
||||
# endif
|
||||
|
||||
/**** FIX COMPILATION ****/
|
||||
@@ -65,7 +65,7 @@ class NimBLEUUID {
|
||||
|
||||
bool operator==(const NimBLEUUID& rhs) const;
|
||||
bool operator!=(const NimBLEUUID& rhs) const;
|
||||
operator std::string() const;
|
||||
operator std::string() const;
|
||||
|
||||
private:
|
||||
ble_uuid_any_t m_uuid{};
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
# include "NimBLEAddress.h"
|
||||
# include "NimBLELog.h"
|
||||
|
||||
#ifdef USING_NIMBLE_ARDUINO_HEADERS
|
||||
# include "nimble/nimble/host/include/host/ble_hs.h"
|
||||
#else
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# include "host/ble_hs.h"
|
||||
# else
|
||||
# include "nimble/nimble/host/include/host/ble_hs.h"
|
||||
# endif
|
||||
|
||||
/**** FIX COMPILATION ****/
|
||||
@@ -72,6 +72,8 @@
|
||||
constexpr uint32_t TASK_BLOCK_BIT = (1 << MYNEWT_VAL(NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT));
|
||||
static const char* LOG_TAG = "NimBLEUtils";
|
||||
|
||||
void* NimBLEUtils::m_hostTaskHandle = nullptr;
|
||||
|
||||
/**
|
||||
* @brief Construct a NimBLETaskData instance.
|
||||
* @param [in] pInstance An instance of the class that will be waiting.
|
||||
@@ -604,4 +606,21 @@ NimBLEAddress NimBLEUtils::generateAddr(bool nrpa) {
|
||||
return NimBLEAddress{addr};
|
||||
} // generateAddr
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the handle of the task that is running the NimBLE host.
|
||||
* @return The task handle or nullptr if there was an error.
|
||||
*/
|
||||
void* NimBLEUtils::getHostTaskHandle() {
|
||||
return m_hostTaskHandle;
|
||||
} // getHostTaskHandle
|
||||
|
||||
/**
|
||||
* @brief Check if the current task is the NimBLE host task.
|
||||
* @return True if the current task is the host task, false otherwise.
|
||||
*/
|
||||
bool NimBLEUtils::inHostTask() {
|
||||
return ble_npl_get_current_task_id() == NimBLEUtils::getHostTaskHandle();
|
||||
}
|
||||
|
||||
#endif // CONFIG_BT_NIMBLE_ENABLED
|
||||
|
||||
@@ -29,17 +29,18 @@
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#if MYNEWT_VAL(NIMBLE_CPP_DEBUG_ASSERT_ENABLED) && !defined NDEBUG
|
||||
void nimble_cpp_assert(const char *file, unsigned line) __attribute((weak, noreturn));
|
||||
# define NIMBLE_ATT_VAL_FILE (__builtin_strrchr(__FILE__, '/') ? \
|
||||
__builtin_strrchr (__FILE__, '/') + 1 : __FILE__)
|
||||
# define NIMBLE_CPP_DEBUG_ASSERT(cond) \
|
||||
if (!(cond)) { \
|
||||
nimble_cpp_assert(NIMBLE_ATT_VAL_FILE, __LINE__); \
|
||||
}
|
||||
#else
|
||||
# define NIMBLE_CPP_DEBUG_ASSERT(cond) (void(0))
|
||||
#endif
|
||||
# if MYNEWT_VAL(NIMBLE_CPP_DEBUG_ASSERT_ENABLED) && !defined NDEBUG
|
||||
void nimble_cpp_assert(const char* file, unsigned line) __attribute__((weak, noreturn));
|
||||
# define NIMBLE_ATT_VAL_FILE (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__)
|
||||
# define NIMBLE_CPP_DEBUG_ASSERT(cond) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
nimble_cpp_assert(NIMBLE_ATT_VAL_FILE, __LINE__); \
|
||||
} \
|
||||
} while (0)
|
||||
# else
|
||||
# define NIMBLE_CPP_DEBUG_ASSERT(cond) (void(0))
|
||||
# endif
|
||||
|
||||
# include <string>
|
||||
|
||||
@@ -74,6 +75,12 @@ class NimBLEUtils {
|
||||
static NimBLEAddress generateAddr(bool nrpa);
|
||||
static bool taskWait(const NimBLETaskData& taskData, uint32_t timeout);
|
||||
static void taskRelease(const NimBLETaskData& taskData, int rc = 0);
|
||||
static void* getHostTaskHandle();
|
||||
static bool inHostTask();
|
||||
|
||||
private:
|
||||
friend class NimBLEDevice;
|
||||
static void* m_hostTaskHandle;
|
||||
};
|
||||
|
||||
#endif // CONFIG_BT_NIMBLE_ENABLED
|
||||
|
||||
Reference in New Issue
Block a user