1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-22 23:48:12 +00:00

support multiple event handlers

This commit is contained in:
Jan Pochyla 2016-05-16 17:10:12 +02:00 committed by Pavol Rusnak
parent 8f374f728b
commit 412ac2daa7
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D
2 changed files with 56 additions and 38 deletions

View File

@ -141,7 +141,9 @@ class PinDialog():
def wait_for_result(self): def wait_for_result(self):
while True: while True:
self.render() self.render()
event, *pos = yield loop.Select(loop.TOUCH_START | loop.TOUCH_MOVE | loop.TOUCH_END) event, *pos = yield loop.Select(loop.TOUCH_START,
loop.TOUCH_MOVE,
loop.TOUCH_END)
result = self.send(event, pos) result = self.send(event, pos)
if result is not None: if result is not None:
return result return result
@ -170,7 +172,6 @@ def layout_tap_to_confirm(address, amount, currency):
# animation = ui.animate_pulse(func, ui.BLACK, ui.GREY, speed=200000) # animation = ui.animate_pulse(func, ui.BLACK, ui.GREY, speed=200000)
pin_dialog = PinDialog() pin_dialog = PinDialog()
pin_result = yield from pin_dialog.wait_for_result() pin_result = yield from pin_dialog.wait_for_result()
if pin_result is PIN_CONFIRMED: if pin_result is PIN_CONFIRMED:

View File

@ -1,6 +1,6 @@
import utime import utime
from uheapq import heappop, heappush from uheapq import heappop, heappush, heapify
from .utils import type_gen from .utils import type_gen
from . import msg from . import msg
from . import log from . import log
@ -17,18 +17,38 @@ TOUCH_MOVE = const(2)
TOUCH_END = const(4) TOUCH_END = const(4)
HID_READ = const(8) HID_READ = const(8)
time_queue = [] blocked_gens = {} # event -> generator
time_queue_ctr = 0 time_queue = [] # [(int, int, generator, any)]
blocked_events = 0 time_ticket = 0
blocked_gen = None
def schedule(gen, data=None, time=None): def schedule(gen, data=None, time=None):
global time_queue_ctr global time_ticket
if not time: if not time:
time = utime.ticks_us() time = utime.ticks_us()
heappush(time_queue, (time, time_queue_ctr, gen, data)) heappush(time_queue, (time, time_ticket, gen, data))
time_queue_ctr += 1 time_ticket += 1
return gen
def unschedule(gen):
global time_queue
time_queue = [entry for entry in time_queue if entry[1] is not gen]
heapify(time_queue)
def block(gen, event):
curr_gen = blocked_gens.get(event, None)
if curr_gen is not None:
log.warning(__name__, 'Closing %s blocked on %s', curr_gen, event)
curr_gen.close()
blocked_gens[event] = gen
def unblock(gen):
for key in blocked_gens:
if blocked_gens[key] is gen:
blocked_gens[key] = None
class Sleep(): class Sleep():
@ -39,40 +59,41 @@ class Sleep():
class Select(): class Select():
def __init__(self, events): def __init__(self, *events):
self.events = events self.events = events
def handle(self, gen):
for event in self.events:
block(gen, event)
class Wait(): class Wait():
def __init__(self, gens, wait_for=1, exit_others=True): def __init__(self, gens, wait_for=1, exit_others=True):
self.gens = gens
self.wait_for = wait_for self.wait_for = wait_for
self.exit_others = exit_others self.exit_others = exit_others
self.received = 0 self.received = 0
self.scheduled = None
self.callback = None self.callback = None
self.gens = gens
for g in gens: def handle(self, gen):
schedule(self._wait(g)) self.scheduled = [schedule(self._wait(g)) for g in self.gens]
self.callback = gen
def _wait(self, gen): def _wait(self, gen):
if isinstance(gen, type_gen): result = yield from gen
ret = yield from gen self._finish(gen, result)
else:
ret = yield gen
self.finish(gen, ret) def _finish(self, gen, result):
def finish(self, gen, result):
self.received += 1 self.received += 1
if self.received == self.wait_for: if self.received == self.wait_for:
schedule(self.callback, (gen, result)) schedule(self.callback, (gen, result))
self.callback = None
if self.exit_others: if self.exit_others:
for g in self.gens: for g in self.scheduled:
if isinstance(gen, type_gen): if g is not gen:
unschedule(g)
unblock(g)
g.close() g.close()
@ -102,13 +123,12 @@ def run_forever():
# Run interrupt handler right away, they have priority # Run interrupt handler right away, they have priority
event = message[0] event = message[0]
data = message data = message
if blocked_events & event: gen = blocked_gens.pop(event, None)
gen = blocked_gen if not gen:
blocked_events = 0
blocked_gen = None
else:
log.info(__name__, 'No handler for event: %s', event) log.info(__name__, 'No handler for event: %s', event)
continue continue
# Cancel other registrations of this handler
unblock(gen)
else: else:
# Run something from the time queue # Run something from the time queue
if time_queue: if time_queue:
@ -127,18 +147,15 @@ def run_forever():
if isinstance(result, Sleep): if isinstance(result, Sleep):
# Sleep until result.time, call us later # Sleep until result.time, call us later
schedule(gen, None, result.time) schedule(gen, result, result.time)
elif isinstance(result, Select): elif isinstance(result, Select):
# Wait for one or more types of event # Wait for one or more types of event
if blocked_gen: result.handle(gen)
blocked_gen.close()
blocked_gen = gen
blocked_events = result.events
elif isinstance(result, Wait): elif isinstance(result, Wait):
# Register the origin generator as a waiting callback # Register us as a waiting callback
result.callback = gen result.handle(gen)
elif result is None: elif result is None:
# Just call us asap # Just call us asap