diff --git a/core/embed/rust/src/ui/api/firmware_micropython.rs b/core/embed/rust/src/ui/api/firmware_micropython.rs index 935d3e0f5d..0f1a3b901b 100644 --- a/core/embed/rust/src/ui/api/firmware_micropython.rs +++ b/core/embed/rust/src/ui/api/firmware_micropython.rs @@ -1068,7 +1068,7 @@ pub static mp_module_trezorui_api: Module = obj_module! { /// def usb_event(self, connected: bool) -> LayoutState | None: /// """Receive a USB connect/disconnect event.""" /// - /// def ble_event(self, event: tuple[int, bytes]) -> LayoutState | None: + /// def ble_event(self, event: tuple[int, int | None]) -> LayoutState | None: /// """Receive a BLE event.""" /// /// def timer(self, token: int) -> LayoutState | None: diff --git a/core/embed/rust/src/ui/event/ble.rs b/core/embed/rust/src/ui/event/ble.rs index fd0f8d0172..b5ee2f9ee0 100644 --- a/core/embed/rust/src/ui/event/ble.rs +++ b/core/embed/rust/src/ui/event/ble.rs @@ -5,18 +5,18 @@ use crate::error::Error; pub enum BLEEvent { Connected, Disconnected, - PairingRequest(&'static [u8]), + PairingRequest(u32), PairingCanceled, } impl BLEEvent { - pub fn new(event: u32, data: &'static [u8]) -> Result { - let result = match event { - 1 => Self::Connected, - 2 => Self::Disconnected, - 3 => Self::PairingRequest(data), - 4 => Self::PairingCanceled, - _ => return Err(Error::OutOfRange), + pub fn new(event: u32, data: Option) -> Result { + let result = match (event, data) { + (1, None) => Self::Connected, + (2, None) => Self::Disconnected, + (3, Some(code)) => Self::PairingRequest(code), + (4, None) => Self::PairingCanceled, + _ => return Err(Error::ValueError(c"Invalid BLE event")), }; Ok(result) } diff --git a/core/embed/rust/src/ui/layout/obj.rs b/core/embed/rust/src/ui/layout/obj.rs index d9675356ac..5f02228f19 100644 --- a/core/embed/rust/src/ui/layout/obj.rs +++ b/core/embed/rust/src/ui/layout/obj.rs @@ -11,8 +11,6 @@ use crate::ui::{event::TouchEvent, geometry::Direction}; #[cfg(feature = "touch")] use num_traits::ToPrimitive; -#[cfg(feature = "ble")] -use crate::micropython::buffer::get_buffer; #[cfg(feature = "ble")] use crate::ui::event::BLEEvent; @@ -545,11 +543,7 @@ extern "C" fn ui_layout_ble_event(n_args: usize, args: *const Obj) -> Obj { } let this: Gc = args[0].try_into()?; - let data = unsafe { get_buffer(args[2]) }; - - let data = unwrap!(data); - - let event = BLEEvent::new(args[1].try_into()?, data)?; + let event = BLEEvent::new(args[1].try_into()?, args[2].try_into_option()?)?; let msg = this.inner_mut().obj_event(Event::BLE(event))?; Ok(msg) }; diff --git a/core/embed/upymod/modtrezorio/modtrezorio-poll.h b/core/embed/upymod/modtrezorio/modtrezorio-poll.h index 11553ed62a..1c34d79b16 100644 --- a/core/embed/upymod/modtrezorio/modtrezorio-poll.h +++ b/core/embed/upymod/modtrezorio/modtrezorio-poll.h @@ -48,6 +48,31 @@ extern uint32_t last_touch_sample_time; +#ifdef USE_BLE + +static mp_obj_t parse_ble_event_data(const ble_event_t *event) { + if (event->data_len == 0) { + return mp_const_none; + } + if (event->type != BLE_PAIRING_REQUEST) { + return mp_const_none; + } + // Parse pairing code + _Static_assert(sizeof(event->data) <= 6); + uint32_t code = 0; + for (int i = 0; i < event->data_len; ++i) { + uint8_t byte = event->data[i]; + if (byte >= '0' && byte <= '9') { + code = 10 * code + (byte - '0'); + } else { + mp_raise_ValueError("Invalid pairing code"); + } + } + return mp_obj_new_int_from_uint(code); +} + +#endif + /// package: trezorio.__init__ /// def poll(ifaces: Iterable[int], list_ref: list, timeout_ms: int) -> bool: @@ -208,13 +233,9 @@ STATIC mp_obj_t mod_trezorio_poll(mp_obj_t ifaces, mp_obj_t list_ref, ble_event_t event = {0}; bool read = ble_get_event(&event); if (read) { - mp_obj_t data = mp_const_empty_bytes; - if (event.data_len > 0) { - data = mp_obj_new_bytes(event.data, event.data_len); - } mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); tuple->items[0] = MP_OBJ_NEW_SMALL_INT(event.type); - tuple->items[1] = data; + tuple->items[1] = parse_ble_event_data(&event); ret->items[0] = MP_OBJ_NEW_SMALL_INT(i); ret->items[1] = MP_OBJ_FROM_PTR(tuple); return mp_const_true; diff --git a/core/mocks/generated/trezorui_api.pyi b/core/mocks/generated/trezorui_api.pyi index 6751bc1450..a70518b4b0 100644 --- a/core/mocks/generated/trezorui_api.pyi +++ b/core/mocks/generated/trezorui_api.pyi @@ -26,7 +26,7 @@ class LayoutObj(Generic[T]): """Receive a progress event.""" def usb_event(self, connected: bool) -> LayoutState | None: """Receive a USB connect/disconnect event.""" - def ble_event(self, event: tuple[int, bytes]) -> LayoutState | None: + def ble_event(self, event: tuple[int, int | None]) -> LayoutState | None: """Receive a BLE event.""" def timer(self, token: int) -> LayoutState | None: """Callback for the timer set by `attach_timer_fn`.