8000 extmod/modbluetooth: implement device.disconnect() · andrewleech/micropython@9d68c50 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9d68c50

Browse files
aykevldpgeorge
authored andcommitted
extmod/modbluetooth: implement device.disconnect()
This commit allows the Python code to explicitly disconnect a central device using device objects from connect or write events.
1 parent fbfd9aa commit 9d68c50

File tree

4 files changed

+63
-12
lines changed

4 files changed

+63
-12
lines changed

extmod/modbluetooth.c

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -259,18 +259,22 @@ STATIC mp_obj_t bluetooth_write_callback(mp_obj_t char_in) {
259259
uint8_t value[20]; // maximum BLE packet size
260260
uint16_t tail = update_buf.tail;
261261
size_t value_len;
262+
uint16_t conn_handle = MP_BT_INVALID_CONN_HANDLE;
262263
if (update_buf.dropped_packets) {
263264
// Handle dropped packet.
264265
update_buf.dropped_packets--;
265266
value_len = (size_t)-1;
266267
} else {
267268
// Copy regular incoming packet.
268-
value_len = update_buf.data[tail++ % UPDATE_BUF_SIZE];
269-
update_buf.tail = tail + value_len;
269+
size_t data_len = update_buf.data[tail++ % UPDATE_BUF_SIZE];
270+
value_len = data_len - 2;
271+
update_buf.tail = tail + data_len;
270272
if (value_len > sizeof(value)) {
271273
// Packet was too big, only pass the first N bytes.
272274
value_len = sizeof(value);
273275
}
276+
conn_handle = update_buf.data[tail++ % UPDATE_BUF_SIZE];
277+
conn_handle |= update_buf.data[tail++ % UPDATE_BUF_SIZE] << 8;
274278
for (size_t i = 0; i < value_len; i++) {
275279
value[i] = update_buf.data[tail++ % UPDATE_BUF_SIZE];
276280
}
@@ -292,12 +296,25 @@ STATIC mp_obj_t bluetooth_write_callback(mp_obj_t char_in) {
292296
if (value_len == (size_t)-1) {
293297
// Unfortunately, there was a dropped packet.
294298
// Report this event by passing None.
295-
mp_call_function_2_protected(item->callback, MP_OBJ_FROM_PTR(item->characteristic), mp_const_none);
299+
mp_obj_t args[3] = {
300+
mp_const_none,
301+
MP_OBJ_FROM_PTR(item->characteristic),
302+
mp_const_none,
303+
};
304+
mp_call_function_n_kw(item->callback, 3, 0, args);
296305
} else {
297306
// Pass the written data directly as a bytearray to the callback.
298307
// WARNING: this array must not be modified by the callee.
299308
mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, value_len, value};
300-
mp_call_function_2_protected(item->callback, MP_OBJ_FROM_PTR(item->characteristic), MP_OBJ_FROM_PTR(&ar));
309+
mp_bt_device_t device = {0};
310+
device.base.type = &device_type;
311+
device.conn_handle = conn_handle;
312+
mp_obj_t args[3] = {
313+
&device,
314+
MP_OBJ_FROM_PTR(item->characteristic),
315+
MP_OBJ_FROM_PTR(&ar),
316+
};
317+
mp_call_function_n_kw(item->callback, 3, 0, args);
301318
}
302319

303320
return mp_const_none;
@@ -306,7 +323,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluetooth_write_callback_obj, bluetooth_write_c
306323

307324
// Call the registered callback for this characteristic, if one has been
308325
// registered.
309-
void mp_bt_characteristic_on_write(uint16_t value_handle, const void *value, size_t value_len) {
326+
void mp_bt_characteristic_on_write(uint16_t conn_handle, uint16_t value_handle, const void *value, size_t value_len) {
310327
// Iterate through the linked list to find to find the characteristic
311328
// with the given handle.
312329
mp_bt_characteristic_callback_t *item = MP_STATE_PORT(bt_characteristic_callbacks);
@@ -321,15 +338,22 @@ void mp_bt_characteristic_on_write(uint16_t value_handle, const void *value, siz
321338
uint16_t head = update_buf.head;
322339
uint16_t tail = update_buf.tail;
323340
size_t bytes_left = ((uint16_t)UPDATE_BUF_SIZE - (head - tail));
324-
while (bytes_left < value_len + 1) {
341+
// A packet has the following components:
342+
// - 1 byte packet size (excluding this byte)
343+
// - 2 byte conn_handle
344+
// - N bytes data
345+
size_t packet_len = value_len + 3;
346+
while (bytes_left < packet_len) {
325347
// Drop oldest packet.
326348
uint8_t packet_len = update_buf.data[tail % UPDATE_BUF_SIZE];
327349
tail += packet_len + 1;
328350
update_buf.tail = tail;
329351
bytes_left = ((uint16_t)UPDATE_BUF_SIZE - (head - tail));
330352
update_buf.dropped_packets++;
331353
}
332-
update_buf.data[head++ % UPDATE_BUF_SIZE] = (uint8_t)value_len;
354+
update_buf.data[head++ % UPDATE_BUF_SIZE] = (uint8_t)(packet_len - 1);
355+
update_buf.data[head++ % UPDATE_BUF_SIZE] = (uint8_t)(conn_handle & 0xff); // low bits
356+
update_buf.data[head++ % UPDATE_BUF_SIZE] = (uint8_t)(conn_handle >> 8); // high bits
333357
for (size_t i = 0; i < value_len; i++) {
334358
update_buf.data[head++ % UPDATE_BUF_SIZE] = ((uint8_t*)value)[i];
335359
}
@@ -555,9 +579,22 @@ STATIC mp_obj_t device_connected(mp_obj_t self_in) {
555579
}
556580
STATIC MP_DEFINE_CONST_FUN_OBJ_1(device_connected_obj, device_connected);
557581

582+
STATIC mp_obj_t device_disconnect(mp_obj_t self_in) {
583+
mp_bt_device_t *device = self_in;
584+
if (device->conn_handle != MP_BT_INVALID_CONN_HANDLE) {
585+
uint16_t conn_handle = device->conn_handle;
586+
device->conn_handle = MP_BT_INVALID_CONN_HANDLE;
587+
int errno_ = mp_bt_device_disconnect(conn_handle);
588+
return bluetooth_handle_errno(errno_);
589+
}
590+
return mp_const_none;
591+
}
592+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(device_disconnect_obj, device_disconnect);
593+
558594
STATIC const mp_rom_map_elem_t device_locals_dict_table[] = {
559-
{ MP_ROM_QSTR(MP_QSTR_address), MP_ROM_PTR(&device_address_obj) },
560-
{ MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&device_connected_obj) },
595+
{ MP_ROM_QSTR(MP_QSTR_address), MP_ROM_PTR(&device_address_obj) },
596+
{ MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&device_connected_obj) },
597+
{ MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&device_disconnect_obj) },
561598
};
562599
STATIC MP_DEFINE_CONST_DICT(device_locals_dict, device_locals_dict_table);
563600

extmod/modbluetooth.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,10 @@ int mp_bt_characteristic_value_notify(mp_bt_characteristic_t *characteristic, ui
101101
int mp_bt_characteristic_value_get(mp_bt_characteristic_t *characteristic, void *value, size_t *value_len);
102102

103103
// Call this when a characteristic is written to.
104-
void mp_bt_characteristic_on_write(uint16_t value_handle, const void *value, size_t value_len);
104+
void mp_bt_characteristic_on_write(uint16_t conn_handle, uint16_t value_handle, const void *value, size_t value_len);
105+
106+
// Disconnect a connected central.
107+
int mp_bt_device_disconnect(uint16_t conn_handle);
105108

106109
// Parse an UUID object from the caller and stores the result in the uuid
107110
// parameter. Must accept both strings and integers for 128-bit and 16-bit

ports/esp32/bluetooth/bluetooth.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,11 @@ int mp_bt_characteristic_value_get(mp_bt_characteristic_t *characteristic, void
340340
return 0;
341341
}
342342

343+
int mp_bt_device_disconnect(uint16_t conn_handle) {
344+
esp_err_t err = esp_ble_gatts_close(bluetooth_gatts_if, conn_handle);
345+
return mp_bt_esp_errno(err);
346+
}
347+
343348
// Parse a UUID object from the caller.
344349
void mp_bt_parse_uuid(mp_obj_t obj, mp_bt_uuid_t *uuid) {
345350
if (MP_OBJ_IS_SMALL_INT(obj) && MP_OBJ_SMALL_INT_VALUE(obj) == (uint32_t)(uint16_t)MP_OBJ_SMALL_INT_VALUE(obj)) {
@@ -444,7 +449,7 @@ STATIC void mp_bt_gatts_callback(esp_gatts_cb_event_t event, esp_gatt_if_t gatts
444449
break;
445450
case ESP_GATTS_WRITE_EVT:
446451
// Characteristic value written by connected device.
447-
mp_bt_characteristic_on_write(param->write.handle, param->write.value, param->write.len);
452+
mp_bt_characteristic_on_write(param->write.conn_id, param->write.handle, param->write.value, param->write.len);
448453
break;
449454
case ESP_GATTS_CONF_EVT:
450455
// Characteristic notify confirmation received.

ports/nrf/bluetooth/bluetooth.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
#include "nrf_sdm.h"
3939
#include "ble.h"
40+
#include "ble_hci.h"
4041
#if !NRF51
4142
#include "nrf_nvic.h"
4243
#endif
@@ -300,7 +301,7 @@ static void ble_evt_handler(ble_evt_t * p_ble_evt) {
300301
break;
301302
#endif
302303
case BLE_GATTS_EVT_WRITE:
303-
mp_bt_characteristic_on_write(p_ble_evt->evt.gatts_evt.params.write.handle, &p_ble_evt->evt.gatts_evt.params.write.data, p_ble_evt->evt.gatts_evt.params.write.len);
304+
mp_bt_characteristic_on_write(p_ble_evt->evt.gatts_evt.conn_handle, p_ble_evt->evt.gatts_evt.params.write.handle, &p_ble_evt->evt.gatts_evt.params.write.data, p_ble_evt->evt.gatts_evt.params.write.len);
304305
break;
305306
}
306307
}
@@ -397,6 +398,11 @@ int mp_bt_characteristic_value_get(mp_bt_characteristic_t *characteristic, void
397398
return mp_bt_errno(err_code);
398399
}
399400

401+
int mp_bt_device_disconnect(uint16_t conn_handle) {
402+
uint32_t err_code = sd_ble_gap_disconnect(conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
403+
return mp_bt_errno(err_code);
404+
}
405+
400406
// Parse a UUID object from the caller.
401407
void mp_bt_parse_uuid(mp_obj_t obj, mp_bt_uuid_t *uuid) {
402408
if (MP_OBJ_IS_SMALL_INT(obj) && MP_OBJ_SMALL_INT_VALUE(obj) == (uint32_t)(uint16_t)MP_OBJ_SMALL_INT_VALUE(obj)) {

0 commit comments

Comments
 (0)
0