Improve ESP BLE and turn on BLE workflow

The BLE workflow will broadcast publicly when the web workflow
isn't activated.
This commit is contained in:
Scott Shawcroft 2024-06-04 12:16:08 -07:00
parent c6da0a4833
commit 63aeb11d7e
No known key found for this signature in database
GPG key ID: 0DFD512649C052DA
25 changed files with 242 additions and 81 deletions

2
.gitmodules vendored
View file

@ -143,7 +143,7 @@
[submodule "ports/espressif/esp-idf"] [submodule "ports/espressif/esp-idf"]
path = ports/espressif/esp-idf path = ports/espressif/esp-idf
url = https://github.com/adafruit/esp-idf.git url = https://github.com/adafruit/esp-idf.git
branch = circuitpython-v5.1.3 branch = circuitpython-v5.2.2
[submodule "ports/espressif/esp-protocols"] [submodule "ports/espressif/esp-protocols"]
path = ports/espressif/esp-protocols path = ports/espressif/esp-protocols
url = https://github.com/espressif/esp-protocols.git url = https://github.com/espressif/esp-protocols.git

View file

@ -113,7 +113,7 @@ msgstr ""
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
#: ports/raspberrypi/common-hal/usb_host/Port.c #: ports/raspberrypi/common-hal/usb_host/Port.c
#: shared-bindings/digitalio/DigitalInOut.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" msgid "%q in use"
msgstr "" msgstr ""
@ -1114,10 +1114,12 @@ msgstr ""
msgid "Input/output error" msgid "Input/output error"
msgstr "" msgstr ""
#: ports/espressif/common-hal/_bleio/__init__.c
#: ports/nordic/common-hal/_bleio/__init__.c #: ports/nordic/common-hal/_bleio/__init__.c
msgid "Insufficient authentication" msgid "Insufficient authentication"
msgstr "" msgstr ""
#: ports/espressif/common-hal/_bleio/__init__.c
#: ports/nordic/common-hal/_bleio/__init__.c #: ports/nordic/common-hal/_bleio/__init__.c
msgid "Insufficient encryption" msgid "Insufficient encryption"
msgstr "" msgstr ""
@ -1154,6 +1156,7 @@ msgstr ""
#: ports/atmel-samd/common-hal/alarm/pin/PinAlarm.c #: ports/atmel-samd/common-hal/alarm/pin/PinAlarm.c
#: ports/atmel-samd/common-hal/countio/Counter.c #: ports/atmel-samd/common-hal/countio/Counter.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.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/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c #: ports/atmel-samd/common-hal/pulseio/PulseIn.c
#: ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c #: ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c
@ -1285,6 +1288,10 @@ msgstr ""
msgid "MAC address was invalid" msgid "MAC address was invalid"
msgstr "" msgstr ""
#: ports/espressif/common-hal/_bleio/Characteristic.c
msgid "MITM security not supported"
msgstr ""
#: shared-bindings/is31fl3741/IS31FL3741.c #: shared-bindings/is31fl3741/IS31FL3741.c
msgid "Mapping must be a tuple" msgid "Mapping must be a tuple"
msgstr "" msgstr ""
@ -2139,6 +2146,7 @@ msgstr ""
msgid "Unknown BLE error: %d" msgid "Unknown BLE error: %d"
msgstr "" msgstr ""
#: ports/espressif/common-hal/max3421e/Max3421E.c
#: ports/raspberrypi/common-hal/wifi/__init__.c #: ports/raspberrypi/common-hal/wifi/__init__.c
#, c-format #, c-format
msgid "Unknown error code %d" msgid "Unknown error code %d"
@ -3810,7 +3818,7 @@ msgstr ""
msgid "pop from empty %q" msgid "pop from empty %q"
msgstr "" msgstr ""
#: shared-bindings/socketpool/Socket.c shared-bindings/ssl/SSLSocket.c #: shared-bindings/socketpool/Socket.c
msgid "port must be >= 0" msgid "port must be >= 0"
msgstr "" msgstr ""

10
main.c
View file

