From 62ea246ce15519031931270f08b74ef1232a9e9e Mon Sep 17 00:00:00 2001 From: Martin Milata Date: Tue, 8 Apr 2025 16:01:34 +0200 Subject: [PATCH 1/5] build(core): allow ble feature in emulator [no changelog] --- core/SConscript.unix | 2 +- core/embed/io/ble/unix/ble.c | 30 +++++++++++++++++++++++++ core/site_scons/models/T3W1/emulator.py | 6 +++++ 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 core/embed/io/ble/unix/ble.c diff --git a/core/SConscript.unix b/core/SConscript.unix index c8724b46df..9a977654f9 100644 --- a/core/SConscript.unix +++ b/core/SConscript.unix @@ -21,7 +21,7 @@ if BENCHMARK and PYOPT != '0': print("BENCHMARK=1 works only with PYOPT=0.") exit(1) -FEATURES_WANTED = ["input", "sd_card", "dma2d", "optiga"] +FEATURES_WANTED = ["input", "sd_card", "dma2d", "optiga", "ble"] if not DISABLE_TROPIC: FEATURES_WANTED.append('tropic') diff --git a/core/embed/io/ble/unix/ble.c b/core/embed/io/ble/unix/ble.c new file mode 100644 index 0000000000..0165da4c8f --- /dev/null +++ b/core/embed/io/ble/unix/ble.c @@ -0,0 +1,30 @@ +#include +#include + +#include + +bool ble_init(void) { return true; } + +void ble_deinit(void) {} + +void ble_start(void) {} + +void ble_stop(void) {} + +bool ble_issue_command(ble_command_t *command) { return true; } + +bool ble_get_event(ble_event_t *event) { return false; } + +void ble_get_state(ble_state_t *state) { + memset(state, 0, sizeof(ble_state_t)); +} + +bool ble_can_write(void) { return true; } + +bool ble_write(const uint8_t *data, uint16_t len) { return len; } + +bool ble_can_read(void) { return false; } + +uint32_t ble_read(uint8_t *data, uint16_t max_len) { return 0; } + +bool ble_get_mac(uint8_t *mac, size_t max_len) { return false; } diff --git a/core/site_scons/models/T3W1/emulator.py b/core/site_scons/models/T3W1/emulator.py index 48e9929667..c97c8bb4c4 100644 --- a/core/site_scons/models/T3W1/emulator.py +++ b/core/site_scons/models/T3W1/emulator.py @@ -87,6 +87,12 @@ def configure( features_available.append("touch") defines += [("USE_TOUCH", "1")] + if "ble" in features_wanted: + sources += ["embed/io/ble/unix/ble.c"] + paths += ["embed/io/ble/inc"] + features_available.append("ble") + defines += [("USE_BLE", "1")] + features_available.append("backlight") defines += [("USE_BACKLIGHT", "1")] From c053ef3012116461df6a00812df767c807512655 Mon Sep 17 00:00:00 2001 From: Martin Milata Date: Tue, 8 Apr 2025 16:05:26 +0200 Subject: [PATCH 2/5] build(core): enable button feature in T3W1 emulator [no changelog] --- core/site_scons/models/T3W1/emulator.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/site_scons/models/T3W1/emulator.py b/core/site_scons/models/T3W1/emulator.py index c97c8bb4c4..3873c1e5e5 100644 --- a/core/site_scons/models/T3W1/emulator.py +++ b/core/site_scons/models/T3W1/emulator.py @@ -87,6 +87,12 @@ def configure( features_available.append("touch") defines += [("USE_TOUCH", "1")] + sources += ["embed/io/button/unix/button.c"] + sources += ["embed/io/button/button_fsm.c"] + paths += ["embed/io/button/inc"] + features_available.append("button") + defines += [("USE_BUTTON", "1")] + if "ble" in features_wanted: sources += ["embed/io/ble/unix/ble.c"] paths += ["embed/io/ble/inc"] From 0d55e1a70b6388be15e3c4c93cc707187ce12063 Mon Sep 17 00:00:00 2001 From: Martin Milata Date: Tue, 8 Apr 2025 16:21:10 +0200 Subject: [PATCH 3/5] feat(core): start BLE advertising on boot [no changelog] --- core/src/main.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/src/main.py b/core/src/main.py index f6433b5fcf..8b03772723 100644 --- a/core/src/main.py +++ b/core/src/main.py @@ -50,10 +50,17 @@ import storage.device usb.bus.open(storage.device.get_device_id()) +# enable BLE, allow connections if utils.USE_BLE: from trezorio import ble ble.start_comm() + # allow connections from bonded peers if any + if ble.peer_count() > 0: + ble.start_advertising(True, storage.device.get_label()) + + del ble + # run the endless loop while True: From ada881458227865a879f7760529922b1f5c32edc Mon Sep 17 00:00:00 2001 From: Martin Milata Date: Tue, 8 Apr 2025 16:27:44 +0200 Subject: [PATCH 4/5] fix(core): modtrezorio-ble cleanup [no changelog] --- .../upymod/modtrezorio/modtrezorio-ble.h | 60 +------------------ core/mocks/generated/trezorio/ble.pyi | 2 +- 2 files changed, 2 insertions(+), 60 deletions(-) diff --git a/core/embed/upymod/modtrezorio/modtrezorio-ble.h b/core/embed/upymod/modtrezorio/modtrezorio-ble.h index 61fe3f9ddf..e08a0b7eee 100644 --- a/core/embed/upymod/modtrezorio/modtrezorio-ble.h +++ b/core/embed/upymod/modtrezorio/modtrezorio-ble.h @@ -19,62 +19,8 @@ #include -// #include "ble/dfu.h" -// #include "ble/messages.h" - /// package: trezorio.ble -// /// def update_init(data: bytes, binsize: int) -> int: -// /// """ -// /// Initializes the BLE firmware update -// /// """ -// STATIC mp_obj_t mod_trezorio_BLE_update_init(mp_obj_t data, mp_obj_t binsize) -// { -// mp_buffer_info_t buffer = {0}; -// mp_int_t binsize_int = mp_obj_get_int(binsize); -// -// mp_get_buffer_raise(data, &buffer, MP_BUFFER_READ); -// -// ble_set_dfu_mode(true); -// -// dfu_result_t result = dfu_update_init(buffer.buf, buffer.len, binsize_int); -// if (result == DFU_NEXT_CHUNK) { -// return mp_obj_new_int(0); -// } else if (result == DFU_SUCCESS) { -// ble_set_dfu_mode(false); -// return mp_obj_new_int(1); -// } else { -// ble_set_dfu_mode(false); -// mp_raise_msg(&mp_type_RuntimeError, "Upload failed."); -// } -// } -// STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_BLE_update_init_obj, -// mod_trezorio_BLE_update_init); -// -// /// def update_chunk(chunk: bytes) -> int: -// /// """ -// /// Writes next chunk of BLE firmware update -// /// """ -// STATIC mp_obj_t mod_trezorio_BLE_update_chunk(mp_obj_t data) { -// mp_buffer_info_t buffer = {0}; -// -// mp_get_buffer_raise(data, &buffer, MP_BUFFER_READ); -// -// dfu_result_t result = dfu_update_chunk(buffer.buf, buffer.len); -// -// if (result == DFU_NEXT_CHUNK) { -// return mp_obj_new_int(0); -// } else if (result == DFU_SUCCESS) { -// ble_set_dfu_mode(false); -// return mp_obj_new_int(1); -// } else { -// ble_set_dfu_mode(false); -// mp_raise_msg(&mp_type_RuntimeError, "Upload failed."); -// } -// } -// STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_BLE_update_chunk_obj, -// mod_trezorio_BLE_update_chunk); - /// /// def erase_bonds() -> bool: /// """ @@ -146,7 +92,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( mod_trezorio_BLE_start_advertising_obj, 1, 2, mod_trezorio_BLE_start_advertising); -/// def stop_advertising(whitelist: bool) -> bool: +/// def stop_advertising() -> bool: /// """ /// Stop advertising /// """ @@ -336,10 +282,6 @@ STATIC const mp_obj_type_t mod_trezorio_BleInterface_type = { STATIC const mp_rom_map_elem_t mod_trezorio_BLE_globals_table[] = { {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ble)}, - // {MP_ROM_QSTR(MP_QSTR_update_init), - // MP_ROM_PTR(&mod_trezorio_BLE_update_init_obj)}, - // {MP_ROM_QSTR(MP_QSTR_update_chunk), - // MP_ROM_PTR(&mod_trezorio_BLE_update_chunk_obj)}, {MP_ROM_QSTR(MP_QSTR_erase_bonds), MP_ROM_PTR(&mod_trezorio_BLE_erase_bonds_obj)}, {MP_ROM_QSTR(MP_QSTR_unpair), MP_ROM_PTR(&mod_trezorio_BLE_unpair_obj)}, diff --git a/core/mocks/generated/trezorio/ble.pyi b/core/mocks/generated/trezorio/ble.pyi index c7cfbd6fa7..31a957ffe8 100644 --- a/core/mocks/generated/trezorio/ble.pyi +++ b/core/mocks/generated/trezorio/ble.pyi @@ -31,7 +31,7 @@ def start_advertising(whitelist: bool, name: str | None) -> bool: # upymod/modtrezorio/modtrezorio-ble.h -def stop_advertising(whitelist: bool) -> bool: +def stop_advertising() -> bool: """ Stop advertising """ From 7ac07be732278cccde925a38f2d9a62777909e19 Mon Sep 17 00:00:00 2001 From: Martin Milata Date: Wed, 9 Apr 2025 01:20:13 +0200 Subject: [PATCH 5/5] refactor(core): ble: expose connection state in micropython [no changelog] --- .../upymod/modtrezorio/modtrezorio-ble.h | 23 +++++++++++++++++++ core/mocks/generated/trezorio/ble.pyi | 13 +++++++++++ 2 files changed, 36 insertions(+) diff --git a/core/embed/upymod/modtrezorio/modtrezorio-ble.h b/core/embed/upymod/modtrezorio/modtrezorio-ble.h index e08a0b7eee..0c67c485be 100644 --- a/core/embed/upymod/modtrezorio/modtrezorio-ble.h +++ b/core/embed/upymod/modtrezorio/modtrezorio-ble.h @@ -126,6 +126,27 @@ STATIC mp_obj_t mod_trezorio_BLE_peer_count(void) { STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorio_BLE_peer_count_obj, mod_trezorio_BLE_peer_count); +/// def connection_state() -> int: +/// """ +/// Returns current connection state as flags: +/// +/// 0x01 state known +/// 0x02 connectable +/// 0x04 connected +/// 0x08 pairing +/// 0x10 pairing request +/// """ +STATIC mp_obj_t mod_trezorio_BLE_connection_state(void) { + ble_state_t state; + ble_get_state(&state); + mp_int_t flags = (state.state_known << 0) | (state.connectable << 1) | + (state.connected << 2) | (state.pairing << 3) | + (state.pairing_requested << 4); + return MP_OBJ_NEW_SMALL_INT(flags); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorio_BLE_connection_state_obj, + mod_trezorio_BLE_connection_state); + const size_t CODE_LEN = 6; static bool encode_pairing_code(mp_obj_t obj, uint8_t *outbuf) { mp_int_t code = mp_obj_get_int(obj); @@ -295,6 +316,8 @@ STATIC const mp_rom_map_elem_t mod_trezorio_BLE_globals_table[] = { MP_ROM_PTR(&mod_trezorio_BLE_disconnect_obj)}, {MP_ROM_QSTR(MP_QSTR_peer_count), MP_ROM_PTR(&mod_trezorio_BLE_peer_count_obj)}, + {MP_ROM_QSTR(MP_QSTR_connection_state), + MP_ROM_PTR(&mod_trezorio_BLE_connection_state_obj)}, {MP_ROM_QSTR(MP_QSTR_allow_pairing), MP_ROM_PTR(&mod_trezorio_BLE_allow_pairing_obj)}, {MP_ROM_QSTR(MP_QSTR_reject_pairing), diff --git a/core/mocks/generated/trezorio/ble.pyi b/core/mocks/generated/trezorio/ble.pyi index 31a957ffe8..27a8411401 100644 --- a/core/mocks/generated/trezorio/ble.pyi +++ b/core/mocks/generated/trezorio/ble.pyi @@ -51,6 +51,19 @@ def peer_count() -> int: """ +# upymod/modtrezorio/modtrezorio-ble.h +def connection_state() -> int: + """ + Returns current connection state as flags: + + 0x01 state known + 0x02 connectable + 0x04 connected + 0x08 pairing + 0x10 pairing request + """ + + # upymod/modtrezorio/modtrezorio-ble.h def allow_pairing(code: int) -> bool: """