mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-18 04:18:10 +00:00
feat(core): Implement SetBusy message.
This commit is contained in:
parent
792dadfc4d
commit
d089fd3187
1
core/.changelog.d/2445.added
Normal file
1
core/.changelog.d/2445.added
Normal file
@ -0,0 +1 @@
|
||||
Support SetBusy message.
|
@ -351,6 +351,8 @@ apps.debug.load_device
|
||||
import apps.debug.load_device
|
||||
apps.homescreen
|
||||
import apps.homescreen
|
||||
apps.homescreen.busyscreen
|
||||
import apps.homescreen.busyscreen
|
||||
apps.homescreen.homescreen
|
||||
import apps.homescreen.homescreen
|
||||
apps.homescreen.lockscreen
|
||||
|
@ -20,9 +20,26 @@ if TYPE_CHECKING:
|
||||
Ping,
|
||||
DoPreauthorized,
|
||||
CancelAuthorization,
|
||||
SetBusy,
|
||||
)
|
||||
|
||||
|
||||
def busy_expiry_ms() -> int:
|
||||
"""
|
||||
Returns the time left until the busy state expires or 0 if the device is not in the busy state.
|
||||
"""
|
||||
|
||||
busy_deadline_bytes = storage.cache.get(storage.cache.APP_COMMON_BUSY_DEADLINE_MS)
|
||||
if busy_deadline_bytes is None:
|
||||
return 0
|
||||
|
||||
import utime
|
||||
|
||||
busy_deadline_ms = int.from_bytes(busy_deadline_bytes, "big")
|
||||
expiry_ms = utime.ticks_diff(busy_deadline_ms, utime.ticks_ms())
|
||||
return expiry_ms if expiry_ms > 0 else 0
|
||||
|
||||
|
||||
def get_features() -> Features:
|
||||
import storage.recovery
|
||||
import storage.sd_salt
|
||||
@ -47,6 +64,7 @@ def get_features() -> Features:
|
||||
label=storage.device.get_label(),
|
||||
pin_protection=config.has_pin(),
|
||||
unlocked=config.is_unlocked(),
|
||||
busy=busy_expiry_ms() > 0,
|
||||
)
|
||||
|
||||
if utils.BITCOIN_ONLY:
|
||||
@ -145,6 +163,24 @@ async def handle_LockDevice(ctx: wire.Context, msg: LockDevice) -> Success:
|
||||
return Success()
|
||||
|
||||
|
||||
async def handle_SetBusy(ctx: wire.Context, msg: SetBusy) -> Success:
|
||||
if not storage.device.is_initialized():
|
||||
raise wire.NotInitialized("Device is not initialized")
|
||||
|
||||
if msg.expiry_ms:
|
||||
import utime
|
||||
|
||||
deadline = utime.ticks_add(utime.ticks_ms(), msg.expiry_ms)
|
||||
storage.cache.set(
|
||||
storage.cache.APP_COMMON_BUSY_DEADLINE_MS, deadline.to_bytes(4, "big")
|
||||
)
|
||||
else:
|
||||
storage.cache.delete(storage.cache.APP_COMMON_BUSY_DEADLINE_MS)
|
||||
set_homescreen()
|
||||
workflow.close_others()
|
||||
return Success()
|
||||
|
||||
|
||||
async def handle_EndSession(ctx: wire.Context, msg: EndSession) -> Success:
|
||||
storage.cache.end_current_session()
|
||||
return Success()
|
||||
@ -200,13 +236,20 @@ ALLOW_WHILE_LOCKED = (
|
||||
MessageType.LockDevice,
|
||||
MessageType.DoPreauthorized,
|
||||
MessageType.WipeDevice,
|
||||
MessageType.SetBusy,
|
||||
)
|
||||
|
||||
|
||||
def set_homescreen() -> None:
|
||||
import storage.recovery
|
||||
import storage # workaround for https://github.com/microsoft/pyright/issues/2685
|
||||
|
||||
if not config.is_unlocked():
|
||||
if storage.cache.is_set(storage.cache.APP_COMMON_BUSY_DEADLINE_MS):
|
||||
from apps.homescreen.busyscreen import busyscreen
|
||||
|
||||
workflow.set_default(busyscreen)
|
||||
|
||||
elif not config.is_unlocked():
|
||||
from apps.homescreen.lockscreen import lockscreen
|
||||
|
||||
workflow.set_default(lockscreen)
|
||||
@ -296,6 +339,7 @@ def boot() -> None:
|
||||
workflow_handlers.register(
|
||||
MessageType.CancelAuthorization, handle_CancelAuthorization
|
||||
)
|
||||
workflow_handlers.register(MessageType.SetBusy, handle_SetBusy)
|
||||
|
||||
reload_settings_from_storage()
|
||||
if config.is_unlocked():
|
||||
|
29
core/src/apps/homescreen/busyscreen.py
Normal file
29
core/src/apps/homescreen/busyscreen.py
Normal file
@ -0,0 +1,29 @@
|
||||
import storage.cache
|
||||
from trezor import loop, ui
|
||||
from trezor.ui.layouts import draw_simple_text
|
||||
|
||||
from apps.base import busy_expiry_ms, set_homescreen
|
||||
|
||||
from . import HomescreenBase
|
||||
|
||||
|
||||
async def busyscreen() -> None:
|
||||
await Busyscreen()
|
||||
|
||||
|
||||
class Busyscreen(HomescreenBase):
|
||||
RENDER_INDICATOR = storage.cache.BUSYSCREEN_ON
|
||||
|
||||
def create_tasks(self) -> tuple[loop.AwaitableTask, ...]:
|
||||
return self.handle_rendering(), self.handle_input(), self.handle_expiry()
|
||||
|
||||
def handle_expiry(self) -> loop.Task: # type: ignore [awaitable-is-generator]
|
||||
yield loop.sleep(busy_expiry_ms())
|
||||
storage.cache.delete(storage.cache.APP_COMMON_BUSY_DEADLINE_MS)
|
||||
set_homescreen()
|
||||
raise ui.Result(None)
|
||||
|
||||
def do_render(self) -> None:
|
||||
draw_simple_text(
|
||||
"Please wait", "CoinJoin in progress.\n\nDo not disconnect your\nTrezor."
|
||||
)
|
@ -30,6 +30,7 @@ APP_COMMON_SEED_WITHOUT_PASSPHRASE = 0 | _SESSIONLESS_FLAG
|
||||
APP_COMMON_SAFETY_CHECKS_TEMPORARY = 1 | _SESSIONLESS_FLAG
|
||||
STORAGE_DEVICE_EXPERIMENTAL_FEATURES = 2 | _SESSIONLESS_FLAG
|
||||
APP_COMMON_REQUEST_PIN_LAST_UNLOCK = 3 | _SESSIONLESS_FLAG
|
||||
APP_COMMON_BUSY_DEADLINE_MS = 4 | _SESSIONLESS_FLAG
|
||||
|
||||
|
||||
# === Homescreen storage ===
|
||||
@ -40,6 +41,7 @@ APP_COMMON_REQUEST_PIN_LAST_UNLOCK = 3 | _SESSIONLESS_FLAG
|
||||
# is still on. This way we can avoid unnecessary fadeins/fadeouts when a workflow ends.
|
||||
HOMESCREEN_ON = object()
|
||||
LOCKSCREEN_ON = object()
|
||||
BUSYSCREEN_ON = object()
|
||||
homescreen_shown: object | None = None
|
||||
|
||||
|
||||
@ -132,6 +134,7 @@ class SessionlessCache(DataCache):
|
||||
1, # APP_COMMON_SAFETY_CHECKS_TEMPORARY
|
||||
1, # STORAGE_DEVICE_EXPERIMENTAL_FEATURES
|
||||
4, # APP_COMMON_REQUEST_PIN_LAST_UNLOCK
|
||||
4, # APP_COMMON_BUSY_DEADLINE_MS
|
||||
)
|
||||
super().__init__()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user