Skip to content

Commit 5c15f79

Browse files
committed
fix(ble): Fix notification timing
1 parent 3dbf481 commit 5c15f79

File tree

2 files changed

+53
-1
lines changed

2 files changed

+53
-1
lines changed

libraries/BLE/src/BLECharacteristic.cpp

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,29 @@ void BLECharacteristicCallbacks::onWrite(BLECharacteristic *pCharacteristic, esp
904904

905905
#if defined(CONFIG_NIMBLE_ENABLED)
906906

907+
/**
908+
* @brief Process a deferred write callback.
909+
*
910+
* This function is called as a FreeRTOS task to execute the onWrite callback
911+
* after the write response has been sent to the client. This maintains backwards
912+
* compatibility with Bluedroid, where the write response is sent before the
913+
* onWrite callback is invoked.
914+
*
915+
* See: https://github.com/espressif/arduino-esp32/issues/11938
916+
*/
917+
void BLECharacteristic::processDeferredWriteCallback(void *pvParameters) {
918+
DeferredWriteCallback *pCallback = (DeferredWriteCallback *)pvParameters;
919+
920+
// Call the onWrite callback now that the response has been sent
921+
pCallback->pCharacteristic->m_pCallbacks->onWrite(pCallback->pCharacteristic, &pCallback->desc);
922+
923+
// Free the allocated memory
924+
delete pCallback;
925+
926+
// Delete this one-shot task
927+
vTaskDelete(NULL);
928+
}
929+
907930
int BLECharacteristic::handleGATTServerEvent(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) {
908931
const ble_uuid_t *uuid;
909932
int rc;
@@ -955,7 +978,27 @@ int BLECharacteristic::handleGATTServerEvent(uint16_t conn_handle, uint16_t attr
955978
rc = ble_gap_conn_find(conn_handle, &desc);
956979
assert(rc == 0);
957980
pCharacteristic->setValue(buf, len);
958-
pCharacteristic->m_pCallbacks->onWrite(pCharacteristic, &desc);
981+
982+
// Defer the onWrite callback to maintain backwards compatibility with Bluedroid.
983+
// In Bluedroid, the write response is sent BEFORE the onWrite callback is invoked.
984+
// In NimBLE, the response is sent implicitly when this function returns.
985+
// By deferring the callback to a separate task, we ensure the response is sent first.
986+
// See: https://github.com/espressif/arduino-esp32/issues/11938
987+
DeferredWriteCallback *pCallback = new DeferredWriteCallback();
988+
pCallback->pCharacteristic = pCharacteristic;
989+
pCallback->desc = desc;
990+
991+
// Create a one-shot task to execute the callback after the response is sent
992+
// Using priority 1 (low priority) and sufficient stack for callback operations
993+
// Note: Stack must be large enough to handle notify() calls from within onWrite()
994+
xTaskCreate(
995+
processDeferredWriteCallback,
996+
"BLEWriteCB",
997+
4096, // Stack size - increased to handle notify() operations
998+
pCallback,
999+
1, // Priority (low)
1000+
NULL // Task handle (not needed for one-shot task)
1001+
);
9591002

9601003
return 0;
9611004
}

libraries/BLE/src/BLECharacteristic.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
#include <host/ble_gatt.h>
4848
#include <host/ble_att.h>
4949
#include "BLEConnInfo.h"
50+
#include <freertos/FreeRTOS.h>
51+
#include <freertos/task.h>
5052
#define ESP_GATT_MAX_ATTR_LEN BLE_ATT_ATTR_MAX_LEN
5153
#define ESP_GATT_CHAR_PROP_BIT_READ BLE_GATT_CHR_PROP_READ
5254
#define ESP_GATT_CHAR_PROP_BIT_WRITE BLE_GATT_CHR_PROP_WRITE
@@ -246,6 +248,12 @@ class BLECharacteristic {
246248
portMUX_TYPE m_readMux;
247249
uint8_t m_removed;
248250
std::vector<std::pair<uint16_t, uint16_t>> m_subscribedVec;
251+
252+
// Deferred callback support for maintaining backwards compatibility with Bluedroid timing
253+
struct DeferredWriteCallback {
254+
BLECharacteristic *pCharacteristic;
255+
ble_gap_conn_desc desc;
256+
};
249257
#endif
250258

251259
/***************************************************************************
@@ -271,6 +279,7 @@ class BLECharacteristic {
271279
#if defined(CONFIG_NIMBLE_ENABLED)
272280
void setSubscribe(struct ble_gap_event *event);
273281
static int handleGATTServerEvent(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg);
282+
static void processDeferredWriteCallback(void *pvParameters);
274283
#endif
275284
}; // BLECharacteristic
276285

0 commit comments

Comments
 (0)