diff --git a/.gitmodules b/.gitmodules index b0a12ffe205e0..510991a5a391e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -143,7 +143,7 @@ [submodule "ports/espressif/esp-idf"] path = ports/espressif/esp-idf url = https://github.com/adafruit/esp-idf.git - branch = circuitpython-v5.1.3 + branch = circuitpython-v5.2.2 [submodule "ports/espressif/esp-protocols"] path = ports/espressif/esp-protocols url = https://github.com/espressif/esp-protocols.git diff --git a/devices/ble_hci/common-hal/_bleio/__init__.c b/devices/ble_hci/common-hal/_bleio/__init__.c index 6cdc37f435c3b..9663e70699807 100644 --- a/devices/ble_hci/common-hal/_bleio/__init__.c +++ b/devices/ble_hci/common-hal/_bleio/__init__.c @@ -37,6 +37,9 @@ bool vm_used_ble; // } // } +void common_hal_bleio_init(void) { +} + void bleio_user_reset() { // HCI doesn't support the BLE workflow so just do a full reset. bleio_reset(); diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 0e3878bc3d8c9..feb9457088c67 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -113,7 +113,7 @@ msgstr "" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/usb_host/Port.c #: shared-bindings/digitalio/DigitalInOut.c -#: shared-bindings/microcontroller/Pin.c +#: shared-bindings/microcontroller/Pin.c shared-module/max3421e/Max3421E.c msgid "%q in use" msgstr "" @@ -1114,10 +1114,12 @@ msgstr "" msgid "Input/output error" msgstr "" +#: ports/espressif/common-hal/_bleio/__init__.c #: ports/nordic/common-hal/_bleio/__init__.c msgid "Insufficient authentication" msgstr "" +#: ports/espressif/common-hal/_bleio/__init__.c #: ports/nordic/common-hal/_bleio/__init__.c msgid "Insufficient encryption" msgstr "" @@ -1154,6 +1156,7 @@ msgstr "" #: ports/atmel-samd/common-hal/alarm/pin/PinAlarm.c #: ports/atmel-samd/common-hal/countio/Counter.c #: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c +#: ports/atmel-samd/common-hal/max3421e/Max3421E.c #: ports/atmel-samd/common-hal/ps2io/Ps2.c #: ports/atmel-samd/common-hal/pulseio/PulseIn.c #: ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c @@ -1285,6 +1288,10 @@ msgstr "" msgid "MAC address was invalid" msgstr "" +#: ports/espressif/common-hal/_bleio/Characteristic.c +msgid "MITM security not supported" +msgstr "" + #: shared-bindings/is31fl3741/IS31FL3741.c msgid "Mapping must be a tuple" msgstr "" @@ -2139,6 +2146,7 @@ msgstr "" msgid "Unknown BLE error: %d" msgstr "" +#: ports/espressif/common-hal/max3421e/Max3421E.c #: ports/raspberrypi/common-hal/wifi/__init__.c #, c-format msgid "Unknown error code %d" @@ -3810,7 +3818,7 @@ msgstr "" msgid "pop from empty %q" msgstr "" -#: shared-bindings/socketpool/Socket.c shared-bindings/ssl/SSLSocket.c +#: shared-bindings/socketpool/Socket.c msgid "port must be >= 0" msgstr "" diff --git a/main.c b/main.c index 3988bc9e7dc0e..a463fbe4afe6b 100644 --- a/main.c +++ b/main.c @@ -1006,10 +1006,6 @@ int __attribute__((used)) main(void) { supervisor_status_bar_init(); #endif - #if CIRCUITPY_BLEIO - // Early init so that a reset press can cause BLE public advertising. - supervisor_bluetooth_init(); - #endif #if !INTERNAL_FLASH_FILESYSTEM // Set up anything that might need to get done before we try to use SPI flash @@ -1027,6 +1023,12 @@ int __attribute__((used)) main(void) { set_safe_mode(SAFE_MODE_NO_CIRCUITPY); } + #if CIRCUITPY_BLEIO + // Early init so that a reset press can cause BLE public advertising. Need the filesystem to + // read settings.toml. + supervisor_bluetooth_init(); + #endif + #if CIRCUITPY_ALARM // Record which alarm woke us up, if any. // common_hal_alarm_record_wake_alarm() should return a static, non-heap object diff --git a/ports/espressif/Makefile b/ports/espressif/Makefile index 17641f683a79a..629376add113e 100644 --- a/ports/espressif/Makefile +++ b/ports/espressif/Makefile @@ -229,11 +229,13 @@ LDFLAGS += \ -Tesp32c6.rom.newlib.ld \ -Tesp32c6.rom.coexist.ld \ -Tesp32c6.rom.heap.ld \ + -Tesp32c6.rom.systimer.ld \ -Tesp32c6.rom.wdt.ld else ifeq ($(IDF_TARGET),esp32h2) LDFLAGS += \ -Tesp32h2.rom.heap.ld \ -Tesp32h2.rom.newlib.ld \ + -Tesp32h2.rom.systimer.ld \ -Tesp32h2.rom.wdt.ld else ifeq ($(IDF_TARGET),esp32s2) LDFLAGS += \ diff --git a/ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h b/ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h index c3d168ac16d20..969bf468574fe 100644 --- a/ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h +++ b/ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h @@ -11,7 +11,9 @@ #define MICROPY_HW_BOARD_NAME "Adafruit Feather ESP32-C6 4MB Flash No PSRAM" #define MICROPY_HW_MCU_NAME "ESP32C6" -#define MICROPY_HW_NEOPIXEL (&pin_GPIO9) +// Don't use the neopixel for status because we can't use it at the same time as +// the boot button. +// #define MICROPY_HW_NEOPIXEL (&pin_GPIO9) #define MICROPY_HW_LED_STATUS (&pin_GPIO15) diff --git a/ports/espressif/common-hal/_bleio/Adapter.c b/ports/espressif/common-hal/_bleio/Adapter.c index 3c08f28ea4dae..0a8550408d895 100644 --- a/ports/espressif/common-hal/_bleio/Adapter.c +++ b/ports/espressif/common-hal/_bleio/Adapter.c @@ -39,6 +39,7 @@ #include "common-hal/_bleio/Connection.h" #include "esp_bt.h" +#include "esp_mac.h" #include "esp_nimble_hci.h" #include "nvs_flash.h" @@ -48,11 +49,6 @@ bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT]; -// static void bluetooth_adapter_background(void *data) { -// supervisor_bluetooth_background(); -// bleio_background(); -// } - bool ble_active = false; static void nimble_host_task(void *param) { @@ -63,7 +59,7 @@ static void nimble_host_task(void *param) { static TaskHandle_t cp_task = NULL; static void _on_sync(void) { - int rc = ble_hs_util_ensure_addr(0); + int rc = ble_hs_util_ensure_addr(false); assert(rc == 0); xTaskNotifyGive(cp_task); @@ -72,6 +68,8 @@ static void _on_sync(void) { // All examples have this. It'd make sense in a header. void ble_store_config_init(void); +char default_ble_name[] = { 'C', 'I', 'R', 'C', 'U', 'I', 'T', 'P', 'Y', 0, 0, 0, 0, 0, 0, 0}; + void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enabled) { const bool is_enabled = common_hal_bleio_adapter_get_enabled(self); @@ -81,15 +79,6 @@ void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enable } if (enabled) { - esp_err_t err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { - // NVS partition was truncated and needs to be erased - // Retry nvs_flash_init - ESP_ERROR_CHECK(nvs_flash_erase()); - err = nvs_flash_init(); - } - ESP_ERROR_CHECK(err); - CHECK_ESP_RESULT(nimble_port_init()); // ble_hs_cfg.reset_cb = blecent_on_reset; @@ -104,8 +93,8 @@ void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enable ble_hs_cfg.sm_our_key_dist |= BLE_SM_PAIR_KEY_DIST_ENC; ble_hs_cfg.sm_their_key_dist |= BLE_SM_PAIR_KEY_DIST_ENC; - ble_hs_cfg.sm_mitm = 1; - ble_hs_cfg.sm_sc = 1; + ble_hs_cfg.sm_mitm = 0; + ble_hs_cfg.sm_sc = 0; /* Stores the IRK */ ble_hs_cfg.sm_our_key_dist |= BLE_SM_PAIR_KEY_DIST_ID; ble_hs_cfg.sm_their_key_dist |= BLE_SM_PAIR_KEY_DIST_ID; @@ -122,7 +111,17 @@ void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enable } else #endif { - ble_svc_gap_device_name_set("CIRCUITPY"); + uint8_t mac[6]; + esp_read_mac(mac, ESP_MAC_BT); + mp_int_t len = sizeof(default_ble_name) - 1; + default_ble_name[len - 6] = nibble_to_hex_lower[mac[3] >> 4 & 0xf]; + default_ble_name[len - 5] = nibble_to_hex_lower[mac[3] & 0xf]; + default_ble_name[len - 4] = nibble_to_hex_lower[mac[4] >> 4 & 0xf]; + default_ble_name[len - 3] = nibble_to_hex_lower[mac[4] & 0xf]; + default_ble_name[len - 2] = nibble_to_hex_lower[mac[5] >> 4 & 0xf]; + default_ble_name[len - 1] = nibble_to_hex_lower[mac[5] & 0xf]; + default_ble_name[len] = '\0'; // for now we add null for compatibility with C ASCIIZ strings + ble_svc_gap_device_name_set(default_ble_name); } // Clear all of the internal connection objects. @@ -180,6 +179,14 @@ bool common_hal_bleio_adapter_set_address(bleio_adapter_obj_t *self, bleio_addre return result == 0; } +uint16_t bleio_adapter_get_name(char *buf, uint16_t len) { + const char *name = ble_svc_gap_device_name(); + uint16_t full_len = strlen(name); + memcpy(buf, name, MIN(full_len, len)); + + return full_len; +} + mp_obj_str_t *common_hal_bleio_adapter_get_name(bleio_adapter_obj_t *self) { const char *name = ble_svc_gap_device_name(); @@ -401,7 +408,8 @@ mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_addre _connect_event, self)); int error_code; - CHECK_NOTIFY(xTaskNotifyWait(0, 0, (uint32_t *)&error_code, 200)); + // Wait an extra 50 ms to give the connect method the opportunity to time out. + CHECK_NOTIFY(xTaskNotifyWait(0, 0, (uint32_t *)&error_code, pdMS_TO_TICKS(timeout * 1000 + 50))); // Negative values are error codes, connection handle otherwise. if (error_code < 0) { CHECK_BLE_ERROR(-error_code); @@ -487,6 +495,7 @@ static int _advertising_event(struct ble_gap_event *event, void *self_in) { #endif break; } + background_callback_add_core(&bleio_background_callback); return 0; } @@ -499,6 +508,8 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, if (ble_gap_adv_active() && !self->user_advertising) { return BLE_HS_EBUSY; } + // Override anonymous because it isn't working with the ESP-IDF. + anonymous = false; uint32_t rc; @@ -521,12 +532,19 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool extended = advertising_data_len > BLE_ADV_LEGACY_DATA_MAX_LEN || scan_response_data_len > BLE_ADV_LEGACY_DATA_MAX_LEN; + bool scannable = scan_response_data_len > 0; + bool legacy_pdu = !extended && !anonymous; + if (legacy_pdu && connectable) { + // Connectable legacy advertisements are always scannable too. + scannable = true; + } + struct ble_gap_ext_adv_params adv_params = { .connectable = connectable, - .scannable = scan_response_data_len > 0, + .scannable = scannable, .directed = directed_to != NULL, .high_duty_directed = high_duty_directed, - .legacy_pdu = !extended, + .legacy_pdu = legacy_pdu, .anonymous = anonymous, .include_tx_power = extended, .scan_req_notif = false, @@ -712,14 +730,46 @@ mp_obj_t common_hal_bleio_adapter_get_connections(bleio_adapter_obj_t *self) { return self->connection_objs; } +#define NIMBLE_NVS_PEER_SEC_KEY "peer_sec" +#define NIMBLE_NVS_OUR_SEC_KEY "our_sec" +#define NIMBLE_NVS_CCCD_SEC_KEY "cccd_sec" +#define NIMBLE_NVS_PEER_RECORDS_KEY "p_dev_rec" +#define NIMBLE_NVS_NAMESPACE "nimble_bond" + +// Implement bonding control ourselves when the adapter isn't enabled so that it +// can run when BLE is off. void common_hal_bleio_adapter_erase_bonding(bleio_adapter_obj_t *self) { - ble_store_clear(); + if (common_hal_bleio_adapter_get_enabled(self)) { + ble_store_clear(); + } else { + nvs_handle_t nimble_handle; + esp_err_t err = nvs_open(NIMBLE_NVS_NAMESPACE, NVS_READWRITE, &nimble_handle); + if (err != ESP_OK) { + return; + } + nvs_erase_all(nimble_handle); + nvs_commit(nimble_handle); + nvs_close(nimble_handle); + } } bool common_hal_bleio_adapter_is_bonded_to_central(bleio_adapter_obj_t *self) { - int count; - ble_store_util_count(BLE_STORE_OBJ_TYPE_PEER_SEC, &count); - return count > 0; + if (common_hal_bleio_adapter_get_enabled(self)) { + int count; + ble_store_util_count(BLE_STORE_OBJ_TYPE_PEER_SEC, &count); + return count > 0; + } + nvs_handle_t nimble_handle; + esp_err_t err = nvs_open(NIMBLE_NVS_NAMESPACE, NVS_READONLY, &nimble_handle); + if (err != ESP_OK) { + return false; + } + err = nvs_find_key(nimble_handle, "peer_sec_1", NULL); + nvs_close(nimble_handle); + if (err == ESP_OK) { + return true; + } + return false; } void bleio_adapter_gc_collect(bleio_adapter_obj_t *adapter) { diff --git a/ports/espressif/common-hal/_bleio/Characteristic.c b/ports/espressif/common-hal/_bleio/Characteristic.c index 4df80a53d991e..a095add66736b 100644 --- a/ports/espressif/common-hal/_bleio/Characteristic.c +++ b/ports/espressif/common-hal/_bleio/Characteristic.c @@ -17,7 +17,6 @@ #include "common-hal/_bleio/Adapter.h" #include "common-hal/_bleio/Service.h" -// #include "common-hal/_bleio/bonding.h" static int characteristic_on_ble_gap_evt(struct ble_gap_event *event, void *param); @@ -57,6 +56,22 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, if ((props & CHAR_PROP_WRITE_NO_RESPONSE) != 0) { self->flags |= BLE_GATT_CHR_F_WRITE_NO_RSP; } + if (read_perm == SECURITY_MODE_ENC_WITH_MITM || write_perm == SECURITY_MODE_ENC_WITH_MITM || + read_perm == SECURITY_MODE_SIGNED_WITH_MITM || write_perm == SECURITY_MODE_SIGNED_WITH_MITM) { + mp_raise_NotImplementedError(MP_ERROR_TEXT("MITM security not supported")); + } + if (read_perm == SECURITY_MODE_ENC_NO_MITM) { + self->flags |= BLE_GATT_CHR_F_READ_ENC; + } + if (read_perm == SECURITY_MODE_SIGNED_NO_MITM) { + self->flags |= BLE_GATT_CHR_F_READ_AUTHEN; + } + if (write_perm == SECURITY_MODE_ENC_NO_MITM) { + self->flags |= BLE_GATT_CHR_F_WRITE_ENC; + } + if (write_perm == SECURITY_MODE_SIGNED_NO_MITM) { + 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 @@ -72,6 +87,12 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, self->current_value = initial_value_bufinfo->buf; assert(self->current_value_len == 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 (gc_alloc_possible()) { @@ -294,6 +315,7 @@ int bleio_characteristic_access_cb(uint16_t conn_handle, uint16_t attr_handle, bleio_packet_buffer_extend(MP_OBJ_FROM_PTR(self->observer), conn_handle, self->current_value, self->current_value_len); } } + background_callback_add_core(&bleio_background_callback); return rc; } return BLE_ATT_ERR_UNLIKELY; diff --git a/ports/espressif/common-hal/_bleio/Connection.c b/ports/espressif/common-hal/_bleio/Connection.c index ea30b1865f595..5957cd5edcf68 100644 --- a/ports/espressif/common-hal/_bleio/Connection.c +++ b/ports/espressif/common-hal/_bleio/Connection.c @@ -91,14 +91,18 @@ int bleio_connection_event_cb(struct ble_gap_event *event, void *connection_in) case BLE_GAP_EVENT_NOTIFY_TX: MP_FALLTHROUGH; case BLE_GAP_EVENT_SUBSCRIBE: - return ble_event_run_handlers(event); + int status = ble_event_run_handlers(event); + background_callback_add_core(&bleio_background_callback); + return status; default: #if CIRCUITPY_VERBOSE_BLE mp_printf(&mp_plat_print, "Unhandled connection event: %d\n", event->type); #endif - return 0; + break; } + + background_callback_add_core(&bleio_background_callback); return 0; } diff --git a/ports/espressif/common-hal/_bleio/PacketBuffer.c b/ports/espressif/common-hal/_bleio/PacketBuffer.c index e6886811966de..8640bf7e42b7f 100644 --- a/ports/espressif/common-hal/_bleio/PacketBuffer.c +++ b/ports/espressif/common-hal/_bleio/PacketBuffer.c @@ -92,6 +92,8 @@ static int queue_next_write(bleio_packet_buffer_obj_t *self) { // Allocate an mbuf because the functions below consume it. struct os_mbuf *om = ble_hs_mbuf_from_flat(self->outgoing[self->pending_index], self->pending_size); if (om == NULL) { + // We may not have any more mbufs if BLE busy. It isn't a problem (yet) so we'll + // just skip queueing for now. return BLE_HS_ENOMEM; } size_t pending_size = self->pending_size; @@ -157,7 +159,7 @@ void _common_hal_bleio_packet_buffer_construct( bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic, uint32_t *incoming_buffer, size_t incoming_buffer_size, uint32_t *outgoing_buffer1, uint32_t *outgoing_buffer2, size_t max_packet_size, - void *static_handler_entry) { + ble_event_handler_t *static_handler_entry) { self->characteristic = characteristic; self->client = self->characteristic->service->is_remote; self->max_packet_size = max_packet_size; @@ -331,7 +333,8 @@ mp_int_t common_hal_bleio_packet_buffer_write(bleio_packet_buffer_obj_t *self, c // If no writes are queued then sneak in this data. if (!self->packet_queued) { - CHECK_NIMBLE_ERROR(queue_next_write(self)); + // This will queue up the packet even if it can't send immediately. + queue_next_write(self); } return num_bytes_written; } diff --git a/ports/espressif/common-hal/_bleio/PacketBuffer.h b/ports/espressif/common-hal/_bleio/PacketBuffer.h index e17a6c7425211..0ab084c5b0175 100644 --- a/ports/espressif/common-hal/_bleio/PacketBuffer.h +++ b/ports/espressif/common-hal/_bleio/PacketBuffer.h @@ -8,6 +8,7 @@ #include "py/ringbuf.h" #include "shared-bindings/_bleio/Characteristic.h" +#include "common-hal/_bleio/ble_events.h" typedef struct { mp_obj_base_t base; @@ -28,4 +29,6 @@ typedef struct { bool packet_queued; } bleio_packet_buffer_obj_t; +typedef ble_event_handler_entry_t ble_event_handler_t; + void bleio_packet_buffer_extend(bleio_packet_buffer_obj_t *self, uint16_t conn_handle, const uint8_t *buffer, size_t len); diff --git a/ports/espressif/common-hal/_bleio/__init__.c b/ports/espressif/common-hal/_bleio/__init__.c index 0d99a97c23c4f..eb51e9f456700 100644 --- a/ports/espressif/common-hal/_bleio/__init__.c +++ b/ports/espressif/common-hal/_bleio/__init__.c @@ -19,9 +19,13 @@ #include "supervisor/shared/bluetooth/bluetooth.h" #include "common-hal/_bleio/__init__.h" -// #include "common-hal/_bleio/bonding.h" #include "common-hal/_bleio/ble_events.h" +#include "nvs_flash.h" + + +background_callback_t bleio_background_callback; + void bleio_user_reset() { // Stop any user scanning or advertising. common_hal_bleio_adapter_stop_scan(&common_hal_bleio_adapter_obj); @@ -36,7 +40,6 @@ void bleio_user_reset() { // Turn off BLE on a reset or reload. void bleio_reset() { // Set this explicitly to save data. - common_hal_bleio_adapter_obj.base.type = &bleio_adapter_type; if (!common_hal_bleio_adapter_get_enabled(&common_hal_bleio_adapter_obj)) { return; } @@ -52,7 +55,26 @@ void bleio_reset() { // It currently only has properties and no state. Inited by bleio_reset bleio_adapter_obj_t common_hal_bleio_adapter_obj; -void bleio_background(void) { +void bleio_background(void *data) { + (void)data; + supervisor_bluetooth_background(); +} + +void common_hal_bleio_init(void) { + common_hal_bleio_adapter_obj.base.type = &bleio_adapter_type; + + esp_err_t err = nvs_flash_init(); + if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { + // NVS partition was truncated and needs to be erased + // Retry nvs_flash_init + ESP_ERROR_CHECK(nvs_flash_erase()); + err = nvs_flash_init(); + } + ESP_ERROR_CHECK(err); + + + bleio_background_callback.fun = bleio_background; + bleio_background_callback.data = NULL; } void common_hal_bleio_gc_collect(void) { @@ -77,7 +99,7 @@ void check_nimble_error(int rc, const char *file, size_t line) { mp_raise_ConnectionError(MP_ERROR_TEXT("Not connected")); return; default: - #if CIRCUITPY_VERBOSE_BLE + #if CIRCUITPY_VERBOSE_BLE || CIRCUITPY_DEBUG if (file) { mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Unknown system firmware error at %s:%d: %d"), file, line, rc); } @@ -104,7 +126,7 @@ void check_ble_error(int error_code, const char *file, size_t line) { mp_raise_bleio_SecurityError(MP_ERROR_TEXT("Insufficient encryption")); return; default: - #if CIRCUITPY_VERBOSE_BLE + #if CIRCUITPY_VERBOSE_BLE || CIRCUITPY_DEBUG if (file) { mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Unknown BLE error at %s:%d: %d"), file, line, error_code); } diff --git a/ports/espressif/common-hal/_bleio/__init__.h b/ports/espressif/common-hal/_bleio/__init__.h index 146281a9f8dc1..1852bd870a6dc 100644 --- a/ports/espressif/common-hal/_bleio/__init__.h +++ b/ports/espressif/common-hal/_bleio/__init__.h @@ -6,9 +6,13 @@ #pragma once +#include "supervisor/background_callback.h" + #include "freertos/FreeRTOS.h" // IWYU pragma: keep; for BaseType_t -void bleio_background(void); +void bleio_background(void *data); + +extern background_callback_t bleio_background_callback; // typedef struct { // ble_gap_enc_key_t own_enc; diff --git a/ports/espressif/esp-idf b/ports/espressif/esp-idf index 0b28b79fafa75..d58f9ce0b4799 160000 --- a/ports/espressif/esp-idf +++ b/ports/espressif/esp-idf @@ -1 +1 @@ -Subproject commit 0b28b79fafa75d36348d84d9eaccdbcd73220571 +Subproject commit d58f9ce0b4799e63490917b7bfc1300a10bc1f43 diff --git a/ports/espressif/mpconfigport.mk b/ports/espressif/mpconfigport.mk index f9d0260acb8f6..95ff29fc1e23a 100644 --- a/ports/espressif/mpconfigport.mk +++ b/ports/espressif/mpconfigport.mk @@ -201,6 +201,9 @@ CIRCUITPY_GIFIO ?= $(CIRCUITPY_DISPLAYIO) CIRCUITPY_JPEGIO ?= $(CIRCUITPY_DISPLAYIO) CIRCUITPY_QRIO ?= $(CIRCUITPY_ESPCAMERA) +CIRCUITPY_BLE_FILE_SERVICE ?= $(CIRCUITPY_BLEIO) +CIRCUITPY_SERIAL_BLE ?= $(CIRCUITPY_BLEIO) + # Features dependent on other features ifneq ($(CIRCUITPY_USB_DEVICE),0) CIRCUITPY_BUILD_EXTENSIONS ?= bin,uf2 diff --git a/ports/nordic/common-hal/_bleio/Adapter.h b/ports/nordic/common-hal/_bleio/Adapter.h index 5a4a147d32a72..5bc1805d0727c 100644 --- a/ports/nordic/common-hal/_bleio/Adapter.h +++ b/ports/nordic/common-hal/_bleio/Adapter.h @@ -20,6 +20,8 @@ #define BLEIO_TOTAL_CONNECTION_COUNT 5 #endif +#define BLEIO_HANDLE_INVALID BLE_CONN_HANDLE_INVALID + extern bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT]; typedef struct { diff --git a/ports/nordic/common-hal/_bleio/PacketBuffer.c b/ports/nordic/common-hal/_bleio/PacketBuffer.c index 3e0a0a56a4f88..f3058f6c23d9c 100644 --- a/ports/nordic/common-hal/_bleio/PacketBuffer.c +++ b/ports/nordic/common-hal/_bleio/PacketBuffer.c @@ -194,7 +194,7 @@ void _common_hal_bleio_packet_buffer_construct( bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic, uint32_t *incoming_buffer, size_t incoming_buffer_size, uint32_t *outgoing_buffer1, uint32_t *outgoing_buffer2, size_t max_packet_size, - void *static_handler_entry) { + ble_event_handler_t *static_handler_entry) { self->characteristic = characteristic; self->client = self->characteristic->service->is_remote; diff --git a/ports/nordic/common-hal/_bleio/PacketBuffer.h b/ports/nordic/common-hal/_bleio/PacketBuffer.h index c55efd0293b60..a8573b048fa7d 100644 --- a/ports/nordic/common-hal/_bleio/PacketBuffer.h +++ b/ports/nordic/common-hal/_bleio/PacketBuffer.h @@ -11,6 +11,8 @@ #include "py/ringbuf.h" #include "shared-bindings/_bleio/Characteristic.h" +#include "bluetooth/ble_drv.h" + typedef struct { mp_obj_base_t base; bleio_characteristic_obj_t *characteristic; @@ -29,3 +31,5 @@ typedef struct { bool client; bool packet_queued; } bleio_packet_buffer_obj_t; + +typedef ble_drv_evt_handler_entry_t ble_event_handler_t; diff --git a/ports/nordic/common-hal/_bleio/__init__.c b/ports/nordic/common-hal/_bleio/__init__.c index 33e12eb3680fa..705bc14539536 100644 --- a/ports/nordic/common-hal/_bleio/__init__.c +++ b/ports/nordic/common-hal/_bleio/__init__.c @@ -74,6 +74,9 @@ void check_sec_status(uint8_t sec_status) { } } +void common_hal_bleio_init(void) { +} + void bleio_user_reset() { // Stop any user scanning or advertising. common_hal_bleio_adapter_stop_scan(&common_hal_bleio_adapter_obj); diff --git a/ports/silabs/common-hal/_bleio/PacketBuffer.c b/ports/silabs/common-hal/_bleio/PacketBuffer.c index 96a7462f6c4ed..6cb3e58121cbb 100644 --- a/ports/silabs/common-hal/_bleio/PacketBuffer.c +++ b/ports/silabs/common-hal/_bleio/PacketBuffer.c @@ -145,7 +145,7 @@ void _common_hal_bleio_packet_buffer_construct( uint32_t *outgoing_buffer1, uint32_t *outgoing_buffer2, size_t max_packet_size, - void *static_handler_entry) { + ble_event_handler_t static_handler_entry) { bleio_characteristic_properties_t temp_prop; self->characteristic = characteristic; diff --git a/ports/silabs/common-hal/_bleio/PacketBuffer.h b/ports/silabs/common-hal/_bleio/PacketBuffer.h index f79eda6cf3a6e..c00db915f9465 100644 --- a/ports/silabs/common-hal/_bleio/PacketBuffer.h +++ b/ports/silabs/common-hal/_bleio/PacketBuffer.h @@ -57,6 +57,9 @@ typedef struct { uint8_t len; } bleio_packet_buffer_obj_list_t; +// Unused +typedef void *ble_event_handler_t; + extern bool packet_buffer_on_ble_evt(uint16_t attribute, uint8_t *data, uint16_t len); diff --git a/ports/silabs/common-hal/_bleio/__init__.c b/ports/silabs/common-hal/_bleio/__init__.c index b5d9270af56c3..6191a88904a91 100644 --- a/ports/silabs/common-hal/_bleio/__init__.c +++ b/ports/silabs/common-hal/_bleio/__init__.c @@ -51,6 +51,9 @@ const osMutexAttr_t bluetooth_connection_mutex_attr = { .cb_size = osMutexCbSize }; +void common_hal_bleio_init(void) { +} + void bleio_user_reset() { // Stop any user scanning or advertising. common_hal_bleio_adapter_stop_scan(&common_hal_bleio_adapter_obj); diff --git a/shared-bindings/_bleio/Adapter.h b/shared-bindings/_bleio/Adapter.h index c6b7aeefc9609..0bc6f051ff3f5 100644 --- a/shared-bindings/_bleio/Adapter.h +++ b/shared-bindings/_bleio/Adapter.h @@ -35,6 +35,7 @@ uint16_t bleio_adapter_get_name(char *buf, uint16_t len); extern mp_obj_str_t *common_hal_bleio_adapter_get_name(bleio_adapter_obj_t *self); extern void common_hal_bleio_adapter_set_name(bleio_adapter_obj_t *self, const char *name); +// Returns 0 if ok, otherwise a BLE stack specific error code. extern uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, bool anonymous, uint32_t timeout, float interval, const uint8_t *advertising_data, uint16_t advertising_data_len, diff --git a/shared-bindings/_bleio/PacketBuffer.h b/shared-bindings/_bleio/PacketBuffer.h index 25d7127a67ec5..e9e642e2677e8 100644 --- a/shared-bindings/_bleio/PacketBuffer.h +++ b/shared-bindings/_bleio/PacketBuffer.h @@ -10,15 +10,24 @@ extern const mp_obj_type_t bleio_packet_buffer_type; +// Maximum size of a packet. +#ifdef BLE_GATTS_VAR_ATTR_LEN_MAX +#define BLEIO_PACKET_BUFFER_MAX_PACKET_SIZE BLE_GATTS_VAR_ATTR_LEN_MAX +#else +#define BLEIO_PACKET_BUFFER_MAX_PACKET_SIZE 512 +#endif + void common_hal_bleio_packet_buffer_construct( bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic, size_t buffer_size, size_t max_packet_size); -// Allocation free +// Allocation free version for BLE workflow use. +#if CIRCUITPY_SERIAL_BLE || CIRCUITPY_BLE_FILE_SERVICE void _common_hal_bleio_packet_buffer_construct( bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic, uint32_t *incoming_buffer, size_t incoming_buffer_size, uint32_t *outgoing_buffer1, uint32_t *outgoing_buffer2, size_t outgoing_buffer_size, - void *static_handler_entry); + ble_event_handler_t *static_handler_entry); +#endif mp_int_t common_hal_bleio_packet_buffer_write(bleio_packet_buffer_obj_t *self, const uint8_t *data, size_t len, uint8_t *header, size_t header_len); mp_int_t common_hal_bleio_packet_buffer_readinto(bleio_packet_buffer_obj_t *self, uint8_t *data, size_t len); mp_int_t common_hal_bleio_packet_buffer_get_incoming_packet_length(bleio_packet_buffer_obj_t *self); diff --git a/shared-bindings/_bleio/__init__.c b/shared-bindings/_bleio/__init__.c index 2643a59618a63..c0cd439f7d924 100644 --- a/shared-bindings/_bleio/__init__.c +++ b/shared-bindings/_bleio/__init__.c @@ -82,6 +82,7 @@ NORETURN void mp_raise_bleio_SecurityError(mp_rom_error_text_t fmt, ...) { // Called when _bleio is imported. static mp_obj_t bleio___init__(void) { // HCI cannot be enabled on import, because we need to setup the HCI adapter first. + common_hal_bleio_init(); #if !CIRCUITPY_BLEIO_HCI common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, true); #endif diff --git a/shared-bindings/_bleio/__init__.h b/shared-bindings/_bleio/__init__.h index 0feb538d81d82..faf11ea1d0637 100644 --- a/shared-bindings/_bleio/__init__.h +++ b/shared-bindings/_bleio/__init__.h @@ -39,6 +39,10 @@ void bleio_user_reset(void); // Completely resets the BLE stack including BLE connections. void bleio_reset(void); +// Init any state needed before calling any bleio functions including those +// having to do with bonding. This doesn't enable the BLE adapter though. +void common_hal_bleio_init(void); + extern mp_obj_t bleio_set_adapter(mp_obj_t adapter_obj); NORETURN void mp_raise_bleio_BluetoothError(mp_rom_error_text_t msg, ...); diff --git a/supervisor/shared/bluetooth/bluetooth.c b/supervisor/shared/bluetooth/bluetooth.c index b1b116b9c01f9..877fbc6ef262d 100644 --- a/supervisor/shared/bluetooth/bluetooth.c +++ b/supervisor/shared/bluetooth/bluetooth.c @@ -12,6 +12,7 @@ #include "shared-bindings/_bleio/Adapter.h" #if defined(CIRCUITPY_BOOT_BUTTON) #include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/time/__init__.h" #endif #include "shared-bindings/microcontroller/Processor.h" #include "shared-bindings/microcontroller/ResetReason.h" @@ -28,18 +29,21 @@ #if CIRCUITPY_BLE_FILE_SERVICE #include "supervisor/shared/bluetooth/file_transfer.h" -#include "bluetooth/ble_drv.h" #endif #if CIRCUITPY_SERIAL_BLE #include "supervisor/shared/bluetooth/serial.h" -#include "bluetooth/ble_drv.h" #endif #if CIRCUITPY_STATUS_BAR #include "supervisor/shared/status_bar.h" #endif +#if CIRCUITPY_WEB_WORKFLOW && CIRCUITPY_WIFI && CIRCUITPY_OS_GETENV +#include "shared-module/os/__init__.h" +#endif + + // This standard advertisement advertises the CircuitPython editing service and a CIRCUITPY short name. const uint8_t public_advertising_data[] = { 0x02, 0x01, 0x06, // 0-2 Flags 0x02, 0x0a, 0xec, // 3-5 TX power level -20 @@ -138,7 +142,7 @@ static void supervisor_bluetooth_start_advertising(void) { _private_advertising = true; // Advertise with less power when doing so publicly to reduce who can hear us. This will make it // harder for someone with bad intentions to pair from a distance. - if (!bonded || boot_in_discovery_mode) { + if (!bonded && boot_in_discovery_mode) { tx_power = -20; adv = public_advertising_data; adv_len = sizeof(public_advertising_data); @@ -169,7 +173,7 @@ static void supervisor_bluetooth_start_advertising(void) { tx_power, NULL); // This may fail if we are already advertising. - advertising = status == NRF_SUCCESS; + advertising = status == 0; } #endif // CIRCUITPY_BLE_FILE_SERVICE || CIRCUITPY_SERIAL_BLE @@ -193,26 +197,18 @@ void supervisor_bluetooth_init(void) { return; } + common_hal_bleio_init(); if (ble_mode == 0) { port_set_saved_word(BLE_DISCOVERY_DATA_GUARD | (0x01 << 8)); } // Wait for a while to allow for reset. - #ifdef CIRCUITPY_BOOT_BUTTON - digitalio_digitalinout_obj_t boot_button; - common_hal_digitalio_digitalinout_construct(&boot_button, CIRCUITPY_BOOT_BUTTON); - common_hal_digitalio_digitalinout_switch_to_input(&boot_button, PULL_UP); - #endif #if CIRCUITPY_STATUS_LED status_led_init(); #endif uint64_t start_ticks = supervisor_ticks_ms64(); uint64_t diff = 0; if (ble_mode != 0) { - #ifdef CIRCUITPY_STATUS_LED - new_status_color(0x0000ff); - #endif - common_hal_bleio_adapter_erase_bonding(&common_hal_bleio_adapter_obj); boot_in_discovery_mode = true; reset_state = 0x0; } @@ -221,7 +217,14 @@ void supervisor_bluetooth_init(void) { // Checking here allows us to have the status LED solidly on even if no button was // pressed. bool bonded = common_hal_bleio_adapter_is_bonded_to_central(&common_hal_bleio_adapter_obj); - if (!bonded) { + bool wifi_workflow_active = false; + #if CIRCUITPY_WEB_WORKFLOW && CIRCUITPY_WIFI && CIRCUITPY_OS_GETENV + char _api_password[64]; + const size_t api_password_len = sizeof(_api_password) - 1; + os_getenv_err_t result = common_hal_os_getenv_str("CIRCUITPY_WEB_API_PASSWORD", _api_password + 1, api_password_len); + wifi_workflow_active = result == GETENV_OK; + #endif + if (!bonded && !wifi_workflow_active) { boot_in_discovery_mode = true; } #endif @@ -235,14 +238,23 @@ void supervisor_bluetooth_init(void) { new_status_color(BLACK); } #endif + // Init the boot button every time in case it is used for LEDs. #ifdef CIRCUITPY_BOOT_BUTTON - if (!common_hal_digitalio_digitalinout_get_value(&boot_button)) { + digitalio_digitalinout_obj_t boot_button; + common_hal_digitalio_digitalinout_construct(&boot_button, CIRCUITPY_BOOT_BUTTON); + common_hal_digitalio_digitalinout_switch_to_input(&boot_button, PULL_UP); + common_hal_time_delay_ms(1); + bool button_pressed = !common_hal_digitalio_digitalinout_get_value(&boot_button); + common_hal_digitalio_digitalinout_deinit(&boot_button); + if (button_pressed) { boot_in_discovery_mode = true; - break; } #endif diff = supervisor_ticks_ms64() - start_ticks; } + if (boot_in_discovery_mode) { + common_hal_bleio_adapter_erase_bonding(&common_hal_bleio_adapter_obj); + } #if CIRCUITPY_STATUS_LED new_status_color(BLACK); status_led_deinit(); diff --git a/supervisor/shared/bluetooth/file_transfer.c b/supervisor/shared/bluetooth/file_transfer.c index de21d7e71e95b..aa49c0a899a80 100644 --- a/supervisor/shared/bluetooth/file_transfer.c +++ b/supervisor/shared/bluetooth/file_transfer.c @@ -14,8 +14,6 @@ #include "shared-bindings/_bleio/Service.h" #include "shared-bindings/_bleio/UUID.h" -#include "bluetooth/ble_drv.h" - #include "supervisor/fatfs.h" #include "supervisor/filesystem.h" #include "supervisor/shared/reload.h" @@ -39,9 +37,9 @@ static mp_obj_t characteristic_list_items[2]; #define PACKET_BUFFER_SIZE (2 * 10 + 512 + 12) // uint32_t so its aligned static uint32_t _buffer[PACKET_BUFFER_SIZE / 4 + 1]; -static uint32_t _outgoing1[BLE_GATTS_VAR_ATTR_LEN_MAX / 4]; -static uint32_t _outgoing2[BLE_GATTS_VAR_ATTR_LEN_MAX / 4]; -static ble_drv_evt_handler_entry_t static_handler_entry; +static uint32_t _outgoing1[BLEIO_PACKET_BUFFER_MAX_PACKET_SIZE / 4]; +static uint32_t _outgoing2[BLEIO_PACKET_BUFFER_MAX_PACKET_SIZE / 4]; +static ble_event_handler_t static_handler_entry; static bleio_packet_buffer_obj_t _transfer_packet_buffer; void supervisor_start_bluetooth_file_transfer(void) { @@ -60,6 +58,7 @@ void supervisor_start_bluetooth_file_transfer(void) { // Version number supervisor_ble_version_uuid.base.type = &bleio_uuid_type; common_hal_bleio_uuid_construct(&supervisor_ble_version_uuid, 0x0100, file_transfer_base_uuid); + supervisor_ble_version_characteristic.base.type = &bleio_characteristic_type; common_hal_bleio_characteristic_construct(&supervisor_ble_version_characteristic, &supervisor_ble_service, 0, // handle (for remote only) @@ -81,6 +80,7 @@ void supervisor_start_bluetooth_file_transfer(void) { // Active filename. supervisor_ble_transfer_uuid.base.type = &bleio_uuid_type; common_hal_bleio_uuid_construct(&supervisor_ble_transfer_uuid, 0x0200, file_transfer_base_uuid); + supervisor_ble_transfer_characteristic.base.type = &bleio_characteristic_type; common_hal_bleio_characteristic_construct(&supervisor_ble_transfer_characteristic, &supervisor_ble_service, 0, // handle (for remote only) @@ -88,15 +88,16 @@ void supervisor_start_bluetooth_file_transfer(void) { CHAR_PROP_READ | CHAR_PROP_WRITE_NO_RESPONSE | CHAR_PROP_NOTIFY, SECURITY_MODE_ENC_NO_MITM, SECURITY_MODE_ENC_NO_MITM, - BLE_GATTS_VAR_ATTR_LEN_MAX, // max length + BLEIO_PACKET_BUFFER_MAX_PACKET_SIZE, // max length false, // fixed length - NULL, // no initial valuen + NULL, // no initial value NULL); + _transfer_packet_buffer.base.type = &bleio_packet_buffer_type; _common_hal_bleio_packet_buffer_construct( &_transfer_packet_buffer, &supervisor_ble_transfer_characteristic, _buffer, PACKET_BUFFER_SIZE, - _outgoing1, _outgoing2, BLE_GATTS_VAR_ATTR_LEN_MAX, + _outgoing1, _outgoing2, BLEIO_PACKET_BUFFER_MAX_PACKET_SIZE, &static_handler_entry); } diff --git a/supervisor/shared/bluetooth/serial.c b/supervisor/shared/bluetooth/serial.c index 179bd23cacfb5..3c8ae71eb4828 100644 --- a/supervisor/shared/bluetooth/serial.c +++ b/supervisor/shared/bluetooth/serial.c @@ -36,10 +36,13 @@ const uint8_t circuitpython_base_uuid[16] = {0x6e, 0x68, 0x74, 0x79, 0x50, 0x74, static mp_obj_list_t characteristic_list; static mp_obj_t characteristic_list_items[3]; -static uint32_t _outgoing1[BLE_GATTS_VAR_ATTR_LEN_MAX / 4]; -static uint32_t _outgoing2[BLE_GATTS_VAR_ATTR_LEN_MAX / 4]; -static ble_drv_evt_handler_entry_t rx_static_handler_entry; -static ble_drv_evt_handler_entry_t tx_static_handler_entry; +#if BLEIO_PACKET_BUFFER_MAX_PACKET_SIZE % 4 != 0 +#error "BLEIO_PACKET_BUFFER_MAX_PACKET_SIZE must be a multiple of 4" +#endif +static uint32_t _outgoing1[BLEIO_PACKET_BUFFER_MAX_PACKET_SIZE / 4]; +static uint32_t _outgoing2[BLEIO_PACKET_BUFFER_MAX_PACKET_SIZE / 4]; +static ble_event_handler_t rx_static_handler_entry; +static ble_event_handler_t tx_static_handler_entry; static bleio_packet_buffer_obj_t _tx_packet_buffer; static uint32_t _incoming[64]; static bleio_characteristic_buffer_obj_t _rx_buffer; @@ -64,6 +67,7 @@ void supervisor_start_bluetooth_serial(void) { // RX supervisor_ble_circuitpython_rx_uuid.base.type = &bleio_uuid_type; common_hal_bleio_uuid_construct(&supervisor_ble_circuitpython_rx_uuid, 0x0002, circuitpython_base_uuid); + supervisor_ble_circuitpython_rx_characteristic.base.type = &bleio_characteristic_type; common_hal_bleio_characteristic_construct(&supervisor_ble_circuitpython_rx_characteristic, &supervisor_ble_circuitpython_service, 0, // handle (for remote only) @@ -71,7 +75,7 @@ void supervisor_start_bluetooth_serial(void) { CHAR_PROP_WRITE | CHAR_PROP_WRITE_NO_RESPONSE, SECURITY_MODE_NO_ACCESS, SECURITY_MODE_ENC_NO_MITM, - BLE_GATTS_VAR_ATTR_LEN_MAX, // max length + BLEIO_PACKET_BUFFER_MAX_PACKET_SIZE, // max length false, // fixed length NULL, // no initial value NULL); @@ -79,6 +83,7 @@ void supervisor_start_bluetooth_serial(void) { // TX supervisor_ble_circuitpython_tx_uuid.base.type = &bleio_uuid_type; common_hal_bleio_uuid_construct(&supervisor_ble_circuitpython_tx_uuid, 0x0003, circuitpython_base_uuid); + supervisor_ble_circuitpython_tx_characteristic.base.type = &bleio_characteristic_type; common_hal_bleio_characteristic_construct(&supervisor_ble_circuitpython_tx_characteristic, &supervisor_ble_circuitpython_service, 0, // handle (for remote only) @@ -86,7 +91,7 @@ void supervisor_start_bluetooth_serial(void) { CHAR_PROP_NOTIFY, SECURITY_MODE_ENC_NO_MITM, SECURITY_MODE_NO_ACCESS, - BLE_GATTS_VAR_ATTR_LEN_MAX, // max length + BLEIO_PACKET_BUFFER_MAX_PACKET_SIZE, // max length false, // fixed length NULL, // no initial value NULL); @@ -99,6 +104,7 @@ void supervisor_start_bluetooth_serial(void) { supervisor_ble_circuitpython_version_uuid.base.type = &bleio_uuid_type; common_hal_bleio_uuid_construct(&supervisor_ble_circuitpython_version_uuid, 0x0100, circuitpython_base_uuid); + supervisor_ble_circuitpython_version_characteristic.base.type = &bleio_characteristic_type; common_hal_bleio_characteristic_construct(&supervisor_ble_circuitpython_version_characteristic, &supervisor_ble_circuitpython_service, 0, // handle (for remote only) @@ -115,13 +121,15 @@ void supervisor_start_bluetooth_serial(void) { // Use a PacketBuffer to transmit so that we glom characters to transmit // together and save BLE overhead. + _tx_packet_buffer.base.type = &bleio_packet_buffer_type; _common_hal_bleio_packet_buffer_construct( &_tx_packet_buffer, &supervisor_ble_circuitpython_tx_characteristic, NULL, 0, - _outgoing1, _outgoing2, BLE_GATTS_VAR_ATTR_LEN_MAX, + _outgoing1, _outgoing2, BLEIO_PACKET_BUFFER_MAX_PACKET_SIZE, &tx_static_handler_entry); // Use a CharacteristicBuffer for rx so we can read a single character at a time. + _rx_buffer.base.type = &bleio_characteristic_buffer_type; _common_hal_bleio_characteristic_buffer_construct(&_rx_buffer, &supervisor_ble_circuitpython_rx_characteristic, 0.1f, @@ -143,7 +151,7 @@ void supervisor_stop_bluetooth_serial(void) { } bool ble_serial_connected(void) { - return _tx_packet_buffer.conn_handle != BLE_CONN_HANDLE_INVALID; + return _tx_packet_buffer.conn_handle != BLEIO_HANDLE_INVALID; } uint32_t ble_serial_available(void) { diff --git a/supervisor/shared/safe_mode.c b/supervisor/shared/safe_mode.c index 81bcb749143de..30e5a23729bad 100644 --- a/supervisor/shared/safe_mode.c +++ b/supervisor/shared/safe_mode.c @@ -10,6 +10,7 @@ #if defined(CIRCUITPY_BOOT_BUTTON) #include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/time/__init__.h" #endif #include "shared-bindings/microcontroller/Processor.h" #include "shared-bindings/microcontroller/ResetReason.h" @@ -64,11 +65,6 @@ safe_mode_t wait_for_safe_mode_reset(void) { #if CIRCUITPY_STATUS_LED status_led_init(); #endif - #ifdef CIRCUITPY_BOOT_BUTTON - digitalio_digitalinout_obj_t boot_button; - common_hal_digitalio_digitalinout_construct(&boot_button, CIRCUITPY_BOOT_BUTTON); - common_hal_digitalio_digitalinout_switch_to_input(&boot_button, PULL_UP); - #endif uint64_t start_ticks = supervisor_ticks_ms64(); uint64_t diff = 0; bool boot_in_safe_mode = false; @@ -82,8 +78,15 @@ safe_mode_t wait_for_safe_mode_reset(void) { new_status_color(BLACK); } #endif + // Init the boot button every time in case it is used for LEDs. #ifdef CIRCUITPY_BOOT_BUTTON - if (!common_hal_digitalio_digitalinout_get_value(&boot_button)) { + digitalio_digitalinout_obj_t boot_button; + common_hal_digitalio_digitalinout_construct(&boot_button, CIRCUITPY_BOOT_BUTTON); + common_hal_digitalio_digitalinout_switch_to_input(&boot_button, PULL_UP); + common_hal_time_delay_ms(1); + bool button_pressed = !common_hal_digitalio_digitalinout_get_value(&boot_button); + common_hal_digitalio_digitalinout_deinit(&boot_button); + if (button_pressed) { boot_in_safe_mode = true; break; }