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"]
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

View file

@ -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 ""

10
main.c
View file

@ -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

View file

@ -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 += \

View file

@ -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)

View file

@ -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();
@ -487,6 +494,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 +507,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 +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 ||
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 +729,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) {
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) {
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) {

View file

@ -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;

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:
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;
}

View file

@ -157,7 +157,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;

View file

@ -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);

View file

@ -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) {

View file

@ -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;

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

View file

@ -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

View file

@ -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 {

View file

@ -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;

View file

@ -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;

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 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,

View file

@ -10,6 +10,13 @@
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);
@ -18,7 +25,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 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_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);

View file

@ -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

View file

@ -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, ...);

View file

@ -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();

View file

@ -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);
}

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_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;
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 +64,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 +72,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 +80,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 +88,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 +101,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 +118,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 +148,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) {

View file

@ -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;
}