mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-18 03:10:58 +00:00
refactor(core/rust): introduce UIFeaturesXXX trait as an abstraction over different UI implementation
[no changelog]
This commit is contained in:
parent
ba741b81fd
commit
535a052df4
@ -1,34 +1,5 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "rust_ui_bootloader.h"
|
||||||
uint32_t screen_install_confirm(const char* vendor_str, uint8_t vendor_str_len,
|
#include "rust_ui_common.h"
|
||||||
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);
|
|
||||||
|
26
core/embed/rust/rust_ui_bootloader.h
Normal file
26
core/embed/rust/rust_ui_bootloader.h
Normal file
@ -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);
|
10
core/embed/rust/rust_ui_common.h
Normal file
10
core/embed/rust/rust_ui_common.h
Normal file
@ -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() -> ! {
|
fn shutdown() -> ! {
|
||||||
unsafe { ffi::trezor_shutdown() }
|
unsafe { ffi::trezor_shutdown() }
|
||||||
@ -13,13 +13,13 @@ fn shutdown() -> ! {
|
|||||||
|
|
||||||
#[cfg(feature = "bootloader")]
|
#[cfg(feature = "bootloader")]
|
||||||
pub fn __fatal_error(_expr: &str, _msg: &str, _file: &str, _line: u32, _func: &str) -> ! {
|
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()
|
shutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "bootloader"))]
|
#[cfg(not(feature = "bootloader"))]
|
||||||
pub fn __fatal_error(_expr: &str, msg: &str, _file: &str, _line: u32, _func: &str) -> ! {
|
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()
|
shutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
127
core/embed/rust/src/ui/api/bootloader_c.rs
Normal file
127
core/embed/rust/src/ui/api/bootloader_c.rs
Normal file
@ -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()
|
||||||
|
}
|
60
core/embed/rust/src/ui/api/common_c.rs
Normal file
60
core/embed/rust/src/ui/api/common_c.rs
Normal file
@ -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);
|
||||||
|
}
|
4
core/embed/rust/src/ui/api/mod.rs
Normal file
4
core/embed/rust/src/ui/api/mod.rs
Normal file
@ -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();
|
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")]
|
#[cfg(feature = "dma2d")]
|
||||||
pub fn image(image: &Image, center: Point) {
|
pub fn image(image: &Image, center: Point) {
|
||||||
let r = Rect::from_center_and_size(center, image.toif.size());
|
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)]
|
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||||
pub struct Icon {
|
pub struct Icon {
|
||||||
pub toif: Toif<'static>,
|
pub toif: Toif<'static>,
|
||||||
|
@ -9,22 +9,11 @@ use crate::ui::event::TouchEvent;
|
|||||||
use crate::ui::{
|
use crate::ui::{
|
||||||
component::{Component, Event, EventCtx, Never},
|
component::{Component, Event, EventCtx, Never},
|
||||||
display,
|
display,
|
||||||
geometry::Rect,
|
ui_features::ModelUI,
|
||||||
|
UIFeaturesCommon,
|
||||||
};
|
};
|
||||||
use num_traits::ToPrimitive;
|
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 {
|
pub trait ReturnToC {
|
||||||
fn return_to_c(self) -> u32;
|
fn return_to_c(self) -> u32;
|
||||||
}
|
}
|
||||||
@ -79,12 +68,12 @@ where
|
|||||||
F: Component,
|
F: Component,
|
||||||
F::Msg: ReturnToC,
|
F::Msg: ReturnToC,
|
||||||
{
|
{
|
||||||
frame.place(ModelFeatures::SCREEN);
|
frame.place(ModelUI::SCREEN);
|
||||||
ModelFeatures::fadeout();
|
ModelUI::fadeout();
|
||||||
display::sync();
|
display::sync();
|
||||||
frame.paint();
|
frame.paint();
|
||||||
display::refresh();
|
display::refresh();
|
||||||
ModelFeatures::fadein();
|
ModelUI::fadein();
|
||||||
|
|
||||||
#[cfg(feature = "button")]
|
#[cfg(feature = "button")]
|
||||||
while button_eval().is_some() {}
|
while button_eval().is_some() {}
|
||||||
@ -115,14 +104,14 @@ pub fn show<F>(frame: &mut F, fading: bool)
|
|||||||
where
|
where
|
||||||
F: Component,
|
F: Component,
|
||||||
{
|
{
|
||||||
frame.place(ModelFeatures::SCREEN);
|
frame.place(ModelUI::SCREEN);
|
||||||
if fading {
|
if fading {
|
||||||
ModelFeatures::fadeout()
|
ModelUI::fadeout()
|
||||||
};
|
};
|
||||||
display::sync();
|
display::sync();
|
||||||
frame.paint();
|
frame.paint();
|
||||||
display::refresh();
|
display::refresh();
|
||||||
if fading {
|
if fading {
|
||||||
ModelFeatures::fadein()
|
ModelUI::fadein()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -8,13 +8,16 @@ pub mod display;
|
|||||||
pub mod event;
|
pub mod event;
|
||||||
pub mod geometry;
|
pub mod geometry;
|
||||||
pub mod lerp;
|
pub mod lerp;
|
||||||
pub mod screens;
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
pub mod layout;
|
pub mod layout;
|
||||||
|
|
||||||
|
mod api;
|
||||||
#[cfg(feature = "model_tr")]
|
#[cfg(feature = "model_tr")]
|
||||||
pub mod model_tr;
|
pub mod model_tr;
|
||||||
#[cfg(feature = "model_tt")]
|
#[cfg(feature = "model_tt")]
|
||||||
pub mod model_tt;
|
pub mod model_tt;
|
||||||
|
pub mod ui_features;
|
||||||
|
|
||||||
|
pub use ui_features::UIFeaturesCommon;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use heapless::String;
|
use heapless::String;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
strutil::hexlify,
|
|
||||||
trezorhal::secbool::secbool,
|
trezorhal::secbool::secbool,
|
||||||
ui::{
|
ui::{
|
||||||
component::{connect::Connect, Label, LineBreaking::BreakWordsNoHyphen},
|
component::{connect::Connect, Label, LineBreaking::BreakWordsNoHyphen},
|
||||||
@ -10,7 +9,6 @@ use crate::{
|
|||||||
display::{self, Color, Font, Icon},
|
display::{self, Color, Font, Icon},
|
||||||
geometry::{Alignment2D, Offset, Point, Rect},
|
geometry::{Alignment2D, Offset, Point, Rect},
|
||||||
layout::simplified::{run, show, ReturnToC},
|
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},
|
bootloader::{BLD_BG, BLD_FG, ICON_ALERT, ICON_SPINNER, ICON_SUCCESS},
|
||||||
ICON_ARM_LEFT, ICON_ARM_RIGHT, TEXT_BOLD, TEXT_NORMAL, WHITE,
|
ICON_ARM_LEFT, ICON_ARM_RIGHT, TEXT_BOLD, TEXT_NORMAL, WHITE,
|
||||||
},
|
},
|
||||||
|
ModelTRFeatures,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod intro;
|
mod intro;
|
||||||
mod menu;
|
mod menu;
|
||||||
mod welcome;
|
mod welcome;
|
||||||
|
|
||||||
|
use crate::ui::ui_features::UIFeaturesBootloader;
|
||||||
use intro::Intro;
|
use intro::Intro;
|
||||||
use menu::Menu;
|
use menu::Menu;
|
||||||
use welcome::Welcome;
|
use welcome::Welcome;
|
||||||
@ -41,285 +41,249 @@ impl ReturnToC for ConfirmMsg {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
impl ModelTRFeatures {
|
||||||
extern "C" fn screen_install_confirm(
|
fn screen_progress(
|
||||||
vendor_str: *const cty::c_char,
|
text: &str,
|
||||||
vendor_str_len: u8,
|
text2: &str,
|
||||||
version: *const cty::c_char,
|
progress: u16,
|
||||||
fingerprint: *const cty::uint8_t,
|
initialize: bool,
|
||||||
should_keep_seed: bool,
|
fg_color: Color,
|
||||||
is_newvendor: bool,
|
bg_color: Color,
|
||||||
version_cmp: cty::c_int,
|
icon: Option<(Icon, Color)>,
|
||||||
) -> u32 {
|
) {
|
||||||
let text = unwrap!(unsafe { from_c_array(vendor_str, vendor_str_len as usize) });
|
if initialize {
|
||||||
let version = unwrap!(unsafe { from_c_str(version) });
|
display::rect_fill(SCREEN, bg_color);
|
||||||
|
}
|
||||||
|
|
||||||
let mut fingerprint_buffer: [u8; 64] = [0; 64];
|
let progress = if progress < 20 { 20 } else { progress };
|
||||||
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();
|
display::rect_rounded2_partial(
|
||||||
unwrap!(version_str.push_str("Firmware version "));
|
Rect::new(
|
||||||
unwrap!(version_str.push_str(version));
|
SCREEN.top_center() + Offset::new(-9, 3),
|
||||||
unwrap!(version_str.push_str("\nby "));
|
SCREEN.top_center() + Offset::new(9, 18 + 3),
|
||||||
unwrap!(version_str.push_str(text));
|
),
|
||||||
|
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,
|
||||||
|
);
|
||||||
|
|
||||||
let title_str = if is_newvendor {
|
display::refresh();
|
||||||
"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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
impl UIFeaturesBootloader for ModelTRFeatures {
|
||||||
extern "C" fn screen_wipe_confirm() -> u32 {
|
fn screen_welcome() {
|
||||||
let message =
|
let mut frame = Welcome::new();
|
||||||
Label::left_aligned("Seed and firmware will be erased!", TEXT_NORMAL).vertically_centered();
|
show(&mut frame, true);
|
||||||
|
|
||||||
let mut frame = Confirm::new(BLD_BG, "FACTORY RESET", message, None, "RESET", false);
|
|
||||||
|
|
||||||
run(&mut frame)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
extern "C" 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);
|
|
||||||
|
|
||||||
run(&mut frame)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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, true);
|
|
||||||
show(&mut frame, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
extern "C" fn screen_menu(firmware_present: secbool) -> u32 {
|
|
||||||
run(&mut Menu::new(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) });
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
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 };
|
fn bld_continue_label(bg_color: Color) {
|
||||||
|
display::text_center(
|
||||||
display::rect_rounded2_partial(
|
Point::new(constant::WIDTH / 2, HEIGHT - 2),
|
||||||
Rect::new(
|
"CONTINUE",
|
||||||
SCREEN.top_center() + Offset::new(-9, 3),
|
Font::NORMAL,
|
||||||
SCREEN.top_center() + Offset::new(9, 18 + 3),
|
WHITE,
|
||||||
),
|
bg_color,
|
||||||
fg_color,
|
);
|
||||||
bg_color,
|
ICON_ARM_LEFT.draw(
|
||||||
((100_u32 * progress as u32) / 1000) as _,
|
Point::new(constant::WIDTH / 2 - 36, HEIGHT - 6),
|
||||||
icon,
|
Alignment2D::TOP_LEFT,
|
||||||
);
|
WHITE,
|
||||||
display::text_center(
|
bg_color,
|
||||||
SCREEN.center() + Offset::y(8),
|
);
|
||||||
text,
|
ICON_ARM_RIGHT.draw(
|
||||||
Font::BOLD,
|
Point::new(constant::WIDTH / 2 + 25, HEIGHT - 6),
|
||||||
fg_color,
|
Alignment2D::TOP_LEFT,
|
||||||
bg_color,
|
WHITE,
|
||||||
);
|
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_install_progress(progress: u16, initialize: bool, _initial_setup: bool) {
|
|
||||||
screen_progress(
|
|
||||||
"Installing",
|
|
||||||
"firmware",
|
|
||||||
progress,
|
|
||||||
initialize,
|
|
||||||
BLD_FG,
|
|
||||||
BLD_BG,
|
|
||||||
Some((ICON_SUCCESS, BLD_FG)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
extern "C" fn screen_wipe_success() {
|
|
||||||
let title = Label::centered("Trezor Reset", TEXT_BOLD).vertically_centered();
|
|
||||||
|
|
||||||
let content =
|
|
||||||
Label::centered("Please reconnect\nthe device", TEXT_NORMAL).vertically_centered();
|
|
||||||
|
|
||||||
let mut frame = ResultScreen::new(BLD_FG, BLD_BG, ICON_SPINNER, title, content, true);
|
|
||||||
show(&mut frame, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
extern "C" fn screen_wipe_fail() {
|
|
||||||
let title = Label::centered("Reset failed", TEXT_BOLD).vertically_centered();
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
extern "C" fn screen_boot_empty(_fading: bool) {
|
|
||||||
display::rect_fill(SCREEN, BLD_BG);
|
|
||||||
|
|
||||||
let mut frame = WelcomeScreen::new(true);
|
|
||||||
show(&mut frame, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
extern "C" fn screen_install_fail() {
|
|
||||||
let title = Label::centered("Install failed", TEXT_BOLD).vertically_centered();
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let title = Label::centered("Firmware installed", TEXT_BOLD).vertically_centered();
|
fn screen_install_success(restart_seconds: u8, _initial_setup: bool, complete_draw: bool) {
|
||||||
|
let mut reboot_msg = BootloaderString::new();
|
||||||
|
|
||||||
let content = Label::centered(reboot_msg.as_str(), 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 = ResultScreen::new(BLD_FG, BLD_BG, ICON_SPINNER, title, content, complete_draw);
|
let title = Label::centered("Firmware installed", TEXT_BOLD).vertically_centered();
|
||||||
show(&mut frame, false);
|
|
||||||
}
|
let content = Label::centered(reboot_msg.as_str(), TEXT_NORMAL).vertically_centered();
|
||||||
|
|
||||||
#[no_mangle]
|
let mut frame =
|
||||||
extern "C" fn screen_welcome() {
|
ResultScreen::new(BLD_FG, BLD_BG, ICON_SPINNER, title, content, complete_draw);
|
||||||
let mut frame = Welcome::new();
|
show(&mut frame, false);
|
||||||
show(&mut frame, false);
|
}
|
||||||
}
|
|
||||||
|
fn screen_install_fail() {
|
||||||
#[no_mangle]
|
let title = Label::centered("Install failed", TEXT_BOLD).vertically_centered();
|
||||||
extern "C" fn bld_continue_label(bg_color: cty::uint16_t) {
|
|
||||||
display::text_center(
|
let content =
|
||||||
Point::new(constant::WIDTH / 2, HEIGHT - 2),
|
Label::centered("Please reconnect\nthe device", TEXT_NORMAL).vertically_centered();
|
||||||
"CONTINUE",
|
|
||||||
Font::NORMAL,
|
let mut frame = ResultScreen::new(BLD_FG, BLD_BG, ICON_ALERT, title, content, true);
|
||||||
WHITE,
|
show(&mut frame, false);
|
||||||
Color::from_u16(bg_color),
|
}
|
||||||
);
|
|
||||||
ICON_ARM_LEFT.draw(
|
fn screen_install_confirm(
|
||||||
Point::new(constant::WIDTH / 2 - 36, HEIGHT - 6),
|
vendor: &str,
|
||||||
Alignment2D::TOP_LEFT,
|
version: &str,
|
||||||
WHITE,
|
fingerprint: &str,
|
||||||
Color::from_u16(bg_color),
|
should_keep_seed: bool,
|
||||||
);
|
is_newvendor: bool,
|
||||||
ICON_ARM_RIGHT.draw(
|
version_cmp: i32,
|
||||||
Point::new(constant::WIDTH / 2 + 25, HEIGHT - 6),
|
) -> u32 {
|
||||||
Alignment2D::TOP_LEFT,
|
let mut version_str: BootloaderString = String::new();
|
||||||
WHITE,
|
unwrap!(version_str.push_str("Firmware version "));
|
||||||
Color::from_u16(bg_color),
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn screen_wipe_confirm() -> u32 {
|
||||||
|
let message = Label::left_aligned("Seed and firmware will be erased!", TEXT_NORMAL)
|
||||||
|
.vertically_centered();
|
||||||
|
|
||||||
|
let mut frame = Confirm::new(BLD_BG, "FACTORY RESET", message, None, "RESET", false);
|
||||||
|
|
||||||
|
run(&mut frame)
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
run(&mut frame)
|
||||||
|
}
|
||||||
|
|
||||||
|
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, true);
|
||||||
|
show(&mut frame, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn screen_menu(firmware_present: secbool) -> u32 {
|
||||||
|
run(&mut Menu::new(firmware_present))
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn screen_boot_empty(_fading: bool) {
|
||||||
|
display::rect_fill(SCREEN, BLD_BG);
|
||||||
|
|
||||||
|
let mut frame = WelcomeScreen::new(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)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn screen_connect(_initial_setup: bool) {
|
||||||
|
let mut frame = Connect::new("Waiting for host...", BLD_FG, BLD_BG);
|
||||||
|
show(&mut frame, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn screen_wipe_success() {
|
||||||
|
let title = Label::centered("Trezor Reset", TEXT_BOLD).vertically_centered();
|
||||||
|
|
||||||
|
let content =
|
||||||
|
Label::centered("Please reconnect\nthe device", TEXT_NORMAL).vertically_centered();
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
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")]
|
#[cfg(feature = "bootloader")]
|
||||||
pub mod bootloader;
|
pub mod bootloader;
|
||||||
@ -7,11 +7,19 @@ pub mod component;
|
|||||||
pub mod constant;
|
pub mod constant;
|
||||||
#[cfg(feature = "micropython")]
|
#[cfg(feature = "micropython")]
|
||||||
pub mod layout;
|
pub mod layout;
|
||||||
pub mod screens;
|
mod screens;
|
||||||
pub mod theme;
|
pub mod theme;
|
||||||
|
|
||||||
pub struct ModelTRFeatures {}
|
pub struct ModelTRFeatures {}
|
||||||
|
|
||||||
impl SimplifiedFeatures for ModelTRFeatures {
|
impl UIFeaturesCommon for ModelTRFeatures {
|
||||||
const SCREEN: Rect = constant::SCREEN;
|
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();
|
frame.paint();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
pub fn screen_boot_full() {
|
||||||
extern "C" fn screen_boot_full() {
|
|
||||||
let mut frame = WelcomeScreen::new(false);
|
let mut frame = WelcomeScreen::new(false);
|
||||||
frame.place(screen());
|
frame.place(screen());
|
||||||
display::sync();
|
display::sync();
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
use heapless::String;
|
use heapless::String;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
strutil::hexlify,
|
|
||||||
trezorhal::secbool::secbool,
|
trezorhal::secbool::secbool,
|
||||||
ui::{
|
ui::{
|
||||||
component::{connect::Connect, Label},
|
component::{connect::Connect, Label},
|
||||||
display::{self, Color, Font, Icon},
|
display::{self, Color, Font, Icon},
|
||||||
geometry::{Point, Rect},
|
geometry::{Point, Rect},
|
||||||
layout::simplified::{run, show, SimplifiedFeatures as _},
|
layout::simplified::{run, show},
|
||||||
util::{from_c_array, from_c_str},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -30,6 +28,7 @@ use super::{
|
|||||||
ModelTTFeatures,
|
ModelTTFeatures,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::ui::{ui_features::UIFeaturesBootloader, UIFeaturesCommon};
|
||||||
use intro::Intro;
|
use intro::Intro;
|
||||||
use menu::Menu;
|
use menu::Menu;
|
||||||
|
|
||||||
@ -43,296 +42,267 @@ const RECONNECT_MESSAGE: &str = "PLEASE RECONNECT\nTHE DEVICE";
|
|||||||
|
|
||||||
const SCREEN: Rect = ModelTTFeatures::SCREEN;
|
const SCREEN: Rect = ModelTTFeatures::SCREEN;
|
||||||
|
|
||||||
#[no_mangle]
|
impl ModelTTFeatures {
|
||||||
extern "C" fn screen_install_confirm(
|
fn screen_progress(
|
||||||
vendor_str: *const cty::c_char,
|
text: &str,
|
||||||
vendor_str_len: u8,
|
progress: u16,
|
||||||
version: *const cty::c_char,
|
initialize: bool,
|
||||||
fingerprint: *const cty::uint8_t,
|
fg_color: Color,
|
||||||
should_keep_seed: bool,
|
bg_color: Color,
|
||||||
is_newvendor: bool,
|
icon: Option<(Icon, Color)>,
|
||||||
version_cmp: cty::c_int,
|
) {
|
||||||
) -> u32 {
|
if initialize {
|
||||||
let text = unwrap!(unsafe { from_c_array(vendor_str, vendor_str_len as usize) });
|
ModelTTFeatures::fadeout();
|
||||||
let version = unwrap!(unsafe { from_c_str(version) });
|
display::rect_fill(SCREEN, bg_color);
|
||||||
|
}
|
||||||
|
|
||||||
let mut fingerprint_buffer: [u8; 64] = [0; 64];
|
display::text_center(
|
||||||
let fingerprint_str = unsafe {
|
Point::new(SCREEN.width() / 2, SCREEN.height() - 45),
|
||||||
let fingerprint_slice = core::slice::from_raw_parts(fingerprint, 32);
|
text,
|
||||||
hexlify(fingerprint_slice, &mut fingerprint_buffer);
|
Font::NORMAL,
|
||||||
core::str::from_utf8_unchecked(fingerprint_buffer.as_ref())
|
fg_color,
|
||||||
};
|
bg_color,
|
||||||
|
);
|
||||||
let mut version_str: BootloaderString = String::new();
|
display::loader(progress, -20, fg_color, bg_color, icon);
|
||||||
unwrap!(version_str.push_str("Firmware version "));
|
display::refresh();
|
||||||
unwrap!(version_str.push_str(version));
|
if initialize {
|
||||||
unwrap!(version_str.push_str("\nby "));
|
ModelTTFeatures::fadein();
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
run(&mut frame)
|
fn screen_install_success_bld(msg: &str, complete_draw: bool) {
|
||||||
}
|
let mut frame = ResultScreen::new(
|
||||||
|
&RESULT_FW_INSTALL,
|
||||||
#[no_mangle]
|
Icon::new(CHECK40),
|
||||||
extern "C" fn screen_wipe_confirm() -> u32 {
|
"Firmware installed\nsuccessfully",
|
||||||
let icon = Icon::new(FIRE40);
|
Label::centered(msg, RESULT_FW_INSTALL.title_style()).vertically_centered(),
|
||||||
|
complete_draw,
|
||||||
let msg = Label::centered(
|
);
|
||||||
"Are you sure you want to factory reset the device?",
|
show(&mut frame, complete_draw);
|
||||||
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);
|
|
||||||
|
|
||||||
run(&mut frame)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
extern "C" fn screen_menu(firmware_present: secbool) -> u32 {
|
|
||||||
run(&mut Menu::new(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) });
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
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(
|
fn screen_install_success_initial(msg: &str, complete_draw: bool) {
|
||||||
Point::new(SCREEN.width() / 2, SCREEN.height() - 45),
|
let mut frame = ResultScreen::new(
|
||||||
text,
|
&RESULT_INITIAL,
|
||||||
Font::NORMAL,
|
Icon::new(CHECK40),
|
||||||
fg_color,
|
"Firmware installed\nsuccessfully",
|
||||||
bg_color,
|
Label::centered(msg, RESULT_INITIAL.title_style()).vertically_centered(),
|
||||||
);
|
complete_draw,
|
||||||
display::loader(progress, -20, fg_color, bg_color, icon);
|
);
|
||||||
display::refresh();
|
show(&mut frame, complete_draw);
|
||||||
if initialize {
|
|
||||||
ModelTTFeatures::fadein();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
impl UIFeaturesBootloader for ModelTTFeatures {
|
||||||
extern "C" fn screen_install_progress(progress: u16, initialize: bool, initial_setup: bool) {
|
fn screen_welcome() {
|
||||||
let bg_color = if initial_setup { WELCOME_COLOR } else { BLD_BG };
|
let mut frame = Welcome::new();
|
||||||
let fg_color = if initial_setup { FG } else { BLD_FG };
|
show(&mut frame, true);
|
||||||
|
|
||||||
screen_progress(
|
|
||||||
"Installing firmware",
|
|
||||||
progress,
|
|
||||||
initialize,
|
|
||||||
fg_color,
|
|
||||||
bg_color,
|
|
||||||
Some((Icon::new(DOWNLOAD32), fg_color)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
extern "C" fn screen_boot_empty(fading: bool) {
|
|
||||||
if fading {
|
|
||||||
ModelTTFeatures::fadeout();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
display::rect_fill(SCREEN, BLACK);
|
fn bld_continue_label(bg_color: Color) {
|
||||||
|
display::text_center(
|
||||||
let mut frame = WelcomeScreen::new(true);
|
Point::new(SCREEN.width() / 2, SCREEN.height() - 5),
|
||||||
show(&mut frame, false);
|
"click to continue ...",
|
||||||
|
Font::NORMAL,
|
||||||
if fading {
|
WHITE,
|
||||||
ModelTTFeatures::fadein();
|
bg_color,
|
||||||
} 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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_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 {
|
fn screen_install_success(restart_seconds: u8, initial_setup: bool, complete_draw: bool) {
|
||||||
screen_install_success_initial(reboot_msg.as_str(), complete_draw)
|
let mut reboot_msg = BootloaderString::new();
|
||||||
} else {
|
|
||||||
screen_install_success_bld(reboot_msg.as_str(), complete_draw)
|
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();
|
||||||
}
|
}
|
||||||
display::refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
fn screen_install_fail() {
|
||||||
extern "C" fn screen_welcome() {
|
let mut frame = ResultScreen::new(
|
||||||
let mut frame = Welcome::new();
|
&RESULT_FW_INSTALL,
|
||||||
show(&mut frame, true);
|
Icon::new(WARNING40),
|
||||||
}
|
"Firmware installation was not successful",
|
||||||
|
Label::centered(RECONNECT_MESSAGE, RESULT_FW_INSTALL.title_style())
|
||||||
|
.vertically_centered(),
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
show(&mut frame, true);
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
fn screen_install_confirm(
|
||||||
extern "C" fn bld_continue_label(bg_color: cty::uint16_t) {
|
vendor: &str,
|
||||||
display::text_center(
|
version: &str,
|
||||||
Point::new(SCREEN.width() / 2, SCREEN.height() - 5),
|
fingerprint: &str,
|
||||||
"click to continue ...",
|
should_keep_seed: bool,
|
||||||
Font::NORMAL,
|
is_newvendor: bool,
|
||||||
WHITE,
|
version_cmp: i32,
|
||||||
Color::from_u16(bg_color),
|
) -> 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn screen_wipe_confirm() -> u32 {
|
||||||
|
let icon = Icon::new(FIRE40);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
run(&mut frame)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn screen_unlock_bootloader_confirm() -> u32 {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn screen_unlock_bootloader_success() {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn screen_menu(firmware_present: secbool) -> u32 {
|
||||||
|
run(&mut Menu::new(firmware_present))
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn screen_boot_empty(fading: bool) {
|
||||||
|
if fading {
|
||||||
|
ModelTTFeatures::fadeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
display::rect_fill(SCREEN, BLACK);
|
||||||
|
|
||||||
|
let mut frame = WelcomeScreen::new(true);
|
||||||
|
show(&mut frame, false);
|
||||||
|
|
||||||
|
if fading {
|
||||||
|
ModelTTFeatures::fadein();
|
||||||
|
} else {
|
||||||
|
display::set_backlight(BACKLIGHT_NORMAL);
|
||||||
|
}
|
||||||
|
display::refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
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)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
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)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
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_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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")]
|
#[cfg(feature = "bootloader")]
|
||||||
pub mod bootloader;
|
pub mod bootloader;
|
||||||
@ -8,11 +8,11 @@ pub mod theme;
|
|||||||
|
|
||||||
#[cfg(feature = "micropython")]
|
#[cfg(feature = "micropython")]
|
||||||
pub mod layout;
|
pub mod layout;
|
||||||
pub mod screens;
|
mod screens;
|
||||||
|
|
||||||
pub struct ModelTTFeatures {}
|
pub struct ModelTTFeatures;
|
||||||
|
|
||||||
impl SimplifiedFeatures for ModelTTFeatures {
|
impl UIFeaturesCommon for ModelTTFeatures {
|
||||||
fn fadein() {
|
fn fadein() {
|
||||||
#[cfg(feature = "backlight")]
|
#[cfg(feature = "backlight")]
|
||||||
crate::ui::display::fade_backlight_duration(theme::BACKLIGHT_NORMAL, 150);
|
crate::ui::display::fade_backlight_duration(theme::BACKLIGHT_NORMAL, 150);
|
||||||
@ -24,4 +24,12 @@ impl SimplifiedFeatures for ModelTTFeatures {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const SCREEN: Rect = constant::SCREEN;
|
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();
|
frame.paint();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
pub fn screen_boot_full() {
|
||||||
extern "C" fn screen_boot_full() {
|
|
||||||
let mut frame = WelcomeScreen::new(false);
|
let mut frame = WelcomeScreen::new(false);
|
||||||
frame.place(screen());
|
frame.place(screen());
|
||||||
display::sync();
|
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);
|
|
||||||
}
|
|
62
core/embed/rust/src/ui/ui_features.rs
Normal file
62
core/embed/rust/src/ui/ui_features.rs
Normal file
@ -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…
Reference in New Issue
Block a user