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
|
import apps.debug.load_device
|
||||||
apps.homescreen
|
apps.homescreen
|
||||||
import apps.homescreen
|
import apps.homescreen
|
||||||
|
apps.homescreen.busyscreen
|
||||||
|
import apps.homescreen.busyscreen
|
||||||
apps.homescreen.homescreen
|
apps.homescreen.homescreen
|
||||||
import apps.homescreen.homescreen
|
import apps.homescreen.homescreen
|
||||||
apps.homescreen.lockscreen
|
apps.homescreen.lockscreen
|
||||||
|
@ -20,9 +20,26 @@ if TYPE_CHECKING:
|
|||||||
Ping,
|
Ping,
|
||||||
DoPreauthorized,
|
DoPreauthorized,
|
||||||
CancelAuthorization,
|
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:
|
def get_features() -> Features:
|
||||||
import storage.recovery
|
import storage.recovery
|
||||||
import storage.sd_salt
|
import storage.sd_salt
|
||||||
@ -47,6 +64,7 @@ def get_features() -> Features:
|
|||||||
label=storage.device.get_label(),
|
label=storage.device.get_label(),
|
||||||
pin_protection=config.has_pin(),
|
pin_protection=config.has_pin(),
|
||||||
unlocked=config.is_unlocked(),
|
unlocked=config.is_unlocked(),
|
||||||
|
busy=busy_expiry_ms() > 0,
|
||||||
)
|
)
|
||||||
|
|
||||||
if utils.BITCOIN_ONLY:
|
if utils.BITCOIN_ONLY:
|
||||||
@ -145,6 +163,24 @@ async def handle_LockDevice(ctx: wire.Context, msg: LockDevice) -> Success:
|
|||||||
return 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:
|
async def handle_EndSession(ctx: wire.Context, msg: EndSession) -> Success:
|
||||||
storage.cache.end_current_session()
|
storage.cache.end_current_session()
|
||||||
return Success()
|
return Success()
|
||||||
@ -200,13 +236,20 @@ ALLOW_WHILE_LOCKED = (
|
|||||||
MessageType.LockDevice,
|
MessageType.LockDevice,
|
||||||
MessageType.DoPreauthorized,
|
MessageType.DoPreauthorized,
|
||||||
MessageType.WipeDevice,
|
MessageType.WipeDevice,
|
||||||
|
MessageType.SetBusy,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def set_homescreen() -> None:
|
def set_homescreen() -> None:
|
||||||
import storage.recovery
|
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
|
from apps.homescreen.lockscreen import lockscreen
|
||||||
|
|
||||||
workflow.set_default(lockscreen)
|
workflow.set_default(lockscreen)
|
||||||
@ -296,6 +339,7 @@ def boot() -> None:
|
|||||||
workflow_handlers.register(
|
workflow_handlers.register(
|
||||||
MessageType.CancelAuthorization, handle_CancelAuthorization
|
MessageType.CancelAuthorization, handle_CancelAuthorization
|
||||||
)
|
)
|
||||||
|
workflow_handlers.register(MessageType.SetBusy, handle_SetBusy)
|
||||||
|
|
||||||
reload_settings_from_storage()
|
reload_settings_from_storage()
|
||||||
if config.is_unlocked():
|
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
|
APP_COMMON_SAFETY_CHECKS_TEMPORARY = 1 | _SESSIONLESS_FLAG
|
||||||
STORAGE_DEVICE_EXPERIMENTAL_FEATURES = 2 | _SESSIONLESS_FLAG
|
STORAGE_DEVICE_EXPERIMENTAL_FEATURES = 2 | _SESSIONLESS_FLAG
|
||||||
APP_COMMON_REQUEST_PIN_LAST_UNLOCK = 3 | _SESSIONLESS_FLAG
|
APP_COMMON_REQUEST_PIN_LAST_UNLOCK = 3 | _SESSIONLESS_FLAG
|
||||||
|
APP_COMMON_BUSY_DEADLINE_MS = 4 | _SESSIONLESS_FLAG
|
||||||
|
|
||||||
|
|
||||||
# === Homescreen storage ===
|
# === 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.
|
# is still on. This way we can avoid unnecessary fadeins/fadeouts when a workflow ends.
|
||||||
HOMESCREEN_ON = object()
|
HOMESCREEN_ON = object()
|
||||||
LOCKSCREEN_ON = object()
|
LOCKSCREEN_ON = object()
|
||||||
|
BUSYSCREEN_ON = object()
|
||||||
homescreen_shown: object | None = None
|
homescreen_shown: object | None = None
|
||||||
|
|
||||||
|
|
||||||
@ -132,6 +134,7 @@ class SessionlessCache(DataCache):
|
|||||||
1, # APP_COMMON_SAFETY_CHECKS_TEMPORARY
|
1, # APP_COMMON_SAFETY_CHECKS_TEMPORARY
|
||||||
1, # STORAGE_DEVICE_EXPERIMENTAL_FEATURES
|
1, # STORAGE_DEVICE_EXPERIMENTAL_FEATURES
|
||||||
4, # APP_COMMON_REQUEST_PIN_LAST_UNLOCK
|
4, # APP_COMMON_REQUEST_PIN_LAST_UNLOCK
|
||||||
|
4, # APP_COMMON_BUSY_DEADLINE_MS
|
||||||
)
|
)
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user