mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-22 07:28:10 +00:00
core: use channels to give feedback over debuglink
all debug input signals are now channels, and DebugLinkDecision handler waits until the input was consumed. This means that the input events are queued; originally, if an input event arrived before the previous was consumed, the previous input would be lost. reset words and their positions are now also channels, and DebugLinkGetState can wait for their updates, if required
This commit is contained in:
parent
6e7fc5f601
commit
0890f68c0c
@ -24,6 +24,8 @@ message DebugLinkDecision {
|
||||
* @next DebugLinkState
|
||||
*/
|
||||
message DebugLinkGetState {
|
||||
optional bool wait_word_list = 1; // Trezor T only - wait until mnemonic words are shown
|
||||
optional bool wait_word_pos = 2; // Trezor T only - wait until reset word position is requested
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4,36 +4,60 @@ if not __debug__:
|
||||
halt("debug mode inactive")
|
||||
|
||||
if __debug__:
|
||||
from trezor import config, loop, utils
|
||||
from trezor import config, log, loop, utils
|
||||
from trezor.messages import MessageType
|
||||
from trezor.wire import register, protobuf_workflow
|
||||
|
||||
if False:
|
||||
from typing import List, Optional
|
||||
from typing import Optional
|
||||
from trezor import wire
|
||||
from trezor.messages.DebugLinkDecision import DebugLinkDecision
|
||||
from trezor.messages.DebugLinkGetState import DebugLinkGetState
|
||||
from trezor.messages.DebugLinkState import DebugLinkState
|
||||
|
||||
reset_internal_entropy = None # type: Optional[bytes]
|
||||
reset_current_words = None # type: Optional[List[str]]
|
||||
reset_word_index = None # type: Optional[int]
|
||||
reset_current_words = loop.chan()
|
||||
reset_word_index = loop.chan()
|
||||
|
||||
confirm_signal = loop.signal()
|
||||
swipe_signal = loop.signal()
|
||||
input_signal = loop.signal()
|
||||
confirm_chan = loop.chan()
|
||||
swipe_chan = loop.chan()
|
||||
input_chan = loop.chan()
|
||||
confirm_signal = confirm_chan.take
|
||||
swipe_signal = swipe_chan.take
|
||||
input_signal = input_chan.take
|
||||
|
||||
async def dispatch_DebugLinkDecision(
|
||||
ctx: wire.Context, msg: DebugLinkDecision
|
||||
) -> None:
|
||||
from trezor.ui import confirm, swipe
|
||||
|
||||
waiting_signals = [
|
||||
bool(s.putters) for s in (confirm_chan, swipe_chan, input_chan)
|
||||
]
|
||||
if sum(waiting_signals) > 0:
|
||||
log.warning(
|
||||
__name__,
|
||||
"Received new DebugLinkDecision before the previous one was handled.",
|
||||
)
|
||||
log.warning(
|
||||
__name__,
|
||||
"received: button {}, swipe {}, input {}".format(
|
||||
msg.yes_no, msg.up_down, msg.input
|
||||
),
|
||||
)
|
||||
log.warning(
|
||||
__name__,
|
||||
"waiting: button {}, swipe {}, input {}".format(*waiting_signals),
|
||||
)
|
||||
|
||||
if msg.yes_no is not None:
|
||||
confirm_signal.send(confirm.CONFIRMED if msg.yes_no else confirm.CANCELLED)
|
||||
await confirm_chan.put(
|
||||
confirm.CONFIRMED if msg.yes_no else confirm.CANCELLED
|
||||
)
|
||||
if msg.up_down is not None:
|
||||
swipe_signal.send(swipe.SWIPE_DOWN if msg.up_down else swipe.SWIPE_UP)
|
||||
await swipe_chan.put(swipe.SWIPE_DOWN if msg.up_down else swipe.SWIPE_UP)
|
||||
if msg.input is not None:
|
||||
input_signal.send(msg.input)
|
||||
await input_chan.put(msg.input)
|
||||
|
||||
async def dispatch_DebugLinkGetState(
|
||||
ctx: wire.Context, msg: DebugLinkGetState
|
||||
@ -45,10 +69,12 @@ if __debug__:
|
||||
m.mnemonic_secret = mnemonic.get_secret()
|
||||
m.mnemonic_type = mnemonic.get_type()
|
||||
m.passphrase_protection = storage.device.has_passphrase()
|
||||
m.reset_word_pos = reset_word_index
|
||||
m.reset_entropy = reset_internal_entropy
|
||||
if reset_current_words:
|
||||
m.reset_word = " ".join(reset_current_words)
|
||||
|
||||
if msg.wait_word_pos:
|
||||
m.reset_word_pos = await reset_word_index.take()
|
||||
if msg.wait_word_list:
|
||||
m.reset_word = " ".join(await reset_current_words.take())
|
||||
return m
|
||||
|
||||
def boot() -> None:
|
||||
|
@ -93,7 +93,7 @@ async def _confirm_word(ctx, share_index, numbered_share_words, count):
|
||||
# we always confirm the first (random) word index
|
||||
checked_index, checked_word = numbered_choices[0]
|
||||
if __debug__:
|
||||
debug.reset_word_index = checked_index
|
||||
debug.reset_word_index.publish(checked_index)
|
||||
|
||||
# shuffle again so the confirmed word is not always the first choice
|
||||
random.shuffle(numbered_choices)
|
||||
@ -200,7 +200,7 @@ async def _bip39_show_mnemonic(ctx, words: list):
|
||||
|
||||
def export_displayed_words():
|
||||
# export currently displayed mnemonic words into debuglink
|
||||
debug.reset_current_words = [w for _, w in words[paginated.page]]
|
||||
debug.reset_current_words.publish([w for _, w in words[paginated.page]])
|
||||
|
||||
paginated.on_change = export_displayed_words
|
||||
export_displayed_words()
|
||||
@ -393,7 +393,8 @@ async def _slip39_show_share_words(ctx, share_index, share_words):
|
||||
|
||||
def export_displayed_words():
|
||||
# export currently displayed mnemonic words into debuglink
|
||||
debug.reset_current_words = [w for _, w in word_pages[paginated.page]]
|
||||
words = [w for _, w in word_pages[paginated.page]]
|
||||
debug.reset_current_words.publish(words)
|
||||
|
||||
paginated.on_change = export_displayed_words
|
||||
export_displayed_words()
|
||||
|
@ -12,3 +12,18 @@ if __debug__:
|
||||
|
||||
class DebugLinkGetState(p.MessageType):
|
||||
MESSAGE_WIRE_TYPE = 101
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
wait_word_list: bool = None,
|
||||
wait_word_pos: bool = None,
|
||||
) -> None:
|
||||
self.wait_word_list = wait_word_list
|
||||
self.wait_word_pos = wait_word_pos
|
||||
|
||||
@classmethod
|
||||
def get_fields(cls) -> Dict:
|
||||
return {
|
||||
1: ('wait_word_list', p.BoolType, 0),
|
||||
2: ('wait_word_pos', p.BoolType, 0),
|
||||
}
|
||||
|
@ -12,3 +12,18 @@ if __debug__:
|
||||
|
||||
class DebugLinkGetState(p.MessageType):
|
||||
MESSAGE_WIRE_TYPE = 101
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
wait_word_list: bool = None,
|
||||
wait_word_pos: bool = None,
|
||||
) -> None:
|
||||
self.wait_word_list = wait_word_list
|
||||
self.wait_word_pos = wait_word_pos
|
||||
|
||||
@classmethod
|
||||
def get_fields(cls) -> Dict:
|
||||
return {
|
||||
1: ('wait_word_list', p.BoolType, 0),
|
||||
2: ('wait_word_pos', p.BoolType, 0),
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user