@ -1006,10 +1006,6 @@ int __attribute__((used)) main(void) {
supervisor_status_bar_init(); supervisor_status_bar_init();
#endif #endif
#if CIRCUITPY_BLEIO
// Early init so that a reset press can cause BLE public advertising.
supervisor_bluetooth_init();
#endif
#if !INTERNAL_FLASH_FILESYSTEM #if !INTERNAL_FLASH_FILESYSTEM
// Set up anything that might need to get done before we try to use SPI flash // 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); 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 #if CIRCUITPY_ALARM
// Record which alarm woke us up, if any. // Record which alarm woke us up, if any.
// common_hal_alarm_record_wake_alarm() should return a static, non-heap object // common_hal_alarm_record_wake_alarm() should return a static, non-heap object

View file

@ -229,11 +229,13 @@ LDFLAGS += \
-Tesp32c6.rom.newlib.ld \ -Tesp32c6.rom.newlib.ld \
-Tesp32c6.rom.coexist.ld \ -Tesp32c6.rom.coexist.ld \
-Tesp32c6.rom.heap.ld \ -Tesp32c6.rom.heap.ld \
-Tesp32c6.rom.systimer.ld \
-Tesp32c6.rom.wdt.ld -Tesp32c6.rom.wdt.ld
else ifeq ($(IDF_TARGET),esp32h2) else ifeq ($(IDF_TARGET),esp32h2)
LDFLAGS += \ LDFLAGS += \
-Tesp32h2.rom.heap.ld \ -Tesp32h2.rom.heap.ld \
-Tesp32h2.rom.newlib.ld \ -Tesp32h2.rom.newlib.ld \
-Tesp32h2.rom.systimer.ld \
-Tesp32h2.rom.wdt.ld -Tesp32h2.rom.wdt.ld
else ifeq ($(IDF_TARGET),esp32s2) else ifeq ($(IDF_TARGET),esp32s2)
LDFLAGS += \ LDFLAGS += \

View file

@ -11,7 +11,9 @@
#define MICROPY_HW_BOARD_NAME "Adafruit Feather ESP32-C6 4MB Flash No PSRAM" #define MICROPY_HW_BOARD_NAME "Adafruit Feather ESP32-C6 4MB Flash No PSRAM"
#define MICROPY_HW_MCU_NAME "ESP32C6" #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) #define MICROPY_HW_LED_STATUS (&pin_GPIO15)

View file

@ -39,6 +39,7 @@
#include "common-hal/_bleio/Connection.h" #include "common-hal/_bleio/Connection.h"
#include "esp_bt.h" #include "esp_bt.h"
#include "esp_mac.h"
#include "esp_nimble_hci.h" #include "esp_nimble_hci.h"
#include "nvs_flash.h" #include "nvs_flash.h"
@ -48,11 +49,6 @@
bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT]; 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; bool ble_active = false;
static void nimble_host_task(void *param) { 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 TaskHandle_t cp_task = NULL;
static void _on_sync(void) { static void _on_sync(void) {
int rc = ble_hs_util_ensure_addr(0); int rc = ble_hs_util_ensure_addr(false);
assert(rc == 0); assert(rc == 0);
xTaskNotifyGive(cp_task); xTaskNotifyGive(cp_task);
@ -72,6 +68,8 @@ static void _on_sync(void) {
// All examples have this. It'd make sense in a header. // All examples have this. It'd make sense in a header.
void ble_store_config_init(void); 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) { 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); 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) { 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()); CHECK_ESP_RESULT(nimble_port_init());
// ble_hs_cfg.reset_cb = blecent_on_reset; // 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_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_their_key_dist |= BLE_SM_PAIR_KEY_DIST_ENC;
ble_hs_cfg.sm_mitm = 1; ble_hs_cfg.sm_mitm = 0;
ble_hs_cfg.sm_sc = 1; ble_hs_cfg.sm_sc = 0;
/* Stores the IRK */ /* Stores the IRK */
ble_hs_cfg.sm_our_key_dist |= BLE_SM_PAIR_KEY_DIST_ID; 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; 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 } else
#endif #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. // 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; 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) { mp_obj_str_t *common_hal_bleio_adapter_get_name(bleio_adapter_obj_t *self) {
const char *name = ble_svc_gap_device_name(); const char *name = ble_svc_gap_device_name();
@ -487,6 +494,7 @@ static int _advertising_event(struct ble_gap_event *event, void *self_in) {
#endif #endif
break; break;
} }
background_callback_add_core(&bleio_background_callback);
return 0; return 0;
} }
@ -499,6 +507,8 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
if (ble_gap_adv_active() && !self->user_advertising) { if (ble_gap_adv_active() && !self->user_advertising) {
return BLE_HS_EBUSY; return BLE_HS_EBUSY;
} }
// Override anonymous because it isn't working with the ESP-IDF.
anonymous = false;
uint32_t rc; uint32_t rc;
@ -521,12 +531,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 || bool extended = advertising_data_len > BLE_ADV_LEGACY_DATA_MAX_LEN ||
scan_response_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 = { struct ble_gap_ext_adv_params adv_params = {
.connectable = connectable, .connectable = connectable,
.scannable = scan_response_data_len > 0, .scannable = scannable,
.directed = directed_to != NULL, .directed = directed_to != NULL,
.high_duty_directed = high_duty_directed, .high_duty_directed = high_duty_directed,
.legacy_pdu = !extended, .legacy_pdu = legacy_pdu,
.anonymous = anonymous, .anonymous = anonymous,
.include_tx_power = extended, .include_tx_power = extended,
.scan_req_notif = false, .scan_req_notif = false,
@ -712,14 +729,46 @@ mp_obj_t common_hal_bleio_adapter_get_connections(bleio_adapter_obj_t *self) {
return self->connection_objs; 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) { void common_hal_bleio_adapter_erase_bonding(bleio_adapter_obj_t *self) {
if (common_hal_bleio_adapter_get_enabled(self)) {
ble_store_clear(); 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) { bool common_hal_bleio_adapter_is_bonded_to_central(bleio_adapter_obj_t *self) {
if (common_hal_bleio_adapter_get_enabled(self)) {
int count; int count;
ble_store_util_count(BLE_STORE_OBJ_TYPE_PEER_SEC, &count); ble_store_util_count(BLE_STORE_OBJ_TYPE_PEER_SEC, &count);
return count > 0; 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) { void bleio_adapter_gc_collect(bleio_adapter_obj_t *adapter) {

View file

@ -17,7 +17,6 @@
#include "common-hal/_bleio/Adapter.h" #include "common-hal/_bleio/Adapter.h"
#include "common-hal/_bleio/Service.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); 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) { if ((props & CHAR_PROP_WRITE_NO_RESPONSE) != 0) {
self->flags |= BLE_GATT_CHR_F_WRITE_NO_RSP; 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) { 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 // 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; self->current_value = initial_value_bufinfo->buf;
assert(self->current_value_len == max_length); 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()) { 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); 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 rc;
} }
return BLE_ATT_ERR_UNLIKELY; return BLE_ATT_ERR_UNLIKELY;

View file

@ -91,14 +91,18 @@ int bleio_connection_event_cb(struct ble_gap_event *event, void *connection_in)
case BLE_GAP_EVENT_NOTIFY_TX: case BLE_GAP_EVENT_NOTIFY_TX:
MP_FALLTHROUGH; MP_FALLTHROUGH;
case BLE_GAP_EVENT_SUBSCRIBE: 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: default:
#if CIRCUITPY_VERBOSE_BLE #if CIRCUITPY_VERBOSE_BLE
mp_printf(&mp_plat_print, "Unhandled connection event: %d\n", event->type); mp_printf(&mp_plat_print, "Unhandled connection event: %d\n", event->type);
#endif #endif
return 0; break;
} }
background_callback_add_core(&bleio_background_callback);
return 0; return 0;
} }

View file

@ -157,7 +157,7 @@ void _common_hal_bleio_packet_buffer_construct(
bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic, bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic,
uint32_t *incoming_buffer, size_t incoming_buffer_size, uint32_t *incoming_buffer, size_t incoming_buffer_size,
uint32_t *outgoing_buffer1, uint32_t *outgoing_buffer2, size_t max_packet_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->characteristic = characteristic;
self->client = self->characteristic->service->is_remote; self->client = self->characteristic->service->is_remote;
self->max_packet_size = max_packet_size; self->max_packet_size = max_packet_size;

View file

@ -8,6 +8,7 @@
#include "py/ringbuf.h" #include "py/ringbuf.h"
#include "shared-bindings/_bleio/Characteristic.h" #include "shared-bindings/_bleio/Characteristic.h"
#include "common-hal/_bleio/ble_events.h"
typedef struct { typedef struct {
mp_obj_base_t base; mp_obj_base_t base;
@ -28,4 +29,6 @@ typedef struct {
bool packet_queued; bool packet_queued;
} bleio_packet_buffer_obj_t; } 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); void bleio_packet_buffer_extend(bleio_packet_buffer_obj_t *self, uint16_t conn_handle, const uint8_t *buffer, size_t len);

View file

@ -19,9 +19,13 @@
#include "supervisor/shared/bluetooth/bluetooth.h" #include "supervisor/shared/bluetooth/bluetooth.h"
#include "common-hal/_bleio/__init__.h" #include "common-hal/_bleio/__init__.h"
// #include "common-hal/_bleio/bonding.h"
#include "common-hal/_bleio/ble_events.h" #include "common-hal/_bleio/ble_events.h"
#include "nvs_flash.h"
background_callback_t bleio_background_callback;
void bleio_user_reset() { void bleio_user_reset() {
// Stop any user scanning or advertising. // Stop any user scanning or advertising.
common_hal_bleio_adapter_stop_scan(&common_hal_bleio_adapter_obj); 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. // Turn off BLE on a reset or reload.
void bleio_reset() { void bleio_reset() {
// Set this explicitly to save data. // 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)) { if (!common_hal_bleio_adapter_get_enabled(&common_hal_bleio_adapter_obj)) {
return; return;
} }
@ -52,7 +55,26 @@ void bleio_reset() {
// It currently only has properties and no state. Inited by bleio_reset // It currently only has properties and no state. Inited by bleio_reset
bleio_adapter_obj_t common_hal_bleio_adapter_obj; 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) { void common_hal_bleio_gc_collect(void) {

View file

@ -6,9 +6,13 @@
#pragma once #pragma once
#include "supervisor/background_callback.h"
#include "freertos/FreeRTOS.h" // IWYU pragma: keep; for BaseType_t #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 { // typedef struct {
// ble_gap_enc_key_t own_enc; // ble_gap_enc_key_t own_enc;

@ -1 +1 @@
Subproject commit 0b28b79fafa75d36348d84d9eaccdbcd73220571 Subproject commit d58f9ce0b4799e63490917b7bfc1300a10bc1f43

View file

@ -201,6 +201,9 @@ CIRCUITPY_GIFIO ?= $(CIRCUITPY_DISPLAYIO)
CIRCUITPY_JPEGIO ?= $(CIRCUITPY_DISPLAYIO) CIRCUITPY_JPEGIO ?= $(CIRCUITPY_DISPLAYIO)
CIRCUITPY_QRIO ?= $(CIRCUITPY_ESPCAMERA) CIRCUITPY_QRIO ?= $(CIRCUITPY_ESPCAMERA)
CIRCUITPY_BLE_FILE_SERVICE ?= $(CIRCUITPY_BLEIO)
CIRCUITPY_SERIAL_BLE ?= $(CIRCUITPY_BLEIO)
# Features dependent on other features # Features dependent on other features
ifneq ($(CIRCUITPY_USB_DEVICE),0) ifneq ($(CIRCUITPY_USB_DEVICE),0)
CIRCUITPY_BUILD_EXTENSIONS ?= bin,uf2 CIRCUITPY_BUILD_EXTENSIONS ?= bin,uf2

View file

@ -20,6 +20,8 @@
#define BLEIO_TOTAL_CONNECTION_COUNT 5 #define BLEIO_TOTAL_CONNECTION_COUNT 5
#endif #endif
#define BLEIO_HANDLE_INVALID BLE_CONN_HANDLE_INVALID
extern bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT]; extern bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT];
typedef struct { typedef struct {

View file

@ -194,7 +194,7 @@ void _common_hal_bleio_packet_buffer_construct(
bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic, bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic,
uint32_t *incoming_buffer, size_t incoming_buffer_size, uint32_t *incoming_buffer, size_t incoming_buffer_size,
uint32_t *outgoing_buffer1, uint32_t *outgoing_buffer2, size_t max_packet_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->characteristic = characteristic;
self->client = self->characteristic->service->is_remote; self->client = self->characteristic->service->is_remote;

View file

@ -11,6 +11,8 @@
#include "py/ringbuf.h" #include "py/ringbuf.h"
#include "shared-bindings/_bleio/Characteristic.h" #include "shared-bindings/_bleio/Characteristic.h"
#include "bluetooth/ble_drv.h"
typedef struct { typedef struct {
mp_obj_base_t base; mp_obj_base_t base;
bleio_characteristic_obj_t *characteristic; bleio_characteristic_obj_t *characteristic;
@ -29,3 +31,5 @@ typedef struct {
bool client; bool client;
bool packet_queued; bool packet_queued;
} bleio_packet_buffer_obj_t; } bleio_packet_buffer_obj_t;
typedef ble_drv_evt_handler_entry_t ble_event_handler_t;

View file

@ -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 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); 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, extern uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
bool connectable, bool anonymous, uint32_t timeout, float interval, bool connectable, bool anonymous, uint32_t timeout, float interval,
const uint8_t *advertising_data, uint16_t advertising_data_len, const uint8_t *advertising_data, uint16_t advertising_data_len,

View file

@ -10,6 +10,13 @@
extern const mp_obj_type_t bleio_packet_buffer_type; 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( void common_hal_bleio_packet_buffer_construct(
bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic, bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic,
size_t buffer_size, size_t max_packet_size); size_t buffer_size, size_t max_packet_size);
@ -18,7 +25,7 @@ void _common_hal_bleio_packet_buffer_construct(
bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic, bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic,
uint32_t *incoming_buffer, size_t incoming_buffer_size, uint32_t *incoming_buffer, size_t incoming_buffer_size,
uint32_t *outgoing_buffer1, uint32_t *outgoing_buffer2, size_t outgoing_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);
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_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_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); mp_int_t common_hal_bleio_packet_buffer_get_incoming_packet_length(bleio_packet_buffer_obj_t *self);

View file

@ -82,6 +82,7 @@ NORETURN void mp_raise_bleio_SecurityError(mp_rom_error_text_t fmt, ...) {
// Called when _bleio is imported. // Called when _bleio is imported.
static mp_obj_t bleio___init__(void) { static mp_obj_t bleio___init__(void) {
// HCI cannot be enabled on import, because we need to setup the HCI adapter first. // HCI cannot be enabled on import, because we need to setup the HCI adapter first.
common_hal_bleio_init();
#if !CIRCUITPY_BLEIO_HCI #if !CIRCUITPY_BLEIO_HCI
common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, true); common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, true);
#endif #endif

View file

@ -39,6 +39,10 @@ void bleio_user_reset(void);
// Completely resets the BLE stack including BLE connections. // Completely resets the BLE stack including BLE connections.
void bleio_reset(void); 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); extern mp_obj_t bleio_set_adapter(mp_obj_t adapter_obj);
NORETURN void mp_raise_bleio_BluetoothError(mp_rom_error_text_t msg, ...); NORETURN void mp_raise_bleio_BluetoothError(mp_rom_error_text_t msg, ...);

View file

@ -12,6 +12,7 @@
#include "shared-bindings/_bleio/Adapter.h" #include "shared-bindings/_bleio/Adapter.h"
#if defined(CIRCUITPY_BOOT_BUTTON) #if defined(CIRCUITPY_BOOT_BUTTON)
#include "shared-bindings/digitalio/DigitalInOut.h" #include "shared-bindings/digitalio/DigitalInOut.h"
#include "shared-bindings/time/__init__.h"
#endif #endif
#include "shared-bindings/microcontroller/Processor.h" #include "shared-bindings/microcontroller/Processor.h"
#include "shared-bindings/microcontroller/ResetReason.h" #include "shared-bindings/microcontroller/ResetReason.h"
@ -28,18 +29,21 @@
#if CIRCUITPY_BLE_FILE_SERVICE #if CIRCUITPY_BLE_FILE_SERVICE
#include "supervisor/shared/bluetooth/file_transfer.h" #include "supervisor/shared/bluetooth/file_transfer.h"
#include "bluetooth/ble_drv.h"
#endif #endif
#if CIRCUITPY_SERIAL_BLE #if CIRCUITPY_SERIAL_BLE
#include "supervisor/shared/bluetooth/serial.h" #include "supervisor/shared/bluetooth/serial.h"
#include "bluetooth/ble_drv.h"
#endif #endif
#if CIRCUITPY_STATUS_BAR #if CIRCUITPY_STATUS_BAR
#include "supervisor/shared/status_bar.h" #include "supervisor/shared/status_bar.h"
#endif #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. // 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 const uint8_t public_advertising_data[] = { 0x02, 0x01, 0x06, // 0-2 Flags
0x02, 0x0a, 0xec, // 3-5 TX power level -20 0x02, 0x0a, 0xec, // 3-5 TX power level -20
@ -138,7 +142,7 @@ static void supervisor_bluetooth_start_advertising(void) {
_private_advertising = true; _private_advertising = true;
// Advertise with less power when doing so publicly to reduce who can hear us. This will make it // 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. // 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; tx_power = -20;
adv = public_advertising_data; adv = public_advertising_data;
adv_len = sizeof(public_advertising_data); adv_len = sizeof(public_advertising_data);
@ -169,7 +173,7 @@ static void supervisor_bluetooth_start_advertising(void) {
tx_power, tx_power,
NULL); NULL);
// This may fail if we are already advertising. // This may fail if we are already advertising.
advertising = status == NRF_SUCCESS; advertising = status == 0;
} }
#endif // CIRCUITPY_BLE_FILE_SERVICE || CIRCUITPY_SERIAL_BLE #endif // CIRCUITPY_BLE_FILE_SERVICE || CIRCUITPY_SERIAL_BLE
@ -193,26 +197,18 @@ void supervisor_bluetooth_init(void) {
return; return;
} }
common_hal_bleio_init();
if (ble_mode == 0) { if (ble_mode == 0) {
port_set_saved_word(BLE_DISCOVERY_DATA_GUARD | (0x01 << 8)); port_set_saved_word(BLE_DISCOVERY_DATA_GUARD | (0x01 << 8));
} }
// Wait for a while to allow for reset. // 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 #if CIRCUITPY_STATUS_LED
status_led_init(); status_led_init();
#endif #endif
uint64_t start_ticks = supervisor_ticks_ms64(); uint64_t start_ticks = supervisor_ticks_ms64();
uint64_t diff = 0; uint64_t diff = 0;
if (ble_mode != 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; boot_in_discovery_mode = true;
reset_state = 0x0; 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 // Checking here allows us to have the status LED solidly on even if no button was
// pressed. // pressed.
bool bonded = common_hal_bleio_adapter_is_bonded_to_central(&common_hal_bleio_adapter_obj); 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; boot_in_discovery_mode = true;
} }
#endif #endif
@ -235,14 +238,23 @@ void supervisor_bluetooth_init(void) {
new_status_color(BLACK); new_status_color(BLACK);
} }
#endif #endif
// Init the boot button every time in case it is used for LEDs.
#ifdef CIRCUITPY_BOOT_BUTTON #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; boot_in_discovery_mode = true;
break;
} }
#endif #endif
diff = supervisor_ticks_ms64() - start_ticks; 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 #if CIRCUITPY_STATUS_LED
new_status_color(BLACK); new_status_color(BLACK);
status_led_deinit(); status_led_deinit();

