refactor(core/rust): introduce UIFeaturesXXX trait as an abstraction over different UI implementation

[no changelog]
pull/3682/head
tychovrahe 2 months ago committed by TychoVrahe
parent ba741b81fd
commit 535a052df4

@ -1,34 +1,5 @@
#include <stdbool.h>
#include "common.h"
uint32_t screen_install_confirm(const char* vendor_str, uint8_t vendor_str_len,
const char* version_str,
const uint8_t* fingerprint,
bool should_keep_seed, bool is_newvendor,
int version_cmp);
uint32_t screen_wipe_confirm(void);
void screen_install_progress(int16_t progress, bool initialize,
bool initial_setup);
void screen_wipe_progress(int16_t progress, bool initialize);
uint32_t screen_intro(const char* bld_version_str, const char* vendor_str,
uint8_t vendor_str_len, const char* version_str,
bool fw_ok);
uint32_t screen_menu(secbool firmware_present);
void screen_connect(bool initial_setup);
void screen_fatal_error_rust(const char* title, const char* msg,
const char* footer);
void screen_wipe_success(void);
void screen_wipe_fail(void);
uint32_t screen_install_success(uint8_t restart_seconds, bool initial_setup,
bool complete_draw);
uint32_t screen_install_fail(void);
void screen_welcome(void);
void screen_boot_empty(bool fading);
void screen_boot_full(void);
uint32_t screen_unlock_bootloader_confirm(void);
void screen_unlock_bootloader_success(void);
void display_image(int16_t x, int16_t y, const uint8_t* data, uint32_t datalen);
void display_icon(int16_t x, int16_t y, const uint8_t* data, uint32_t datalen,
uint16_t fg_color, uint16_t bg_color);
void bld_continue_label(uint16_t bg_color);
#include "rust_ui_bootloader.h"
#include "rust_ui_common.h"

@ -0,0 +1,26 @@
#include "common.h"
uint32_t screen_install_confirm(const char* vendor_str, uint8_t vendor_str_len,
const char* version_str,
const uint8_t* fingerprint,
bool should_keep_seed, bool is_newvendor,
int version_cmp);
uint32_t screen_wipe_confirm(void);
void screen_install_progress(int16_t progress, bool initialize,
bool initial_setup);
void screen_wipe_progress(int16_t progress, bool initialize);
uint32_t screen_intro(const char* bld_version_str, const char* vendor_str,
uint8_t vendor_str_len, const char* version_str,
bool fw_ok);
uint32_t screen_menu(secbool firmware_present);
void screen_connect(bool initial_setup);
void screen_wipe_success(void);
void screen_wipe_fail(void);
uint32_t screen_install_success(uint8_t restart_seconds, bool initial_setup,
bool complete_draw);
uint32_t screen_install_fail(void);
void screen_welcome(void);
void screen_boot_empty(bool fading);
uint32_t screen_unlock_bootloader_confirm(void);
void screen_unlock_bootloader_success(void);
void bld_continue_label(uint16_t bg_color);

@ -0,0 +1,10 @@
#include "common.h"
void screen_fatal_error_rust(const char* title, const char* msg,
const char* footer);
void screen_boot_full(void);
void display_image(int16_t x, int16_t y, const uint8_t* data, uint32_t datalen);
void display_icon(int16_t x, int16_t y, const uint8_t* data, uint32_t datalen,
uint16_t fg_color, uint16_t bg_color);

