mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-02-19 19:12:03 +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
|
* @next DebugLinkState
|
||||||
*/
|
*/
|
||||||
message DebugLinkGetState {
|
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")
|
halt("debug mode inactive")
|
||||||
|
|
||||||
if __debug__:
|
if __debug__:
|
||||||
from trezor import config, loop, utils
|
from trezor import config, log, loop, utils
|
||||||
from trezor.messages import MessageType
|
from trezor.messages import MessageType
|
||||||
from trezor.wire import register, protobuf_workflow
|
from trezor.wire import register, protobuf_workflow
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
from typing import List, Optional
|
from typing import Optional
|
||||||
from trezor import wire
|
from trezor import wire
|
||||||
from trezor.messages.DebugLinkDecision import DebugLinkDecision
|
from trezor.messages.DebugLinkDecision import DebugLinkDecision
|
||||||
from trezor.messages.DebugLinkGetState import DebugLinkGetState
|
from trezor.messages.DebugLinkGetState import DebugLinkGetState
|
||||||
from trezor.messages.DebugLinkState import DebugLinkState
|
from trezor.messages.DebugLinkState import DebugLinkState
|
||||||
|
|
||||||
reset_internal_entropy = None # type: Optional[bytes]
|
reset_internal_entropy = None # type: Optional[bytes]
|
||||||
reset_current_words = None # type: Optional[List[str]]
|
reset_current_words = loop.chan()
|
||||||
reset_word_index = None # type: Optional[int]
|
reset_word_index = loop.chan()
|
||||||
|
|
||||||
confirm_signal = loop.signal()
|
confirm_chan = loop.chan()
|
||||||
swipe_signal = loop.signal()
|
swipe_chan = loop.chan()
|
||||||
input_signal = loop.signal()
|
input_chan = loop.chan()
|
||||||
|
confirm_signal = confirm_chan.take
|
||||||
|
swipe_signal = swipe_chan.take
|
||||||
|
input_signal = input_chan.take
|
||||||
|
|
||||||
async def dispatch_DebugLinkDecision(
|
async def dispatch_DebugLinkDecision(
|
||||||
ctx: wire.Context, msg: DebugLinkDecision
|
ctx: wire.Context, msg: DebugLinkDecision
|
||||||
) -> None:
|
) -> None:
|
||||||
from trezor.ui import confirm, swipe
|
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:
|
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:
|
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:
|
if msg.input is not None:
|
||||||
input_signal.send(msg.input)
|
await input_chan.put(msg.input)
|
||||||
|
|
||||||
async def dispatch_DebugLinkGetState(
|
async def dispatch_DebugLinkGetState(
|
||||||
ctx: wire.Context, msg: DebugLinkGetState
|
ctx: wire.Context, msg: DebugLinkGetState
|
||||||
@ -45,10 +69,12 @@ if __debug__:
|
|||||||
m.mnemonic_secret = mnemonic.get_secret()
|
m.mnemonic_secret = mnemonic.get_secret()
|
||||||
m.mnemonic_type = mnemonic.get_type()
|
m.mnemonic_type = mnemonic.get_type()
|
||||||
m.passphrase_protection = storage.device.has_passphrase()
|
m.passphrase_protection = storage.device.has_passphrase()
|
||||||
m.reset_word_pos = reset_word_index
|
|
||||||
m.reset_entropy = reset_internal_entropy
|
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
|
return m
|
||||||
|
|
||||||
def boot() -> None:
|
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
|
# we always confirm the first (random) word index
|
||||||
checked_index, checked_word = numbered_choices[0]
|
checked_index, checked_word = numbered_choices[0]
|
||||||
if __debug__:
|
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
|
# shuffle again so the confirmed word is not always the first choice
|
||||||
random.shuffle(numbered_choices)
|
random.shuffle(numbered_choices)
|
||||||
@ -200,7 +200,7 @@ async def _bip39_show_mnemonic(ctx, words: list):
|
|||||||
|
|
||||||
def export_displayed_words():
|
def export_displayed_words():
|
||||||
# export currently displayed mnemonic words into debuglink
|
# 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
|
paginated.on_change = export_displayed_words
|
||||||
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():
|
def export_displayed_words():
|
||||||
# export currently displayed mnemonic words into debuglink
|
# 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
|
paginated.on_change = export_displayed_words
|
||||||
export_displayed_words()
|
export_displayed_words()
|
||||||
|
@ -12,3 +12,18 @@ if __debug__:
|
|||||||
|
|
||||||
class DebugLinkGetState(p.MessageType):
|
class DebugLinkGetState(p.MessageType):
|
||||||
MESSAGE_WIRE_TYPE = 101
|
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):
|
class DebugLinkGetState(p.MessageType):
|
||||||
MESSAGE_WIRE_TYPE = 101
|
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