1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-23 14:58:09 +00:00

refactor(core): provide backlight values from Rust

This commit is contained in:
matejcik 2024-05-22 11:21:29 +02:00 committed by TychoVrahe
parent a65511846b
commit 9bed793f68
22 changed files with 207 additions and 82 deletions

View File

@ -6,14 +6,20 @@
static void _librust_qstrs(void) {
MP_QSTR_;
MP_QSTR_BacklightLevels;
MP_QSTR_CANCELLED;
MP_QSTR_CONFIRMED;
MP_QSTR_DIM;
MP_QSTR_INFO;
MP_QSTR_LOW;
MP_QSTR_LayoutObj;
MP_QSTR_MAX;
MP_QSTR_MESSAGE_NAME;
MP_QSTR_MESSAGE_WIRE_TYPE;
MP_QSTR_Msg;
MP_QSTR_MsgDef;
MP_QSTR_NONE;
MP_QSTR_NORMAL;
MP_QSTR_TR;
MP_QSTR_TranslationsHeader;
MP_QSTR___dict__;

View File

@ -0,0 +1,43 @@
use crate::{
error::Error,
micropython::{ffi, obj::Obj, qstr::Qstr, simple_type::SimpleTypeObj, typ::Type, util},
ui::{ui_features::ModelUI, UIFeaturesCommon},
};
/*
* This whole module should be removed, in favor of fully
* moving backlight control into Rust. Relatively easy to do, but not
* necessary right now. Filed as https://github.com/trezor/trezor-firmware/issues/3849
*
* Consider this module temporary. (yeah yeah everyone knows "temporary"
* things stay forever. Written in May 2024.)
*/
static BACKLIGHT_LEVELS_TYPE: Type = obj_type! {
name: Qstr::MP_QSTR_BacklightLevels,
attr_fn: backlight_levels_attr,
};
unsafe extern "C" fn backlight_levels_attr(_self_in: Obj, attr: ffi::qstr, dest: *mut Obj) {
let block = || {
let arg = unsafe { dest.read() };
if !arg.is_null() {
// Null destination would mean a `setattr`.
return Err(Error::TypeError);
}
let attr = Qstr::from_u16(attr as _);
let value = match attr {
Qstr::MP_QSTR_NONE => ModelUI::get_backlight_none(),
Qstr::MP_QSTR_NORMAL => ModelUI::get_backlight_normal(),
Qstr::MP_QSTR_LOW => ModelUI::get_backlight_low(),
Qstr::MP_QSTR_DIM => ModelUI::get_backlight_dim(),
Qstr::MP_QSTR_MAX => ModelUI::get_backlight_max(),
_ => return Err(Error::AttributeError(attr)),
};
unsafe { dest.write(value.into()) };
Ok(())
};
unsafe { util::try_or_raise(block) }
}
pub static BACKLIGHT_LEVELS_OBJ: SimpleTypeObj = SimpleTypeObj::new(&BACKLIGHT_LEVELS_TYPE);

View File

@ -2,6 +2,8 @@
pub mod macros;
pub mod animation;
#[cfg(feature = "micropython")]
pub mod backlight;
pub mod button_request;
pub mod component;
pub mod constant;

View File

@ -44,8 +44,8 @@ use super::{
FidoMsg, Frame, FrameMsg, Homescreen, HomescreenMsg, IconDialog, Lockscreen, MnemonicInput,
MnemonicKeyboard, MnemonicKeyboardMsg, PassphraseKeyboard, PassphraseKeyboardMsg,
PinKeyboard, PinKeyboardMsg, Progress, PromptScreen, SelectWordCount, SelectWordCountMsg,
SetBrightnessDialog, SimplePage, Slip39Input, StatusScreen, SwipeUpScreen, SwipeUpScreenMsg,
VerticalMenu, VerticalMenuChoiceMsg,
SetBrightnessDialog, SimplePage, Slip39Input, StatusScreen, SwipeUpScreen,
SwipeUpScreenMsg, VerticalMenu, VerticalMenuChoiceMsg,
},
flow, theme,
};
@ -2033,6 +2033,17 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// ) -> LayoutObj[UiResult]:
/// """Total summary and hold to confirm."""
Qstr::MP_QSTR_flow_confirm_summary => obj_fn_kw!(0, flow::new_confirm_summary).as_obj(),
/// class BacklightLevels:
/// """Backlight levels. Values dynamically update based on user settings."""
/// MAX: ClassVar[int]
/// NORMAL: ClassVar[int]
/// LOW: ClassVar[int]
/// DIM: ClassVar[int]
/// NONE: ClassVar[int]
///
/// mock:global
Qstr::MP_QSTR_BacklightLevels => BACKLIGHT_LEVELS_OBJ.as_obj(),
};
#[cfg(test)]

