mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-26 17:38:39 +00:00
bunch of api cleanups
This commit is contained in:
parent
a7b6ea808a
commit
49cc4651c2
@ -3,7 +3,8 @@ from trezor.utils import unimport
|
|||||||
|
|
||||||
# used to confirm/cancel the dialogs from outside of this module (i.e.
|
# used to confirm/cancel the dialogs from outside of this module (i.e.
|
||||||
# through debug link)
|
# through debug link)
|
||||||
signal = loop.Signal()
|
if __debug__:
|
||||||
|
signal = loop.signal()
|
||||||
|
|
||||||
|
|
||||||
@unimport
|
@unimport
|
||||||
@ -20,7 +21,12 @@ async def confirm(ctx, content, code=None, *args, **kwargs):
|
|||||||
if code is None:
|
if code is None:
|
||||||
code = Other
|
code = Other
|
||||||
await ctx.call(ButtonRequest(code=code), ButtonAck)
|
await ctx.call(ButtonRequest(code=code), ButtonAck)
|
||||||
return await loop.Wait((signal, dialog)) == CONFIRMED
|
|
||||||
|
if __debug__:
|
||||||
|
waiter = loop.wait(signal, dialog)
|
||||||
|
else:
|
||||||
|
waiter = dialog
|
||||||
|
return await waiter == CONFIRMED
|
||||||
|
|
||||||
|
|
||||||
@unimport
|
@unimport
|
||||||
@ -37,7 +43,12 @@ async def hold_to_confirm(ctx, content, code=None, *args, **kwargs):
|
|||||||
if code is None:
|
if code is None:
|
||||||
code = Other
|
code = Other
|
||||||
await ctx.call(ButtonRequest(code=code), ButtonAck)
|
await ctx.call(ButtonRequest(code=code), ButtonAck)
|
||||||
return await loop.Wait((signal, dialog)) == CONFIRMED
|
|
||||||
|
if __debug__:
|
||||||
|
waiter = loop.wait(signal, dialog)
|
||||||
|
else:
|
||||||
|
waiter = dialog
|
||||||
|
return await waiter == CONFIRMED
|
||||||
|
|
||||||
|
|
||||||
@unimport
|
@unimport
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
from micropython import const
|
from micropython import const
|
||||||
|
|
||||||
import ustruct
|
import ustruct
|
||||||
import utime
|
import utime
|
||||||
|
|
||||||
|
@ -312,7 +312,7 @@ def send_cmd(cmd: Cmd, iface: io.HID) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def boot(iface: io.HID):
|
def boot(iface: io.HID):
|
||||||
loop.schedule_task(handle_reports(iface))
|
loop.schedule(handle_reports(iface))
|
||||||
|
|
||||||
|
|
||||||
async def handle_reports(iface: io.HID):
|
async def handle_reports(iface: io.HID):
|
||||||
@ -446,7 +446,7 @@ class ConfirmState:
|
|||||||
self.deadline_ms = utime.ticks_ms() + _CONFIRM_STATE_TIMEOUT_MS
|
self.deadline_ms = utime.ticks_ms() + _CONFIRM_STATE_TIMEOUT_MS
|
||||||
self.task = self.confirm()
|
self.task = self.confirm()
|
||||||
workflow.onstart(self.task)
|
workflow.onstart(self.task)
|
||||||
loop.schedule_task(self.task)
|
loop.schedule(self.task)
|
||||||
|
|
||||||
def kill(self) -> None:
|
def kill(self) -> None:
|
||||||
if self.task is not None:
|
if self.task is not None:
|
||||||
|
@ -10,10 +10,10 @@ async def swipe_to_rotate():
|
|||||||
|
|
||||||
|
|
||||||
async def dim_screen():
|
async def dim_screen():
|
||||||
await loop.Sleep(5 * 1000000)
|
await loop.sleep(5 * 1000000)
|
||||||
await ui.backlight_slide(ui.BACKLIGHT_DIM)
|
await ui.backlight_slide(ui.BACKLIGHT_DIM)
|
||||||
while True:
|
while True:
|
||||||
await loop.Sleep(1000000)
|
await loop.sleep(1000000)
|
||||||
|
|
||||||
|
|
||||||
def display_homescreen():
|
def display_homescreen():
|
||||||
@ -35,4 +35,4 @@ def display_homescreen():
|
|||||||
async def layout_homescreen():
|
async def layout_homescreen():
|
||||||
while True:
|
while True:
|
||||||
display_homescreen()
|
display_homescreen()
|
||||||
await loop.Wait([swipe_to_rotate(), dim_screen()])
|
await loop.wait(swipe_to_rotate(), dim_screen())
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
from micropython import const
|
|
||||||
|
|
||||||
from trezor import config
|
from trezor import config
|
||||||
from trezor import io
|
from trezor import io
|
||||||
from trezor import log
|
from trezor import log
|
||||||
|
@ -5,20 +5,20 @@ bytes, string, embedded message and repeated fields.
|
|||||||
For de-sererializing (loading) protobuf types, object with `AsyncReader`
|
For de-sererializing (loading) protobuf types, object with `AsyncReader`
|
||||||
interface is required:
|
interface is required:
|
||||||
|
|
||||||
class AsyncReader:
|
>>> class AsyncReader:
|
||||||
async def areadinto(self, buffer):
|
>>> async def areadinto(self, buffer):
|
||||||
"""
|
>>> """
|
||||||
Reads `len(buffer)` bytes into `buffer`, or raises `EOFError`.
|
>>> Reads `len(buffer)` bytes into `buffer`, or raises `EOFError`.
|
||||||
"""
|
>>> """
|
||||||
|
|
||||||
For serializing (dumping) protobuf types, object with `AsyncWriter` interface is
|
For serializing (dumping) protobuf types, object with `AsyncWriter` interface is
|
||||||
required:
|
required:
|
||||||
|
|
||||||
class AsyncWriter:
|
>>> class AsyncWriter:
|
||||||
async def awrite(self, buffer):
|
>>> async def awrite(self, buffer):
|
||||||
"""
|
>>> """
|
||||||
Writes all bytes from `buffer`, or raises `EOFError`.
|
>>> Writes all bytes from `buffer`, or raises `EOFError`.
|
||||||
"""
|
>>> """
|
||||||
'''
|
'''
|
||||||
|
|
||||||
from micropython import const
|
from micropython import const
|
||||||
|
@ -2,14 +2,15 @@
|
|||||||
class Hmac:
|
class Hmac:
|
||||||
|
|
||||||
def __init__(self, key, msg, digestmod):
|
def __init__(self, key, msg, digestmod):
|
||||||
self.__digestmod = digestmod
|
self.digestmod = digestmod
|
||||||
self.__inner = digestmod()
|
self.inner = digestmod()
|
||||||
self.digest_size = self.__inner.digest_size
|
self.digest_size = self.inner.digest_size
|
||||||
self.block_size = self.__inner.block_size
|
self.block_size = self.inner.block_size
|
||||||
|
|
||||||
if len(key) > self.block_size:
|
if len(key) > self.block_size:
|
||||||
key = digestmod(key).digest()
|
key = digestmod(key).digest()
|
||||||
self.__key = key + bytes(self.block_size - len(key))
|
self.key = key + bytes(self.block_size - len(key))
|
||||||
self.__inner.update(bytes((x ^ 0x36) for x in self.__key))
|
self.inner.update(bytes((x ^ 0x36) for x in self.key))
|
||||||
if msg is not None:
|
if msg is not None:
|
||||||
self.update(msg)
|
self.update(msg)
|
||||||
|
|
||||||
@ -17,15 +18,15 @@ class Hmac:
|
|||||||
'''
|
'''
|
||||||
Update the context with data.
|
Update the context with data.
|
||||||
'''
|
'''
|
||||||
self.__inner.update(msg)
|
self.inner.update(msg)
|
||||||
|
|
||||||
def digest(self) -> bytes:
|
def digest(self) -> bytes:
|
||||||
'''
|
'''
|
||||||
Returns the digest of processed data.
|
Returns the digest of processed data.
|
||||||
'''
|
'''
|
||||||
outer = self.__digestmod()
|
outer = self.digestmod()
|
||||||
outer.update(bytes((x ^ 0x5C) for x in self.__key))
|
outer.update(bytes((x ^ 0x5C) for x in self.key))
|
||||||
outer.update(self.__inner.digest())
|
outer.update(self.inner.digest())
|
||||||
return outer.digest()
|
return outer.digest()
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,8 +4,7 @@ the form of python coroutines (either plain generators or `async` functions) are
|
|||||||
stepped through until completion, and can get asynchronously blocked by
|
stepped through until completion, and can get asynchronously blocked by
|
||||||
`yield`ing or `await`ing a syscall.
|
`yield`ing or `await`ing a syscall.
|
||||||
|
|
||||||
See `schedule_task`, `run`, and syscalls `Sleep`, `Select`, `Signal`
|
See `schedule`, `run`, and syscalls `sleep`, `select`, `signal` and `wait`.
|
||||||
and `Wait`.
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import utime
|
import utime
|
||||||
@ -14,21 +13,11 @@ from micropython import const
|
|||||||
from trezor import log
|
from trezor import log
|
||||||
from trezor import io
|
from trezor import io
|
||||||
|
|
||||||
TOUCH = io.TOUCH
|
|
||||||
TOUCH_START = io.TOUCH_START
|
|
||||||
TOUCH_MOVE = io.TOUCH_MOVE
|
|
||||||
TOUCH_END = io.TOUCH_END
|
|
||||||
|
|
||||||
READ = io.POLL_READ
|
|
||||||
WRITE = io.POLL_WRITE
|
|
||||||
|
|
||||||
after_step_hook = None # function, called after each task step
|
after_step_hook = None # function, called after each task step
|
||||||
|
|
||||||
_MAX_SELECT_DELAY = const(1000000) # usec delay if queue is empty
|
_QUEUE_SIZE = const(64) # maximum number of scheduled tasks
|
||||||
_MAX_QUEUE_SIZE = const(64) # maximum number of scheduled tasks
|
_queue = utimeq.utimeq(_QUEUE_SIZE)
|
||||||
|
_paused = {}
|
||||||
_paused_tasks = {} # {message interface: [task]}
|
|
||||||
_scheduled_tasks = utimeq.utimeq(_MAX_QUEUE_SIZE)
|
|
||||||
|
|
||||||
if __debug__:
|
if __debug__:
|
||||||
# for performance stats
|
# for performance stats
|
||||||
@ -38,47 +27,48 @@ if __debug__:
|
|||||||
log_delay_rb = array.array('i', [0] * log_delay_rb_len)
|
log_delay_rb = array.array('i', [0] * log_delay_rb_len)
|
||||||
|
|
||||||
|
|
||||||
def schedule_task(task, value=None, deadline=None):
|
def schedule(task, value=None, deadline=None):
|
||||||
'''
|
'''
|
||||||
Schedule task to be executed with `value` on given `deadline` (in
|
Schedule task to be executed with `value` on given `deadline` (in
|
||||||
microseconds). Does not start the event loop itself, see `run`.
|
microseconds). Does not start the event loop itself, see `run`.
|
||||||
'''
|
'''
|
||||||
if deadline is None:
|
if deadline is None:
|
||||||
deadline = utime.ticks_us()
|
deadline = utime.ticks_us()
|
||||||
_scheduled_tasks.push(deadline, task, value)
|
_queue.push(deadline, task, value)
|
||||||
|
|
||||||
|
|
||||||
def unschedule_task(task):
|
def unschedule(task):
|
||||||
'''
|
'''
|
||||||
Remove task from the time queue. Cancels previous `schedule_task`.
|
Remove task from the time queue. Cancels previous `schedule`.
|
||||||
'''
|
'''
|
||||||
global _scheduled_tasks
|
global _queue
|
||||||
task_entry = [0, 0, 0] # deadline, task, value
|
task_entry = [0, 0, 0] # deadline, task, value
|
||||||
queue_copy = utimeq.utimeq(_MAX_QUEUE_SIZE)
|
queue_copy = utimeq.utimeq(_QUEUE_SIZE)
|
||||||
while _scheduled_tasks:
|
while _queue:
|
||||||
_scheduled_tasks.pop(task_entry)
|
_queue.pop(task_entry)
|
||||||
if task_entry[1] is not task:
|
t, v, d = task_entry
|
||||||
queue_copy.push(task_entry[0], task_entry[1], task_entry[2])
|
if t is not task:
|
||||||
_scheduled_tasks = queue_copy
|
queue_copy.push(t, v, d)
|
||||||
|
_queue = queue_copy
|
||||||
|
|
||||||
|
|
||||||
def _pause_task(task, iface):
|
def pause(task, iface):
|
||||||
tasks = _paused_tasks.get(iface, None)
|
tasks = _paused.get(iface, None)
|
||||||
if tasks is None:
|
if tasks is None:
|
||||||
tasks = _paused_tasks[iface] = []
|
tasks = _paused[iface] = []
|
||||||
tasks.append(task)
|
tasks.append(task)
|
||||||
|
|
||||||
|
|
||||||
def _unpause_task(task):
|
def unpause(task):
|
||||||
for iface in _paused_tasks:
|
for iface in _paused:
|
||||||
if task in _paused_tasks[iface]:
|
if task in _paused[iface]:
|
||||||
_paused_tasks[iface].remove(task)
|
_paused[iface].remove(task)
|
||||||
|
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
'''
|
'''
|
||||||
Loop forever, stepping through scheduled tasks and awaiting I/O events
|
Loop forever, stepping through scheduled tasks and awaiting I/O events
|
||||||
inbetween. Use `schedule_task` first to add a coroutine to the task queue.
|
inbetween. Use `schedule` first to add a coroutine to the task queue.
|
||||||
Tasks yield back to the scheduler on any I/O, usually by calling `await` on
|
Tasks yield back to the scheduler on any I/O, usually by calling `await` on
|
||||||
a `Syscall`.
|
a `Syscall`.
|
||||||
'''
|
'''
|
||||||
@ -86,34 +76,35 @@ def run():
|
|||||||
if __debug__:
|
if __debug__:
|
||||||
global log_delay_pos
|
global log_delay_pos
|
||||||
|
|
||||||
|
max_delay = const(1000000) # usec delay if queue is empty
|
||||||
|
|
||||||
task_entry = [0, 0, 0] # deadline, task, value
|
task_entry = [0, 0, 0] # deadline, task, value
|
||||||
msg_entry = [0, 0] # iface | flags, value
|
msg_entry = [0, 0] # iface | flags, value
|
||||||
while True:
|
while True:
|
||||||
# compute the maximum amount of time we can wait for a message
|
# compute the maximum amount of time we can wait for a message
|
||||||
if _scheduled_tasks:
|
if _queue:
|
||||||
delay = utime.ticks_diff(
|
delay = utime.ticks_diff(_queue.peektime(), utime.ticks_us())
|
||||||
_scheduled_tasks.peektime(), utime.ticks_us())
|
|
||||||
else:
|
else:
|
||||||
delay = _MAX_SELECT_DELAY
|
delay = max_delay
|
||||||
|
|
||||||
if __debug__:
|
if __debug__:
|
||||||
# add current delay to ring buffer for performance stats
|
# add current delay to ring buffer for performance stats
|
||||||
log_delay_rb[log_delay_pos] = delay
|
log_delay_rb[log_delay_pos] = delay
|
||||||
log_delay_pos = (log_delay_pos + 1) % log_delay_rb_len
|
log_delay_pos = (log_delay_pos + 1) % log_delay_rb_len
|
||||||
|
|
||||||
if io.poll(_paused_tasks, msg_entry, delay):
|
if io.poll(_paused, msg_entry, delay):
|
||||||
# message received, run tasks paused on the interface
|
# message received, run tasks paused on the interface
|
||||||
msg_tasks = _paused_tasks.pop(msg_entry[0], ())
|
msg_tasks = _paused.pop(msg_entry[0], ())
|
||||||
for task in msg_tasks:
|
for task in msg_tasks:
|
||||||
_step_task(task, msg_entry[1])
|
_step(task, msg_entry[1])
|
||||||
else:
|
else:
|
||||||
# timeout occurred, run the first scheduled task
|
# timeout occurred, run the first scheduled task
|
||||||
if _scheduled_tasks:
|
if _queue:
|
||||||
_scheduled_tasks.pop(task_entry)
|
_queue.pop(task_entry)
|
||||||
_step_task(task_entry[1], task_entry[2])
|
_step(task_entry[1], task_entry[2])
|
||||||
|
|
||||||
|
|
||||||
def _step_task(task, value):
|
def _step(task, value):
|
||||||
try:
|
try:
|
||||||
if isinstance(value, Exception):
|
if isinstance(value, Exception):
|
||||||
result = task.throw(value)
|
result = task.throw(value)
|
||||||
@ -129,7 +120,7 @@ def _step_task(task, value):
|
|||||||
if isinstance(result, Syscall):
|
if isinstance(result, Syscall):
|
||||||
result.handle(task)
|
result.handle(task)
|
||||||
elif result is None:
|
elif result is None:
|
||||||
schedule_task(task)
|
schedule(task)
|
||||||
else:
|
else:
|
||||||
if __debug__:
|
if __debug__:
|
||||||
log.error(__name__, 'unknown syscall: %s', result)
|
log.error(__name__, 'unknown syscall: %s', result)
|
||||||
@ -148,15 +139,16 @@ class Syscall:
|
|||||||
return (yield self)
|
return (yield self)
|
||||||
|
|
||||||
|
|
||||||
class Sleep(Syscall):
|
class sleep(Syscall):
|
||||||
'''
|
'''
|
||||||
Pause current task and resume it after given delay. Although the delay is
|
Pause current task and resume it after given delay. Although the delay is
|
||||||
given in microseconds, sub-millisecond precision is not guaranteed. Result
|
given in microseconds, sub-millisecond precision is not guaranteed. Result
|
||||||
value is the calculated deadline.
|
value is the calculated deadline.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
planned = await loop.Sleep(1000 * 1000) # sleep for 1ms
|
|
||||||
print('missed by %d us', utime.ticks_diff(utime.ticks_us(), planned))
|
>>> planned = await loop.sleep(1000 * 1000) # sleep for 1ms
|
||||||
|
>>> print('missed by %d us', utime.ticks_diff(utime.ticks_us(), planned))
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, delay_us):
|
def __init__(self, delay_us):
|
||||||
@ -164,43 +156,45 @@ class Sleep(Syscall):
|
|||||||
|
|
||||||
def handle(self, task):
|
def handle(self, task):
|
||||||
deadline = utime.ticks_add(utime.ticks_us(), self.delay_us)
|
deadline = utime.ticks_add(utime.ticks_us(), self.delay_us)
|
||||||
schedule_task(task, deadline, deadline)
|
schedule(task, deadline, deadline)
|
||||||
|
|
||||||
|
|
||||||
class Select(Syscall):
|
class select(Syscall):
|
||||||
'''
|
'''
|
||||||
Pause current task, and resume only after a message on `msg_iface` is
|
Pause current task, and resume only after a message on `msg_iface` is
|
||||||
received. Messages are received either from an USB interface, or the
|
received. Messages are received either from an USB interface, or the
|
||||||
touch display. Result value a tuple of message values.
|
touch display. Result value a tuple of message values.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
hid_report, = await loop.Select(0xABCD) # await USB HID report
|
|
||||||
event, x, y = await loop.Select(loop.TOUCH) # await touch event
|
>>> hid_report, = await loop.select(0xABCD) # await USB HID report
|
||||||
|
>>> event, x, y = await loop.select(io.TOUCH) # await touch event
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, msg_iface):
|
def __init__(self, msg_iface):
|
||||||
self.msg_iface = msg_iface
|
self.msg_iface = msg_iface
|
||||||
|
|
||||||
def handle(self, task):
|
def handle(self, task):
|
||||||
_pause_task(task, self.msg_iface)
|
pause(task, self.msg_iface)
|
||||||
|
|
||||||
|
|
||||||
_NO_VALUE = ()
|
_NO_VALUE = ()
|
||||||
|
|
||||||
|
|
||||||
class Signal(Syscall):
|
class signal(Syscall):
|
||||||
'''
|
'''
|
||||||
Pause current task, and let other running task to resume it later with a
|
Pause current task, and let other running task to resume it later with a
|
||||||
result value or an exception.
|
result value or an exception.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
# in task #1:
|
|
||||||
signal = loop.Signal()
|
>>> # in task #1:
|
||||||
result = await signal
|
>>> signal = loop.signal()
|
||||||
print('awaited result:', result)
|
>>> result = await signal
|
||||||
# in task #2:
|
>>> print('awaited result:', result)
|
||||||
signal.send('hello from task #2')
|
>>> # in task #2:
|
||||||
# prints in the next iteration of the event loop
|
>>> signal.send('hello from task #2')
|
||||||
|
>>> # prints in the next iteration of the event loop
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -217,36 +211,37 @@ class Signal(Syscall):
|
|||||||
|
|
||||||
def _deliver(self):
|
def _deliver(self):
|
||||||
if self.task is not None and self.value is not _NO_VALUE:
|
if self.task is not None and self.value is not _NO_VALUE:
|
||||||
schedule_task(self.task, self.value)
|
schedule(self.task, self.value)
|
||||||
self.task = None
|
self.task = None
|
||||||
self.value = _NO_VALUE
|
self.value = _NO_VALUE
|
||||||
|
|
||||||
|
|
||||||
class Wait(Syscall):
|
class wait(Syscall):
|
||||||
'''
|
'''
|
||||||
Execute one or more children tasks and wait until one or more of them exit.
|
Execute one or more children tasks and wait until one or more of them exit.
|
||||||
Return value of `Wait` is the return value of task that triggered the
|
Return value of `wait` is the return value of task that triggered the
|
||||||
completion. By default, `Wait` returns after the first child completes, and
|
completion. By default, `wait` returns after the first child completes, and
|
||||||
other running children are killed (by cancelling any pending schedules and
|
other running children are killed (by cancelling any pending schedules and
|
||||||
calling `close()`).
|
calling `close()`).
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
# async def wait_for_touch(): ...
|
|
||||||
# async def animate_logo(): ...
|
|
||||||
touch_task = wait_for_touch()
|
|
||||||
animation_task = animate_logo()
|
|
||||||
waiter = loop.Wait((touch_task, animation_task))
|
|
||||||
result = await waiter
|
|
||||||
if animation_task in waiter.finished:
|
|
||||||
print('animation task returned', result)
|
|
||||||
else:
|
|
||||||
print('touch task returned', result)
|
|
||||||
|
|
||||||
Note: You should not directly `yield` a `Wait` instance, see logic in
|
>>> # async def wait_for_touch(): ...
|
||||||
`Wait.__iter__` for explanation. Always use `await`.
|
>>> # async def animate_logo(): ...
|
||||||
|
>>> touch_task = wait_for_touch()
|
||||||
|
>>> animation_task = animate_logo()
|
||||||
|
>>> waiter = loop.wait(touch_task, animation_task)
|
||||||
|
>>> result = await waiter
|
||||||
|
>>> if animation_task in waiter.finished:
|
||||||
|
>>> print('animation task returned', result)
|
||||||
|
>>> else:
|
||||||
|
>>> print('touch task returned', result)
|
||||||
|
|
||||||
|
Note: You should not directly `yield` a `wait` instance, see logic in
|
||||||
|
`wait.__iter__` for explanation. Always use `await`.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, children, wait_for=1, exit_others=True):
|
def __init__(self, *children, wait_for=1, exit_others=True):
|
||||||
self.children = children
|
self.children = children
|
||||||
self.wait_for = wait_for
|
self.wait_for = wait_for
|
||||||
self.exit_others = exit_others
|
self.exit_others = exit_others
|
||||||
@ -259,13 +254,13 @@ class Wait(Syscall):
|
|||||||
self.finished = []
|
self.finished = []
|
||||||
self.scheduled = [self._wait(c) for c in self.children]
|
self.scheduled = [self._wait(c) for c in self.children]
|
||||||
for ct in self.scheduled:
|
for ct in self.scheduled:
|
||||||
schedule_task(ct)
|
schedule(ct)
|
||||||
|
|
||||||
def exit(self):
|
def exit(self):
|
||||||
for task in self.scheduled:
|
for task in self.scheduled:
|
||||||
if task not in self.finished:
|
if task not in self.finished:
|
||||||
_unpause_task(task)
|
unpause(task)
|
||||||
unschedule_task(task)
|
unschedule(task)
|
||||||
task.close()
|
task.close()
|
||||||
|
|
||||||
async def _wait(self, child):
|
async def _wait(self, child):
|
||||||
@ -281,7 +276,7 @@ class Wait(Syscall):
|
|||||||
if self.wait_for == len(self.finished) or isinstance(result, Exception):
|
if self.wait_for == len(self.finished) or isinstance(result, Exception):
|
||||||
if self.exit_others:
|
if self.exit_others:
|
||||||
self.exit()
|
self.exit()
|
||||||
schedule_task(self.callback, result)
|
schedule(self.callback, result)
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
try:
|
try:
|
||||||
@ -293,10 +288,10 @@ class Wait(Syscall):
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
class Put(Syscall):
|
class put(Syscall):
|
||||||
|
|
||||||
def __init__(self, chan, value=None):
|
def __init__(self, ch, value=None):
|
||||||
self.chan = chan
|
self.ch = ch
|
||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
def __call__(self, value):
|
def __call__(self, value):
|
||||||
@ -304,30 +299,30 @@ class Put(Syscall):
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
def handle(self, task):
|
def handle(self, task):
|
||||||
self.chan.schedule_put(schedule_task, task, self.value)
|
self.ch.schedule_put(schedule, task, self.value)
|
||||||
|
|
||||||
|
|
||||||
class Take(Syscall):
|
class take(Syscall):
|
||||||
|
|
||||||
def __init__(self, chan):
|
def __init__(self, ch):
|
||||||
self.chan = chan
|
self.ch = ch
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def handle(self, task):
|
def handle(self, task):
|
||||||
if self.chan.schedule_take(schedule_task, task) and self.chan.id is not None:
|
if self.ch.schedule_take(schedule, task) and self.ch.id is not None:
|
||||||
_pause_task(self.chan, self.chan.id)
|
pause(self.ch, self.ch.id)
|
||||||
|
|
||||||
|
|
||||||
class Chan:
|
class chan:
|
||||||
|
|
||||||
def __init__(self, id=None):
|
def __init__(self, id=None):
|
||||||
self.id = id
|
self.id = id
|
||||||
self.putters = []
|
self.putters = []
|
||||||
self.takers = []
|
self.takers = []
|
||||||
self.put = Put(self)
|
self.put = put(self)
|
||||||
self.take = Take(self)
|
self.take = take(self)
|
||||||
|
|
||||||
def schedule_publish(self, schedule, value):
|
def schedule_publish(self, schedule, value):
|
||||||
if self.takers:
|
if self.takers:
|
||||||
@ -357,9 +352,3 @@ class Chan:
|
|||||||
else:
|
else:
|
||||||
self.takers.append(taker)
|
self.takers.append(taker)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
select = Select
|
|
||||||
sleep = Sleep
|
|
||||||
wait = Wait
|
|
||||||
signal = Signal
|
|
||||||
|
@ -5,11 +5,14 @@ import math
|
|||||||
import utime
|
import utime
|
||||||
|
|
||||||
from trezorui import Display
|
from trezorui import Display
|
||||||
from trezor import loop, res
|
|
||||||
|
from trezor import io
|
||||||
|
from trezor import loop
|
||||||
|
from trezor import res
|
||||||
|
|
||||||
display = Display()
|
display = Display()
|
||||||
|
|
||||||
if sys.platform not in ('trezor', 'pyboard'): # stmhal
|
if sys.platform != 'trezor':
|
||||||
loop.after_step_hook = display.refresh
|
loop.after_step_hook = display.refresh
|
||||||
|
|
||||||
|
|
||||||
@ -72,7 +75,7 @@ ICON_WIPE = 'trezor/res/header_icons/wipe.toig'
|
|||||||
ICON_RECOVERY = 'trezor/res/header_icons/recovery.toig'
|
ICON_RECOVERY = 'trezor/res/header_icons/recovery.toig'
|
||||||
|
|
||||||
|
|
||||||
def in_area(pos: tuple, area: tuple) -> bool:
|
def contains(pos: tuple, area: tuple) -> bool:
|
||||||
x, y = pos
|
x, y = pos
|
||||||
ax, ay, aw, ah = area
|
ax, ay, aw, ah = area
|
||||||
return ax <= x <= ax + aw and ay <= y <= ay + ah
|
return ax <= x <= ax + aw and ay <= y <= ay + ah
|
||||||
@ -88,42 +91,35 @@ def blend(ca: int, cb: int, t: float) -> int:
|
|||||||
lerpi((ca << 3) & 0xF8, (cb << 3) & 0xF8, t))
|
lerpi((ca << 3) & 0xF8, (cb << 3) & 0xF8, t))
|
||||||
|
|
||||||
|
|
||||||
|
def pulse(delay):
|
||||||
|
while True:
|
||||||
|
# normalize sin from interval -1:1 to 0:1
|
||||||
|
yield 0.5 + 0.5 * math.sin(utime.ticks_us() / delay)
|
||||||
|
|
||||||
|
|
||||||
async def alert(count=3):
|
async def alert(count=3):
|
||||||
|
short_sleep = loop.sleep(20000)
|
||||||
|
long_sleep = loop.sleep(80000)
|
||||||
current = display.backlight()
|
current = display.backlight()
|
||||||
for i in range(count * 2):
|
for i in range(count * 2):
|
||||||
if i % 2 == 0:
|
if i % 2 == 0:
|
||||||
display.backlight(BACKLIGHT_MAX)
|
display.backlight(BACKLIGHT_MAX)
|
||||||
yield loop.Sleep(20000)
|
yield short_sleep
|
||||||
else:
|
else:
|
||||||
display.backlight(BACKLIGHT_NORMAL)
|
display.backlight(BACKLIGHT_NORMAL)
|
||||||
yield loop.Sleep(80000)
|
yield long_sleep
|
||||||
display.backlight(current)
|
display.backlight(current)
|
||||||
|
|
||||||
|
|
||||||
async def backlight_slide(val, speed=20000):
|
async def backlight_slide(val, delay=20000):
|
||||||
|
sleep = loop.sleep(delay)
|
||||||
current = display.backlight()
|
current = display.backlight()
|
||||||
for i in range(current, val, -1 if current > val else 1):
|
for i in range(current, val, -1 if current > val else 1):
|
||||||
display.backlight(i)
|
display.backlight(i)
|
||||||
await loop.Sleep(speed)
|
await sleep
|
||||||
|
|
||||||
|
|
||||||
def animate_pulse(func, ca, cb, speed=200000, delay=30000):
|
def rotate(pos: tuple) -> tuple:
|
||||||
while True:
|
|
||||||
# normalize sin from interval -1:1 to 0:1
|
|
||||||
y = 0.5 + 0.5 * math.sin(utime.ticks_us() / speed)
|
|
||||||
c = blend(ca, cb, y)
|
|
||||||
func(c)
|
|
||||||
yield loop.Sleep(delay)
|
|
||||||
|
|
||||||
|
|
||||||
def header(title, icon=ICON_RESET, fg=BLACK, bg=BLACK):
|
|
||||||
display.bar(0, 0, 240, 32, bg)
|
|
||||||
if icon is not None:
|
|
||||||
display.icon(8, 4, res.load(icon), fg, bg)
|
|
||||||
display.text(8 + 24 + 2, 24, title, BOLD, fg, bg)
|
|
||||||
|
|
||||||
|
|
||||||
def rotate_coords(pos: tuple) -> tuple:
|
|
||||||
r = display.orientation()
|
r = display.orientation()
|
||||||
if r == 0:
|
if r == 0:
|
||||||
return pos
|
return pos
|
||||||
@ -136,6 +132,13 @@ def rotate_coords(pos: tuple) -> tuple:
|
|||||||
return (240 - y, x)
|
return (240 - y, x)
|
||||||
|
|
||||||
|
|
||||||
|
def header(title, icon=ICON_RESET, fg=BLACK, bg=BLACK):
|
||||||
|
display.bar(0, 0, 240, 32, bg)
|
||||||
|
if icon is not None:
|
||||||
|
display.icon(8, 4, res.load(icon), fg, bg)
|
||||||
|
display.text(8 + 24 + 2, 24, title, BOLD, fg, bg)
|
||||||
|
|
||||||
|
|
||||||
class Widget:
|
class Widget:
|
||||||
|
|
||||||
def render(self):
|
def render(self):
|
||||||
@ -145,9 +148,10 @@ class Widget:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
|
touch = loop.select(io.TOUCH)
|
||||||
while True:
|
while True:
|
||||||
self.render()
|
self.render()
|
||||||
event, *pos = yield loop.Select(loop.TOUCH)
|
event, *pos = yield touch
|
||||||
result = self.touch(event, pos)
|
result = self.touch(event, pos)
|
||||||
if result is not None:
|
if result is not None:
|
||||||
return result
|
return result
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
from micropython import const
|
from micropython import const
|
||||||
from trezor import ui, loop
|
|
||||||
from . import display, in_area, rotate_coords, Widget
|
from trezor import io
|
||||||
|
from trezor import ui
|
||||||
|
|
||||||
|
from trezor.ui import display
|
||||||
|
from trezor.ui import contains
|
||||||
|
from trezor.ui import rotate
|
||||||
|
from trezor.ui import Widget
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_BUTTON = {
|
DEFAULT_BUTTON = {
|
||||||
@ -142,18 +148,18 @@ class Button(Widget):
|
|||||||
if self.state & BTN_DISABLED:
|
if self.state & BTN_DISABLED:
|
||||||
return
|
return
|
||||||
if not self.absolute:
|
if not self.absolute:
|
||||||
pos = rotate_coords(pos)
|
pos = rotate(pos)
|
||||||
if event == loop.TOUCH_START:
|
if event == io.TOUCH_START:
|
||||||
if in_area(pos, self.area):
|
if contains(pos, self.area):
|
||||||
self.state = BTN_STARTED | BTN_DIRTY | BTN_ACTIVE
|
self.state = BTN_STARTED | BTN_DIRTY | BTN_ACTIVE
|
||||||
elif event == loop.TOUCH_MOVE and self.state & BTN_STARTED:
|
elif event == io.TOUCH_MOVE and self.state & BTN_STARTED:
|
||||||
if in_area(pos, self.area):
|
if contains(pos, self.area):
|
||||||
if not self.state & BTN_ACTIVE:
|
if not self.state & BTN_ACTIVE:
|
||||||
self.state = BTN_STARTED | BTN_DIRTY | BTN_ACTIVE
|
self.state = BTN_STARTED | BTN_DIRTY | BTN_ACTIVE
|
||||||
else:
|
else:
|
||||||
if self.state & BTN_ACTIVE:
|
if self.state & BTN_ACTIVE:
|
||||||
self.state = BTN_STARTED | BTN_DIRTY
|
self.state = BTN_STARTED | BTN_DIRTY
|
||||||
elif event == loop.TOUCH_END and self.state & BTN_STARTED:
|
elif event == io.TOUCH_END and self.state & BTN_STARTED:
|
||||||
self.state = BTN_DIRTY
|
self.state = BTN_DIRTY
|
||||||
if in_area(pos, self.area):
|
if contains(pos, self.area):
|
||||||
return BTN_CLICKED
|
return BTN_CLICKED
|
||||||
|
@ -41,7 +41,7 @@ class ConfirmDialog(Widget):
|
|||||||
return CANCELLED
|
return CANCELLED
|
||||||
|
|
||||||
async def __iter__(self):
|
async def __iter__(self):
|
||||||
return await loop.Wait((super().__iter__(), self.content))
|
return await loop.wait(super().__iter__(), self.content)
|
||||||
|
|
||||||
|
|
||||||
_STARTED = const(-1)
|
_STARTED = const(-1)
|
||||||
@ -82,5 +82,5 @@ class HoldToConfirmDialog(Widget):
|
|||||||
else:
|
else:
|
||||||
content_loop = self.content
|
content_loop = self.content
|
||||||
confirm_loop = super().__iter__() # default loop (render on touch)
|
confirm_loop = super().__iter__() # default loop (render on touch)
|
||||||
result = await loop.wait((content_loop, confirm_loop))
|
result = await loop.wait(content_loop, confirm_loop)
|
||||||
return result
|
return result
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from trezor import ui, res, loop
|
from trezor import ui, res, loop, io
|
||||||
from trezor.crypto import bip39
|
from trezor.crypto import bip39
|
||||||
from trezor.ui import display
|
from trezor.ui import display
|
||||||
from trezor.ui.button import Button, BTN_CLICKED, CLEAR_BUTTON, CLEAR_BUTTON_ACTIVE
|
from trezor.ui.button import Button, BTN_CLICKED, CLEAR_BUTTON, CLEAR_BUTTON_ACTIVE
|
||||||
@ -136,9 +136,9 @@ class KeyboardMultiTap(ui.Widget):
|
|||||||
btn.disable()
|
btn.disable()
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
timeout = loop.Sleep(1000 * 1000 * 1)
|
timeout = loop.sleep(1000 * 1000 * 1)
|
||||||
touch = loop.Select(loop.TOUCH)
|
touch = loop.select(io.TOUCH)
|
||||||
wait = loop.Wait((touch, timeout))
|
wait = loop.wait(touch, timeout)
|
||||||
while True:
|
while True:
|
||||||
self.render()
|
self.render()
|
||||||
result = yield wait
|
result = yield wait
|
||||||
@ -223,9 +223,9 @@ class KeyboardZooming(ui.Widget):
|
|||||||
break
|
break
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
timeout = loop.Sleep(1000 * 1000 * 1)
|
timeout = loop.sleep(1000 * 1000 * 1)
|
||||||
touch = loop.Select(loop.TOUCH)
|
touch = loop.select(io.TOUCH)
|
||||||
wait = loop.Wait((touch, timeout))
|
wait = loop.wait(touch, timeout)
|
||||||
while True:
|
while True:
|
||||||
self.render()
|
self.render()
|
||||||
result = yield wait
|
result = yield wait
|
||||||
|
@ -16,7 +16,7 @@ async def paginate(render_page, page_count, page=0, *args):
|
|||||||
while True:
|
while True:
|
||||||
changer = change_page(page, page_count)
|
changer = change_page(page, page_count)
|
||||||
renderer = render_page(page, page_count, *args)
|
renderer = render_page(page, page_count, *args)
|
||||||
waiter = loop.Wait([changer, renderer])
|
waiter = loop.wait(changer, renderer)
|
||||||
result = await waiter
|
result = await waiter
|
||||||
if changer in waiter.finished:
|
if changer in waiter.finished:
|
||||||
page = result
|
page = result
|
||||||
@ -25,25 +25,28 @@ async def paginate(render_page, page_count, page=0, *args):
|
|||||||
|
|
||||||
|
|
||||||
async def animate_swipe():
|
async def animate_swipe():
|
||||||
await ui.animate_pulse(render_swipe_icon, ui.GREY, ui.DARK_GREY, speed=300000, delay=200000)
|
time_delay = const(30000)
|
||||||
|
draw_delay = const(200000)
|
||||||
|
|
||||||
|
sleep = loop.sleep(time_delay)
|
||||||
def render_swipe_icon(fg):
|
for t in ui.pulse(draw_delay):
|
||||||
|
fg = ui.blend(ui.GREY, ui.DARK_GREY, t)
|
||||||
ui.display.bar_radius(102, 214, 36, 4, fg, ui.BLACK, 2)
|
ui.display.bar_radius(102, 214, 36, 4, fg, ui.BLACK, 2)
|
||||||
ui.display.bar_radius(106, 222, 28, 4, fg, ui.BLACK, 2)
|
ui.display.bar_radius(106, 222, 28, 4, fg, ui.BLACK, 2)
|
||||||
ui.display.bar_radius(110, 230, 20, 4, fg, ui.BLACK, 2)
|
ui.display.bar_radius(110, 230, 20, 4, fg, ui.BLACK, 2)
|
||||||
|
await sleep
|
||||||
|
|
||||||
|
|
||||||
def render_scrollbar(page, page_count):
|
def render_scrollbar(page, page_count):
|
||||||
screen_height = const(220)
|
bbox = const(220)
|
||||||
size = const(10)
|
size = const(10)
|
||||||
|
|
||||||
padding = 18
|
padding = 18
|
||||||
if page_count * padding > screen_height:
|
if page_count * padding > bbox:
|
||||||
padding = screen_height // page_count
|
padding = bbox // page_count
|
||||||
|
|
||||||
x = const(225)
|
x = const(225)
|
||||||
y = (screen_height // 2) - (page_count // 2) * padding
|
y = (bbox // 2) - (page_count // 2) * padding
|
||||||
|
|
||||||
for i in range(0, page_count):
|
for i in range(0, page_count):
|
||||||
if i != page:
|
if i != page:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import utime
|
import utime
|
||||||
from micropython import const
|
from micropython import const
|
||||||
from trezor import loop, ui
|
from trezor import io, ui
|
||||||
from . import in_area, rotate_coords
|
from . import contains, rotate
|
||||||
|
|
||||||
_SWIPE_DISTANCE_THRESHOLD = const(20) # Min pixels in the primary direction
|
_SWIPE_DISTANCE_THRESHOLD = const(20) # Min pixels in the primary direction
|
||||||
_SWIPE_VELOCITY_THRESHOLD = const(200) # Min pixels per second
|
_SWIPE_VELOCITY_THRESHOLD = const(200) # Min pixels per second
|
||||||
@ -26,12 +26,12 @@ class Swipe(ui.Widget):
|
|||||||
def touch(self, event, pos):
|
def touch(self, event, pos):
|
||||||
|
|
||||||
if not self.absolute:
|
if not self.absolute:
|
||||||
pos = rotate_coords(pos)
|
pos = rotate(pos)
|
||||||
|
|
||||||
temp_time = utime.ticks_ms() / 1000
|
temp_time = utime.ticks_ms() / 1000
|
||||||
|
|
||||||
# primary now for fading purposes
|
# primary now for fading purposes
|
||||||
if event == loop.TOUCH_MOVE and self.start_pos is not None:
|
if event == io.TOUCH_MOVE and self.start_pos is not None:
|
||||||
pdx = pos[0] - self.start_pos[0]
|
pdx = pos[0] - self.start_pos[0]
|
||||||
pdy = pos[1] - self.start_pos[1]
|
pdy = pos[1] - self.start_pos[1]
|
||||||
td = temp_time - self.start_time
|
td = temp_time - self.start_time
|
||||||
@ -52,13 +52,13 @@ class Swipe(ui.Widget):
|
|||||||
else:
|
else:
|
||||||
ui.display.backlight(self.light_target)
|
ui.display.backlight(self.light_target)
|
||||||
|
|
||||||
elif event == loop.TOUCH_START and in_area(pos, self.area):
|
elif event == io.TOUCH_START and contains(pos, self.area):
|
||||||
self.start_time = temp_time
|
self.start_time = temp_time
|
||||||
self.start_pos = pos
|
self.start_pos = pos
|
||||||
self.light_origin = ui.BACKLIGHT_NORMAL
|
self.light_origin = ui.BACKLIGHT_NORMAL
|
||||||
ui.display.backlight(self.light_origin)
|
ui.display.backlight(self.light_origin)
|
||||||
|
|
||||||
elif event == loop.TOUCH_END and self.start_pos is not None:
|
elif event == io.TOUCH_END and self.start_pos is not None:
|
||||||
td = temp_time - self.start_time
|
td = temp_time - self.start_time
|
||||||
pdx = pos[0] - self.start_pos[0]
|
pdx = pos[0] - self.start_pos[0]
|
||||||
pdy = pos[1] - self.start_pos[1]
|
pdy = pos[1] - self.start_pos[1]
|
||||||
|
@ -22,7 +22,7 @@ def setup(iface):
|
|||||||
'''Initialize the wire stack on passed USB interface.'''
|
'''Initialize the wire stack on passed USB interface.'''
|
||||||
session_supervisor = codec_v2.SesssionSupervisor(iface, session_handler)
|
session_supervisor = codec_v2.SesssionSupervisor(iface, session_handler)
|
||||||
session_supervisor.open(codec_v1.SESSION_ID)
|
session_supervisor.open(codec_v1.SESSION_ID)
|
||||||
loop.schedule_task(session_supervisor.listen())
|
loop.schedule(session_supervisor.listen())
|
||||||
|
|
||||||
|
|
||||||
class Context:
|
class Context:
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from micropython import const
|
from micropython import const
|
||||||
import ustruct
|
import ustruct
|
||||||
|
|
||||||
|
from trezor import io
|
||||||
from trezor import loop
|
from trezor import loop
|
||||||
from trezor import utils
|
from trezor import utils
|
||||||
|
|
||||||
@ -37,7 +38,7 @@ class Reader:
|
|||||||
on this session. `self.type` and `self.size` are initialized and
|
on this session. `self.type` and `self.size` are initialized and
|
||||||
available after `aopen()` returns.
|
available after `aopen()` returns.
|
||||||
'''
|
'''
|
||||||
read = loop.select(self.iface.iface_num() | loop.READ)
|
read = loop.select(self.iface.iface_num() | io.POLL_READ)
|
||||||
while True:
|
while True:
|
||||||
# wait for initial report
|
# wait for initial report
|
||||||
report = await read
|
report = await read
|
||||||
@ -63,7 +64,7 @@ class Reader:
|
|||||||
if self.size < len(buf):
|
if self.size < len(buf):
|
||||||
raise EOFError
|
raise EOFError
|
||||||
|
|
||||||
read = loop.select(self.iface.iface_num() | loop.READ)
|
read = loop.select(self.iface.iface_num() | io.POLL_READ)
|
||||||
nread = 0
|
nread = 0
|
||||||
while nread < len(buf):
|
while nread < len(buf):
|
||||||
if self.ofs == len(self.data):
|
if self.ofs == len(self.data):
|
||||||
@ -122,7 +123,7 @@ class Writer:
|
|||||||
if self.size < len(buf):
|
if self.size < len(buf):
|
||||||
raise EOFError
|
raise EOFError
|
||||||
|
|
||||||
write = loop.select(self.iface.iface_num() | loop.WRITE)
|
write = loop.select(self.iface.iface_num() | io.POLL_WRITE)
|
||||||
nwritten = 0
|
nwritten = 0
|
||||||
while nwritten < len(buf):
|
while nwritten < len(buf):
|
||||||
# copy as much as possible to report buffer
|
# copy as much as possible to report buffer
|
||||||
@ -148,5 +149,5 @@ class Writer:
|
|||||||
self.data[self.ofs] = 0x00
|
self.data[self.ofs] = 0x00
|
||||||
self.ofs += 1
|
self.ofs += 1
|
||||||
|
|
||||||
await loop.select(self.iface.iface_num() | loop.WRITE)
|
await loop.select(self.iface.iface_num() | io.POLL_WRITE)
|
||||||
self.iface.write(self.data)
|
self.iface.write(self.data)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from micropython import const
|
from micropython import const
|
||||||
import ustruct
|
import ustruct
|
||||||
|
|
||||||
|
from trezor import io
|
||||||
from trezor import loop
|
from trezor import loop
|
||||||
from trezor import utils
|
from trezor import utils
|
||||||
from trezor.crypto import random
|
from trezor.crypto import random
|
||||||
@ -59,7 +60,7 @@ class Reader:
|
|||||||
on this session. `self.type` and `self.size` are initialized and
|
on this session. `self.type` and `self.size` are initialized and
|
||||||
available after `aopen()` returns.
|
available after `aopen()` returns.
|
||||||
'''
|
'''
|
||||||
read = loop.select(self.iface.iface_num() | loop.READ)
|
read = loop.select(self.iface.iface_num() | io.POLL_READ)
|
||||||
while True:
|
while True:
|
||||||
# wait for initial report
|
# wait for initial report
|
||||||
report = await read
|
report = await read
|
||||||
@ -83,7 +84,7 @@ class Reader:
|
|||||||
if self.size < len(buf):
|
if self.size < len(buf):
|
||||||
raise EOFError
|
raise EOFError
|
||||||
|
|
||||||
read = loop.select(self.iface.iface_num() | loop.READ)
|
read = loop.select(self.iface.iface_num() | io.POLL_READ)
|
||||||
nread = 0
|
nread = 0
|
||||||
while nread < len(buf):
|
while nread < len(buf):
|
||||||
if self.ofs == len(self.data):
|
if self.ofs == len(self.data):
|
||||||
@ -148,7 +149,7 @@ class Writer:
|
|||||||
if self.size < len(buf):
|
if self.size < len(buf):
|
||||||
raise EOFError
|
raise EOFError
|
||||||
|
|
||||||
write = loop.select(self.iface.iface_num() | loop.WRITE)
|
write = loop.select(self.iface.iface_num() | io.POLL_WRITE)
|
||||||
nwritten = 0
|
nwritten = 0
|
||||||
while nwritten < len(buf):
|
while nwritten < len(buf):
|
||||||
# copy as much as possible to report buffer
|
# copy as much as possible to report buffer
|
||||||
@ -177,7 +178,7 @@ class Writer:
|
|||||||
self.data[self.ofs] = 0x00
|
self.data[self.ofs] = 0x00
|
||||||
self.ofs += 1
|
self.ofs += 1
|
||||||
|
|
||||||
await loop.select(self.iface.iface_num() | loop.WRITE)
|
await loop.select(self.iface.iface_num() | io.POLL_WRITE)
|
||||||
self.iface.write(self.data)
|
self.iface.write(self.data)
|
||||||
|
|
||||||
|
|
||||||
@ -197,8 +198,8 @@ class SesssionSupervisor:
|
|||||||
After close request, the handling task is closed and session terminated.
|
After close request, the handling task is closed and session terminated.
|
||||||
Both requests receive responses confirming the operation.
|
Both requests receive responses confirming the operation.
|
||||||
'''
|
'''
|
||||||
read = loop.select(self.iface.iface_num() | loop.READ)
|
read = loop.select(self.iface.iface_num() | io.POLL_READ)
|
||||||
write = loop.select(self.iface.iface_num() | loop.WRITE)
|
write = loop.select(self.iface.iface_num() | io.POLL_WRITE)
|
||||||
while True:
|
while True:
|
||||||
report = await read
|
report = await read
|
||||||
repmarker, repsid = ustruct.unpack(_REP, report)
|
repmarker, repsid = ustruct.unpack(_REP, report)
|
||||||
@ -221,7 +222,7 @@ class SesssionSupervisor:
|
|||||||
def open(self, sid):
|
def open(self, sid):
|
||||||
if sid not in self.handling_tasks:
|
if sid not in self.handling_tasks:
|
||||||
task = self.handling_tasks[sid] = self.handler(self.iface, sid)
|
task = self.handling_tasks[sid] = self.handler(self.iface, sid)
|
||||||
loop.schedule_task(task)
|
loop.schedule(task)
|
||||||
|
|
||||||
def close(self, sid):
|
def close(self, sid):
|
||||||
if sid in self.handling_tasks:
|
if sid in self.handling_tasks:
|
||||||
|
@ -38,6 +38,6 @@ def startdefault(handler):
|
|||||||
if not default:
|
if not default:
|
||||||
default_handler = handler
|
default_handler = handler
|
||||||
default = handler()
|
default = handler()
|
||||||
loop.schedule_task(default)
|
loop.schedule(default)
|
||||||
ui.display.backlight(ui.BACKLIGHT_NORMAL)
|
ui.display.backlight(ui.BACKLIGHT_NORMAL)
|
||||||
log.debug(__name__, 'startdefault')
|
log.debug(__name__, 'startdefault')
|
||||||
|
@ -6,7 +6,8 @@ from utest import *
|
|||||||
from ustruct import pack, unpack
|
from ustruct import pack, unpack
|
||||||
from ubinascii import hexlify, unhexlify
|
from ubinascii import hexlify, unhexlify
|
||||||
|
|
||||||
from trezor.loop import Select, Syscall, READ, WRITE
|
from trezor import io
|
||||||
|
from trezor.loop import select, Syscall
|
||||||
from trezor.crypto import random
|
from trezor.crypto import random
|
||||||
from trezor.utils import chunks
|
from trezor.utils import chunks
|
||||||
from trezor.wire import codec_v1
|
from trezor.wire import codec_v1
|
||||||
@ -39,7 +40,7 @@ def test_reader():
|
|||||||
|
|
||||||
# open, expected one read
|
# open, expected one read
|
||||||
first_report = report_header + message[:rep_len - len(report_header)]
|
first_report = report_header + message[:rep_len - len(report_header)]
|
||||||
assert_async(reader.aopen(), [(None, Select(READ | interface_num)), (first_report, StopIteration()),])
|
assert_async(reader.aopen(), [(None, select(io.POLL_READ | interface_num)), (first_report, StopIteration()),])
|
||||||
assert_eq(reader.type, message_type)
|
assert_eq(reader.type, message_type)
|
||||||
assert_eq(reader.size, message_len)
|
assert_eq(reader.size, message_len)
|
||||||
|
|
||||||
@ -66,7 +67,7 @@ def test_reader():
|
|||||||
next_report_header = bytearray(unhexlify('3f'))
|
next_report_header = bytearray(unhexlify('3f'))
|
||||||
next_report = next_report_header + message[rep_len - len(report_header):][:rep_len - len(next_report_header)]
|
next_report = next_report_header + message[rep_len - len(report_header):][:rep_len - len(next_report_header)]
|
||||||
onebyte_buffer = bytearray(1)
|
onebyte_buffer = bytearray(1)
|
||||||
assert_async(reader.areadinto(onebyte_buffer), [(None, Select(READ | interface_num)), (next_report, StopIteration()),])
|
assert_async(reader.areadinto(onebyte_buffer), [(None, select(io.POLL_READ | interface_num)), (next_report, StopIteration()),])
|
||||||
assert_eq(onebyte_buffer, message[len(short_buffer):][len(aligned_buffer):][:len(onebyte_buffer)])
|
assert_eq(onebyte_buffer, message[len(short_buffer):][len(aligned_buffer):][:len(onebyte_buffer)])
|
||||||
assert_eq(reader.size, message_len - len(short_buffer) - len(aligned_buffer) - len(onebyte_buffer))
|
assert_eq(reader.size, message_len - len(short_buffer) - len(aligned_buffer) - len(onebyte_buffer))
|
||||||
|
|
||||||
@ -85,7 +86,7 @@ def test_reader():
|
|||||||
expected_syscalls = []
|
expected_syscalls = []
|
||||||
for i, _ in enumerate(next_reports):
|
for i, _ in enumerate(next_reports):
|
||||||
prev_report = next_reports[i - 1] if i > 0 else None
|
prev_report = next_reports[i - 1] if i > 0 else None
|
||||||
expected_syscalls.append((prev_report, Select(READ | interface_num)))
|
expected_syscalls.append((prev_report, select(io.POLL_READ | interface_num)))
|
||||||
expected_syscalls.append((next_reports[-1], StopIteration()))
|
expected_syscalls.append((next_reports[-1], StopIteration()))
|
||||||
assert_async(reader.areadinto(long_buffer), expected_syscalls)
|
assert_async(reader.areadinto(long_buffer), expected_syscalls)
|
||||||
assert_eq(long_buffer, message[-start_size:])
|
assert_eq(long_buffer, message[-start_size:])
|
||||||
@ -128,7 +129,7 @@ def test_writer():
|
|||||||
# aligned write, expected one report
|
# aligned write, expected one report
|
||||||
start_size = writer.size
|
start_size = writer.size
|
||||||
aligned_payload = bytearray(range(rep_len - len(report_header) - len(short_payload)))
|
aligned_payload = bytearray(range(rep_len - len(report_header) - len(short_payload)))
|
||||||
assert_async(writer.awrite(aligned_payload), [(None, Select(WRITE | interface_num)), (None, StopIteration()),])
|
assert_async(writer.awrite(aligned_payload), [(None, select(io.POLL_WRITE | interface_num)), (None, StopIteration()),])
|
||||||
assert_eq(interface.data, [report_header
|
assert_eq(interface.data, [report_header
|
||||||
+ short_payload
|
+ short_payload
|
||||||
+ aligned_payload
|
+ aligned_payload
|
||||||
@ -154,7 +155,7 @@ def test_writer():
|
|||||||
expected_reports[-1] += bytearray(bytes(1) * (rep_len - len(expected_reports[-1])))
|
expected_reports[-1] += bytearray(bytes(1) * (rep_len - len(expected_reports[-1])))
|
||||||
# test write
|
# test write
|
||||||
expected_write_reports = expected_reports[:-1]
|
expected_write_reports = expected_reports[:-1]
|
||||||
assert_async(writer.awrite(long_payload), len(expected_write_reports) * [(None, Select(WRITE | interface_num))] + [(None, StopIteration())])
|
assert_async(writer.awrite(long_payload), len(expected_write_reports) * [(None, select(io.POLL_WRITE | interface_num))] + [(None, StopIteration())])
|
||||||
assert_eq(interface.data, expected_write_reports)
|
assert_eq(interface.data, expected_write_reports)
|
||||||
assert_eq(writer.size, start_size - len(long_payload))
|
assert_eq(writer.size, start_size - len(long_payload))
|
||||||
interface.data.clear()
|
interface.data.clear()
|
||||||
@ -163,7 +164,7 @@ def test_writer():
|
|||||||
assert_eq(interface.data, [])
|
assert_eq(interface.data, [])
|
||||||
# test close
|
# test close
|
||||||
expected_close_reports = expected_reports[-1:]
|
expected_close_reports = expected_reports[-1:]
|
||||||
assert_async(writer.aclose(), len(expected_close_reports) * [(None, Select(WRITE | interface_num))] + [(None, StopIteration())])
|
assert_async(writer.aclose(), len(expected_close_reports) * [(None, select(io.POLL_WRITE | interface_num))] + [(None, StopIteration())])
|
||||||
assert_eq(interface.data, expected_close_reports)
|
assert_eq(interface.data, expected_close_reports)
|
||||||
assert_eq(writer.size, 0)
|
assert_eq(writer.size, 0)
|
||||||
|
|
||||||
|
@ -6,7 +6,8 @@ from utest import *
|
|||||||
from ustruct import pack, unpack
|
from ustruct import pack, unpack
|
||||||
from ubinascii import hexlify, unhexlify
|
from ubinascii import hexlify, unhexlify
|
||||||
|
|
||||||
from trezor.loop import Select, Syscall, READ, WRITE
|
from trezor import io
|
||||||
|
from trezor.loop import select, Syscall
|
||||||
from trezor.utils import chunks
|
from trezor.utils import chunks
|
||||||
from trezor.wire import codec_v2
|
from trezor.wire import codec_v2
|
||||||
|
|
||||||
@ -39,7 +40,7 @@ def test_reader():
|
|||||||
|
|
||||||
# open, expected one read
|
# open, expected one read
|
||||||
first_report = report_header + message[:rep_len - len(report_header)]
|
first_report = report_header + message[:rep_len - len(report_header)]
|
||||||
assert_async(reader.aopen(), [(None, Select(READ | interface_num)), (first_report, StopIteration()),])
|
assert_async(reader.aopen(), [(None, select(io.POLL_READ | interface_num)), (first_report, StopIteration()),])
|
||||||
assert_eq(reader.type, message_type)
|
assert_eq(reader.type, message_type)
|
||||||
assert_eq(reader.size, message_len)
|
assert_eq(reader.size, message_len)
|
||||||
|
|
||||||
@ -66,7 +67,7 @@ def test_reader():
|
|||||||
next_report_header = bytearray(unhexlify('021234567800000000'))
|
next_report_header = bytearray(unhexlify('021234567800000000'))
|
||||||
next_report = next_report_header + message[rep_len - len(report_header):][:rep_len - len(next_report_header)]
|
next_report = next_report_header + message[rep_len - len(report_header):][:rep_len - len(next_report_header)]
|
||||||
onebyte_buffer = bytearray(1)
|
onebyte_buffer = bytearray(1)
|
||||||
assert_async(reader.areadinto(onebyte_buffer), [(None, Select(READ | interface_num)), (next_report, StopIteration()),])
|
assert_async(reader.areadinto(onebyte_buffer), [(None, select(io.POLL_READ | interface_num)), (next_report, StopIteration()),])
|
||||||
assert_eq(onebyte_buffer, message[len(short_buffer):][len(aligned_buffer):][:len(onebyte_buffer)])
|
assert_eq(onebyte_buffer, message[len(short_buffer):][len(aligned_buffer):][:len(onebyte_buffer)])
|
||||||
assert_eq(reader.size, message_len - len(short_buffer) - len(aligned_buffer) - len(onebyte_buffer))
|
assert_eq(reader.size, message_len - len(short_buffer) - len(aligned_buffer) - len(onebyte_buffer))
|
||||||
|
|
||||||
@ -85,7 +86,7 @@ def test_reader():
|
|||||||
expected_syscalls = []
|
expected_syscalls = []
|
||||||
for i, _ in enumerate(next_reports):
|
for i, _ in enumerate(next_reports):
|
||||||
prev_report = next_reports[i - 1] if i > 0 else None
|
prev_report = next_reports[i - 1] if i > 0 else None
|
||||||
expected_syscalls.append((prev_report, Select(READ | interface_num)))
|
expected_syscalls.append((prev_report, select(io.POLL_READ | interface_num)))
|
||||||
expected_syscalls.append((next_reports[-1], StopIteration()))
|
expected_syscalls.append((next_reports[-1], StopIteration()))
|
||||||
assert_async(reader.areadinto(long_buffer), expected_syscalls)
|
assert_async(reader.areadinto(long_buffer), expected_syscalls)
|
||||||
assert_eq(long_buffer, message[-start_size:])
|
assert_eq(long_buffer, message[-start_size:])
|
||||||
@ -129,7 +130,7 @@ def test_writer():
|
|||||||
# aligned write, expected one report
|
# aligned write, expected one report
|
||||||
start_size = writer.size
|
start_size = writer.size
|
||||||
aligned_payload = bytearray(range(rep_len - len(report_header) - len(short_payload)))
|
aligned_payload = bytearray(range(rep_len - len(report_header) - len(short_payload)))
|
||||||
assert_async(writer.awrite(aligned_payload), [(None, Select(WRITE | interface_num)), (None, StopIteration()),])
|
assert_async(writer.awrite(aligned_payload), [(None, select(io.POLL_WRITE | interface_num)), (None, StopIteration()),])
|
||||||
assert_eq(interface.data, [report_header
|
assert_eq(interface.data, [report_header
|
||||||
+ short_payload
|
+ short_payload
|
||||||
+ aligned_payload
|
+ aligned_payload
|
||||||
@ -157,7 +158,7 @@ def test_writer():
|
|||||||
expected_reports[-1] += bytearray(bytes(1) * (rep_len - len(expected_reports[-1])))
|
expected_reports[-1] += bytearray(bytes(1) * (rep_len - len(expected_reports[-1])))
|
||||||
# test write
|
# test write
|
||||||
expected_write_reports = expected_reports[:-1]
|
expected_write_reports = expected_reports[:-1]
|
||||||
assert_async(writer.awrite(long_payload), len(expected_write_reports) * [(None, Select(WRITE | interface_num))] + [(None, StopIteration())])
|
assert_async(writer.awrite(long_payload), len(expected_write_reports) * [(None, select(io.POLL_WRITE | interface_num))] + [(None, StopIteration())])
|
||||||
assert_eq(interface.data, expected_write_reports)
|
assert_eq(interface.data, expected_write_reports)
|
||||||
assert_eq(writer.size, start_size - len(long_payload))
|
assert_eq(writer.size, start_size - len(long_payload))
|
||||||
interface.data.clear()
|
interface.data.clear()
|
||||||
@ -166,7 +167,7 @@ def test_writer():
|
|||||||
assert_eq(interface.data, [])
|
assert_eq(interface.data, [])
|
||||||
# test close
|
# test close
|
||||||
expected_close_reports = expected_reports[-1:]
|
expected_close_reports = expected_reports[-1:]
|
||||||
assert_async(writer.aclose(), len(expected_close_reports) * [(None, Select(WRITE | interface_num))] + [(None, StopIteration())])
|
assert_async(writer.aclose(), len(expected_close_reports) * [(None, select(io.POLL_WRITE | interface_num))] + [(None, StopIteration())])
|
||||||
assert_eq(interface.data, expected_close_reports)
|
assert_eq(interface.data, expected_close_reports)
|
||||||
assert_eq(writer.size, 0)
|
assert_eq(writer.size, 0)
|
||||||
interface.data.clear()
|
interface.data.clear()
|
||||||
|
Loading…
Reference in New Issue
Block a user