View file

@ -14,8 +14,6 @@
#include "shared-bindings/_bleio/Service.h" #include "shared-bindings/_bleio/Service.h"
#include "shared-bindings/_bleio/UUID.h" #include "shared-bindings/_bleio/UUID.h"
#include "bluetooth/ble_drv.h"
#include "supervisor/fatfs.h" #include "supervisor/fatfs.h"
#include "supervisor/filesystem.h" #include "supervisor/filesystem.h"
#include "supervisor/shared/reload.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) #define PACKET_BUFFER_SIZE (2 * 10 + 512 + 12)
// uint32_t so its aligned // uint32_t so its aligned
static uint32_t _buffer[PACKET_BUFFER_SIZE / 4 + 1]; static uint32_t _buffer[PACKET_BUFFER_SIZE / 4 + 1];
static uint32_t _outgoing1[BLE_GATTS_VAR_ATTR_LEN_MAX / 4]; static uint32_t _outgoing1[BLEIO_PACKET_BUFFER_MAX_PACKET_SIZE / 4];
static uint32_t _outgoing2[BLE_GATTS_VAR_ATTR_LEN_MAX / 4]; static uint32_t _outgoing2[BLEIO_PACKET_BUFFER_MAX_PACKET_SIZE / 4];
static ble_drv_evt_handler_entry_t static_handler_entry; static ble_event_handler_t static_handler_entry;
static bleio_packet_buffer_obj_t _transfer_packet_buffer; static bleio_packet_buffer_obj_t _transfer_packet_buffer;
void supervisor_start_bluetooth_file_transfer(void) { void supervisor_start_bluetooth_file_transfer(void) {
@ -60,6 +58,7 @@ void supervisor_start_bluetooth_file_transfer(void) {
// Version number // Version number
supervisor_ble_version_uuid.base.type = &bleio_uuid_type; supervisor_ble_version_uuid.base.type = &bleio_uuid_type;
common_hal_bleio_uuid_construct(&supervisor_ble_version_uuid, 0x0100, file_transfer_base_uuid); 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, common_hal_bleio_characteristic_construct(&supervisor_ble_version_characteristic,
&supervisor_ble_service, &supervisor_ble_service,
0, // handle (for remote only) 0, // handle (for remote only)
@ -81,6 +80,7 @@ void supervisor_start_bluetooth_file_transfer(void) {
// Active filename. // Active filename.
supervisor_ble_transfer_uuid.base.type = &bleio_uuid_type; supervisor_ble_transfer_uuid.base.type = &bleio_uuid_type;
common_hal_bleio_uuid_construct(&supervisor_ble_transfer_uuid, 0x0200, file_transfer_base_uuid); 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, common_hal_bleio_characteristic_construct(&supervisor_ble_transfer_characteristic,
&supervisor_ble_service, &supervisor_ble_service,
0, // handle (for remote only) 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, CHAR_PROP_READ | CHAR_PROP_WRITE_NO_RESPONSE | CHAR_PROP_NOTIFY,
SECURITY_MODE_ENC_NO_MITM, SECURITY_MODE_ENC_NO_MITM,
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 false, // fixed length
NULL, // no initial valuen NULL, // no initial value
NULL); NULL);
_transfer_packet_buffer.base.type = &bleio_packet_buffer_type;
_common_hal_bleio_packet_buffer_construct( _common_hal_bleio_packet_buffer_construct(
&_transfer_packet_buffer, &supervisor_ble_transfer_characteristic, &_transfer_packet_buffer, &supervisor_ble_transfer_characteristic,
_buffer, PACKET_BUFFER_SIZE, _buffer, PACKET_BUFFER_SIZE,
_outgoing1, _outgoing2, BLE_GATTS_VAR_ATTR_LEN_MAX, _outgoing1, _outgoing2, BLEIO_PACKET_BUFFER_MAX_PACKET_SIZE,
&static_handler_entry); &static_handler_entry);
} }

View file

@ -36,10 +36,10 @@ const uint8_t circuitpython_base_uuid[16] = {0x6e, 0x68, 0x74, 0x79, 0x50, 0x74,
static mp_obj_list_t characteristic_list; static mp_obj_list_t characteristic_list;
static mp_obj_t characteristic_list_items[3]; static mp_obj_t characteristic_list_items[3];
static uint32_t _outgoing1[BLE_GATTS_VAR_ATTR_LEN_MAX / 4]; static uint32_t _outgoing1[BLEIO_PACKET_BUFFER_MAX_PACKET_SIZE / 4];
static uint32_t _outgoing2[BLE_GATTS_VAR_ATTR_LEN_MAX / 4]; static uint32_t _outgoing2[BLEIO_PACKET_BUFFER_MAX_PACKET_SIZE / 4];
static ble_drv_evt_handler_entry_t rx_static_handler_entry; static ble_event_handler_t rx_static_handler_entry;
static ble_drv_evt_handler_entry_t tx_static_handler_entry; static ble_event_handler_t tx_static_handler_entry;
static bleio_packet_buffer_obj_t _tx_packet_buffer; static bleio_packet_buffer_obj_t _tx_packet_buffer;
static uint32_t _incoming[64]; static uint32_t _incoming[64];
static bleio_characteristic_buffer_obj_t _rx_buffer; static bleio_characteristic_buffer_obj_t _rx_buffer;
@ -64,6 +64,7 @@ void supervisor_start_bluetooth_serial(void) {
// RX // RX
supervisor_ble_circuitpython_rx_uuid.base.type = &bleio_uuid_type; supervisor_ble_circuitpython_rx_uuid.base.type = &bleio_uuid_type;
common_hal_bleio_uuid_construct(&supervisor_ble_circuitpython_rx_uuid, 0x0002, circuitpython_base_uuid); 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, common_hal_bleio_characteristic_construct(&supervisor_ble_circuitpython_rx_characteristic,
&supervisor_ble_circuitpython_service, &supervisor_ble_circuitpython_service,
0, // handle (for remote only) 0, // handle (for remote only)
@ -71,7 +72,7 @@ void supervisor_start_bluetooth_serial(void) {
CHAR_PROP_WRITE | CHAR_PROP_WRITE_NO_RESPONSE, CHAR_PROP_WRITE | CHAR_PROP_WRITE_NO_RESPONSE,
SECURITY_MODE_NO_ACCESS, SECURITY_MODE_NO_ACCESS,
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 false, // fixed length
NULL, // no initial value NULL, // no initial value
NULL); NULL);
@ -79,6 +80,7 @@ void supervisor_start_bluetooth_serial(void) {
// TX // TX
supervisor_ble_circuitpython_tx_uuid.base.type = &bleio_uuid_type; supervisor_ble_circuitpython_tx_uuid.base.type = &bleio_uuid_type;
common_hal_bleio_uuid_construct(&supervisor_ble_circuitpython_tx_uuid, 0x0003, circuitpython_base_uuid); 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, common_hal_bleio_characteristic_construct(&supervisor_ble_circuitpython_tx_characteristic,
&supervisor_ble_circuitpython_service, &supervisor_ble_circuitpython_service,
0, // handle (for remote only) 0, // handle (for remote only)
@ -86,7 +88,7 @@ void supervisor_start_bluetooth_serial(void) {
CHAR_PROP_NOTIFY, CHAR_PROP_NOTIFY,
SECURITY_MODE_ENC_NO_MITM, SECURITY_MODE_ENC_NO_MITM,
SECURITY_MODE_NO_ACCESS, SECURITY_MODE_NO_ACCESS,
BLE_GATTS_VAR_ATTR_LEN_MAX, // max length BLEIO_PACKET_BUFFER_MAX_PACKET_SIZE, // max length
false, // fixed length false, // fixed length
NULL, // no initial value NULL, // no initial value
NULL); NULL);
@ -99,6 +101,7 @@ void supervisor_start_bluetooth_serial(void) {
supervisor_ble_circuitpython_version_uuid.base.type = &bleio_uuid_type; supervisor_ble_circuitpython_version_uuid.base.type = &bleio_uuid_type;
common_hal_bleio_uuid_construct(&supervisor_ble_circuitpython_version_uuid, 0x0100, circuitpython_base_uuid); 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, common_hal_bleio_characteristic_construct(&supervisor_ble_circuitpython_version_characteristic,
&supervisor_ble_circuitpython_service, &supervisor_ble_circuitpython_service,
0, // handle (for remote only) 0, // handle (for remote only)
@ -115,13 +118,15 @@ void supervisor_start_bluetooth_serial(void) {
// Use a PacketBuffer to transmit so that we glom characters to transmit // Use a PacketBuffer to transmit so that we glom characters to transmit
// together and save BLE overhead. // together and save BLE overhead.
_tx_packet_buffer.base.type = &bleio_packet_buffer_type;
_common_hal_bleio_packet_buffer_construct( _common_hal_bleio_packet_buffer_construct(
&_tx_packet_buffer, &supervisor_ble_circuitpython_tx_characteristic, &_tx_packet_buffer, &supervisor_ble_circuitpython_tx_characteristic,
NULL, 0, NULL, 0,
_outgoing1, _outgoing2, BLE_GATTS_VAR_ATTR_LEN_MAX, _outgoing1, _outgoing2, BLEIO_PACKET_BUFFER_MAX_PACKET_SIZE,
&tx_static_handler_entry); &tx_static_handler_entry);
// Use a CharacteristicBuffer for rx so we can read a single character at a time. // 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, _common_hal_bleio_characteristic_buffer_construct(&_rx_buffer,
&supervisor_ble_circuitpython_rx_characteristic, &supervisor_ble_circuitpython_rx_characteristic,
0.1f, 0.1f,
@ -143,7 +148,7 @@ void supervisor_stop_bluetooth_serial(void) {
} }
bool ble_serial_connected(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) { uint32_t ble_serial_available(void) {

View file

@ -10,6 +10,7 @@
#if defined(CIRCUITPY_BOOT_BUTTON) #if defined(CIRCUITPY_BOOT_BUTTON)
#include "shared-bindings/digitalio/DigitalInOut.h" #include "shared-bindings/digitalio/DigitalInOut.h"
#include "shared-bindings/time/__init__.h"
#endif #endif
#include "shared-bindings/microcontroller/Processor.h" #include "shared-bindings/microcontroller/Processor.h"
#include "shared-bindings/microcontroller/ResetReason.h" #include "shared-bindings/microcontroller/ResetReason.h"
@ -64,11 +65,6 @@ safe_mode_t wait_for_safe_mode_reset(void) {
#if CIRCUITPY_STATUS_LED #if CIRCUITPY_STATUS_LED
status_led_init(); status_led_init();
#endif #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 start_ticks = supervisor_ticks_ms64();
uint64_t diff = 0; uint64_t diff = 0;
bool boot_in_safe_mode = false; bool boot_in_safe_mode = false;
@ -82,8 +78,15 @@ safe_mode_t wait_for_safe_mode_reset(void) {
new_status_color(BLACK); new_status_color(BLACK);
} }
#endif #endif
// Init the boot button every time in case it is used for LEDs.
#ifdef CIRCUITPY_BOOT_BUTTON #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; boot_in_safe_mode = true;
break; break;
} }