From 81e92d3d6e1a605a6115821ac24dcbc2546ba0f9 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 28 Oct 2020 13:06:45 +1100 Subject: [PATCH] extmod/modbluetooth: Re-instate optional no-ringbuf modbluetooth. This requires that the event handlers are called from non-interrupt context (i.e. the MicroPython scheduler). This will allow the BLE stack (e.g. NimBLE) to run from the scheduler rather than an IRQ like PENDSV, and therefore be able to invoke Python callbacks directly/synchronously. This allows writing Python BLE handlers for events that require immediate response such as _IRQ_READ_REQUEST (which was previous a hard IRQ) and future events relating to pairing/bonding. Signed-off-by: Jim Mussared --- extmod/btstack/modbluetooth_btstack.c | 4 +- extmod/modbluetooth.c | 224 +++++++++++++++++++++----- extmod/modbluetooth.h | 8 +- extmod/nimble/modbluetooth_nimble.c | 4 +- ports/stm32/Makefile | 1 - ports/unix/Makefile | 2 - 6 files changed, 189 insertions(+), 54 deletions(-) diff --git a/extmod/btstack/modbluetooth_btstack.c b/extmod/btstack/modbluetooth_btstack.c index a4cc601746..97dd2cbb53 100644 --- a/extmod/btstack/modbluetooth_btstack.c +++ b/extmod/btstack/modbluetooth_btstack.c @@ -838,15 +838,15 @@ STATIC uint16_t att_read_callback(hci_con_handle_t connection_handle, uint16_t a return 0; } - #if MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK // Allow Python code to override value (by using gatts_write), or deny (by returning false) the read. + // Note this will be a no-op if the ringbuffer implementation is being used, as the Python callback cannot + // be executed synchronously. This is currently always the case for btstack. if ((buffer == NULL) && (buffer_size == 0)) { if (!mp_bluetooth_gatts_on_read_request(connection_handle, att_handle)) { DEBUG_printf("att_read_callback: read request denied\n"); return 0; } } - #endif uint16_t ret = att_read_callback_handle_blob(entry->data, entry->data_len, offset, buffer, buffer_size); return ret; diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 6bad134959..d8068df594 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -47,15 +47,18 @@ #define MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN 5 +#if !MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS // This formula is intended to allow queuing the data of a large characteristic // while still leaving room for a couple of normal (small, fixed size) events. #define MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN(ringbuf_size) (MAX((int)((ringbuf_size) / 2), (int)(ringbuf_size) - 64)) +#endif // bluetooth.BLE type. This is currently a singleton, however in the future // this could allow having multiple BLE interfaces on different UARTs. typedef struct { mp_obj_base_t base; mp_obj_t irq_handler; + #if !MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS bool irq_scheduled; mp_obj_t irq_data_tuple; uint8_t irq_data_addr_bytes[6]; @@ -64,8 +67,6 @@ typedef struct { mp_obj_array_t irq_data_data; mp_obj_bluetooth_uuid_t irq_data_uuid; ringbuf_t ringbuf; - #if MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK - mp_obj_t irq_read_request_data_tuple; #endif } mp_obj_bluetooth_ble_t; @@ -206,8 +207,7 @@ STATIC mp_int_t bluetooth_uuid_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bu return 0; } -#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE - +#if !MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS && MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE STATIC void ringbuf_put_uuid(ringbuf_t *ringbuf, mp_obj_bluetooth_uuid_t *uuid) { assert(ringbuf_free(ringbuf) >= (size_t)uuid->type + 1); ringbuf_put(ringbuf, uuid->type); @@ -252,14 +252,10 @@ STATIC mp_obj_t bluetooth_ble_make_new(const mp_obj_type_t *type, size_t n_args, o->irq_handler = mp_const_none; + #if !MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS // Pre-allocate the event data tuple to prevent needing to allocate in the IRQ handler. o->irq_data_tuple = mp_obj_new_tuple(MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN, NULL); - #if MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK - // Pre-allocate a separate data tuple for the read request "hard" irq. - o->irq_read_request_data_tuple = mp_obj_new_tuple(2, NULL); - #endif - // Pre-allocated buffers for address, payload and uuid. mp_obj_memoryview_init(&o->irq_data_addr, 'B', 0, 0, o->irq_data_addr_bytes); o->irq_data_data_alloc = MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN(MICROPY_PY_BLUETOOTH_RINGBUF_SIZE); @@ -268,6 +264,7 @@ STATIC mp_obj_t bluetooth_ble_make_new(const mp_obj_type_t *type, size_t n_args, // Allocate the default ringbuf. ringbuf_alloc(&o->ringbuf, MICROPY_PY_BLUETOOTH_RINGBUF_SIZE); + #endif MP_STATE_VM(bluetooth) = MP_OBJ_FROM_PTR(o); } @@ -290,8 +287,6 @@ STATIC mp_obj_t bluetooth_ble_active(size_t n_args, const mp_obj_t *args) { STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_active_obj, 1, 2, bluetooth_ble_active); STATIC mp_obj_t bluetooth_ble_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { - mp_obj_bluetooth_ble_t *self = MP_OBJ_TO_PTR(args[0]); - if (kwargs->used == 0) { // Get config value if (n_args != 2) { @@ -311,8 +306,12 @@ STATIC mp_obj_t bluetooth_ble_config(size_t n_args, const mp_obj_t *args, mp_map mp_obj_t items[] = { MP_OBJ_NEW_SMALL_INT(addr_type), mp_obj_new_bytes(addr, MP_ARRAY_SIZE(addr)) }; return mp_obj_new_tuple(2, items); } - case MP_QSTR_rxbuf: + #if !MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS + case MP_QSTR_rxbuf: { + mp_obj_bluetooth_ble_t *self = MP_OBJ_TO_PTR(args[0]); return mp_obj_new_int(self->ringbuf.size); + } + #endif case MP_QSTR_mtu: return mp_obj_new_int(mp_bluetooth_get_preferred_mtu()); default: @@ -334,6 +333,7 @@ STATIC mp_obj_t bluetooth_ble_config(size_t n_args, const mp_obj_t *args, mp_map bluetooth_handle_errno(mp_bluetooth_gap_set_device_name(bufinfo.buf, bufinfo.len)); break; } + #if !MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS case MP_QSTR_rxbuf: { // Determine new buffer sizes mp_int_t ringbuf_alloc = mp_obj_get_int(e->value); @@ -347,6 +347,7 @@ STATIC mp_obj_t bluetooth_ble_config(size_t n_args, const mp_obj_t *args, mp_map uint8_t *irq_data = m_new(uint8_t, irq_data_alloc); // Get old buffer sizes and pointers + mp_obj_bluetooth_ble_t *self = MP_OBJ_TO_PTR(args[0]); uint8_t *old_ringbuf_buf = self->ringbuf.buf; size_t old_ringbuf_alloc = self->ringbuf.size; uint8_t *old_irq_data_buf = (uint8_t *)self->irq_data_data.items; @@ -367,6 +368,7 @@ STATIC mp_obj_t bluetooth_ble_config(size_t n_args, const mp_obj_t *args, mp_map m_del(uint8_t, old_irq_data_buf, old_irq_data_alloc); break; } + #endif case MP_QSTR_mtu: { mp_int_t mtu = mp_obj_get_int(e->value); bluetooth_handle_errno(mp_bluetooth_set_preferred_mtu(mtu)); @@ -845,8 +847,7 @@ const mp_obj_module_t mp_module_ubluetooth = { // Helpers -#include - +#if !MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS STATIC void ringbuf_extract(ringbuf_t *ringbuf, mp_obj_tuple_t *data_tuple, size_t n_u16, size_t n_u8, mp_obj_array_t *bytes_addr, size_t n_i8, mp_obj_bluetooth_uuid_t *uuid, mp_obj_array_t *bytes_data) { assert(ringbuf_avail(ringbuf) >= n_u16 * 2 + n_u8 + (bytes_addr ? 6 : 0) + n_i8 + (uuid ? 1 : 0) + (bytes_data ? 1 : 0)); size_t j = 0; @@ -854,7 +855,7 @@ STATIC void ringbuf_extract(ringbuf_t *ringbuf, mp_obj_tuple_t *data_tuple, size for (size_t i = 0; i < n_u16; ++i) { data_tuple->items[j++] = MP_OBJ_NEW_SMALL_INT(ringbuf_get16(ringbuf)); } - if (n_u8) { + for (size_t i = 0; i < n_u8; ++i) { data_tuple->items[j++] = MP_OBJ_NEW_SMALL_INT(ringbuf_get(ringbuf)); } if (bytes_addr) { @@ -960,11 +961,166 @@ STATIC mp_obj_t bluetooth_ble_invoke_irq(mp_obj_t none_in) { return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluetooth_ble_invoke_irq_obj, bluetooth_ble_invoke_irq); +#endif // !MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS // ---------------------------------------------------------------------------- // Port API // ---------------------------------------------------------------------------- +#if MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS + +STATIC mp_obj_t invoke_irq_handler(uint16_t event, + const uint16_t *u16, size_t n_u16, + const uint8_t *u8, size_t n_u8, + const uint8_t *addr, + const int8_t *i8, size_t n_i8, + const mp_obj_bluetooth_uuid_t *uuid, + const uint8_t *data, size_t data_len) { + mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); + if (o->irq_handler == mp_const_none) { + return mp_const_none; + } + + mp_obj_array_t mv_addr; + mp_obj_array_t mv_data; + + mp_obj_tuple_t *data_tuple = mp_local_alloc(sizeof(mp_obj_tuple_t) + sizeof(mp_obj_t) * MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN); + data_tuple->base.type = &mp_type_tuple; + data_tuple->len = 0; + + for (size_t i = 0; i < n_u16; ++i) { + data_tuple->items[data_tuple->len++] = MP_OBJ_NEW_SMALL_INT(u16[i]); + } + for (size_t i = 0; i < n_u8; ++i) { + data_tuple->items[data_tuple->len++] = MP_OBJ_NEW_SMALL_INT(u8[i]); + } + if (addr) { + mp_obj_memoryview_init(&mv_addr, 'B', 0, 6, (void *)addr); + data_tuple->items[data_tuple->len++] = MP_OBJ_FROM_PTR(&mv_addr); + } + for (size_t i = 0; i < n_i8; ++i) { + data_tuple->items[data_tuple->len++] = MP_OBJ_NEW_SMALL_INT(i8[i]); + } + #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE + if (uuid) { + data_tuple->items[data_tuple->len++] = MP_OBJ_FROM_PTR(uuid); + } + #endif + if (data) { + mp_obj_memoryview_init(&mv_data, 'B', 0, data_len, (void *)data); + data_tuple->items[data_tuple->len++] = MP_OBJ_FROM_PTR(&mv_data); + } + assert(data_tuple->len <= MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN); + + mp_obj_t result = mp_call_function_2(o->irq_handler, MP_OBJ_NEW_SMALL_INT(event), MP_OBJ_FROM_PTR(data_tuple)); + + mp_local_free(data_tuple); + + return result; +} + +#define NULL_U16 NULL +#define NULL_U8 NULL +#define NULL_ADDR NULL +#define NULL_I8 NULL +#define NULL_UUID NULL +#define NULL_DATA NULL + +void mp_bluetooth_gap_on_connected_disconnected(uint8_t event, uint16_t conn_handle, uint8_t addr_type, const uint8_t *addr) { + invoke_irq_handler(event, &conn_handle, 1, &addr_type, 1, addr, NULL_I8, 0, NULL_UUID, NULL_DATA, 0); +} + +void mp_bluetooth_gatts_on_write(uint16_t conn_handle, uint16_t value_handle) { + uint16_t args[] = {conn_handle, value_handle}; + invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTS_WRITE, args, 2, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0); +} + +void mp_bluetooth_gatts_on_indicate_complete(uint16_t conn_handle, uint16_t value_handle, uint8_t status) { + uint16_t args[] = {conn_handle, value_handle}; + invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTS_INDICATE_DONE, args, 2, &status, 1, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0); +} + +bool mp_bluetooth_gatts_on_read_request(uint16_t conn_handle, uint16_t value_handle) { + uint16_t args[] = {conn_handle, value_handle}; + mp_obj_t result = invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTS_READ_REQUEST, args, 2, NULL, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0); + return result == mp_const_none || mp_obj_is_true(result); +} + +void mp_bluetooth_gatts_on_mtu_exchanged(uint16_t conn_handle, uint16_t value) { + uint16_t args[] = {conn_handle, value}; + invoke_irq_handler(MP_BLUETOOTH_IRQ_MTU_EXCHANGED, args, 2, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0); +} + +#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE +void mp_bluetooth_gap_on_scan_complete(void) { + invoke_irq_handler(MP_BLUETOOTH_IRQ_SCAN_DONE, NULL_U16, 0, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0); +} + +void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uint8_t adv_type, const int8_t rssi, const uint8_t *data, size_t data_len) { + int8_t args[] = {adv_type, rssi}; + invoke_irq_handler(MP_BLUETOOTH_IRQ_SCAN_RESULT, NULL_U16, 0, &addr_type, 1, addr, args, 2, NULL_UUID, data, data_len); +} + +void mp_bluetooth_gattc_on_primary_service_result(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, mp_obj_bluetooth_uuid_t *service_uuid) { + uint16_t args[] = {conn_handle, start_handle, end_handle}; + invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTC_SERVICE_RESULT, args, 3, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, service_uuid, NULL_DATA, 0); +} + +void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t def_handle, uint16_t value_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid) { + uint16_t args[] = {conn_handle, def_handle, value_handle}; + invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT, args, 3, &properties, 1, NULL_ADDR, NULL_I8, 0, characteristic_uuid, NULL_DATA, 0); +} + +void mp_bluetooth_gattc_on_descriptor_result(uint16_t conn_handle, uint16_t handle, mp_obj_bluetooth_uuid_t *descriptor_uuid) { + uint16_t args[] = {conn_handle, handle}; + invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_RESULT, args, 2, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, descriptor_uuid, NULL_DATA, 0); +} + +void mp_bluetooth_gattc_on_discover_complete(uint8_t event, uint16_t conn_handle, uint16_t status) { + uint16_t args[] = {conn_handle, status}; + invoke_irq_handler(event, args, 2, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0); +} + +void mp_bluetooth_gattc_on_data_available(uint8_t event, uint16_t conn_handle, uint16_t value_handle, const uint8_t **data, uint16_t *data_len, size_t num) { + const uint8_t *combined_data; + uint16_t total_len; + + if (num > 1) { + // Fragmented buffer, need to combine into a new heap-allocated buffer + // in order to pass to Python. + total_len = 0; + for (size_t i = 0; i < num; ++i) { + total_len += data_len[i]; + } + uint8_t *buf = m_new(uint8_t, total_len); + uint8_t *p = buf; + for (size_t i = 0; i < num; ++i) { + memcpy(p, data[i], data_len[i]); + p += data_len[i]; + } + combined_data = buf; + } else { + // Single buffer, use directly. + combined_data = *data; + total_len = *data_len; + } + + uint16_t args[] = {conn_handle, value_handle}; + invoke_irq_handler(event, args, 2, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, combined_data, total_len); + + if (num > 1) { + m_del(uint8_t, (uint8_t *)combined_data, total_len); + } +} + +void mp_bluetooth_gattc_on_read_write_status(uint8_t event, uint16_t conn_handle, uint16_t value_handle, uint16_t status) { + uint16_t args[] = {conn_handle, value_handle, status}; + invoke_irq_handler(event, args, 3, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0); +} + +#endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE + +#else // !MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS // Callbacks are called in interrupt context (i.e. can't allocate), so we need to push the data // into the ringbuf and schedule the callback via mp_sched_schedule. @@ -1169,36 +1325,12 @@ void mp_bluetooth_gattc_on_read_write_status(uint8_t event, uint16_t conn_handle #endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE -#if MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK -// This can only be enabled when the thread invoking this is a MicroPython thread. -// On ESP32, for example, this is not the case. bool mp_bluetooth_gatts_on_read_request(uint16_t conn_handle, uint16_t value_handle) { - mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); - if (o->irq_handler != mp_const_none) { - // When executing code within a handler we must lock the scheduler to - // prevent any scheduled callbacks from running, and lock the GC to - // prevent any memory allocations. - mp_sched_lock(); - gc_lock(); - - // Use pre-allocated tuple distinct to the one used by the "soft" IRQs. - mp_obj_tuple_t *data = MP_OBJ_TO_PTR(o->irq_read_request_data_tuple); - data->items[0] = MP_OBJ_NEW_SMALL_INT(conn_handle); - data->items[1] = MP_OBJ_NEW_SMALL_INT(value_handle); - data->len = 2; - mp_obj_t irq_ret = mp_call_function_2_protected(o->irq_handler, MP_OBJ_NEW_SMALL_INT(MP_BLUETOOTH_IRQ_GATTS_READ_REQUEST), o->irq_read_request_data_tuple); - - gc_unlock(); - mp_sched_unlock(); - - // If the IRQ handler explicitly returned false, then deny the read. Otherwise if it returns None/True, allow it. - return irq_ret != MP_OBJ_NULL && (irq_ret == mp_const_none || mp_obj_is_true(irq_ret)); - } else { - // No IRQ handler, allow the read. - return true; - } + (void)conn_handle; + (void)value_handle; + // This must be handled synchronously and therefore cannot implemented with the ringbuffer. + return true; } -#endif void mp_bluetooth_gatts_on_mtu_exchanged(uint16_t conn_handle, uint16_t value) { MICROPY_PY_BLUETOOTH_ENTER @@ -1210,6 +1342,12 @@ void mp_bluetooth_gatts_on_mtu_exchanged(uint16_t conn_handle, uint16_t value) { schedule_ringbuf(atomic_state); } +#endif // MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS + +// ---------------------------------------------------------------------------- +// GATTS DB +// ---------------------------------------------------------------------------- + void mp_bluetooth_gatts_db_create_entry(mp_gatts_db_t db, uint16_t handle, size_t len) { mp_map_elem_t *elem = mp_map_lookup(db, MP_OBJ_NEW_SMALL_INT(handle), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); mp_bluetooth_gatts_db_entry_t *entry = m_new(mp_bluetooth_gatts_db_entry_t, 1); diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h index dee7186a2d..6ed086d553 100644 --- a/extmod/modbluetooth.h +++ b/extmod/modbluetooth.h @@ -43,8 +43,10 @@ #define MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE (0) #endif -#ifndef MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK -#define MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK (0) +#ifndef MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS +// This can be enabled if the BLE stack runs entirely in scheduler context +// and therefore is able to call directly into the VM to run Python callbacks. +#define MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS (0) #endif // This is used to protect the ringbuffer. @@ -261,10 +263,8 @@ void mp_bluetooth_gatts_on_write(uint16_t conn_handle, uint16_t value_handle); // Call this when an acknowledgment is received for an indication. void mp_bluetooth_gatts_on_indicate_complete(uint16_t conn_handle, uint16_t value_handle, uint8_t status); -#if MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK // Call this when a characteristic is read from. Return false to deny the read. bool mp_bluetooth_gatts_on_read_request(uint16_t conn_handle, uint16_t value_handle); -#endif // Call this when an MTU exchange completes. void mp_bluetooth_gatts_on_mtu_exchanged(uint16_t conn_handle, uint16_t value); diff --git a/extmod/nimble/modbluetooth_nimble.c b/extmod/nimble/modbluetooth_nimble.c index b387e6ae1f..7ee6ae8677 100644 --- a/extmod/nimble/modbluetooth_nimble.c +++ b/extmod/nimble/modbluetooth_nimble.c @@ -586,12 +586,12 @@ static int characteristic_access_cb(uint16_t conn_handle, uint16_t value_handle, switch (ctxt->op) { case BLE_GATT_ACCESS_OP_READ_CHR: case BLE_GATT_ACCESS_OP_READ_DSC: - #if MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK // Allow Python code to override (by using gatts_write), or deny (by returning false) the read. + // Note this will be a no-op if the ringbuffer implementation is being used (i.e. the stack isn't + // run in the scheduler). The ringbuffer is not used on STM32 and Unix-H4 only. if (!mp_bluetooth_gatts_on_read_request(conn_handle, value_handle)) { return BLE_ATT_ERR_READ_NOT_PERMITTED; } - #endif entry = mp_bluetooth_gatts_db_lookup(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, value_handle); if (!entry) { diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 18f7e8a1a1..75090a077e 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -430,7 +430,6 @@ USBDEV_SRC_C += $(addprefix $(USBDEV_DIR)/,\ ifeq ($(MICROPY_PY_BLUETOOTH),1) CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH=1 CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE=1 -CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK=1 endif ifeq ($(MICROPY_PY_NETWORK_CYW43),1) diff --git a/ports/unix/Makefile b/ports/unix/Makefile index 048ef97f77..f72c05f1ad 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -156,8 +156,6 @@ endif CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH=1 CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE=1 -# Runs in a thread, cannot make calls into the VM. -CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK=0 ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1)