Skip to content

Commit fcbef18

Browse files
committed
fix(ble): Rework notification timing
1 parent 5a91832 commit fcbef18

File tree

2 files changed

+52
-10
lines changed

2 files changed

+52
-10
lines changed

libraries/BLE/src/BLECharacteristic.cpp

Lines changed: 43 additions & 7 deletions
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;
@@ -958,14 +981,27 @@ int BLECharacteristic::handleGATTServerEvent(uint16_t conn_handle, uint16_t attr
958981
// Set write context flag to defer notifications
959982
pCharacteristic->m_inWriteContext = true;
960983
pCharacteristic->setValue(buf, len);
961-
pCharacteristic->m_pCallbacks->onWrite(pCharacteristic, &desc);
962-
pCharacteristic->m_inWriteContext = false;
963984

964-
// Execute any deferred notifications after write context ends
965-
if (pCharacteristic->m_deferNotifications) {
966-
pCharacteristic->m_deferNotifications = false;
967-
pCharacteristic->notifyDeferred();
968-
}
985+
// Defer the onWrite callback to maintain backwards compatibility with Bluedroid.
986+
// In Bluedroid, the write response is sent BEFORE the onWrite callback is invoked.
987+
// In NimBLE, the response is sent implicitly when this function returns.
988+
// By deferring the callback to a separate task, we ensure the response is sent first.
989+
// See: https://github.com/espressif/arduino-esp32/issues/11938
990+
DeferredWriteCallback *pCallback = new DeferredWriteCallback();
991+
pCallback->pCharacteristic = pCharacteristic;
992+
pCallback->desc = desc;
993+
994+
// Create a one-shot task to execute the callback after the response is sent
995+
// Using priority 1 (low priority) and sufficient stack for callback operations
996+
// Note: Stack must be large enough to handle notify() calls from within onWrite()
997+
xTaskCreate(
998+
processDeferredWriteCallback,
999+
"BLEWriteCB",
1000+
4096, // Stack size - increased to handle notify() operations
1001+
pCallback,
1002+
1, // Priority (low)
1003+
NULL // Task handle (not needed for one-shot task)
1004+
);
9691005

9701006
return 0;
9711007
}

libraries/BLE/src/BLECharacteristic.h

Lines changed: 9 additions & 3 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,8 +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;
249-
bool m_inWriteContext = false;
250-
bool m_deferNotifications = false;
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+
};
251257
#endif
252258

253259
/***************************************************************************
@@ -273,7 +279,7 @@ class BLECharacteristic {
273279
#if defined(CONFIG_NIMBLE_ENABLED)
274280
void setSubscribe(struct ble_gap_event *event);
275281
static int handleGATTServerEvent(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg);
276-
void notifyDeferred();
282+
static void processDeferredWriteCallback(void *pvParameters);
277283
#endif
278284
}; // BLECharacteristic
279285

0 commit comments

Comments
 (0)