Skip to content

Commit bba081b

Browse files
committed
nRF52: Add 'phy' and 'mtu' events to NRF/BluetoothDevice when these change on a connection
Thanks to @fanoush for the event handling code!
1 parent 6efdd8c commit bba081b

File tree

5 files changed

+183
-1
lines changed

5 files changed

+183
-1
lines changed

ChangeLog

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
: Add `E.internal` as a way to access the 'hidden root' containing Espruino internal variables that previously needed `global["\xff"]`
22
Bangle.js: Fix back handler not removed when using E.setUI with a back button but without widgets (#2636)
33
nRF52: Add 'slaveLatency' option to BluetoothRemoteGATTServer.connect, default changed from 2 to 4
4+
nRF52: Add 'phy' and 'mtu' events to NRF/BluetoothDevice when these change on a connection
45

56
2v27 : nRF5x: Ensure Bluetooth notifications work correctly when two separate connections use the same handle for their characteristics
67
nRF5x: Remove handlers from our handlers array when a device is disconnected

libs/bluetooth/bluetooth.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@ typedef enum {
166166
BLEP_RESTART_SOFTDEVICE, //< Perform a softdevice restart (again, we don't want to do this in an IRQ!)
167167
BLEP_RSSI_PERIPH, //< RSSI data from peripheral connection (rssi as data)
168168
BLEP_ADV_REPORT, //< Advertising received (as buffer)
169+
#ifndef SAVE_ON_FLASH
170+
BLEP_PHY_UPDATE_REQUEST, //< PHY update request (connection handle as data, [tx_phy,rx_phy] as buffer)
171+
BLEP_PHY_UPDATE, //< PHY update finished (connection handle as data, [tx_phy,rx_phy,status] as buffer)
172+
BLEP_MTU_UPDATE, //< MTU update finished (connection handle as data, [mtu_16bit] as buffer)
173+
#endif
169174
#if CENTRAL_LINK_COUNT>0
170175
BLEP_RSSI_CENTRAL, //< RSSI data from central connection (rssi as data low byte, index in m_central_conn_handles as high byte )
171176
BLEP_TASK_FAIL, //< Task failed because unknown

libs/bluetooth/jswrap_bluetooth.c

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,14 @@ JsVar *bleGetActiveBluetoothGattServer(int idx) {
173173
return jsvObjectGetChildIfExists(execInfo.hiddenRoot, name);
174174
}
175175

176+
JsVar *bleGetActiveBluetoothDevice(int idx) {
177+
JsVar *gattServer = bleGetActiveBluetoothGattServer(idx);
178+
if (!gattServer) return 0;
179+
JsVar *bluetoothDevice = jsvObjectGetChildIfExists(gattServer, "device");
180+
jsvUnLock(gattServer);
181+
return bluetoothDevice;
182+
}
183+
176184
uint16_t jswrap_ble_BluetoothRemoteGATTServer_getHandle(JsVar *parent) {
177185
JsVar *handle = jsvObjectGetChildIfExists(parent, "handle");
178186
if (!jsvIsInt(handle)) return BLE_CONN_HANDLE_INVALID;
@@ -492,7 +500,56 @@ Called with discovered services when discovery is finished
492500
}
493501
Called with discovered characteristics when discovery is finished
494502
*/
503+
/*JSON{
504+
"type" : "event",
505+
"class" : "NRF",
506+
"name" : "phy",
507+
"params" : [
508+
["arr","JsVar","An array containing `[tx_phy, rx_phy, status]` (see below)"]
509+
],
510+
"#if" : "defined(NRF52_SERIES)"
511+
}
512+
(2v28+) This event is fired when the phy (radio) is changed for the active Bluetooth connection. The parameter is the data `[tx_phy, rx_phy, status]`
513+
514+
`tx_phy`/`rx_phy` are integers where each bit corresponds to:
515+
516+
* 1 : 1mbps phy
517+
* 2 : 2mbps phy
518+
* 4 : coded phy
519+
520+
`status` is an integer containing the status code. 0 = success
521+
*/
522+
/*JSON{
523+
"type" : "event",
524+
"class" : "NRF",
525+
"name" : "phy_req",
526+
"params" : [
527+
["arr","JsVar","An array containing `[tx_phy, rx_phy]` (see below)"]
528+
],
529+
"#if" : "defined(NRF52_SERIES)"
530+
}
531+
(2v28+) This event is fired when the phy (radio) is requested to change for the active Bluetooth connection. The parameter is the data `[tx_phy, rx_phy]`
532+
533+
`tx_phy`/`rx_phy` are integers where each bit corresponds to:
495534
535+
* 1 : 1mbps phy
536+
* 2 : 2mbps phy
537+
* 4 : coded phy
538+
539+
eg. `7` means all phys (eg any) have been requested
540+
*/
541+
/*JSON{
542+
"type" : "event",
543+
"class" : "NRF",
544+
"name" : "mtu",
545+
"params" : [
546+
["arr","int","The negotiated MTU"]
547+
],
548+
"#if" : "defined(NRF52_SERIES)"
549+
}
550+
(2v28+) This event is fired when the MTU changes for the active Bluetooth connection. Yhis is the amount of
551+
data that can be transferred in one packet.
552+
*/
496553

497554
/*JSON{
498555
"type" : "event",
@@ -523,6 +580,56 @@ When NFC is started with `NRF.nfcStart`, this is fired when NFC data is
523580
received. It doesn't get called if NFC is started with `NRF.nfcURL` or
524581
`NRF.nfcRaw`
525582
*/
583+
/*JSON{
584+
"type" : "event",
585+
"class" : "BluetoothDevice",
586+
"name" : "phy",
587+
"params" : [
588+
["arr","JsVar","An array containing `[tx_phy, rx_phy, status]` (see below)"]
589+
],
590+
"#if" : "defined(NRF52_SERIES)"
591+
}
592+
(2v28+) This event is fired when the phy (radio) is changed for this Bluetooth connection. The parameter is the data `[tx_phy, rx_phy, status]`
593+
594+
`tx_phy`/`rx_phy` are integers where each bit corresponds to:
595+
596+
* 1 : 1mbps phy
597+
* 2 : 2mbps phy
598+
* 4 : coded phy
599+
600+
`status` is an integer containing the status code. 0 = success
601+
*/
602+
/*JSON{
603+
"type" : "event",
604+
"class" : "BluetoothDevice",
605+
"name" : "phy_req",
606+
"params" : [
607+
["arr","JsVar","An array containing `[tx_phy, rx_phy]` (see below)"]
608+
],
609+
"#if" : "defined(NRF52_SERIES)"
610+
}
611+
(2v28+) This event is fired when the phy (radio) is requested to change for this Bluetooth connection. The parameter is the data `[tx_phy, rx_phy]`
612+
613+
`tx_phy`/`rx_phy` are integers where each bit corresponds to:
614+
615+
* 1 : 1mbps phy
616+
* 2 : 2mbps phy
617+
* 4 : coded phy
618+
619+
eg. `7` means all phys (eg any) have been requested
620+
*/
621+
/*JSON{
622+
"type" : "event",
623+
"class" : "BluetoothDevice",
624+
"name" : "mtu",
625+
"params" : [
626+
["arr","int","The negotiated MTU"]
627+
],
628+
"#if" : "defined(NRF52_SERIES)"
629+
}
630+
(2v28+) This event is fired when the MTU changes for the active Bluetooth connection. Yhis is the amount of
631+
data that can be transferred in one packet.
632+
*/
526633
/*JSON{
527634
"type" : "event",
528635
"class" : "BluetoothDevice",
@@ -3957,7 +4064,20 @@ JsVar *jswrap_BluetoothDevice_gatt(JsVar *parent) {
39574064
"generate" : false,
39584065
"return" : ["bool", "The last received RSSI (signal strength) for this device" ]
39594066
}
3960-
*//*Documentation only*/
4067+
This is set whenever the RSSI of the connection is changed. `BluetoothGATTServer.on("rssi", ...)` is also emitted.
4068+
*/
4069+
/*Documentation only*/
4070+
/*JSON{
4071+
"type" : "event",
4072+
"class" : "BluetoothGATTServer",
4073+
"name" : "rssi",
4074+
"params" : [
4075+
["rssi","int","The current RSSI value for this connection"]
4076+
],
4077+
"ifdef" : "NRF52_SERIES"
4078+
}
4079+
This event is fired whenever the RSSI of the connection is changed. `BluetoothDevice.rssi` is also updated
4080+
*/
39614081
/*JSON{
39624082
"type" : "event",
39634083
"class" : "BluetoothDevice",

libs/bluetooth/jswrap_bluetooth.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ void bleSwitchTask(BleTask task);
6969
void bleSetActiveBluetoothGattServer(int idx, JsVar *var);
7070
// Get the currently active GATT server based on the index in m_central_conn_handles (the return value needs unlocking)
7171
JsVar *bleGetActiveBluetoothGattServer(int idx);
72+
// Get the currently active BluetoothDevice based on the index in m_central_conn_handles (the return value needs unlocking)
73+
JsVar *bleGetActiveBluetoothDevice(int idx);
7274

7375
uint16_t jswrap_ble_BluetoothRemoteGATTServer_getHandle(JsVar *parent);
7476
uint16_t jswrap_ble_BluetoothDevice_getHandle(JsVar *parent);

targets/nrf5x/bluetooth.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,18 @@ JsVar *jsble_get_error_string(uint32_t err_code) {
295295
return jsvVarPrintf("ERR 0x%x", err_code);
296296
}
297297

298+
/** If the connection handle matches a current connection, return the BluetoothDevice for that,
299+
otherwise just return the NRF object if it's a peripheral connection (or NULL if not known) */
300+
static JsVar *jsble_device_from_handle(uint16_t conn_handle) {
301+
JsVar *device = 0;
302+
#if CENTRAL_LINK_COUNT>0
303+
device = bleGetActiveBluetoothDevice(jsble_get_central_connection_idx(conn_handle));
304+
#endif
305+
if (!device && conn_handle == m_peripheral_conn_handle)
306+
device = jsvObjectGetChildIfExists(execInfo.root, "NRF");
307+
return device;
308+
}
309+
298310
// -----------------------------------------------------------------------------------
299311
// -----------------------------------------------------------------------------------
300312

@@ -338,6 +350,30 @@ int jsble_exec_pending(uint8_t *buffer, int bufferLen) {
338350
jsble_restart_softdevice(NULL);
339351
break;
340352
}
353+
#ifndef SAVE_ON_FLASH
354+
case BLEP_PHY_UPDATE_REQUEST:
355+
case BLEP_PHY_UPDATE: {
356+
uint16_t conn_handle = data;
357+
JsVar *eventTarget = jsble_device_from_handle(conn_handle);
358+
if (eventTarget) {
359+
JsVar *v = jsvNewArrayFromBytes(buffer, bufferLen);
360+
const char *evt = (blep == BLEP_PHY_UPDATE_REQUEST) ? JS_EVENT_PREFIX"phy_req" : JS_EVENT_PREFIX"phy";
361+
jsiQueueObjectCallbacks(eventTarget, evt, &v, 1);
362+
jsvUnLock2(eventTarget, v);
363+
}
364+
break;
365+
}
366+
case BLEP_MTU_UPDATE: {
367+
uint16_t conn_handle = data;
368+
JsVar *eventTarget = jsble_device_from_handle(conn_handle);
369+
if (eventTarget) {
370+
JsVar *v = jsvNewFromInteger(*(uint16_t*)buffer);
371+
jsiQueueObjectCallbacks(eventTarget, JS_EVENT_PREFIX"mtu", &v, 1);
372+
jsvUnLock2(eventTarget, v);
373+
}
374+
break;
375+
}
376+
#endif
341377
case BLEP_RSSI_PERIPH: {
342378
JsVar *evt = jsvNewFromInteger((signed char)data);
343379
if (evt) jsiQueueObjectCallbacks(execInfo.root, BLE_RSSI_EVENT, &evt, 1);
@@ -1397,6 +1433,9 @@ static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) {
13971433
if (m_peripheral_conn_handle == conn_handle){
13981434
m_peripheral_effective_mtu = effective_mtu;
13991435
}
1436+
#ifndef SAVE_ON_FLASH
1437+
jsble_queue_pending_buf(BLEP_MTU_UPDATE, p_ble_evt->evt.gap_evt.conn_handle, (char*)effective_mtu, sizeof(effective_mtu));
1438+
#endif
14001439
} break; // BLE_GATTC_EVT_EXCHANGE_MTU_RSP
14011440
#endif
14021441
case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: {
@@ -1443,6 +1482,13 @@ static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) {
14431482
/* Allow SoftDevice to choose PHY Update Procedure parameters automatically. */
14441483
ble_gap_phys_t phys = {BLE_GAP_PHY_AUTO, BLE_GAP_PHY_AUTO};
14451484
sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
1485+
#ifndef SAVE_ON_FLASH
1486+
uint8_t req_phys[] = {
1487+
p_ble_evt->evt.gap_evt.params.phy_update_request.peer_preferred_phys.tx_phys,
1488+
p_ble_evt->evt.gap_evt.params.phy_update_request.peer_preferred_phys.rx_phys
1489+
};
1490+
jsble_queue_pending_buf(BLEP_PHY_UPDATE_REQUEST, p_ble_evt->evt.gap_evt.conn_handle, (char*) req_phys, sizeof(req_phys));
1491+
#endif
14461492
break;
14471493
}
14481494
case BLE_GAP_EVT_PHY_UPDATE: {
@@ -1452,6 +1498,14 @@ static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) {
14521498
p_ble_evt->evt.gap_evt.params.phy_update.rx_phy for the currently active PHYs of
14531499
the link. */
14541500
}
1501+
#ifndef SAVE_ON_FLASH
1502+
uint8_t res[] = {
1503+
p_ble_evt->evt.gap_evt.params.phy_update.tx_phy,
1504+
p_ble_evt->evt.gap_evt.params.phy_update.rx_phy,
1505+
p_ble_evt->evt.gap_evt.params.phy_update.status
1506+
};
1507+
jsble_queue_pending_buf(BLEP_PHY_UPDATE, p_ble_evt->evt.gap_evt.conn_handle, (char*) res, sizeof(res));
1508+
#endif
14551509
break;
14561510
}
14571511
#endif

0 commit comments

Comments
 (0)