From 03b077dd912d9fd7faf9fb167fb7d8f48af300ab Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Thu, 12 Sep 2024 13:13:09 -0700 Subject: [PATCH 1/3] Add deinit() to _bleio.Characteristic Espressif's Characteristics allocate memory that may be on the supervisor heap. We need to free it when stopping BLE workflow. Otherwise, we leak the memory and eventually safe mode. Fixes #9599 --- .../common-hal/_bleio/Characteristic.c | 11 ++++ .../common-hal/_bleio/Characteristic.c | 64 +++++++++---------- .../common-hal/_bleio/PacketBuffer.c | 1 + .../nordic/common-hal/_bleio/Characteristic.c | 13 ++++ .../silabs/common-hal/_bleio/Characteristic.c | 7 ++ shared-bindings/_bleio/Characteristic.c | 28 ++++++++ shared-bindings/_bleio/Characteristic.h | 2 + supervisor/shared/bluetooth/bluetooth.c | 4 ++ supervisor/shared/bluetooth/file_transfer.c | 7 ++ supervisor/shared/bluetooth/file_transfer.h | 4 +- supervisor/shared/bluetooth/serial.c | 5 ++ 11 files changed, 113 insertions(+), 33 deletions(-) diff --git a/devices/ble_hci/common-hal/_bleio/Characteristic.c b/devices/ble_hci/common-hal/_bleio/Characteristic.c index f142239ded22..a33b8ff47847 100644 --- a/devices/ble_hci/common-hal/_bleio/Characteristic.c +++ b/devices/ble_hci/common-hal/_bleio/Characteristic.c @@ -50,6 +50,17 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, } } +bool common_hal_bleio_characteristic_deinited(bleio_characteristic_obj_t *self) { + return self->handle == BLE_GATT_HANDLE_INVALID; +} + +void common_hal_bleio_characteristic_deinit(bleio_characteristic_obj_t *self) { + if (common_hal_bleio_characteristic_deinited(self)) { + return; + } + self->handle = BLE_GATT_HANDLE_INVALID; +} + mp_obj_tuple_t *common_hal_bleio_characteristic_get_descriptors(bleio_characteristic_obj_t *self) { return mp_obj_new_tuple(self->descriptor_list->len, self->descriptor_list->items); } diff --git a/ports/espressif/common-hal/_bleio/Characteristic.c b/ports/espressif/common-hal/_bleio/Characteristic.c index 342c729baf4f..5de3680c6748 100644 --- a/ports/espressif/common-hal/_bleio/Characteristic.c +++ b/ports/espressif/common-hal/_bleio/Characteristic.c @@ -16,6 +16,7 @@ #include "shared-bindings/_bleio/PacketBuffer.h" #include "shared-bindings/_bleio/Service.h" #include "shared-bindings/time/__init__.h" +#include "supervisor/shared/safe_mode.h" #include "common-hal/_bleio/Adapter.h" #include "common-hal/_bleio/Service.h" @@ -100,27 +101,20 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, self->flags |= BLE_GATT_CHR_F_WRITE_AUTHEN; } - if (initial_value_bufinfo != NULL) { - // Copy the initial value if it's on the heap. Otherwise it's internal and we may not be able - // to allocate. - self->current_value_len = initial_value_bufinfo->len; - if (gc_alloc_possible()) { - self->current_value = m_malloc(max_length); - self->current_value_alloc = max_length; - if (gc_nbytes(initial_value_bufinfo->buf) > 0) { - memcpy(self->current_value, initial_value_bufinfo->buf, self->current_value_len); - } - } else { - self->current_value = initial_value_bufinfo->buf; - assert(self->current_value_len == max_length); - } + if (gc_alloc_possible()) { + self->current_value = m_malloc(max_length); } else { self->current_value = port_malloc(max_length, false); - if (self->current_value != NULL) { - self->current_value_alloc = max_length; - self->current_value_len = 0; + if (self->current_value == NULL) { + reset_into_safe_mode(SAFE_MODE_NO_HEAP); } } + self->current_value_alloc = max_length; + self->current_value_len = 0; + + if (initial_value_bufinfo != NULL) { + common_hal_bleio_characteristic_set_value(self, initial_value_bufinfo); + } if (gc_alloc_possible()) { self->descriptor_list = mp_obj_new_list(0, NULL); @@ -140,6 +134,26 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, } } +bool common_hal_bleio_characteristic_deinited(bleio_characteristic_obj_t *self) { + return self->current_value == NULL; +} + +void common_hal_bleio_characteristic_deinit(bleio_characteristic_obj_t *self) { + if (common_hal_bleio_characteristic_deinited(self)) { + return; + } + if (self->current_value == NULL) { + return; + } + + if (gc_nbytes(self->current_value) > 0) { + m_free(self->current_value); + } else { + port_free(self->current_value); + } + self->current_value = NULL; +} + mp_obj_tuple_t *common_hal_bleio_characteristic_get_descriptors(bleio_characteristic_obj_t *self) { if (self->descriptor_list == NULL) { return mp_const_empty_tuple; @@ -245,21 +259,7 @@ void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, } self->current_value_len = bufinfo->len; - // If we've already allocated an internal buffer or the provided buffer - // is on the heap, then copy into the internal buffer. - if (self->current_value_alloc > 0 || gc_nbytes(bufinfo->buf) > 0) { - if (self->current_value_alloc < bufinfo->len) { - self->current_value = m_realloc(self->current_value, bufinfo->len); - // Get the number of bytes from the heap because it may be more - // than the len due to gc block size. - self->current_value_alloc = gc_nbytes(self->current_value); - } - memcpy(self->current_value, bufinfo->buf, bufinfo->len); - } else { - // Otherwise, use the provided buffer to delay any heap allocation. - self->current_value = bufinfo->buf; - self->current_value_alloc = 0; - } + memcpy(self->current_value, bufinfo->buf, self->current_value_len); ble_gatts_chr_updated(self->handle); } diff --git a/ports/espressif/common-hal/_bleio/PacketBuffer.c b/ports/espressif/common-hal/_bleio/PacketBuffer.c index cf362d89e92c..a6cbdc530699 100644 --- a/ports/espressif/common-hal/_bleio/PacketBuffer.c +++ b/ports/espressif/common-hal/_bleio/PacketBuffer.c @@ -436,6 +436,7 @@ void common_hal_bleio_packet_buffer_deinit(bleio_packet_buffer_obj_t *self) { return; } bleio_characteristic_clear_observer(self->characteristic); + self->characteristic = NULL; ble_event_remove_handler(packet_buffer_on_ble_client_evt, self); ringbuf_deinit(&self->ringbuf); } diff --git a/ports/nordic/common-hal/_bleio/Characteristic.c b/ports/nordic/common-hal/_bleio/Characteristic.c index f3238f2fd501..33a373f76c47 100644 --- a/ports/nordic/common-hal/_bleio/Characteristic.c +++ b/ports/nordic/common-hal/_bleio/Characteristic.c @@ -109,6 +109,19 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, } } +bool common_hal_bleio_characteristic_deinited(bleio_characteristic_obj_t *self) { + return self->handle == BLE_GATT_HANDLE_INVALID; +} + +void common_hal_bleio_characteristic_deinit(bleio_characteristic_obj_t *self) { + if (common_hal_bleio_characteristic_deinited(self)) { + return; + } + self->handle = BLE_GATT_HANDLE_INVALID; + // TODO: Can we remove this from the soft device? Right now we assume the + // reset clears things. +} + mp_obj_tuple_t *common_hal_bleio_characteristic_get_descriptors(bleio_characteristic_obj_t *self) { if (self->descriptor_list == NULL) { return mp_const_empty_tuple; diff --git a/ports/silabs/common-hal/_bleio/Characteristic.c b/ports/silabs/common-hal/_bleio/Characteristic.c index f065a939a601..f2c137c1a0de 100644 --- a/ports/silabs/common-hal/_bleio/Characteristic.c +++ b/ports/silabs/common-hal/_bleio/Characteristic.c @@ -155,6 +155,13 @@ void common_hal_bleio_characteristic_construct( } } +bool common_hal_bleio_characteristic_deinited(bleio_characteristic_obj_t *self) { + return false; +} + +void common_hal_bleio_characteristic_deinit(bleio_characteristic_obj_t *self) { +} + // A tuple of Descriptor that describe this characteristic mp_obj_tuple_t *common_hal_bleio_characteristic_get_descriptors( bleio_characteristic_obj_t *self) { diff --git a/shared-bindings/_bleio/Characteristic.c b/shared-bindings/_bleio/Characteristic.c index 6b32e39ff434..f321b3cfd7ef 100644 --- a/shared-bindings/_bleio/Characteristic.c +++ b/shared-bindings/_bleio/Characteristic.c @@ -12,6 +12,8 @@ #include "shared-bindings/_bleio/Characteristic.h" #include "shared-bindings/_bleio/Service.h" #include "shared-bindings/_bleio/UUID.h" +#include "shared-bindings/util.h" + //| class Characteristic: //| """Stores information about a BLE service characteristic and allows reading @@ -137,7 +139,21 @@ static mp_obj_t bleio_characteristic_add_to_service(size_t n_args, const mp_obj_ static MP_DEFINE_CONST_FUN_OBJ_KW(bleio_characteristic_add_to_service_fun_obj, 1, bleio_characteristic_add_to_service); static MP_DEFINE_CONST_CLASSMETHOD_OBJ(bleio_characteristic_add_to_service_obj, MP_ROM_PTR(&bleio_characteristic_add_to_service_fun_obj)); +//| def deinit(self) -> None: +//| """Deinitialises the Characteristic and releases any hardware resources for reuse.""" +//| ... +static mp_obj_t bleio_characteristic_deinit(mp_obj_t self_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_bleio_characteristic_deinit(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_deinit_obj, bleio_characteristic_deinit); +static void check_for_deinit(bleio_characteristic_obj_t *self) { + if (common_hal_bleio_characteristic_deinited(self)) { + raise_deinited_error(); + } +} //| properties: int //| """An int bitmask representing which properties are set, specified as bitwise or'ing of @@ -145,6 +161,7 @@ static MP_DEFINE_CONST_CLASSMETHOD_OBJ(bleio_characteristic_add_to_service_obj, //| `BROADCAST`, `INDICATE`, `NOTIFY`, `READ`, `WRITE`, `WRITE_NO_RESPONSE`.""" static mp_obj_t bleio_characteristic_get_properties(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); return MP_OBJ_NEW_SMALL_INT(common_hal_bleio_characteristic_get_properties(self)); } @@ -159,6 +176,7 @@ MP_PROPERTY_GETTER(bleio_characteristic_properties_obj, //| Will be ``None`` if the 128-bit UUID for this characteristic is not known.""" static mp_obj_t bleio_characteristic_get_uuid(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); bleio_uuid_obj_t *uuid = common_hal_bleio_characteristic_get_uuid(self); return uuid ? MP_OBJ_FROM_PTR(uuid) : mp_const_none; @@ -172,6 +190,7 @@ MP_PROPERTY_GETTER(bleio_characteristic_uuid_obj, //| """The value of this characteristic.""" static mp_obj_t bleio_characteristic_get_value(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); uint8_t temp[512]; size_t actual_len = common_hal_bleio_characteristic_get_value(self, temp, sizeof(temp)); @@ -181,6 +200,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_value_obj, bleio_chara static mp_obj_t bleio_characteristic_set_value(mp_obj_t self_in, mp_obj_t value_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); mp_buffer_info_t bufinfo; mp_get_buffer_raise(value_in, &bufinfo, MP_BUFFER_READ); @@ -199,6 +219,7 @@ MP_PROPERTY_GETSET(bleio_characteristic_value_obj, //| """The max length of this characteristic.""" static mp_obj_t bleio_characteristic_get_max_length(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); return MP_OBJ_NEW_SMALL_INT(common_hal_bleio_characteristic_get_max_length(self)); } @@ -211,6 +232,8 @@ MP_PROPERTY_GETTER(bleio_characteristic_max_length_obj, //| """A tuple of :py:class:`Descriptor` objects related to this characteristic. (read-only)""" static mp_obj_t bleio_characteristic_get_descriptors(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + // Return list as a tuple so user won't be able to change it. return MP_OBJ_FROM_PTR(common_hal_bleio_characteristic_get_descriptors(self)); } @@ -224,6 +247,7 @@ MP_PROPERTY_GETTER(bleio_characteristic_descriptors_obj, //| """The Service this Characteristic is a part of.""" static mp_obj_t bleio_characteristic_get_service(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); return common_hal_bleio_characteristic_get_service(self); } @@ -241,6 +265,7 @@ MP_PROPERTY_GETTER(bleio_characteristic_service_obj, //| ... static mp_obj_t bleio_characteristic_set_cccd(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); enum { ARG_notify, ARG_indicate }; static const mp_arg_t allowed_args[] = { @@ -258,6 +283,9 @@ static mp_obj_t bleio_characteristic_set_cccd(mp_uint_t n_args, const mp_obj_t * static MP_DEFINE_CONST_FUN_OBJ_KW(bleio_characteristic_set_cccd_obj, 1, bleio_characteristic_set_cccd); static const mp_rom_map_elem_t bleio_characteristic_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&bleio_characteristic_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&bleio_characteristic_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_add_to_service), MP_ROM_PTR(&bleio_characteristic_add_to_service_obj) }, { MP_ROM_QSTR(MP_QSTR_descriptors), MP_ROM_PTR(&bleio_characteristic_descriptors_obj) }, { MP_ROM_QSTR(MP_QSTR_properties), MP_ROM_PTR(&bleio_characteristic_properties_obj) }, diff --git a/shared-bindings/_bleio/Characteristic.h b/shared-bindings/_bleio/Characteristic.h index 2d343b8b07f9..67b1062691da 100644 --- a/shared-bindings/_bleio/Characteristic.h +++ b/shared-bindings/_bleio/Characteristic.h @@ -24,5 +24,7 @@ extern size_t common_hal_bleio_characteristic_get_max_length(bleio_characteristi extern size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self, uint8_t *buf, size_t len); extern void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *self, bleio_descriptor_obj_t *descriptor); extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo, const char *user_description); +extern bool common_hal_bleio_characteristic_deinited(bleio_characteristic_obj_t *self); +extern void common_hal_bleio_characteristic_deinit(bleio_characteristic_obj_t *self); extern void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate); extern void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo); diff --git a/supervisor/shared/bluetooth/bluetooth.c b/supervisor/shared/bluetooth/bluetooth.c index 68b43871ce16..2fe97f9f0b01 100644 --- a/supervisor/shared/bluetooth/bluetooth.c +++ b/supervisor/shared/bluetooth/bluetooth.c @@ -339,6 +339,10 @@ void supervisor_stop_bluetooth(void) { ble_started = false; + #if CIRCUITPY_BLE_FILE_SERVICE + supervisor_stop_bluetooth_file_transfer(); + #endif + #if CIRCUITPY_SERIAL_BLE supervisor_stop_bluetooth_serial(); #endif diff --git a/supervisor/shared/bluetooth/file_transfer.c b/supervisor/shared/bluetooth/file_transfer.c index aa49c0a899a8..66eccf8cbf2c 100644 --- a/supervisor/shared/bluetooth/file_transfer.c +++ b/supervisor/shared/bluetooth/file_transfer.c @@ -101,6 +101,13 @@ void supervisor_start_bluetooth_file_transfer(void) { &static_handler_entry); } +void supervisor_stop_bluetooth_file_transfer(void) { + common_hal_bleio_packet_buffer_deinit(&_transfer_packet_buffer); + common_hal_bleio_characteristic_deinit(&supervisor_ble_transfer_characteristic); + common_hal_bleio_characteristic_deinit(&supervisor_ble_version_characteristic); + common_hal_bleio_service_deinit(&supervisor_ble_service); +} + #define COMMAND_SIZE 1024 #define ANY_COMMAND 0x00 diff --git a/supervisor/shared/bluetooth/file_transfer.h b/supervisor/shared/bluetooth/file_transfer.h index 12c75e1f548c..8d4fc9c66848 100644 --- a/supervisor/shared/bluetooth/file_transfer.h +++ b/supervisor/shared/bluetooth/file_transfer.h @@ -8,6 +8,8 @@ #include -void supervisor_bluetooth_file_transfer_background(void); void supervisor_start_bluetooth_file_transfer(void); +void supervisor_stop_bluetooth_file_transfer(void); + +void supervisor_bluetooth_file_transfer_background(void); void supervisor_bluetooth_file_transfer_disconnected(void); diff --git a/supervisor/shared/bluetooth/serial.c b/supervisor/shared/bluetooth/serial.c index 3c8ae71eb482..42c9b4bb3877 100644 --- a/supervisor/shared/bluetooth/serial.c +++ b/supervisor/shared/bluetooth/serial.c @@ -148,6 +148,11 @@ void supervisor_stop_bluetooth_serial(void) { return; } common_hal_bleio_packet_buffer_flush(&_tx_packet_buffer); + common_hal_bleio_packet_buffer_deinit(&_tx_packet_buffer); + common_hal_bleio_characteristic_deinit(&supervisor_ble_circuitpython_rx_characteristic); + common_hal_bleio_characteristic_deinit(&supervisor_ble_circuitpython_tx_characteristic); + common_hal_bleio_characteristic_deinit(&supervisor_ble_circuitpython_version_characteristic); + common_hal_bleio_service_deinit(&supervisor_ble_circuitpython_service); } bool ble_serial_connected(void) { From 30d57b1adeef3093c5f5ed5cf57b7643fab0cec1 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Thu, 12 Sep 2024 13:17:17 -0700 Subject: [PATCH 2/3] Fix gc_alloc_possible() The BLE workflow was allocating to the VM heap when it wasn't active and causing a port_malloc. --- py/gc.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/py/gc.c b/py/gc.c index dcf07c6467e7..2c5d2d2c29e6 100644 --- a/py/gc.c +++ b/py/gc.c @@ -759,13 +759,10 @@ void gc_info(gc_info_t *info) { GC_EXIT(); } -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: C code may be used when the VM heap isn't active. This +// allows that code to test if it is. It can use the outer pool if needed. bool gc_alloc_possible(void) { - #if MICROPY_GC_SPLIT_HEAP - return MP_STATE_MEM(gc_last_free_area) != 0; - #else return MP_STATE_MEM(area).gc_pool_start != 0; - #endif } void *gc_alloc(size_t n_bytes, unsigned int alloc_flags) { From b5517cb04bc3a748a6ca06a1ff25395455fd372c Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Thu, 12 Sep 2024 13:18:12 -0700 Subject: [PATCH 3/3] Always clear RX buffer on CTRL-C Some serial sources clear their RX buffers and others didn't. This cause CP to skip into the REPL based on characters typed before the CTRL-C. The serial file transfer code looks for "press any key" which is skipped in this case. Fixes https://github.com/circuitpython/web-editor/issues/238 --- ports/espressif/common-hal/_bleio/CharacteristicBuffer.c | 1 + ports/espressif/supervisor/usb_serial_jtag.c | 1 + ports/nordic/common-hal/_bleio/CharacteristicBuffer.c | 1 + supervisor/shared/usb/host_keyboard.c | 3 ++- supervisor/shared/web_workflow/websocket.c | 1 + 5 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ports/espressif/common-hal/_bleio/CharacteristicBuffer.c b/ports/espressif/common-hal/_bleio/CharacteristicBuffer.c index 082cd492a919..8020af2873db 100644 --- a/ports/espressif/common-hal/_bleio/CharacteristicBuffer.c +++ b/ports/espressif/common-hal/_bleio/CharacteristicBuffer.c @@ -26,6 +26,7 @@ void bleio_characteristic_buffer_extend(bleio_characteristic_buffer_obj_t *self, for (uint16_t i = 0; i < len; i++) { if (data[i] == mp_interrupt_char) { mp_sched_keyboard_interrupt(); + ringbuf_clear(&self->ringbuf); } else { ringbuf_put(&self->ringbuf, data[i]); } diff --git a/ports/espressif/supervisor/usb_serial_jtag.c b/ports/espressif/supervisor/usb_serial_jtag.c index 1a5282de8e93..b4cb91b7d7eb 100644 --- a/ports/espressif/supervisor/usb_serial_jtag.c +++ b/ports/espressif/supervisor/usb_serial_jtag.c @@ -46,6 +46,7 @@ static void _copy_out_of_fifo(void) { for (size_t i = 0; i < len; ++i) { if (rx_buf[i] == mp_interrupt_char) { mp_sched_keyboard_interrupt(); + ringbuf_clear(&ringbuf); } else { ringbuf_put(&ringbuf, rx_buf[i]); } diff --git a/ports/nordic/common-hal/_bleio/CharacteristicBuffer.c b/ports/nordic/common-hal/_bleio/CharacteristicBuffer.c index 4374907adf4e..9a86afb39ac3 100644 --- a/ports/nordic/common-hal/_bleio/CharacteristicBuffer.c +++ b/ports/nordic/common-hal/_bleio/CharacteristicBuffer.c @@ -29,6 +29,7 @@ static void write_to_ringbuf(bleio_characteristic_buffer_obj_t *self, uint8_t *d for (uint16_t i = 0; i < len; i++) { if (data[i] == mp_interrupt_char) { mp_sched_keyboard_interrupt(); + ringbuf_clear(&self->ringbuf); } else { ringbuf_put(&self->ringbuf, data[i]); } diff --git a/supervisor/shared/usb/host_keyboard.c b/supervisor/shared/usb/host_keyboard.c index 78c3f3673ba0..661ebb642235 100644 --- a/supervisor/shared/usb/host_keyboard.c +++ b/supervisor/shared/usb/host_keyboard.c @@ -155,8 +155,9 @@ static void send_bufn_core(const char *buf, size_t n) { for (; n--; buf++) { int code = *buf; if (code == mp_interrupt_char) { + ringbuf_clear(&_incoming_ringbuf); mp_sched_keyboard_interrupt(); - return; + continue; } if (ringbuf_num_empty(&_incoming_ringbuf) == 0) { // Drop on the floor diff --git a/supervisor/shared/web_workflow/websocket.c b/supervisor/shared/web_workflow/websocket.c index accd2398e1e5..67b003b18a4f 100644 --- a/supervisor/shared/web_workflow/websocket.c +++ b/supervisor/shared/web_workflow/websocket.c @@ -227,6 +227,7 @@ void websocket_background(void) { while (ringbuf_num_empty(&_incoming_ringbuf) > 0 && _read_next_payload_byte(&c)) { if (c == mp_interrupt_char) { + ringbuf_clear(&_incoming_ringbuf); mp_sched_keyboard_interrupt(); continue; }