From b71b4cdc8255956f665d14be657586f1e638f5dc Mon Sep 17 00:00:00 2001 From: tychovrahe Date: Tue, 25 Apr 2023 22:44:59 +0200 Subject: [PATCH] refactor(core): unify touch and button handling, enable usage of both in one model [no changelog] --- .../extmod/modtrezorio/modtrezorio-poll.h | 61 ++++++++++--------- core/embed/extmod/modtrezorio/modtrezorio.c | 20 +++--- .../extmod/modtrezorutils/modtrezorutils.c | 12 ++++ core/embed/rust/src/ui/event.rs | 4 +- core/embed/trezorhal/boards/board-unix.h | 6 -- core/mocks/generated/trezorio/__init__.pyi | 3 +- core/mocks/generated/trezorutils.pyi | 2 + core/src/apps/debug/__init__.py | 8 +-- core/src/trezor/loop.py | 2 +- core/src/trezor/ui/layouts/tr/__init__.py | 2 +- core/src/trezor/ui/layouts/tt/__init__.py | 16 +++-- core/src/trezor/utils.py | 2 + core/tests/production_tests/main.py | 8 +-- 13 files changed, 83 insertions(+), 63 deletions(-) diff --git a/core/embed/extmod/modtrezorio/modtrezorio-poll.h b/core/embed/extmod/modtrezorio/modtrezorio-poll.h index 5b703970f..9bf42b03d 100644 --- a/core/embed/extmod/modtrezorio/modtrezorio-poll.h +++ b/core/embed/extmod/modtrezorio/modtrezorio-poll.h @@ -32,11 +32,12 @@ #define BLE_EVENTS_IFACE (252) #define USB_DATA_IFACE (253) -#define BUTTON_IFACE (254) -#define TOUCH_IFACE (255) +#define INPUT_IFACE (255) #define USB_RW_IFACE_MAX (15) // 0-15 reserved for USB #define BLE_IFACE_INT (16) #define BLE_IFACE_EXT (17) +#define TOUCH_INPUT_FLAG (0x400000) +#define BUTTON_INPUT_FLAG (0x800000) #define POLL_READ (0x0000) #define POLL_WRITE (0x0100) @@ -89,17 +90,36 @@ STATIC mp_obj_t mod_trezorio_poll(mp_obj_t ifaces, mp_obj_t list_ref, #endif if (false) { - } -#if defined USE_TOUCH - else if (iface == TOUCH_IFACE) { - const uint32_t evt = touch_read(); + } else if (iface == INPUT_IFACE) { + uint32_t evt; +#ifdef USE_BUTTON + evt = button_read(); + if (evt & (BTN_EVT_DOWN | BTN_EVT_UP)) { + mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); + uint32_t etype = + ((evt >> 24) & 0x3U) | BUTTON_INPUT_FLAG; // button down/up + uint32_t en = evt & 0xFFFF; // button number + if (display_orientation(-1) == 180) { + en = (en == BTN_LEFT) ? BTN_RIGHT : BTN_LEFT; + } + tuple->items[0] = MP_OBJ_NEW_SMALL_INT(etype); + tuple->items[1] = MP_OBJ_NEW_SMALL_INT(en); + tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); + ret->items[0] = MP_OBJ_NEW_SMALL_INT(i); + ret->items[1] = MP_OBJ_FROM_PTR(tuple); + return mp_const_true; + } +#endif +#ifdef USE_TOUCH + evt = touch_read(); if (evt) { mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); - const uint32_t etype = (evt >> 24) & 0xFFU; // event type - const uint32_t ex = (evt >> 12) & 0xFFFU; // x position - const uint32_t ey = evt & 0xFFFU; // y position - uint32_t exr; // rotated x position - uint32_t eyr; // rotated y position + const uint32_t etype = + ((evt >> 24) & 0xFFU) | TOUCH_INPUT_FLAG; // event type + const uint32_t ex = (evt >> 12) & 0xFFFU; // x position + const uint32_t ey = evt & 0xFFFU; // y position + uint32_t exr; // rotated x position + uint32_t eyr; // rotated y position switch (display_orientation(-1)) { case 90: exr = ey; @@ -125,6 +145,7 @@ STATIC mp_obj_t mod_trezorio_poll(mp_obj_t ifaces, mp_obj_t list_ref, ret->items[1] = MP_OBJ_FROM_PTR(tuple); return mp_const_true; } +#endif } else if (iface == USB_DATA_IFACE) { bool usb_connected = usb_configured() == sectrue ? true : false; if (usb_connected != usb_connected_previously) { @@ -135,24 +156,6 @@ STATIC mp_obj_t mod_trezorio_poll(mp_obj_t ifaces, mp_obj_t list_ref, } } #endif -#if USE_BUTTON - else if (iface == BUTTON_IFACE) { - const uint32_t evt = button_read(); - if (evt & (BTN_EVT_DOWN | BTN_EVT_UP)) { - mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); - uint32_t etype = (evt >> 24) & 0x3U; // button down/up - uint32_t en = evt & 0xFFFF; // button number - if (display_orientation(-1) == 180) { - en = (en == BTN_LEFT) ? BTN_RIGHT : BTN_LEFT; - } - tuple->items[0] = MP_OBJ_NEW_SMALL_INT(etype); - tuple->items[1] = MP_OBJ_NEW_SMALL_INT(en); - ret->items[0] = MP_OBJ_NEW_SMALL_INT(i); - ret->items[1] = MP_OBJ_FROM_PTR(tuple); - return mp_const_true; - } - } -#endif #ifdef USE_BLE else if (iface == BLE_EVENTS_IFACE) { ble_event_poll(); diff --git a/core/embed/extmod/modtrezorio/modtrezorio.c b/core/embed/extmod/modtrezorio/modtrezorio.c index b75ef562c..692ecbfc1 100644 --- a/core/embed/extmod/modtrezorio/modtrezorio.c +++ b/core/embed/extmod/modtrezorio/modtrezorio.c @@ -68,12 +68,12 @@ bool ble_connected_previously = false; /// POLL_READ: int # wait until interface is readable and return read data /// POLL_WRITE: int # wait until interface is writable /// -/// TOUCH: int # interface id of the touch events +/// INPUT: int # interface id of unified input events +/// /// TOUCH_START: int # event id of touch start event /// TOUCH_MOVE: int # event id of touch move event /// TOUCH_END: int # event id of touch end event -/// BUTTON: int # interface id of button events /// BUTTON_PRESSED: int # button down event /// BUTTON_RELEASED: int # button up event /// BUTTON_LEFT: int # button number of left button @@ -100,18 +100,20 @@ STATIC const mp_rom_map_elem_t mp_module_trezorio_globals_table[] = { {MP_ROM_QSTR(MP_QSTR_ble), MP_ROM_PTR(&mod_trezorio_BLE_module)}, #endif + {MP_ROM_QSTR(MP_QSTR_INPUT), MP_ROM_INT(INPUT_IFACE)}, #ifdef USE_TOUCH - {MP_ROM_QSTR(MP_QSTR_TOUCH), MP_ROM_INT(TOUCH_IFACE)}, - {MP_ROM_QSTR(MP_QSTR_TOUCH_START), MP_ROM_INT((TOUCH_START >> 24) & 0xFFU)}, - {MP_ROM_QSTR(MP_QSTR_TOUCH_MOVE), MP_ROM_INT((TOUCH_MOVE >> 24) & 0xFFU)}, - {MP_ROM_QSTR(MP_QSTR_TOUCH_END), MP_ROM_INT((TOUCH_END >> 24) & 0xFFU)}, + {MP_ROM_QSTR(MP_QSTR_TOUCH_START), + MP_ROM_INT(((TOUCH_START >> 24) & 0xFFU) | TOUCH_INPUT_FLAG)}, + {MP_ROM_QSTR(MP_QSTR_TOUCH_MOVE), + MP_ROM_INT(((TOUCH_MOVE >> 24) & 0xFFU) | TOUCH_INPUT_FLAG)}, + {MP_ROM_QSTR(MP_QSTR_TOUCH_END), + MP_ROM_INT(((TOUCH_END >> 24) & 0xFFU) | TOUCH_INPUT_FLAG)}, #endif #ifdef USE_BUTTON - {MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_INT(BUTTON_IFACE)}, {MP_ROM_QSTR(MP_QSTR_BUTTON_PRESSED), - MP_ROM_INT((BTN_EVT_DOWN >> 24) & 0x3U)}, + MP_ROM_INT(((BTN_EVT_DOWN >> 24) & 0x3U) | BUTTON_INPUT_FLAG)}, {MP_ROM_QSTR(MP_QSTR_BUTTON_RELEASED), - MP_ROM_INT((BTN_EVT_UP >> 24) & 0x3U)}, + MP_ROM_INT(((BTN_EVT_UP >> 24) & 0x3U) | BUTTON_INPUT_FLAG)}, {MP_ROM_QSTR(MP_QSTR_BUTTON_LEFT), MP_ROM_INT(BTN_LEFT)}, {MP_ROM_QSTR(MP_QSTR_BUTTON_RIGHT), MP_ROM_INT(BTN_RIGHT)}, #endif diff --git a/core/embed/extmod/modtrezorutils/modtrezorutils.c b/core/embed/extmod/modtrezorutils/modtrezorutils.c index f0898648a..396d0b13a 100644 --- a/core/embed/extmod/modtrezorutils/modtrezorutils.c +++ b/core/embed/extmod/modtrezorutils/modtrezorutils.c @@ -385,6 +385,8 @@ STATIC mp_obj_str_t mod_trezorutils_full_name_obj = { /// """Whether the hardware supports backlight brightness control.""" /// USE_OPTIGA: bool /// """Whether the hardware supports Optiga secure element.""" +/// USE_TOUCH: bool +/// USE_BUTTON: bool /// MODEL: str /// """Model name.""" /// MODEL_FULL_NAME: str @@ -433,6 +435,16 @@ STATIC const mp_rom_map_elem_t mp_module_trezorutils_globals_table[] = { #else {MP_ROM_QSTR(MP_QSTR_USE_BLE), mp_const_false}, #endif +#ifdef USE_TOUCH + {MP_ROM_QSTR(MP_QSTR_USE_TOUCH), mp_const_true}, +#else + {MP_ROM_QSTR(MP_QSTR_USE_TOUCH), mp_const_false}, +#endif +#ifdef USE_BUTTON + {MP_ROM_QSTR(MP_QSTR_USE_BUTTON), mp_const_true}, +#else + {MP_ROM_QSTR(MP_QSTR_USE_BUTTON), mp_const_false}, +#endif #ifdef USE_BACKLIGHT {MP_ROM_QSTR(MP_QSTR_USE_BACKLIGHT), mp_const_true}, #else diff --git a/core/embed/rust/src/ui/event.rs b/core/embed/rust/src/ui/event.rs index fd1f55554..0bb6bc7b0 100644 --- a/core/embed/rust/src/ui/event.rs +++ b/core/embed/rust/src/ui/event.rs @@ -26,7 +26,7 @@ impl ButtonEvent { 1 => PhysicalButton::Right, _ => return Err(error::Error::OutOfRange), }; - let result = match event { + let result = match event & 0xFF { 1 => Self::ButtonPressed(button), 2 => Self::ButtonReleased(button), _ => return Err(error::Error::OutOfRange), @@ -50,7 +50,7 @@ pub enum TouchEvent { impl TouchEvent { pub fn new(event: u32, x: u32, y: u32) -> Result { let point = Point::new(x.try_into()?, y.try_into()?); - let result = match event { + let result = match event & 0xFF { 1 => Self::TouchStart(point), 2 => Self::TouchMove(point), 4 => Self::TouchEnd(point), diff --git a/core/embed/trezorhal/boards/board-unix.h b/core/embed/trezorhal/boards/board-unix.h index 0cb2ef591..0bff9e2a0 100644 --- a/core/embed/trezorhal/boards/board-unix.h +++ b/core/embed/trezorhal/boards/board-unix.h @@ -30,10 +30,4 @@ #include "display-unix.h" -#ifdef TREZOR_MODEL_R -#define USE_BUTTON 1 -#elif TREZOR_MODEL_T -#define USE_TOUCH 1 -#endif - #endif //_BOARD_UNIX_H diff --git a/core/mocks/generated/trezorio/__init__.pyi b/core/mocks/generated/trezorio/__init__.pyi index c0b42a5d7..2570c2ef3 100644 --- a/core/mocks/generated/trezorio/__init__.pyi +++ b/core/mocks/generated/trezorio/__init__.pyi @@ -193,11 +193,10 @@ class WebUSB: from . import fatfs, sdcard, ble POLL_READ: int # wait until interface is readable and return read data POLL_WRITE: int # wait until interface is writable -TOUCH: int # interface id of the touch events +INPUT: int # interface id of unified input events TOUCH_START: int # event id of touch start event TOUCH_MOVE: int # event id of touch move event TOUCH_END: int # event id of touch end event -BUTTON: int # interface id of button events BUTTON_PRESSED: int # button down event BUTTON_RELEASED: int # button up event BUTTON_LEFT: int # button number of left button diff --git a/core/mocks/generated/trezorutils.pyi b/core/mocks/generated/trezorutils.pyi index 9308aab98..bc93b63dd 100644 --- a/core/mocks/generated/trezorutils.pyi +++ b/core/mocks/generated/trezorutils.pyi @@ -115,6 +115,8 @@ VERSION_PATCH: int USE_BLE: bool USE_SD_CARD: bool """Whether the hardware supports SD card.""" +USE_TOUCH: bool +USE_BUTTON: bool USE_BACKLIGHT: bool """Whether the hardware supports backlight brightness control.""" USE_OPTIGA: bool diff --git a/core/src/apps/debug/__init__.py b/core/src/apps/debug/__init__.py index e6426045c..3b9174f68 100644 --- a/core/src/apps/debug/__init__.py +++ b/core/src/apps/debug/__init__.py @@ -167,11 +167,11 @@ if __debug__: # Incrementing the counter for last events so we know what to await debug_events.last_event += 1 - # TT click on specific coordinates, with possible hold - if x is not None and y is not None and utils.INTERNAL_MODEL in ("T2T1", "D001"): + # click on specific coordinates, with possible hold + if x is not None and y is not None: click_chan.publish((debug_events.last_event, x, y, msg.hold_ms)) - # TR press specific button - elif msg.physical_button is not None and utils.INTERNAL_MODEL in ("T2B1",): + # press specific button + elif msg.physical_button is not None: button_chan.publish( (debug_events.last_event, msg.physical_button, msg.hold_ms) ) diff --git a/core/src/trezor/loop.py b/core/src/trezor/loop.py index d631e54ae..d3f78aded 100644 --- a/core/src/trezor/loop.py +++ b/core/src/trezor/loop.py @@ -227,7 +227,7 @@ class wait(Syscall): Example: >>> hid_report, = await loop.wait(0xABCD) # await USB HID report - >>> event, x, y = await loop.wait(io.TOUCH) # await touch event + >>> event, x, y = await loop.wait(io.INPUT) # await input event """ def __init__(self, msg_iface: int) -> None: diff --git a/core/src/trezor/ui/layouts/tr/__init__.py b/core/src/trezor/ui/layouts/tr/__init__.py index fa4ccb2aa..ca5835b54 100644 --- a/core/src/trezor/ui/layouts/tr/__init__.py +++ b/core/src/trezor/ui/layouts/tr/__init__.py @@ -218,7 +218,7 @@ class RustLayout(ui.Layout): def handle_input_and_rendering(self) -> loop.Task: # type: ignore [awaitable-is-generator] from trezor import workflow - button = loop.wait(io.BUTTON) + button = loop.wait(io.INPUT) self._first_paint() while True: # Using `yield` instead of `await` to avoid allocations. diff --git a/core/src/trezor/ui/layouts/tt/__init__.py b/core/src/trezor/ui/layouts/tt/__init__.py index 4f5f0d6fc..84ade8e95 100644 --- a/core/src/trezor/ui/layouts/tt/__init__.py +++ b/core/src/trezor/ui/layouts/tt/__init__.py @@ -1,7 +1,7 @@ from typing import TYPE_CHECKING import trezorui2 -from trezor import io, loop, ui +from trezor import io, loop, ui, utils from trezor.enums import ButtonRequestType from trezor.wire import ActionCancelled from trezor.wire.context import wait as ctx_wait @@ -190,15 +190,21 @@ class RustLayout(ui.Layout): def handle_input_and_rendering(self) -> loop.Task: # type: ignore [awaitable-is-generator] from trezor import workflow - touch = loop.wait(io.TOUCH) + input = loop.wait(io.INPUT) self._first_paint() while True: # Using `yield` instead of `await` to avoid allocations. - event, x, y = yield touch + event, p0, p1 = yield input workflow.idle_timer.touch() msg = None - if event in (io.TOUCH_START, io.TOUCH_MOVE, io.TOUCH_END): - msg = self.layout.touch_event(event, x, y) + if utils.USE_TOUCH and event in ( + io.TOUCH_START, + io.TOUCH_MOVE, + io.TOUCH_END, + ): + msg = self.layout.touch_event(event, p0, p1) + if utils.USE_BUTTON and event in (io.BUTTON_PRESSED, io.BUTTON_RELEASED): + msg = self.layout.button_event(event, p0) if msg is not None: raise ui.Result(msg) self._paint() diff --git a/core/src/trezor/utils.py b/core/src/trezor/utils.py index 528a1f9ef..7f7ab193a 100644 --- a/core/src/trezor/utils.py +++ b/core/src/trezor/utils.py @@ -11,7 +11,9 @@ from trezorutils import ( # noqa: F401 USE_BACKLIGHT, USE_BLE, USE_OPTIGA, + USE_BUTTON, USE_SD_CARD, + USE_TOUCH, VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, diff --git a/core/tests/production_tests/main.py b/core/tests/production_tests/main.py index 90f106e74..fab70bc32 100644 --- a/core/tests/production_tests/main.py +++ b/core/tests/production_tests/main.py @@ -62,23 +62,23 @@ def test_touch(v): d.refresh() r = [0, 0] # flush all events - while io.poll([io.TOUCH], r, 10000): + while io.poll([io.INPUT], r, 10000): pass # wait for event touch = False while True: if not touch: - if io.poll([io.TOUCH], r, 10000) and r[0] == io.TOUCH and r[1][0] == io.TOUCH_START: + if io.poll([io.INPUT], r, 10000) and r[0] == io.INPUT and r[1][0] == io.TOUCH_START: touch = True else: - if io.poll([io.TOUCH], r, 10000) and r[0] == io.TOUCH and r[1][0] == io.TOUCH_END: + if io.poll([io.INPUT], r, 10000) and r[0] == io.INPUT and r[1][0] == io.TOUCH_END: print(f'OK {r[1][1]} {r[1][2]}') break if utime.ticks_us() > deadline: print('ERROR TIMEOUT') break # flush all events - while io.poll([io.TOUCH], r, 10000): + while io.poll([io.INPUT], r, 10000): pass d.clear() d.refresh()