From f0bb8ac7069260e4433347c01d95b22f5cd4ab7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ioan=20Biz=C4=83u?= Date: Wed, 2 Apr 2025 16:49:26 +0200 Subject: [PATCH] feat(eckhart): layouts for device pairing --- core/embed/rust/librust_qstr.h | 4 ++ .../rust/src/ui/api/firmware_micropython.rs | 38 +++++++++++++++++++ .../rust/src/ui/layout_bolt/ui_firmware.rs | 14 +++++++ .../rust/src/ui/layout_caesar/ui_firmware.rs | 14 +++++++ .../rust/src/ui/layout_delizia/ui_firmware.rs | 14 +++++++ .../rust/src/ui/layout_eckhart/ui_firmware.rs | 36 +++++++++++++++++- core/embed/rust/src/ui/ui_firmware.rs | 6 +++ core/mocks/generated/trezorui_api.pyi | 16 ++++++++ 8 files changed, 141 insertions(+), 1 deletion(-) diff --git a/core/embed/rust/librust_qstr.h b/core/embed/rust/librust_qstr.h index adc70b4596..340eb8fbe7 100644 --- a/core/embed/rust/librust_qstr.h +++ b/core/embed/rust/librust_qstr.h @@ -199,6 +199,7 @@ static void _librust_qstrs(void) { MP_QSTR_case_sensitive; MP_QSTR_check_homescreen_format; MP_QSTR_chunkify; + MP_QSTR_code; MP_QSTR_coinjoin__access_account; MP_QSTR_coinjoin__do_not_disconnect; MP_QSTR_coinjoin__max_mining_fee; @@ -242,6 +243,7 @@ static void _librust_qstrs(void) { MP_QSTR_deinit; MP_QSTR_description; MP_QSTR_details_title; + MP_QSTR_device_name; MP_QSTR_device_name__change_template; MP_QSTR_device_name__title; MP_QSTR_disable_animation; @@ -682,6 +684,8 @@ static void _librust_qstrs(void) { MP_QSTR_show_instructions; MP_QSTR_show_lockscreen; MP_QSTR_show_mismatch; + MP_QSTR_show_pairing_code; + MP_QSTR_show_pairing_device_name; MP_QSTR_show_progress; MP_QSTR_show_progress_coinjoin; MP_QSTR_show_remaining_shares; diff --git a/core/embed/rust/src/ui/api/firmware_micropython.rs b/core/embed/rust/src/ui/api/firmware_micropython.rs index c5d672fb16..c54f959c36 100644 --- a/core/embed/rust/src/ui/api/firmware_micropython.rs +++ b/core/embed/rust/src/ui/api/firmware_micropython.rs @@ -815,6 +815,30 @@ extern "C" fn new_show_device_menu(n_args: usize, args: *const Obj, kwargs: *mut unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } } +extern "C" fn new_show_pairing_device_name( + n_args: usize, + args: *const Obj, + kwargs: *mut Map, +) -> Obj { + let block = move |_args: &[Obj], kwargs: &Map| { + let device_name: TString = kwargs.get(Qstr::MP_QSTR_device_name)?.try_into()?; + let layout = ModelUI::show_pairing_device_name(device_name)?; + let layout_obj = LayoutObj::new_root(layout)?; + Ok(layout_obj.into()) + }; + unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } +} + +extern "C" fn new_show_pairing_code(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { + let block = move |_args: &[Obj], kwargs: &Map| { + let code: TString = kwargs.get(Qstr::MP_QSTR_code)?.try_into()?; + let layout = ModelUI::show_pairing_code(code)?; + let layout_obj = LayoutObj::new_root(layout)?; + Ok(layout_obj.into()) + }; + unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } +} + extern "C" fn new_show_info(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { let block = move |_args: &[Obj], kwargs: &Map| { let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; @@ -1583,6 +1607,20 @@ pub static mp_module_trezorui_api: Module = obj_module! { /// """Show the device menu.""" Qstr::MP_QSTR_show_device_menu => obj_fn_kw!(0, new_show_device_menu).as_obj(), + /// def show_pairing_device_name( + /// *, + /// device_name: str, + /// ) -> LayoutObj[UiResult]: + /// """Pairing device: first screen (device name).""" + Qstr::MP_QSTR_show_pairing_device_name => obj_fn_kw!(0, new_show_pairing_device_name).as_obj(), + + /// def show_pairing_code( + /// *, + /// code: str, + /// ) -> LayoutObj[UiResult]: + /// """Pairing device: second screen (pairing code).""" + Qstr::MP_QSTR_show_pairing_code => obj_fn_kw!(0, new_show_pairing_code).as_obj(), + /// def show_info( /// *, /// title: str, diff --git a/core/embed/rust/src/ui/layout_bolt/ui_firmware.rs b/core/embed/rust/src/ui/layout_bolt/ui_firmware.rs index 25fce0e5d8..e4780698f0 100644 --- a/core/embed/rust/src/ui/layout_bolt/ui_firmware.rs +++ b/core/embed/rust/src/ui/layout_bolt/ui_firmware.rs @@ -871,6 +871,20 @@ impl FirmwareUI for UIBolt { )) } + fn show_pairing_device_name( + _device_name: TString<'static>, + ) -> Result { + Err::, Error>(Error::ValueError( + c"show_pairing_device_name not supported", + )) + } + + fn show_pairing_code(_code: TString<'static>) -> Result { + Err::, Error>(Error::ValueError( + c"show_pairing_code not supported", + )) + } + fn show_info( title: TString<'static>, description: TString<'static>, diff --git a/core/embed/rust/src/ui/layout_caesar/ui_firmware.rs b/core/embed/rust/src/ui/layout_caesar/ui_firmware.rs index ba093f7471..ec051c261e 100644 --- a/core/embed/rust/src/ui/layout_caesar/ui_firmware.rs +++ b/core/embed/rust/src/ui/layout_caesar/ui_firmware.rs @@ -1037,6 +1037,20 @@ impl FirmwareUI for UICaesar { )) } + fn show_pairing_device_name( + _device_name: TString<'static>, + ) -> Result { + Err::, Error>(Error::ValueError( + c"show_pairing_device_name not supported", + )) + } + + fn show_pairing_code(_code: TString<'static>) -> Result { + Err::, Error>(Error::ValueError( + c"show_pairing_code not supported", + )) + } + fn show_info( title: TString<'static>, description: TString<'static>, diff --git a/core/embed/rust/src/ui/layout_delizia/ui_firmware.rs b/core/embed/rust/src/ui/layout_delizia/ui_firmware.rs index 11241d0970..895e9a0be5 100644 --- a/core/embed/rust/src/ui/layout_delizia/ui_firmware.rs +++ b/core/embed/rust/src/ui/layout_delizia/ui_firmware.rs @@ -894,6 +894,20 @@ impl FirmwareUI for UIDelizia { )) } + fn show_pairing_device_name( + _device_name: TString<'static>, + ) -> Result { + Err::, Error>(Error::ValueError( + c"show_pairing_device_name not supported", + )) + } + + fn show_pairing_code(_code: TString<'static>) -> Result { + Err::, Error>(Error::ValueError( + c"show_pairing_code not supported", + )) + } + fn show_info( title: TString<'static>, description: TString<'static>, diff --git a/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs b/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs index 608903acfe..fea918db14 100644 --- a/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs +++ b/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs @@ -17,7 +17,7 @@ use crate::{ }, Empty, FormattedText, }, - geometry::{LinearPlacement, Offset}, + geometry::{Alignment, LinearPlacement, Offset}, layout::{ obj::{LayoutMaybeTrace, LayoutObj, RootComponent}, util::{ConfirmValueParams, RecoveryType, StrOrBytes}, @@ -796,6 +796,40 @@ impl FirmwareUI for UIEckhart { Ok(layout) } + fn show_pairing_device_name( + device_name: TString<'static>, + ) -> Result { + let font = fonts::FONT_SATOSHI_REGULAR_38; + let text_style = theme::firmware::TEXT_REGULAR; + let mut ops = OpTextLayout::new(text_style); + ops = ops.color(theme::GREEN); + ops = ops.text(device_name, font); + ops = ops.color(text_style.text_color); + let text: TString = " is your Trezor's name.".into(); + ops = ops.text(text, font); + let screen = TextScreen::new(FormattedText::new(ops)) + .with_header(Header::new("Pair with new device".into()).with_close_button()) + .with_action_bar(ActionBar::new_single(Button::with_text( + "Continue on host".into(), + ))); + let layout = RootComponent::new(screen); + Ok(layout) + } + + fn show_pairing_code(code: TString<'static>) -> Result { + let text: TString<'static> = "Pairing code match?".into(); + let mut ops = OpTextLayout::new(theme::firmware::TEXT_REGULAR); + ops = ops.text(text, fonts::FONT_SATOSHI_REGULAR_38); + ops = ops.newline().newline().newline(); + ops = ops.alignment(Alignment::Center); + ops = ops.text(code, fonts::FONT_SATOSHI_EXTRALIGHT_72); + let screen = TextScreen::new(FormattedText::new(ops)) + .with_header(Header::new("Bluetooth pairing".into())) + .with_action_bar(ActionBar::new_cancel_confirm()); + let layout = RootComponent::new(screen); + Ok(layout) + } + fn show_info( title: TString<'static>, description: TString<'static>, diff --git a/core/embed/rust/src/ui/ui_firmware.rs b/core/embed/rust/src/ui/ui_firmware.rs index c0642ff05c..dc0942b0ad 100644 --- a/core/embed/rust/src/ui/ui_firmware.rs +++ b/core/embed/rust/src/ui/ui_firmware.rs @@ -309,6 +309,12 @@ pub trait FirmwareUI { paired_devices: Vec, 1>, ) -> Result; + fn show_pairing_device_name( + device_name: TString<'static>, + ) -> Result; + + fn show_pairing_code(code: TString<'static>) -> Result; + fn show_info( title: TString<'static>, description: TString<'static>, diff --git a/core/mocks/generated/trezorui_api.pyi b/core/mocks/generated/trezorui_api.pyi index 9d6e098e9a..38994d6c62 100644 --- a/core/mocks/generated/trezorui_api.pyi +++ b/core/mocks/generated/trezorui_api.pyi @@ -542,6 +542,22 @@ def show_device_menu( """Show the device menu.""" +# rust/src/ui/api/firmware_micropython.rs +def show_pairing_device_name( + *, + device_name: str, +) -> LayoutObj[UiResult]: + """Pairing device: first screen (device name).""" + + +# rust/src/ui/api/firmware_micropython.rs +def show_pairing_code( + *, + code: str, +) -> LayoutObj[UiResult]: + """Pairing device: second screen (pairing code).""" + + # rust/src/ui/api/firmware_micropython.rs def show_info( *,