mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-23 07:58:09 +00:00
support multiple event handlers
This commit is contained in:
parent
8f374f728b
commit
412ac2daa7
@ -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:
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user