mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-05-24 17:58:45 +00:00
feat(core/ui): eckhart: BLE event handling
[no changelog]
This commit is contained in:
parent
926c08f8c6
commit
e9d7c1ed6d
@ -1627,14 +1627,16 @@ pub static mp_module_trezorui_api: Module = obj_module! {
|
|||||||
/// *,
|
/// *,
|
||||||
/// device_name: str,
|
/// device_name: str,
|
||||||
/// ) -> LayoutObj[UiResult]:
|
/// ) -> LayoutObj[UiResult]:
|
||||||
/// """Pairing device: first screen (device name)."""
|
/// """Pairing device: first screen (device name).
|
||||||
|
/// Returns if BLEEvent::PairingRequest is received."""
|
||||||
Qstr::MP_QSTR_show_pairing_device_name => obj_fn_kw!(0, new_show_pairing_device_name).as_obj(),
|
Qstr::MP_QSTR_show_pairing_device_name => obj_fn_kw!(0, new_show_pairing_device_name).as_obj(),
|
||||||
|
|
||||||
/// def show_pairing_code(
|
/// def show_pairing_code(
|
||||||
/// *,
|
/// *,
|
||||||
/// code: str,
|
/// code: str,
|
||||||
/// ) -> LayoutObj[UiResult]:
|
/// ) -> LayoutObj[UiResult]:
|
||||||
/// """Pairing device: second screen (pairing code)."""
|
/// """Pairing device: second screen (pairing code).
|
||||||
|
/// Returns on BLEEvent::{PairingCanceled, Disconnected}."""
|
||||||
Qstr::MP_QSTR_show_pairing_code => obj_fn_kw!(0, new_show_pairing_code).as_obj(),
|
Qstr::MP_QSTR_show_pairing_code => obj_fn_kw!(0, new_show_pairing_code).as_obj(),
|
||||||
|
|
||||||
/// def show_info(
|
/// def show_info(
|
||||||
|
84
core/embed/rust/src/ui/component/ble.rs
Normal file
84
core/embed/rust/src/ui/component/ble.rs
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
use crate::ui::{
|
||||||
|
component::{Component, Event, EventCtx},
|
||||||
|
event::BLEEvent,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct BLEHandler<T> {
|
||||||
|
inner: T,
|
||||||
|
waiting_for_pairing: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum BLEHandlerMsg<T> {
|
||||||
|
Content(T),
|
||||||
|
PairingCode(u32),
|
||||||
|
Cancelled,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> BLEHandler<T> {
|
||||||
|
pub fn new(inner: T, waiting_for_pairing: bool) -> Self {
|
||||||
|
Self {
|
||||||
|
inner,
|
||||||
|
waiting_for_pairing,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Component for BLEHandler<T>
|
||||||
|
where
|
||||||
|
T: Component,
|
||||||
|
{
|
||||||
|
type Msg = BLEHandlerMsg<T::Msg>;
|
||||||
|
|
||||||
|
fn place(&mut self, bounds: crate::ui::geometry::Rect) -> crate::ui::geometry::Rect {
|
||||||
|
self.inner.place(bounds)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||||
|
match (event, self.waiting_for_pairing) {
|
||||||
|
(Event::BLE(BLEEvent::PairingRequest(num)), true) => {
|
||||||
|
return Some(BLEHandlerMsg::PairingCode(num))
|
||||||
|
}
|
||||||
|
(Event::BLE(BLEEvent::PairingCanceled | BLEEvent::Disconnected), _) => {
|
||||||
|
return Some(BLEHandlerMsg::Cancelled)
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
self.inner.event(ctx, event).map(BLEHandlerMsg::Content)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render<'s>(&'s self, target: &mut impl crate::ui::shape::Renderer<'s>) {
|
||||||
|
self.inner.render(target)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ui_debug")]
|
||||||
|
impl<T> crate::trace::Trace for BLEHandler<T>
|
||||||
|
where
|
||||||
|
T: crate::trace::Trace,
|
||||||
|
{
|
||||||
|
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||||
|
self.inner.trace(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "micropython")]
|
||||||
|
mod micropython {
|
||||||
|
use super::*;
|
||||||
|
use crate::{
|
||||||
|
error::Error,
|
||||||
|
micropython::obj::Obj,
|
||||||
|
ui::layout::{obj::ComponentMsgObj, result::CANCELLED},
|
||||||
|
};
|
||||||
|
impl<T> ComponentMsgObj for BLEHandler<T>
|
||||||
|
where
|
||||||
|
T: ComponentMsgObj,
|
||||||
|
{
|
||||||
|
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
|
||||||
|
match msg {
|
||||||
|
BLEHandlerMsg::Content(msg) => self.inner.msg_try_into_obj(msg),
|
||||||
|
BLEHandlerMsg::PairingCode(num) => num.try_into(),
|
||||||
|
BLEHandlerMsg::Cancelled => Ok(CANCELLED.as_obj()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
pub mod bar;
|
pub mod bar;
|
||||||
pub mod base;
|
pub mod base;
|
||||||
|
#[cfg(feature = "ble")]
|
||||||
|
mod ble;
|
||||||
pub mod border;
|
pub mod border;
|
||||||
pub mod button_request;
|
pub mod button_request;
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
@ -32,6 +34,8 @@ pub mod timeout;
|
|||||||
|
|
||||||
pub use bar::Bar;
|
pub use bar::Bar;
|
||||||
pub use base::{Child, Component, ComponentExt, Event, EventCtx, FlowMsg, Never, Timer};
|
pub use base::{Child, Component, ComponentExt, Event, EventCtx, FlowMsg, Never, Timer};
|
||||||
|
#[cfg(feature = "ble")]
|
||||||
|
pub use ble::BLEHandler;
|
||||||
pub use border::Border;
|
pub use border::Border;
|
||||||
pub use button_request::{ButtonRequestExt, SendButtonRequest};
|
pub use button_request::{ButtonRequestExt, SendButtonRequest};
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
|
@ -184,6 +184,10 @@ impl<'a> DeviceMenuScreen<'a> {
|
|||||||
let device = screen.add_device_menu(device_name, about);
|
let device = screen.add_device_menu(device_name, about);
|
||||||
let settings = screen.add_settings_menu(security, device);
|
let settings = screen.add_settings_menu(security, device);
|
||||||
|
|
||||||
|
let is_connected = !paired_devices.is_empty(); // TODO this is mostly bad
|
||||||
|
let connected_subtext: Option<TString<'static>> =
|
||||||
|
is_connected.then_some("1 device connected".into());
|
||||||
|
|
||||||
let mut paired_device_indices: Vec<usize, 1> = Vec::new();
|
let mut paired_device_indices: Vec<usize, 1> = Vec::new();
|
||||||
for (i, device) in paired_devices.iter().enumerate() {
|
for (i, device) in paired_devices.iter().enumerate() {
|
||||||
unwrap!(paired_device_indices
|
unwrap!(paired_device_indices
|
||||||
@ -191,9 +195,10 @@ impl<'a> DeviceMenuScreen<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let devices = screen.add_paired_devices_menu(paired_devices, paired_device_indices);
|
let devices = screen.add_paired_devices_menu(paired_devices, paired_device_indices);
|
||||||
let pair_and_connect = screen.add_pair_and_connect_menu(devices);
|
let pair_and_connect = screen.add_pair_and_connect_menu(devices, connected_subtext);
|
||||||
|
|
||||||
let root = screen.add_root_menu(failed_backup, pair_and_connect, settings);
|
let root =
|
||||||
|
screen.add_root_menu(failed_backup, pair_and_connect, settings, connected_subtext);
|
||||||
|
|
||||||
screen.set_active_subscreen(root);
|
screen.set_active_subscreen(root);
|
||||||
|
|
||||||
@ -223,17 +228,18 @@ impl<'a> DeviceMenuScreen<'a> {
|
|||||||
self.add_subscreen(Subscreen::Submenu(submenu_index))
|
self.add_subscreen(Subscreen::Submenu(submenu_index))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_pair_and_connect_menu(&mut self, manage_devices_index: usize) -> usize {
|
fn add_pair_and_connect_menu(
|
||||||
|
&mut self,
|
||||||
|
manage_devices_index: usize,
|
||||||
|
connected_subtext: Option<TString<'static>>,
|
||||||
|
) -> usize {
|
||||||
let mut items: Vec<MenuItem, SHORT_MENU_ITEMS> = Vec::new();
|
let mut items: Vec<MenuItem, SHORT_MENU_ITEMS> = Vec::new();
|
||||||
unwrap!(items.push(
|
unwrap!(items.push(
|
||||||
MenuItem::new(
|
MenuItem::new(
|
||||||
"Manage paired devices".into(),
|
"Manage paired devices".into(),
|
||||||
Some(Action::GoTo(manage_devices_index)),
|
Some(Action::GoTo(manage_devices_index)),
|
||||||
)
|
)
|
||||||
.with_subtext(Some((
|
.with_subtext(connected_subtext.map(|t| (t, Some(Button::SUBTEXT_STYLE_GREEN))))
|
||||||
"1 device connected".into(),
|
|
||||||
Some(Button::SUBTEXT_STYLE_GREEN)
|
|
||||||
)))
|
|
||||||
));
|
));
|
||||||
unwrap!(items.push(MenuItem::new(
|
unwrap!(items.push(MenuItem::new(
|
||||||
"Pair new device".into(),
|
"Pair new device".into(),
|
||||||
@ -297,6 +303,7 @@ impl<'a> DeviceMenuScreen<'a> {
|
|||||||
failed_backup: bool,
|
failed_backup: bool,
|
||||||
pair_and_connect_index: usize,
|
pair_and_connect_index: usize,
|
||||||
settings_index: usize,
|
settings_index: usize,
|
||||||
|
connected_subtext: Option<TString<'static>>,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
let mut items: Vec<MenuItem, SHORT_MENU_ITEMS> = Vec::new();
|
let mut items: Vec<MenuItem, SHORT_MENU_ITEMS> = Vec::new();
|
||||||
if failed_backup {
|
if failed_backup {
|
||||||
@ -314,10 +321,7 @@ impl<'a> DeviceMenuScreen<'a> {
|
|||||||
"Pair & connect".into(),
|
"Pair & connect".into(),
|
||||||
Some(Action::GoTo(pair_and_connect_index)),
|
Some(Action::GoTo(pair_and_connect_index)),
|
||||||
)
|
)
|
||||||
.with_subtext(Some((
|
.with_subtext(connected_subtext.map(|t| (t, Some(Button::SUBTEXT_STYLE_GREEN))))
|
||||||
"1 device connected".into(),
|
|
||||||
Some(Button::SUBTEXT_STYLE_GREEN)
|
|
||||||
)))
|
|
||||||
));
|
));
|
||||||
unwrap!(items.push(MenuItem::new(
|
unwrap!(items.push(MenuItem::new(
|
||||||
"Settings".into(),
|
"Settings".into(),
|
||||||
|
@ -1006,6 +1006,8 @@ impl FirmwareUI for UIEckhart {
|
|||||||
.with_action_bar(ActionBar::new_single(Button::with_text(
|
.with_action_bar(ActionBar::new_single(Button::with_text(
|
||||||
"Continue on host".into(),
|
"Continue on host".into(),
|
||||||
)));
|
)));
|
||||||
|
#[cfg(feature = "ble")]
|
||||||
|
let screen = crate::ui::component::BLEHandler::new(screen, true);
|
||||||
let layout = RootComponent::new(screen);
|
let layout = RootComponent::new(screen);
|
||||||
Ok(layout)
|
Ok(layout)
|
||||||
}
|
}
|
||||||
@ -1020,6 +1022,8 @@ impl FirmwareUI for UIEckhart {
|
|||||||
let screen = TextScreen::new(FormattedText::new(ops))
|
let screen = TextScreen::new(FormattedText::new(ops))
|
||||||
.with_header(Header::new("Bluetooth pairing".into()))
|
.with_header(Header::new("Bluetooth pairing".into()))
|
||||||
.with_action_bar(ActionBar::new_cancel_confirm());
|
.with_action_bar(ActionBar::new_cancel_confirm());
|
||||||
|
#[cfg(feature = "ble")]
|
||||||
|
let screen = crate::ui::component::BLEHandler::new(screen, false);
|
||||||
let layout = RootComponent::new(screen);
|
let layout = RootComponent::new(screen);
|
||||||
Ok(layout)
|
Ok(layout)
|
||||||
}
|
}
|
||||||
|
@ -550,7 +550,8 @@ def show_pairing_device_name(
|
|||||||
*,
|
*,
|
||||||
device_name: str,
|
device_name: str,
|
||||||
) -> LayoutObj[UiResult]:
|
) -> LayoutObj[UiResult]:
|
||||||
"""Pairing device: first screen (device name)."""
|
"""Pairing device: first screen (device name).
|
||||||
|
Returns if BLEEvent::PairingRequest is received."""
|
||||||
|
|
||||||
|
|
||||||
# rust/src/ui/api/firmware_micropython.rs
|
# rust/src/ui/api/firmware_micropython.rs
|
||||||
@ -558,7 +559,8 @@ def show_pairing_code(
|
|||||||
*,
|
*,
|
||||||
code: str,
|
code: str,
|
||||||
) -> LayoutObj[UiResult]:
|
) -> LayoutObj[UiResult]:
|
||||||
"""Pairing device: second screen (pairing code)."""
|
"""Pairing device: second screen (pairing code).
|
||||||
|
Returns on BLEEvent::{PairingCanceled, Disconnected}."""
|
||||||
|
|
||||||
|
|
||||||
# rust/src/ui/api/firmware_micropython.rs
|
# rust/src/ui/api/firmware_micropython.rs
|
||||||
|
Loading…
Reference in New Issue
Block a user