1
0
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:
matejcik 2019-07-30 17:57:59 +02:00 committed by matejcik
parent 6e7fc5f601
commit 0890f68c0c
5 changed files with 75 additions and 16 deletions

View File

@ -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
}
/**

View File

@ -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:

View File

@ -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()

View File

@ -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),
}

View File

@ -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),
}