View File

@ -1,4 +1,5 @@
use super::{geometry::Rect, UIFeaturesCommon};
use crate::ui::model_mercury::theme::backlight;
#[cfg(feature = "bootloader")]
pub mod bootloader;
@ -16,19 +17,44 @@ pub mod shapes;
pub struct ModelMercuryFeatures;
impl UIFeaturesCommon for ModelMercuryFeatures {
#[cfg(feature = "backlight")]
fn fadein() {
#[cfg(feature = "backlight")]
crate::ui::display::fade_backlight_duration(theme::backlight::get_backlight_normal(), 150);
crate::ui::display::fade_backlight_duration(backlight::get_backlight_normal(), 150);
}
#[cfg(feature = "backlight")]
fn fadeout() {
#[cfg(feature = "backlight")]
crate::ui::display::fade_backlight_duration(theme::backlight::get_backlight_dim(), 150);
crate::ui::display::fade_backlight_duration(backlight::get_backlight_dim(), 150);
}
#[cfg(feature = "backlight")]
fn backlight_on() {
#[cfg(feature = "backlight")]
crate::ui::display::set_backlight(theme::backlight::get_backlight_normal());
crate::ui::display::set_backlight(backlight::get_backlight_normal());
}
#[cfg(feature = "backlight")]
fn get_backlight_none() -> u16 {
backlight::get_backlight_none()
}
#[cfg(feature = "backlight")]
fn get_backlight_normal() -> u16 {
backlight::get_backlight_normal()
}
#[cfg(feature = "backlight")]
fn get_backlight_low() -> u16 {
backlight::get_backlight_low()
}
#[cfg(feature = "backlight")]
fn get_backlight_dim() -> u16 {
backlight::get_backlight_dim()
}
#[cfg(feature = "backlight")]
fn get_backlight_max() -> u16 {
backlight::get_backlight_max()
}
const SCREEN: Rect = constant::SCREEN;

View File

@ -5,7 +5,7 @@ use crate::storage;
const BACKLIGHT_NORMAL: u8 = 150;
const BACKLIGHT_LOW: u8 = 45;
const BACKLIGHT_DIM: u8 = 5;
const BACKLIGHT_NONE: u8 = 2;
const BACKLIGHT_NONE: u8 = 0;
const BACKLIGHT_MIN: u8 = 10;
const BACKLIGHT_MAX: u8 = 255;

View File

@ -13,6 +13,7 @@ use crate::{
translations::TR,
trezorhal::model,
ui::{
backlight::BACKLIGHT_LEVELS_OBJ,
component::{
base::Component,
connect::Connect,
@ -2037,4 +2038,15 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// def show_wait_text(message: str, /) -> None:
/// """Show single-line text in the middle of the screen."""
Qstr::MP_QSTR_show_wait_text => obj_fn_1!(new_show_wait_text).as_obj(),
/// class BacklightLevels:
/// """Backlight levels. Values dynamically update based on user settings."""
/// MAX: ClassVar[int]
/// NORMAL: ClassVar[int]
/// LOW: ClassVar[int]
/// DIM: ClassVar[int]
/// NONE: ClassVar[int]
///
/// mock:global
Qstr::MP_QSTR_BacklightLevels => BACKLIGHT_LEVELS_OBJ.as_obj(),
};

View File

@ -10,6 +10,7 @@ use crate::{
translations::TR,
trezorhal::model,
ui::{
backlight::BACKLIGHT_LEVELS_OBJ,
component::{
base::ComponentExt,
connect::Connect,
@ -2117,6 +2118,17 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// def show_wait_text(message: str, /) -> LayoutObj[None]:
/// """Show single-line text in the middle of the screen."""
Qstr::MP_QSTR_show_wait_text => obj_fn_1!(new_show_wait_text).as_obj(),
/// class BacklightLevels:
/// """Backlight levels. Values dynamically update based on user settings."""
/// MAX: ClassVar[int]
/// NORMAL: ClassVar[int]
/// LOW: ClassVar[int]
/// DIM: ClassVar[int]
/// NONE: ClassVar[int]
///
/// mock:global
Qstr::MP_QSTR_BacklightLevels => BACKLIGHT_LEVELS_OBJ.as_obj(),
};
#[cfg(test)]

View File

@ -20,21 +20,44 @@ use crate::ui::{
pub struct ModelTTFeatures;
impl UIFeaturesCommon for ModelTTFeatures {
#[cfg(feature = "backlight")]
fn fadein() {
#[cfg(feature = "backlight")]
crate::ui::display::fade_backlight_duration(backlight::get_backlight_normal(), 150);
}
#[cfg(feature = "backlight")]
fn fadeout() {
#[cfg(feature = "backlight")]
crate::ui::display::fade_backlight_duration(backlight::get_backlight_normal(), 150);
}
#[cfg(feature = "backlight")]
fn backlight_on() {
#[cfg(feature = "backlight")]
crate::ui::display::set_backlight(backlight::get_backlight_normal());
}
#[cfg(feature = "backlight")]
fn get_backlight_none() -> u16 {
backlight::get_backlight_none()
}
#[cfg(feature = "backlight")]
fn get_backlight_normal() -> u16 {
backlight::get_backlight_normal()
}
#[cfg(feature = "backlight")]
fn get_backlight_low() -> u16 {
backlight::get_backlight_low()
}
#[cfg(feature = "backlight")]
fn get_backlight_dim() -> u16 {
backlight::get_backlight_dim()
}
#[cfg(feature = "backlight")]
fn get_backlight_max() -> u16 {
backlight::get_backlight_max()
}
const SCREEN: Rect = constant::SCREEN;
fn screen_fatal_error(title: &str, msg: &str, footer: &str) {

View File

@ -5,7 +5,7 @@ use crate::storage;
const BACKLIGHT_NORMAL: u8 = 150;
const BACKLIGHT_LOW: u8 = 45;
const BACKLIGHT_DIM: u8 = 5;
const BACKLIGHT_NONE: u8 = 2;
const BACKLIGHT_NONE: u8 = 0;
const BACKLIGHT_MIN: u8 = 10;
const BACKLIGHT_MAX: u8 = 255;

View File

@ -11,6 +11,22 @@ pub trait UIFeaturesCommon {
fn fadeout() {}
fn backlight_on() {}
fn get_backlight_none() -> u16 {
0
}
fn get_backlight_normal() -> u16 {
0
}
fn get_backlight_low() -> u16 {
0
}
fn get_backlight_dim() -> u16 {
0
}
fn get_backlight_max() -> u16 {
0
}
const SCREEN: Rect;
fn screen_fatal_error(title: &str, msg: &str, footer: &str);

View File

@ -592,6 +592,16 @@ def flow_confirm_summary(
br_type: str,
) -> LayoutObj[UiResult]:
"""Total summary and hold to confirm."""
# rust/src/ui/model_mercury/layout.rs
class BacklightLevels:
"""Backlight levels. Values dynamically update based on user settings."""
MAX: ClassVar[int]
NORMAL: ClassVar[int]
LOW: ClassVar[int]
DIM: ClassVar[int]
NONE: ClassVar[int]
CONFIRMED: UiResult
CANCELLED: UiResult
INFO: UiResult
@ -1586,3 +1596,13 @@ def confirm_firmware_update(
# rust/src/ui/model_tt/layout.rs
def show_wait_text(message: str, /) -> LayoutObj[None]:
"""Show single-line text in the middle of the screen."""
# rust/src/ui/model_tt/layout.rs
class BacklightLevels:
"""Backlight levels. Values dynamically update based on user settings."""
MAX: ClassVar[int]
NORMAL: ClassVar[int]
LOW: ClassVar[int]
DIM: ClassVar[int]
NONE: ClassVar[int]

View File

@ -195,8 +195,6 @@ trezor.ui.layouts.tt.recovery
import trezor.ui.layouts.tt.recovery
trezor.ui.layouts.tt.reset
import trezor.ui.layouts.tt.reset
trezor.ui.style
import trezor.ui.style
trezor.utils
import trezor.utils
trezor.wire

View File

@ -437,7 +437,7 @@ def reload_settings_from_storage() -> None:
)
wire.EXPERIMENTAL_ENABLED = storage_device.get_experimental_features()
if ui.display.orientation() != storage_device.get_rotation():
ui.backlight_fade(ui.style.get_backlight_dim())
ui.backlight_fade(ui.BacklightLevels.DIM)
ui.display.orientation(storage_device.get_rotation())

View File

@ -49,7 +49,7 @@ async def bootscreen() -> None:
if can_lock_device():
enforce_welcome_screen_duration()
ui.backlight_fade(ui.style.get_backlight_dim())
ui.backlight_fade(ui.BacklightLevels.NONE)
ui.display.orientation(storage.device.get_rotation())
await lockscreen
await verify_user_pin()
@ -64,7 +64,7 @@ async def bootscreen() -> None:
if rotation != ui.display.orientation():
# there is a slight delay before next screen is shown,
# so we don't fade unless there is a change of orientation
ui.backlight_fade(ui.style.get_backlight_dim())
ui.backlight_fade(ui.BacklightLevels.DIM)
ui.display.orientation(rotation)
allow_all_loader_messages()
return

View File

@ -4,6 +4,7 @@ from trezorui import Display
from typing import TYPE_CHECKING, Any, Awaitable, Generator
from trezor import loop, utils
from trezorui2 import BacklightLevels
if TYPE_CHECKING:
from typing import Generic, TypeVar
@ -53,21 +54,17 @@ if utils.EMULATOR or utils.INTERNAL_MODEL in ("T1B1", "T2B1"):
loop.after_step_hook = refresh
# import style later to avoid circular dep
from trezor.ui import style # isort:skip
async def _alert(count: int) -> None:
short_sleep = loop.sleep(20)
long_sleep = loop.sleep(80)
for i in range(count * 2):
if i % 2 == 0:
display.backlight(style.get_backlight_max())
display.backlight(BacklightLevels.MAX)
await short_sleep
else:
display.backlight(style.get_backlight_dim())
display.backlight(BacklightLevels.DIM)
await long_sleep
display.backlight(style.get_backlight_normal())
display.backlight(BacklightLevels.NORMAL)
global _alert_in_progress
_alert_in_progress = False

View File

@ -38,7 +38,7 @@ class RustLayout(ui.Layout):
self.timer = loop.Timer()
self.layout.attach_timer_fn(self.set_timer)
self._send_button_request()
self.backlight_level = ui.style.get_backlight_normal()
self.backlight_level = ui.BacklightLevels.NORMAL
def set_timer(self, token: int, deadline: int) -> None:
self.timer.schedule(deadline, token)
@ -187,7 +187,7 @@ class RustLayout(ui.Layout):
)
def _first_paint(self) -> None:
ui.backlight_fade(ui.style.get_backlight_none())
ui.backlight_fade(ui.BacklightLevels.NONE)
self._paint()
if __debug__ and self.should_notify_layout_change:
@ -263,10 +263,10 @@ def draw_simple(layout: Any) -> None:
raise RuntimeError
layout.attach_timer_fn(dummy_set_timer)
ui.backlight_fade(ui.style.get_backlight_dim())
ui.backlight_fade(ui.BacklightLevels.DIM)
layout.paint()
ui.refresh()
ui.backlight_fade(ui.style.get_backlight_normal())
ui.backlight_fade(ui.BacklightLevels.NORMAL)
async def raise_if_not_confirmed(

View File

@ -93,9 +93,9 @@ class Lockscreen(HomescreenBase):
coinjoin_authorized: bool = False,
) -> None:
self.bootscreen = bootscreen
self.backlight_level = ui.style.get_backlight_low()
self.backlight_level = ui.BacklightLevels.LOW
if bootscreen:
self.backlight_level = ui.style.get_backlight_normal()
self.backlight_level = ui.BacklightLevels.NORMAL
skip = (
not bootscreen and storage_cache.homescreen_shown is self.RENDER_INDICATOR

View File

@ -34,11 +34,11 @@ class RustProgress:
layout: Any,
):
self.layout = layout
ui.backlight_fade(ui.style.get_backlight_dim())
ui.backlight_fade(ui.BacklightLevels.DIM)
self.layout.attach_timer_fn(self.set_timer)
self.layout.paint()
ui.refresh()
ui.backlight_fade(ui.style.get_backlight_normal())
ui.backlight_fade(ui.BacklightLevels.NORMAL)
def set_timer(self, token: int, deadline: int) -> None:
raise RuntimeError # progress layouts should not set timers

View File

@ -44,7 +44,7 @@ class RustLayout(LayoutParentType[T]):
self.timer = loop.Timer()
self.layout.attach_timer_fn(self.set_timer)
self._send_button_request()
self.backlight_level = ui.style.get_backlight_normal()
self.backlight_level = ui.BacklightLevels.NORMAL
def set_timer(self, token: int, deadline: int) -> None:
self.timer.schedule(deadline, token)
@ -193,7 +193,7 @@ class RustLayout(LayoutParentType[T]):
)
def _first_paint(self) -> None:
ui.backlight_fade(ui.style.get_backlight_none())
ui.backlight_fade(ui.BacklightLevels.NONE)
self._paint()
if __debug__ and self.should_notify_layout_change:
@ -269,10 +269,10 @@ def draw_simple(layout: trezorui2.LayoutObj[Any]) -> None:
raise RuntimeError
layout.attach_timer_fn(dummy_set_timer)
ui.backlight_fade(ui.style.get_backlight_dim())
ui.backlight_fade(ui.BacklightLevels.DIM)
layout.paint()
ui.refresh()
ui.backlight_fade(ui.style.get_backlight_normal())
ui.backlight_fade(ui.BacklightLevels.NORMAL)
async def raise_if_not_confirmed(

View File

@ -93,9 +93,9 @@ class Lockscreen(HomescreenBase):
coinjoin_authorized: bool = False,
) -> None:
self.bootscreen = bootscreen
self.backlight_level = ui.style.get_backlight_low()
self.backlight_level = ui.BacklightLevels.LOW
if bootscreen:
self.backlight_level = ui.style.get_backlight_normal()
self.backlight_level = ui.BacklightLevels.NORMAL
skip = (
not bootscreen and storage_cache.homescreen_shown is self.RENDER_INDICATOR

View File

@ -1,41 +0,0 @@
from micropython import const
import storage.device
# backlight brightness
_BACKLIGHT_NORMAL = const(150)
_BACKLIGHT_LOW = const(45)
_BACKLIGHT_DIM = const(5)
_BACKLIGHT_NONE = const(0)
_BACKLIGHT_MIN = const(10)
_BACKLIGHT_MAX = const(255)
def get_backlight_normal() -> int:
val = storage.device.get_brightness()
if val is None:
return _BACKLIGHT_NORMAL
return val
def get_backlight_low() -> int:
val = storage.device.get_brightness()
if val is None or val > _BACKLIGHT_LOW:
return _BACKLIGHT_LOW
return val
def get_backlight_dim() -> int:
return _BACKLIGHT_DIM
def get_backlight_none() -> int:
return _BACKLIGHT_NONE
def get_backlight_min() -> int:
return _BACKLIGHT_MIN
def get_backlight_max() -> int:
return _BACKLIGHT_MAX