Skip to content

Commit bb104c6

Browse files
committed
nRF5x: Ensure Bluetooth notifications work correctly when two separate connections use the same handle for their characteristics
nRF5x: Remove handlers from our handlers array when a device is disconnected
1 parent 12a82ce commit bb104c6

File tree

6 files changed

+23
-4
lines changed

6 files changed

+23
-4
lines changed

ChangeLog

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
...
1+
nRF5x: Ensure Bluetooth notifications work correctly when two separate connections use the same handle for their characteristics
2+
nRF5x: Remove handlers from our handlers array when a device is disconnected
23

34
2v26 : nRF5x: ensure TIMER1_IRQHandler doesn't always wake idle loop up (fix #1900)
45
Puck.js: On v2.1 ensure Puck.mag behaves like other variants - just returning the last reading (avoids glitches when used with Puck.magOn)

libs/bluetooth/bluetooth.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,10 @@ typedef enum {
214214
#endif
215215
} BLEPending;
216216

217+
/// amount to shift the connection index for the 16 bit 'data' field in jsble_queue_pending_buf(BLEP_CENTRAL_NOTIFICATION, ...
218+
#define BLEP_CENTRAL_NOTIFICATION_CONN_SHIFT (15)
219+
/// we need to mask off the handle (as we're using the top bits for the connection)
220+
#define BLEP_CENTRAL_NOTIFICATION_HANDLE_MASK (0x7FFF)
217221

218222
extern volatile BLEStatus bleStatus;
219223
/// Filter to use when discovering BLE Services/Characteristics

libs/bluetooth/bluetooth_utils.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,19 @@ bool jsble_exec_pending_common(BLEPending blep, uint16_t data, unsigned char *bu
539539
jsvUnLock2(gattServer, bluetoothDevice);
540540
}
541541
bleSetActiveBluetoothGattServer(centralIdx, 0);
542+
// when we disconnect, remove handles for notifications for this connection
543+
JsVar *handles = jsvObjectGetChildIfExists(execInfo.hiddenRoot, "bleHdl");
544+
JsvObjectIterator it;
545+
jsvObjectIteratorNew(&it, handles); // it's actually an array, but object iterator is ok
546+
while (jsvObjectIteratorHasValue(&it)) {
547+
int handleValue = jsvGetIntegerAndUnLock(jsvObjectIteratorGetKey(&it));
548+
if ((handleValue >> BLEP_CENTRAL_NOTIFICATION_CONN_SHIFT) == centralIdx)
549+
jsvObjectIteratorRemoveAndGotoNext(&it, handles);
550+
else
551+
jsvObjectIteratorNext(&it);
552+
}
553+
jsvObjectIteratorFree(&it);
554+
jsvUnLock(handles);
542555
break;
543556
}
544557
case BLEP_CENTRAL_NOTIFICATION: {

libs/bluetooth/jswrap_bluetooth.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4655,7 +4655,7 @@ JsVar *jswrap_ble_BluetoothRemoteGATTCharacteristic_startNotifications(JsVar *ch
46554655
uint16_t handle = (uint16_t)jsvObjectGetIntegerChild(characteristic, "handle_value");
46564656
JsVar *handles = jsvObjectGetChild(execInfo.hiddenRoot, "bleHdl", JSV_ARRAY);
46574657
if (handles) {
4658-
jsvSetArrayItem(handles, handle, characteristic);
4658+
jsvSetArrayItem(handles, handle | (jsble_get_central_connection_idx(central_conn_handle) << BLEP_CENTRAL_NOTIFICATION_CONN_SHIFT), characteristic);
46594659
jsvUnLock(handles);
46604660
}
46614661

@@ -4705,7 +4705,7 @@ JsVar *jswrap_ble_BluetoothRemoteGATTCharacteristic_stopNotifications(JsVar *cha
47054705
uint16_t handle = (uint16_t)jsvObjectGetIntegerChild(characteristic, "handle_value");
47064706
JsVar *handles = jsvObjectGetChild(execInfo.hiddenRoot, "bleHdl", JSV_ARRAY);
47074707
if (handles) {
4708-
jsvSetArrayItem(handles, handle, 0);
4708+
jsvSetArrayItem(handles, handle + (jsble_get_central_connection_idx(central_conn_handle) << BLEP_CENTRAL_NOTIFICATION_CONN_SHIFT), 0);
47094709
jsvUnLock(handles);
47104710
}
47114711
JsVar *promise = jsvLockAgainSafe(blePromise);

targets/esp32/BLE/esp32_gattc_func.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp
9797
case ESP_GATTC_NOTIFY_EVT:
9898
// We've been notified of new data
9999
// p_data->notify.is_notify is whether it's notify or indicate
100+
// FIXME: for >1 connection we need to add (jsble_get_central_connection_idx(central_conn_handle) << BLEP_CENTRAL_NOTIFICATION_CONN_SHIFT) to this
100101
jsble_queue_pending_buf(BLEP_CENTRAL_NOTIFICATION, p_data->notify.handle, (char*)p_data->notify.value, p_data->notify.value_len);
101102
// Do we have to send a confirmation if it's an indication?
102103
break;

targets/nrf5x/bluetooth.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1623,7 +1623,7 @@ static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) {
16231623
// Notification/Indication
16241624
const ble_gattc_evt_hvx_t *p_hvx = &p_ble_evt->evt.gattc_evt.params.hvx;
16251625
// p_hvx->type is BLE_GATT_HVX_NOTIFICATION or BLE_GATT_HVX_INDICATION
1626-
jsble_queue_pending_buf(BLEP_CENTRAL_NOTIFICATION, p_hvx->handle, (char*)p_hvx->data, p_hvx->len);
1626+
jsble_queue_pending_buf(BLEP_CENTRAL_NOTIFICATION, p_hvx->handle | (jsble_get_central_connection_idx(p_ble_evt->evt.common_evt.conn_handle) << BLEP_CENTRAL_NOTIFICATION_CONN_SHIFT), (char*)p_hvx->data, p_hvx->len);
16271627
if (p_hvx->type == BLE_GATT_HVX_INDICATION) {
16281628
sd_ble_gattc_hv_confirm(p_ble_evt->evt.gattc_evt.conn_handle, p_hvx->handle);
16291629
}

0 commit comments

Comments
 (0)