@ -5,7 +5,7 @@ mod ffi {
}
}
use crate::ui::screens::screen_fatal_error;
use crate::ui::ui_features::{ModelUI, UIFeaturesCommon};
fn shutdown() -> ! {
unsafe { ffi::trezor_shutdown() }
@ -13,13 +13,13 @@ fn shutdown() -> ! {
#[cfg(feature = "bootloader")]
pub fn __fatal_error(_expr: &str, _msg: &str, _file: &str, _line: u32, _func: &str) -> ! {
screen_fatal_error("BL.rs", "BL.rs", "PLEASE VISIT\nTREZOR.IO/RSOD");
ModelUI::screen_fatal_error("BL.rs", "BL.rs", "PLEASE VISIT\nTREZOR.IO/RSOD");
shutdown()
}
#[cfg(not(feature = "bootloader"))]
pub fn __fatal_error(_expr: &str, msg: &str, _file: &str, _line: u32, _func: &str) -> ! {
screen_fatal_error("INTERNAL_ERROR", msg, "PLEASE VISIT\nTREZOR.IO/RSOD");
ModelUI::screen_fatal_error("INTERNAL_ERROR", msg, "PLEASE VISIT\nTREZOR.IO/RSOD");
shutdown()
}

@ -0,0 +1,127 @@
use crate::{
strutil::hexlify,
trezorhal::secbool::secbool,
ui::{
ui_features::{ModelUI, UIFeaturesBootloader},
util::{from_c_array, from_c_str},
},
};
#[no_mangle]
extern "C" fn screen_welcome() {
ModelUI::screen_welcome();
}
#[no_mangle]
extern "C" fn bld_continue_label(bg_color: cty::uint16_t) {
ModelUI::bld_continue_label(bg_color.into());
}
#[no_mangle]
extern "C" fn screen_install_success(
restart_seconds: u8,
initial_setup: bool,
complete_draw: bool,
) {
ModelUI::screen_install_success(restart_seconds, initial_setup, complete_draw);
}
#[no_mangle]
extern "C" fn screen_install_fail() {
ModelUI::screen_install_fail();
}
#[no_mangle]
extern "C" fn screen_install_confirm(
vendor_str: *const cty::c_char,
vendor_str_len: u8,
version: *const cty::c_char,
fingerprint: *const cty::uint8_t,
should_keep_seed: bool,
is_newvendor: bool,
version_cmp: cty::c_int,
) -> u32 {
let text = unwrap!(unsafe { from_c_array(vendor_str, vendor_str_len as usize) });
let version = unwrap!(unsafe { from_c_str(version) });
let mut fingerprint_buffer: [u8; 64] = [0; 64];
let fingerprint_str = unsafe {
let fingerprint_slice = core::slice::from_raw_parts(fingerprint, 32);
hexlify(fingerprint_slice, &mut fingerprint_buffer);
core::str::from_utf8_unchecked(fingerprint_buffer.as_ref())
};
ModelUI::screen_install_confirm(
text,
version,
fingerprint_str,
should_keep_seed,
is_newvendor,
version_cmp,
)
}
#[no_mangle]
extern "C" fn screen_wipe_confirm() -> u32 {
ModelUI::screen_wipe_confirm()
}
#[no_mangle]
extern "C" fn screen_unlock_bootloader_confirm() -> u32 {
ModelUI::screen_unlock_bootloader_confirm()
}
#[no_mangle]
extern "C" fn screen_unlock_bootloader_success() {
ModelUI::screen_unlock_bootloader_success();
}
#[no_mangle]
extern "C" fn screen_menu(firmware_present: secbool) -> u32 {
ModelUI::screen_menu(firmware_present)
}
#[no_mangle]
extern "C" fn screen_intro(
bld_version: *const cty::c_char,
vendor_str: *const cty::c_char,
vendor_str_len: u8,
version: *const cty::c_char,
fw_ok: bool,
) -> u32 {
let vendor = unwrap!(unsafe { from_c_array(vendor_str, vendor_str_len as usize) });
let version = unwrap!(unsafe { from_c_str(version) });
let bld_version = unwrap!(unsafe { from_c_str(bld_version) });
ModelUI::screen_intro(bld_version, vendor, version, fw_ok)
}
#[no_mangle]
extern "C" fn screen_boot_empty(fading: bool) {
ModelUI::screen_boot_empty(fading)
}
#[no_mangle]
extern "C" fn screen_wipe_progress(progress: u16, initialize: bool) {
ModelUI::screen_wipe_progress(progress, initialize)
}
#[no_mangle]
extern "C" fn screen_install_progress(progress: u16, initialize: bool, initial_setup: bool) {
ModelUI::screen_install_progress(progress, initialize, initial_setup)
}
#[no_mangle]
extern "C" fn screen_connect(initial_setup: bool) {
ModelUI::screen_connect(initial_setup)
}
#[no_mangle]
extern "C" fn screen_wipe_success() {
ModelUI::screen_wipe_success()
}
#[no_mangle]
extern "C" fn screen_wipe_fail() {
ModelUI::screen_wipe_fail()
}

@ -0,0 +1,60 @@
//! Reexporting the `screens` module according to the
//! current feature (Trezor model)
use crate::ui::{
component::image::Image,
display::{Color, Icon},
geometry::{Alignment2D, Point},
ui_features::{ModelUI, UIFeaturesCommon},
};
use crate::ui::util::from_c_str;
#[no_mangle]
extern "C" fn screen_fatal_error_rust(
title: *const cty::c_char,
msg: *const cty::c_char,
footer: *const cty::c_char,
) {
let title = unsafe { from_c_str(title) }.unwrap_or("");
let msg = unsafe { from_c_str(msg) }.unwrap_or("");
let footer = unsafe { from_c_str(footer) }.unwrap_or("");
ModelUI::screen_fatal_error(title, msg, footer);
}
#[no_mangle]
extern "C" fn screen_boot_full() {
ModelUI::screen_boot_full();
}
#[no_mangle]
extern "C" fn display_icon(
x: cty::int16_t,
y: cty::int16_t,
data: *const cty::uint8_t,
data_len: cty::uint32_t,
fg_color: cty::uint16_t,
bg_color: cty::uint16_t,
) {
let data_slice = unsafe { core::slice::from_raw_parts(data, data_len as usize) };
let icon = Icon::new(data_slice);
icon.draw(
Point::new(x, y),
Alignment2D::TOP_LEFT,
Color::from_u16(fg_color),
Color::from_u16(bg_color),
);
}
#[no_mangle]
extern "C" fn display_image(
x: cty::int16_t,
y: cty::int16_t,
data: *const cty::uint8_t,
data_len: cty::uint32_t,
) {
let data_slice = unsafe { core::slice::from_raw_parts(data, data_len as usize) };
let image = Image::new(data_slice);
image.draw(Point::new(x, y), Alignment2D::TOP_LEFT);
}

@ -0,0 +1,4 @@
pub mod common_c;
#[cfg(feature = "bootloader")]
pub mod bootloader_c;

@ -117,18 +117,6 @@ pub fn render_toif(toif: &Toif, center: Point, fg_color: Color, bg_color: Color)
pixeldata_dirty();
}
#[no_mangle]
extern "C" fn display_image(
x: cty::int16_t,
y: cty::int16_t,
data: *const cty::uint8_t,
data_len: cty::uint32_t,
) {
let data_slice = unsafe { core::slice::from_raw_parts(data, data_len as usize) };
let image = Image::new(data_slice);
image.draw(Point::new(x, y), Alignment2D::TOP_LEFT);
}
#[cfg(feature = "dma2d")]
pub fn image(image: &Image, center: Point) {
let r = Rect::from_center_and_size(center, image.toif.size());
@ -303,25 +291,6 @@ impl<'i> Toif<'i> {
}
}
#[no_mangle]
extern "C" fn display_icon(
x: cty::int16_t,
y: cty::int16_t,
data: *const cty::uint8_t,
data_len: cty::uint32_t,
fg_color: cty::uint16_t,
bg_color: cty::uint16_t,
) {
let data_slice = unsafe { core::slice::from_raw_parts(data, data_len as usize) };
let icon = Icon::new(data_slice);
icon.draw(
Point::new(x, y),
Alignment2D::TOP_LEFT,
Color::from_u16(fg_color),
Color::from_u16(bg_color),
);
}
#[derive(PartialEq, Eq, Clone, Copy)]
pub struct Icon {
pub toif: Toif<'static>,

@ -9,22 +9,11 @@ use crate::ui::event::TouchEvent;
use crate::ui::{
component::{Component, Event, EventCtx, Never},
display,
geometry::Rect,
ui_features::ModelUI,
UIFeaturesCommon,
};
use num_traits::ToPrimitive;
pub trait SimplifiedFeatures {
fn fadein() {}
fn fadeout() {}
const SCREEN: Rect;
}
#[cfg(all(feature = "model_tr", not(feature = "model_tt")))]
pub type ModelFeatures = crate::ui::model_tr::ModelTRFeatures;
#[cfg(feature = "model_tt")]
pub type ModelFeatures = crate::ui::model_tt::ModelTTFeatures;
pub trait ReturnToC {
fn return_to_c(self) -> u32;
}
@ -79,12 +68,12 @@ where
F: Component,
F::Msg: ReturnToC,
{
frame.place(ModelFeatures::SCREEN);
ModelFeatures::fadeout();
frame.place(ModelUI::SCREEN);
ModelUI::fadeout();
display::sync();
frame.paint();
display::refresh();
ModelFeatures::fadein();
ModelUI::fadein();
#[cfg(feature = "button")]
while button_eval().is_some() {}
@ -115,14 +104,14 @@ pub fn show<F>(frame: &mut F, fading: bool)
where
F: Component,
{
frame.place(ModelFeatures::SCREEN);
frame.place(ModelUI::SCREEN);
if fading {
ModelFeatures::fadeout()
ModelUI::fadeout()
};
display::sync();
frame.paint();
display::refresh();
if fading {
ModelFeatures::fadein()
ModelUI::fadein()
};
}

@ -8,13 +8,16 @@ pub mod display;
pub mod event;
pub mod geometry;
pub mod lerp;
pub mod screens;
#[macro_use]
pub mod util;
pub mod layout;
mod api;
#[cfg(feature = "model_tr")]
pub mod model_tr;
#[cfg(feature = "model_tt")]
pub mod model_tt;
pub mod ui_features;
pub use ui_features::UIFeaturesCommon;

@ -1,7 +1,6 @@
use heapless::String;
use crate::{
strutil::hexlify,
trezorhal::secbool::secbool,
ui::{
component::{connect::Connect, Label, LineBreaking::BreakWordsNoHyphen},
@ -10,7 +9,6 @@ use crate::{
display::{self, Color, Font, Icon},
geometry::{Alignment2D, Offset, Point, Rect},
layout::simplified::{run, show, ReturnToC},
util::{from_c_array, from_c_str},
},
};
@ -23,12 +21,14 @@ use super::{
bootloader::{BLD_BG, BLD_FG, ICON_ALERT, ICON_SPINNER, ICON_SUCCESS},
ICON_ARM_LEFT, ICON_ARM_RIGHT, TEXT_BOLD, TEXT_NORMAL, WHITE,
},
ModelTRFeatures,
};
mod intro;
mod menu;
mod welcome;
use crate::ui::ui_features::UIFeaturesBootloader;
use intro::Intro;
use menu::Menu;
use welcome::Welcome;
@ -41,285 +41,249 @@ impl ReturnToC for ConfirmMsg {
}
}
#[no_mangle]
extern "C" fn screen_install_confirm(
vendor_str: *const cty::c_char,
vendor_str_len: u8,
version: *const cty::c_char,
fingerprint: *const cty::uint8_t,
should_keep_seed: bool,
is_newvendor: bool,
version_cmp: cty::c_int,
) -> u32 {
let text = unwrap!(unsafe { from_c_array(vendor_str, vendor_str_len as usize) });
let version = unwrap!(unsafe { from_c_str(version) });
let mut fingerprint_buffer: [u8; 64] = [0; 64];
let fingerprint_str = unsafe {
let fingerprint_slice = core::slice::from_raw_parts(fingerprint, 32);
hexlify(fingerprint_slice, &mut fingerprint_buffer);
core::str::from_utf8_unchecked(fingerprint_buffer.as_ref())
};
let mut version_str: BootloaderString = String::new();
unwrap!(version_str.push_str("Firmware version "));
unwrap!(version_str.push_str(version));
unwrap!(version_str.push_str("\nby "));
unwrap!(version_str.push_str(text));
let title_str = if is_newvendor {
"CHANGE FW VENDOR"
} else if version_cmp > 0 {
"UPDATE FIRMWARE"
} else if version_cmp == 0 {
"REINSTALL FW"
} else {
"DOWNGRADE FW"
};
let message = Label::left_aligned(version_str.as_str(), TEXT_NORMAL).vertically_centered();
let fingerprint = Label::left_aligned(
fingerprint_str,
TEXT_NORMAL.with_line_breaking(BreakWordsNoHyphen),
)
.vertically_centered();
let alert =
(!should_keep_seed).then_some(Label::left_aligned("Seed will be erased!", TEXT_NORMAL));
let mut frame = Confirm::new(BLD_BG, title_str, message, alert, "INSTALL", false)
.with_info_screen("FW FINGERPRINT", fingerprint);
run(&mut frame)
impl ModelTRFeatures {
fn screen_progress(
text: &str,
text2: &str,
progress: u16,
initialize: bool,
fg_color: Color,
bg_color: Color,
icon: Option<(Icon, Color)>,
) {
if initialize {
display::rect_fill(SCREEN, bg_color);
}
let progress = if progress < 20 { 20 } else { progress };
display::rect_rounded2_partial(
Rect::new(
SCREEN.top_center() + Offset::new(-9, 3),
SCREEN.top_center() + Offset::new(9, 18 + 3),
),
fg_color,
bg_color,
((100_u32 * progress as u32) / 1000) as _,
icon,
);
display::text_center(
SCREEN.center() + Offset::y(8),
text,
Font::BOLD,
fg_color,
bg_color,
);
display::text_center(
SCREEN.center() + Offset::y(20),
text2,
Font::BOLD,
fg_color,
bg_color,
);
display::refresh();
}
}
#[no_mangle]
extern "C" fn screen_wipe_confirm() -> u32 {
let message =
Label::left_aligned("Seed and firmware will be erased!", TEXT_NORMAL).vertically_centered();
impl UIFeaturesBootloader for ModelTRFeatures {
fn screen_welcome() {
let mut frame = Welcome::new();
show(&mut frame, true);
}
let mut frame = Confirm::new(BLD_BG, "FACTORY RESET", message, None, "RESET", false);
fn bld_continue_label(bg_color: Color) {
display::text_center(
Point::new(constant::WIDTH / 2, HEIGHT - 2),
"CONTINUE",
Font::NORMAL,
WHITE,
bg_color,
);
ICON_ARM_LEFT.draw(
Point::new(constant::WIDTH / 2 - 36, HEIGHT - 6),
Alignment2D::TOP_LEFT,
WHITE,
bg_color,
);
ICON_ARM_RIGHT.draw(
Point::new(constant::WIDTH / 2 + 25, HEIGHT - 6),
Alignment2D::TOP_LEFT,
WHITE,
bg_color,
);
}
run(&mut frame)
}
fn screen_install_success(restart_seconds: u8, _initial_setup: bool, complete_draw: bool) {
let mut reboot_msg = BootloaderString::new();
#[no_mangle]
extern "C" fn screen_unlock_bootloader_confirm() -> u32 {
let message =
Label::left_aligned("This action cannot be undone!", TEXT_NORMAL).vertically_centered();
if restart_seconds >= 1 {
unwrap!(reboot_msg.push_str("Restarting in "));
// in practice, restart_seconds is 5 or less so this is fine
let seconds_char = b'0' + restart_seconds % 10;
unwrap!(reboot_msg.push(seconds_char as char));
} else {
unwrap!(reboot_msg.push_str("Reconnect the device"));
}
let mut frame = Confirm::new(BLD_BG, "UNLOCK BOOTLOADER?", message, None, "UNLOCK", true);
let title = Label::centered("Firmware installed", TEXT_BOLD).vertically_centered();
run(&mut frame)
}
let content = Label::centered(reboot_msg.as_str(), TEXT_NORMAL).vertically_centered();
#[no_mangle]
extern "C" fn screen_unlock_bootloader_success() {
let title = Label::centered("Bootloader unlocked", TEXT_BOLD).vertically_centered();
let content =
Label::centered("Please reconnect the\ndevice", TEXT_NORMAL).vertically_centered();
let mut frame =
ResultScreen::new(BLD_FG, BLD_BG, ICON_SPINNER, title, content, complete_draw);
show(&mut frame, false);
}
let mut frame = ResultScreen::new(BLD_FG, BLD_BG, ICON_SPINNER, title, content, true);
show(&mut frame, false);
}
fn screen_install_fail() {
let title = Label::centered("Install failed", TEXT_BOLD).vertically_centered();
#[no_mangle]
extern "C" fn screen_menu(firmware_present: secbool) -> u32 {
run(&mut Menu::new(firmware_present))
}
let content =
Label::centered("Please reconnect\nthe device", TEXT_NORMAL).vertically_centered();
#[no_mangle]
extern "C" fn screen_intro(
bld_version: *const cty::c_char,
vendor_str: *const cty::c_char,
vendor_str_len: u8,
version: *const cty::c_char,
fw_ok: bool,
) -> u32 {
let vendor = unwrap!(unsafe { from_c_array(vendor_str, vendor_str_len as usize) });
let version = unwrap!(unsafe { from_c_str(version) });
let bld_version = unwrap!(unsafe { from_c_str(bld_version) });
let mut title_str: BootloaderString = String::new();
unwrap!(title_str.push_str("BOOTLOADER "));
unwrap!(title_str.push_str(bld_version));
let mut version_str: BootloaderString = String::new();
unwrap!(version_str.push_str("Firmware version "));
unwrap!(version_str.push_str(version));
unwrap!(version_str.push_str("\nby "));
unwrap!(version_str.push_str(vendor));
let mut frame = Intro::new(title_str.as_str(), version_str.as_str(), fw_ok);
run(&mut frame)
}
let mut frame = ResultScreen::new(BLD_FG, BLD_BG, ICON_ALERT, title, content, true);
show(&mut frame, false);
}
fn screen_progress(
text: &str,
text2: &str,
progress: u16,
initialize: bool,
fg_color: Color,
bg_color: Color,
icon: Option<(Icon, Color)>,
) {
if initialize {
display::rect_fill(SCREEN, bg_color);
fn screen_install_confirm(
vendor: &str,
version: &str,
fingerprint: &str,
should_keep_seed: bool,
is_newvendor: bool,
version_cmp: i32,
) -> u32 {
let mut version_str: BootloaderString = String::new();
unwrap!(version_str.push_str("Firmware version "));
unwrap!(version_str.push_str(version));
unwrap!(version_str.push_str("\nby "));
unwrap!(version_str.push_str(vendor));
let title_str = if is_newvendor {
"CHANGE FW VENDOR"
} else if version_cmp > 0 {
"UPDATE FIRMWARE"
} else if version_cmp == 0 {
"REINSTALL FW"
} else {
"DOWNGRADE FW"
};
let message = Label::left_aligned(version_str.as_str(), TEXT_NORMAL).vertically_centered();
let fingerprint = Label::left_aligned(
fingerprint,
TEXT_NORMAL.with_line_breaking(BreakWordsNoHyphen),
)
.vertically_centered();
let alert =
(!should_keep_seed).then_some(Label::left_aligned("Seed will be erased!", TEXT_NORMAL));
let mut frame = Confirm::new(BLD_BG, title_str, message, alert, "INSTALL", false)
.with_info_screen("FW FINGERPRINT", fingerprint);
run(&mut frame)
}
let progress = if progress < 20 { 20 } else { progress };
display::rect_rounded2_partial(
Rect::new(
SCREEN.top_center() + Offset::new(-9, 3),
SCREEN.top_center() + Offset::new(9, 18 + 3),
),
fg_color,
bg_color,
((100_u32 * progress as u32) / 1000) as _,
icon,
);
display::text_center(
SCREEN.center() + Offset::y(8),
text,
Font::BOLD,
fg_color,
bg_color,
);
display::text_center(
SCREEN.center() + Offset::y(20),
text2,
Font::BOLD,
fg_color,
bg_color,
);
display::refresh();
}
fn screen_wipe_confirm() -> u32 {
let message = Label::left_aligned("Seed and firmware will be erased!", TEXT_NORMAL)
.vertically_centered();
#[no_mangle]
extern "C" fn screen_install_progress(progress: u16, initialize: bool, _initial_setup: bool) {
screen_progress(
"Installing",
"firmware",
progress,
initialize,
BLD_FG,
BLD_BG,
Some((ICON_SUCCESS, BLD_FG)),
);
}
let mut frame = Confirm::new(BLD_BG, "FACTORY RESET", message, None, "RESET", false);
#[no_mangle]
extern "C" fn screen_wipe_progress(progress: u16, initialize: bool) {
screen_progress(
"Resetting",
"Trezor",
progress,
initialize,
BLD_FG,
BLD_BG,
Some((ICON_SUCCESS, BLD_FG)),
);
}
run(&mut frame)
}
#[no_mangle]
extern "C" fn screen_connect(_initial_setup: bool) {
let mut frame = Connect::new("Waiting for host...", BLD_FG, BLD_BG);
show(&mut frame, false);
}
fn screen_unlock_bootloader_confirm() -> u32 {
let message =
Label::left_aligned("This action cannot be undone!", TEXT_NORMAL).vertically_centered();
let mut frame = Confirm::new(BLD_BG, "UNLOCK BOOTLOADER?", message, None, "UNLOCK", true);
#[no_mangle]
extern "C" fn screen_wipe_success() {
let title = Label::centered("Trezor Reset", TEXT_BOLD).vertically_centered();
run(&mut frame)
}
let content =
Label::centered("Please reconnect\nthe device", TEXT_NORMAL).vertically_centered();
fn screen_unlock_bootloader_success() {
let title = Label::centered("Bootloader unlocked", TEXT_BOLD).vertically_centered();
let mut frame = ResultScreen::new(BLD_FG, BLD_BG, ICON_SPINNER, title, content, true);
show(&mut frame, false);
}
let content =
Label::centered("Please reconnect the\ndevice", TEXT_NORMAL).vertically_centered();
#[no_mangle]
extern "C" fn screen_wipe_fail() {
let title = Label::centered("Reset failed", TEXT_BOLD).vertically_centered();
let mut frame = ResultScreen::new(BLD_FG, BLD_BG, ICON_SPINNER, title, content, true);
show(&mut frame, false);
}
let content =
Label::centered("Please reconnect\nthe device", TEXT_NORMAL).vertically_centered();
fn screen_menu(firmware_present: secbool) -> u32 {
run(&mut Menu::new(firmware_present))
}
let mut frame = ResultScreen::new(BLD_FG, BLD_BG, ICON_ALERT, title, content, true);
show(&mut frame, false);
}
fn screen_intro(bld_version: &str, vendor: &str, version: &str, fw_ok: bool) -> u32 {
let mut title_str: BootloaderString = String::new();
unwrap!(title_str.push_str("BOOTLOADER "));
unwrap!(title_str.push_str(bld_version));
#[no_mangle]
extern "C" fn screen_boot_empty(_fading: bool) {
display::rect_fill(SCREEN, BLD_BG);
let mut version_str: BootloaderString = String::new();
unwrap!(version_str.push_str("Firmware version "));
unwrap!(version_str.push_str(version));
unwrap!(version_str.push_str("\nby "));
unwrap!(version_str.push_str(vendor));
let mut frame = WelcomeScreen::new(true);
show(&mut frame, false);
}
let mut frame = Intro::new(title_str.as_str(), version_str.as_str(), fw_ok);
run(&mut frame)
}
#[no_mangle]
extern "C" fn screen_install_fail() {
let title = Label::centered("Install failed", TEXT_BOLD).vertically_centered();
fn screen_boot_empty(_fading: bool) {
display::rect_fill(SCREEN, BLD_BG);
let content =
Label::centered("Please reconnect\nthe device", TEXT_NORMAL).vertically_centered();
let mut frame = WelcomeScreen::new(true);
show(&mut frame, false);
}
let mut frame = ResultScreen::new(BLD_FG, BLD_BG, ICON_ALERT, title, content, true);
show(&mut frame, false);
}
fn screen_wipe_progress(progress: u16, initialize: bool) {
ModelTRFeatures::screen_progress(
"Resetting",
"Trezor",
progress,
initialize,
BLD_FG,
BLD_BG,
Some((ICON_SUCCESS, BLD_FG)),
);
}
#[no_mangle]
extern "C" fn screen_install_success(
restart_seconds: u8,
_initial_setup: bool,
complete_draw: bool,
) {
let mut reboot_msg = BootloaderString::new();
if restart_seconds >= 1 {
unwrap!(reboot_msg.push_str("Restarting in "));
// in practice, restart_seconds is 5 or less so this is fine
let seconds_char = b'0' + restart_seconds % 10;
unwrap!(reboot_msg.push(seconds_char as char));
} else {
unwrap!(reboot_msg.push_str("Reconnect the device"));
fn screen_install_progress(progress: u16, initialize: bool, _initial_setup: bool) {
ModelTRFeatures::screen_progress(
"Installing",
"firmware",
progress,
initialize,
BLD_FG,
BLD_BG,
Some((ICON_SUCCESS, BLD_FG)),
);
}
let title = Label::centered("Firmware installed", TEXT_BOLD).vertically_centered();
fn screen_connect(_initial_setup: bool) {
let mut frame = Connect::new("Waiting for host...", BLD_FG, BLD_BG);
show(&mut frame, false);
}
let content = Label::centered(reboot_msg.as_str(), TEXT_NORMAL).vertically_centered();
fn screen_wipe_success() {
let title = Label::centered("Trezor Reset", TEXT_BOLD).vertically_centered();
let mut frame = ResultScreen::new(BLD_FG, BLD_BG, ICON_SPINNER, title, content, complete_draw);
show(&mut frame, false);
}
let content =
Label::centered("Please reconnect\nthe device", TEXT_NORMAL).vertically_centered();
#[no_mangle]
extern "C" fn screen_welcome() {
let mut frame = Welcome::new();
show(&mut frame, false);
}
let mut frame = ResultScreen::new(BLD_FG, BLD_BG, ICON_SPINNER, title, content, true);
show(&mut frame, false);
}
fn screen_wipe_fail() {
let title = Label::centered("Reset failed", TEXT_BOLD).vertically_centered();
#[no_mangle]
extern "C" fn bld_continue_label(bg_color: cty::uint16_t) {
display::text_center(
Point::new(constant::WIDTH / 2, HEIGHT - 2),
"CONTINUE",
Font::NORMAL,
WHITE,
Color::from_u16(bg_color),
);
ICON_ARM_LEFT.draw(
Point::new(constant::WIDTH / 2 - 36, HEIGHT - 6),
Alignment2D::TOP_LEFT,
WHITE,
Color::from_u16(bg_color),
);
ICON_ARM_RIGHT.draw(
Point::new(constant::WIDTH / 2 + 25, HEIGHT - 6),
Alignment2D::TOP_LEFT,
WHITE,
Color::from_u16(bg_color),
);
let content =
Label::centered("Please reconnect\nthe device", TEXT_NORMAL).vertically_centered();
let mut frame = ResultScreen::new(BLD_FG, BLD_BG, ICON_ALERT, title, content, true);
show(&mut frame, false);
}
}

@ -1,4 +1,4 @@
use super::{geometry::Rect, layout::simplified::SimplifiedFeatures};
use super::{geometry::Rect, UIFeaturesCommon};
#[cfg(feature = "bootloader")]
pub mod bootloader;
@ -7,11 +7,19 @@ pub mod component;
pub mod constant;
#[cfg(feature = "micropython")]
pub mod layout;
pub mod screens;
mod screens;
pub mod theme;
pub struct ModelTRFeatures {}
impl SimplifiedFeatures for ModelTRFeatures {
impl UIFeaturesCommon for ModelTRFeatures {
const SCREEN: Rect = constant::SCREEN;
fn screen_fatal_error(title: &str, msg: &str, footer: &str) {
screens::screen_fatal_error(title, msg, footer);
}
fn screen_boot_full() {
screens::screen_boot_full();
}
}

@ -30,8 +30,7 @@ pub fn screen_fatal_error(title: &str, msg: &str, footer: &str) {
frame.paint();
}
#[no_mangle]
extern "C" fn screen_boot_full() {
pub fn screen_boot_full() {
let mut frame = WelcomeScreen::new(false);
frame.place(screen());
display::sync();

@ -1,14 +1,12 @@
use heapless::String;
use crate::{
strutil::hexlify,
trezorhal::secbool::secbool,
ui::{
component::{connect::Connect, Label},
display::{self, Color, Font, Icon},
geometry::{Point, Rect},
layout::simplified::{run, show, SimplifiedFeatures as _},
util::{from_c_array, from_c_str},
layout::simplified::{run, show},
},
};
@ -30,6 +28,7 @@ use super::{
ModelTTFeatures,
};
use crate::ui::{ui_features::UIFeaturesBootloader, UIFeaturesCommon};
use intro::Intro;
use menu::Menu;
@ -43,296 +42,267 @@ const RECONNECT_MESSAGE: &str = "PLEASE RECONNECT\nTHE DEVICE";
const SCREEN: Rect = ModelTTFeatures::SCREEN;
#[no_mangle]
extern "C" fn screen_install_confirm(
vendor_str: *const cty::c_char,
vendor_str_len: u8,
version: *const cty::c_char,
fingerprint: *const cty::uint8_t,
should_keep_seed: bool,
is_newvendor: bool,
version_cmp: cty::c_int,
) -> u32 {
let text = unwrap!(unsafe { from_c_array(vendor_str, vendor_str_len as usize) });
let version = unwrap!(unsafe { from_c_str(version) });
let mut fingerprint_buffer: [u8; 64] = [0; 64];
let fingerprint_str = unsafe {
let fingerprint_slice = core::slice::from_raw_parts(fingerprint, 32);
hexlify(fingerprint_slice, &mut fingerprint_buffer);
core::str::from_utf8_unchecked(fingerprint_buffer.as_ref())
};
let mut version_str: BootloaderString = String::new();
unwrap!(version_str.push_str("Firmware version "));
unwrap!(version_str.push_str(version));
unwrap!(version_str.push_str("\nby "));
unwrap!(version_str.push_str(text));
let title_str = if is_newvendor {
"CHANGE FW\nVENDOR"
} else if version_cmp > 0 {
"UPDATE FIRMWARE"
} else if version_cmp == 0 {
"REINSTALL FW"
} else {
"DOWNGRADE FW"
};
let title = Label::left_aligned(title_str, TEXT_BOLD).vertically_centered();
let msg = Label::left_aligned(version_str.as_ref(), TEXT_NORMAL);
let alert =
(!should_keep_seed).then_some(Label::left_aligned("SEED WILL BE ERASED!", TEXT_BOLD));
let (left, right) = if should_keep_seed {
let l = Button::with_text("CANCEL").styled(button_bld());
let r = Button::with_text("INSTALL").styled(button_confirm());
(l, r)
} else {
let l = Button::with_icon(Icon::new(X24)).styled(button_bld());
let r = Button::with_icon(Icon::new(CHECK24)).styled(button_confirm());
(l, r)
};
let mut frame = Confirm::new(BLD_BG, left, right, ConfirmTitle::Text(title), msg).with_info(
"FW FINGERPRINT",
fingerprint_str,
button_bld_menu(),
);
if let Some(alert) = alert {
frame = frame.with_alert(alert);
impl ModelTTFeatures {
fn screen_progress(
text: &str,
progress: u16,
initialize: bool,
fg_color: Color,
bg_color: Color,
icon: Option<(Icon, Color)>,
) {
if initialize {
ModelTTFeatures::fadeout();
display::rect_fill(SCREEN, bg_color);
}
display::text_center(
Point::new(SCREEN.width() / 2, SCREEN.height() - 45),
text,
Font::NORMAL,
fg_color,
bg_color,
);
display::loader(progress, -20, fg_color, bg_color, icon);
display::refresh();
if initialize {
ModelTTFeatures::fadein();
}
}
run(&mut frame)
fn screen_install_success_bld(msg: &str, complete_draw: bool) {
let mut frame = ResultScreen::new(
&RESULT_FW_INSTALL,
Icon::new(CHECK40),
"Firmware installed\nsuccessfully",
Label::centered(msg, RESULT_FW_INSTALL.title_style()).vertically_centered(),
complete_draw,
);
show(&mut frame, complete_draw);
}
fn screen_install_success_initial(msg: &str, complete_draw: bool) {
let mut frame = ResultScreen::new(
&RESULT_INITIAL,
Icon::new(CHECK40),
"Firmware installed\nsuccessfully",
Label::centered(msg, RESULT_INITIAL.title_style()).vertically_centered(),
complete_draw,
);
show(&mut frame, complete_draw);
}
}
#[no_mangle]
extern "C" fn screen_wipe_confirm() -> u32 {
let icon = Icon::new(FIRE40);
impl UIFeaturesBootloader for ModelTTFeatures {
fn screen_welcome() {
let mut frame = Welcome::new();
show(&mut frame, true);
}
let msg = Label::centered(
"Are you sure you want to factory reset the device?",
TEXT_WIPE_NORMAL,
);
let alert = Label::centered("SEED AND FIRMWARE\nWILL BE ERASED!", TEXT_WIPE_BOLD);
fn bld_continue_label(bg_color: Color) {
display::text_center(
Point::new(SCREEN.width() / 2, SCREEN.height() - 5),
"click to continue ...",
Font::NORMAL,
WHITE,
bg_color,
);
}
let right = Button::with_text("RESET").styled(button_wipe_confirm());
let left = Button::with_text("CANCEL").styled(button_wipe_cancel());
fn screen_install_success(restart_seconds: u8, initial_setup: bool, complete_draw: bool) {
let mut reboot_msg = BootloaderString::new();
if restart_seconds >= 1 {
unwrap!(reboot_msg.push_str("RESTARTING IN "));
// in practice, restart_seconds is 5 or less so this is fine
let seconds_char = b'0' + restart_seconds % 10;
unwrap!(reboot_msg.push(seconds_char as char));
} else {
unwrap!(reboot_msg.push_str(RECONNECT_MESSAGE));
}
if initial_setup {
ModelTTFeatures::screen_install_success_initial(reboot_msg.as_str(), complete_draw)
} else {
ModelTTFeatures::screen_install_success_bld(reboot_msg.as_str(), complete_draw)
}
display::refresh();
}
let mut frame =
Confirm::new(BLD_WIPE_COLOR, left, right, ConfirmTitle::Icon(icon), msg).with_alert(alert);
fn screen_install_fail() {
let mut frame = ResultScreen::new(
&RESULT_FW_INSTALL,
Icon::new(WARNING40),
"Firmware installation was not successful",
Label::centered(RECONNECT_MESSAGE, RESULT_FW_INSTALL.title_style())
.vertically_centered(),
true,
);
show(&mut frame, true);
}
run(&mut frame)
}
fn screen_install_confirm(
vendor: &str,
version: &str,
fingerprint: &str,
should_keep_seed: bool,
is_newvendor: bool,
version_cmp: i32,
) -> u32 {
let mut version_str: BootloaderString = String::new();
unwrap!(version_str.push_str("Firmware version "));
unwrap!(version_str.push_str(version));
unwrap!(version_str.push_str("\nby "));
unwrap!(version_str.push_str(vendor));
let title_str = if is_newvendor {
"CHANGE FW\nVENDOR"
} else if version_cmp > 0 {
"UPDATE FIRMWARE"
} else if version_cmp == 0 {
"REINSTALL FW"
} else {
"DOWNGRADE FW"
};
let title = Label::left_aligned(title_str, TEXT_BOLD).vertically_centered();
let msg = Label::left_aligned(version_str.as_ref(), TEXT_NORMAL);
let alert =
(!should_keep_seed).then_some(Label::left_aligned("SEED WILL BE ERASED!", TEXT_BOLD));
let (left, right) = if should_keep_seed {
let l = Button::with_text("CANCEL").styled(button_bld());
let r = Button::with_text("INSTALL").styled(button_confirm());
(l, r)
} else {
let l = Button::with_icon(Icon::new(X24)).styled(button_bld());
let r = Button::with_icon(Icon::new(CHECK24)).styled(button_confirm());
(l, r)
};
let mut frame = Confirm::new(BLD_BG, left, right, ConfirmTitle::Text(title), msg)
.with_info("FW FINGERPRINT", fingerprint, button_bld_menu());
if let Some(alert) = alert {
frame = frame.with_alert(alert);
}
run(&mut frame)
}
#[no_mangle]
extern "C" fn screen_menu(firmware_present: secbool) -> u32 {
run(&mut Menu::new(firmware_present))
}
fn screen_wipe_confirm() -> u32 {
let icon = Icon::new(FIRE40);
#[no_mangle]
extern "C" fn screen_intro(
bld_version: *const cty::c_char,
vendor_str: *const cty::c_char,
vendor_str_len: u8,
version: *const cty::c_char,
fw_ok: bool,
) -> u32 {
let vendor = unwrap!(unsafe { from_c_array(vendor_str, vendor_str_len as usize) });
let version = unwrap!(unsafe { from_c_str(version) });
let bld_version = unwrap!(unsafe { from_c_str(bld_version) });
let mut title_str: BootloaderString = String::new();
unwrap!(title_str.push_str("BOOTLOADER "));
unwrap!(title_str.push_str(bld_version));
let mut version_str: BootloaderString = String::new();
unwrap!(version_str.push_str("Firmware version "));
unwrap!(version_str.push_str(version));
unwrap!(version_str.push_str("\nby "));
unwrap!(version_str.push_str(vendor));
let mut frame = Intro::new(title_str.as_str(), version_str.as_str(), fw_ok);
run(&mut frame)
}
let msg = Label::centered(
"Are you sure you want to factory reset the device?",
TEXT_WIPE_NORMAL,
);
let alert = Label::centered("SEED AND FIRMWARE\nWILL BE ERASED!", TEXT_WIPE_BOLD);
let right = Button::with_text("RESET").styled(button_wipe_confirm());
let left = Button::with_text("CANCEL").styled(button_wipe_cancel());
let mut frame = Confirm::new(BLD_WIPE_COLOR, left, right, ConfirmTitle::Icon(icon), msg)
.with_alert(alert);
fn screen_progress(
text: &str,
progress: u16,
initialize: bool,
fg_color: Color,
bg_color: Color,
icon: Option<(Icon, Color)>,
) {
if initialize {
ModelTTFeatures::fadeout();
display::rect_fill(SCREEN, bg_color);
run(&mut frame)
}
display::text_center(
Point::new(SCREEN.width() / 2, SCREEN.height() - 45),
text,
Font::NORMAL,
fg_color,
bg_color,
);
display::loader(progress, -20, fg_color, bg_color, icon);
display::refresh();
if initialize {
ModelTTFeatures::fadein();
fn screen_unlock_bootloader_confirm() -> u32 {
unimplemented!();
}
}
#[no_mangle]
extern "C" fn screen_install_progress(progress: u16, initialize: bool, initial_setup: bool) {
let bg_color = if initial_setup { WELCOME_COLOR } else { BLD_BG };
let fg_color = if initial_setup { FG } else { BLD_FG };
screen_progress(
"Installing firmware",
progress,
initialize,
fg_color,
bg_color,
Some((Icon::new(DOWNLOAD32), fg_color)),
)
}
fn screen_unlock_bootloader_success() {
unimplemented!();
}
#[no_mangle]
extern "C" fn screen_wipe_progress(progress: u16, initialize: bool) {
screen_progress(
"Resetting Trezor",
progress,
initialize,
BLD_FG,
BLD_WIPE_COLOR,
Some((Icon::new(FIRE32), BLD_FG)),
)
}
fn screen_menu(firmware_present: secbool) -> u32 {
run(&mut Menu::new(firmware_present))
}
#[no_mangle]
extern "C" fn screen_connect(initial_setup: bool) {
let bg = if initial_setup { WELCOME_COLOR } else { BLD_BG };
let mut frame = Connect::new("Waiting for host...", BLD_TITLE_COLOR, bg);
show(&mut frame, true);
}
fn screen_intro(bld_version: &str, vendor: &str, version: &str, fw_ok: bool) -> u32 {
let mut title_str: BootloaderString = String::new();
unwrap!(title_str.push_str("BOOTLOADER "));
unwrap!(title_str.push_str(bld_version));
#[no_mangle]
extern "C" fn screen_wipe_success() {
let mut frame = ResultScreen::new(
&RESULT_WIPE,
Icon::new(CHECK40),
"Trezor reset\nsuccessfully",
Label::centered(RECONNECT_MESSAGE, RESULT_WIPE.title_style()).vertically_centered(),
true,
);
show(&mut frame, true);
}
let mut version_str: BootloaderString = String::new();
unwrap!(version_str.push_str("Firmware version "));
unwrap!(version_str.push_str(version));
unwrap!(version_str.push_str("\nby "));
unwrap!(version_str.push_str(vendor));
#[no_mangle]
extern "C" fn screen_wipe_fail() {
let mut frame = ResultScreen::new(
&RESULT_WIPE,
Icon::new(WARNING40),
"Trezor reset was\nnot successful",
Label::centered(RECONNECT_MESSAGE, RESULT_WIPE.title_style()).vertically_centered(),
true,
);
show(&mut frame, true);
}
let mut frame = Intro::new(title_str.as_str(), version_str.as_str(), fw_ok);
#[no_mangle]
extern "C" fn screen_boot_empty(fading: bool) {
if fading {
ModelTTFeatures::fadeout();
run(&mut frame)
}
display::rect_fill(SCREEN, BLACK);
fn screen_boot_empty(fading: bool) {
if fading {
ModelTTFeatures::fadeout();
}
let mut frame = WelcomeScreen::new(true);
show(&mut frame, false);
display::rect_fill(SCREEN, BLACK);
if fading {
ModelTTFeatures::fadein();
} else {
display::set_backlight(BACKLIGHT_NORMAL);
}
display::refresh();
}
#[no_mangle]
extern "C" fn screen_install_fail() {
let mut frame = ResultScreen::new(
&RESULT_FW_INSTALL,
Icon::new(WARNING40),
"Firmware installation was not successful",
Label::centered(RECONNECT_MESSAGE, RESULT_FW_INSTALL.title_style()).vertically_centered(),
true,
);
show(&mut frame, true);
}
let mut frame = WelcomeScreen::new(true);
show(&mut frame, false);
fn screen_install_success_bld(msg: &str, complete_draw: bool) {
let mut frame = ResultScreen::new(
&RESULT_FW_INSTALL,
Icon::new(CHECK40),
"Firmware installed\nsuccessfully",
Label::centered(msg, RESULT_FW_INSTALL.title_style()).vertically_centered(),
complete_draw,
);
show(&mut frame, complete_draw);
}
if fading {
ModelTTFeatures::fadein();
} else {
display::set_backlight(BACKLIGHT_NORMAL);
}
display::refresh();
}
fn screen_install_success_initial(msg: &str, complete_draw: bool) {
let mut frame = ResultScreen::new(
&RESULT_INITIAL,
Icon::new(CHECK40),
"Firmware installed\nsuccessfully",
Label::centered(msg, RESULT_INITIAL.title_style()).vertically_centered(),
complete_draw,
);
show(&mut frame, complete_draw);
}
fn screen_wipe_progress(progress: u16, initialize: bool) {
ModelTTFeatures::screen_progress(
"Resetting Trezor",
progress,
initialize,
BLD_FG,
BLD_WIPE_COLOR,
Some((Icon::new(FIRE32), BLD_FG)),
)
}
#[no_mangle]
extern "C" fn screen_install_success(
restart_seconds: u8,
initial_setup: bool,
complete_draw: bool,
) {
let mut reboot_msg = BootloaderString::new();
if restart_seconds >= 1 {
unwrap!(reboot_msg.push_str("RESTARTING IN "));
// in practice, restart_seconds is 5 or less so this is fine
let seconds_char = b'0' + restart_seconds % 10;
unwrap!(reboot_msg.push(seconds_char as char));
} else {
unwrap!(reboot_msg.push_str(RECONNECT_MESSAGE));
fn screen_install_progress(progress: u16, initialize: bool, initial_setup: bool) {
let bg_color = if initial_setup { WELCOME_COLOR } else { BLD_BG };
let fg_color = if initial_setup { FG } else { BLD_FG };
ModelTTFeatures::screen_progress(
"Installing firmware",
progress,
initialize,
fg_color,
bg_color,
Some((Icon::new(DOWNLOAD32), fg_color)),
)
}
if initial_setup {
screen_install_success_initial(reboot_msg.as_str(), complete_draw)
} else {
screen_install_success_bld(reboot_msg.as_str(), complete_draw)
fn screen_connect(initial_setup: bool) {
let bg = if initial_setup { WELCOME_COLOR } else { BLD_BG };
let mut frame = Connect::new("Waiting for host...", BLD_TITLE_COLOR, bg);
show(&mut frame, true);
}
display::refresh();
}
#[no_mangle]
extern "C" fn screen_welcome() {
let mut frame = Welcome::new();
show(&mut frame, true);
}
fn screen_wipe_success() {
let mut frame = ResultScreen::new(
&RESULT_WIPE,
Icon::new(CHECK40),
"Trezor reset\nsuccessfully",
Label::centered(RECONNECT_MESSAGE, RESULT_WIPE.title_style()).vertically_centered(),
true,
);
show(&mut frame, true);
}
#[no_mangle]
extern "C" fn bld_continue_label(bg_color: cty::uint16_t) {
display::text_center(
Point::new(SCREEN.width() / 2, SCREEN.height() - 5),
"click to continue ...",
Font::NORMAL,
WHITE,
Color::from_u16(bg_color),
);
fn screen_wipe_fail() {
let mut frame = ResultScreen::new(
&RESULT_WIPE,
Icon::new(WARNING40),
"Trezor reset was\nnot successful",
Label::centered(RECONNECT_MESSAGE, RESULT_WIPE.title_style()).vertically_centered(),
true,
);
show(&mut frame, true);
}
}

@ -1,4 +1,4 @@
use super::{geometry::Rect, layout::simplified::SimplifiedFeatures};
use super::{geometry::Rect, UIFeaturesCommon};
#[cfg(feature = "bootloader")]
pub mod bootloader;
@ -8,11 +8,11 @@ pub mod theme;
#[cfg(feature = "micropython")]
pub mod layout;
pub mod screens;
mod screens;
pub struct ModelTTFeatures {}
pub struct ModelTTFeatures;
impl SimplifiedFeatures for ModelTTFeatures {
impl UIFeaturesCommon for ModelTTFeatures {
fn fadein() {
#[cfg(feature = "backlight")]
crate::ui::display::fade_backlight_duration(theme::BACKLIGHT_NORMAL, 150);
@ -24,4 +24,12 @@ impl SimplifiedFeatures for ModelTTFeatures {
}
const SCREEN: Rect = constant::SCREEN;
fn screen_fatal_error(title: &str, msg: &str, footer: &str) {
screens::screen_fatal_error(title, msg, footer);
}
fn screen_boot_full() {
screens::screen_boot_full();
}
}

@ -34,8 +34,7 @@ pub fn screen_fatal_error(title: &str, msg: &str, footer: &str) {
frame.paint();
}
#[no_mangle]
extern "C" fn screen_boot_full() {
pub fn screen_boot_full() {
let mut frame = WelcomeScreen::new(false);
frame.place(screen());
display::sync();

@ -1,21 +0,0 @@
//! Reexporting the `screens` module according to the
//! current feature (Trezor model)
#[cfg(all(feature = "model_tr", not(feature = "model_tt")))]
pub use super::model_tr::screens::*;
#[cfg(feature = "model_tt")]
pub use super::model_tt::screens::*;
use crate::ui::util::from_c_str;
#[no_mangle]
extern "C" fn screen_fatal_error_rust(
title: *const cty::c_char,
msg: *const cty::c_char,
footer: *const cty::c_char,
) {
let title = unsafe { from_c_str(title) }.unwrap_or("");
let msg = unsafe { from_c_str(msg) }.unwrap_or("");
let footer = unsafe { from_c_str(footer) }.unwrap_or("");
screen_fatal_error(title, msg, footer);
}

@ -0,0 +1,62 @@
use crate::ui::geometry::Rect;
#[cfg(feature = "bootloader")]
use crate::{trezorhal::secbool::secbool, ui::display::Color};
pub trait UIFeaturesCommon {
fn fadein() {}
fn fadeout() {}
const SCREEN: Rect;
fn screen_fatal_error(title: &str, msg: &str, footer: &str);
fn screen_boot_full();
}
#[cfg(feature = "bootloader")]
pub trait UIFeaturesBootloader {
fn screen_welcome();
fn bld_continue_label(bg_color: Color);
fn screen_install_success(restart_seconds: u8, initial_setup: bool, complete_draw: bool);
fn screen_install_fail();
fn screen_install_confirm(
vendor: &str,
version: &str,
fingerprint: &str,
should_keep_seed: bool,
is_newvendor: bool,
version_cmp: i32,
) -> u32;
fn screen_wipe_confirm() -> u32;
fn screen_unlock_bootloader_confirm() -> u32;
fn screen_unlock_bootloader_success();
fn screen_menu(firmware_present: secbool) -> u32;
fn screen_intro(bld_version: &str, vendor: &str, version: &str, fw_ok: bool) -> u32;
fn screen_boot_empty(fading: bool);
fn screen_wipe_progress(progress: u16, initialize: bool);
fn screen_install_progress(progress: u16, initialize: bool, initial_setup: bool);
fn screen_connect(initial_setup: bool);
fn screen_wipe_success();
fn screen_wipe_fail();
}
#[cfg(all(feature = "model_tr", not(feature = "model_tt")))]
pub type ModelUI = crate::ui::model_tr::ModelTRFeatures;
#[cfg(feature = "model_tt")]
pub type ModelUI = crate::ui::model_tt::ModelTTFeatures;
Loading…
Cancel
Save