diff --git a/core/embed/extmod/modtrezorio/modtrezorio-poll.h b/core/embed/extmod/modtrezorio/modtrezorio-poll.h index c795282e56..87a8efc7f5 100644 --- a/core/embed/extmod/modtrezorio/modtrezorio-poll.h +++ b/core/embed/extmod/modtrezorio/modtrezorio-poll.h @@ -30,8 +30,9 @@ #endif #define USB_DATA_IFACE (253) -#define BUTTON_IFACE (254) -#define TOUCH_IFACE (255) +#define INPUT_IFACE (255) +#define TOUCH_INPUT_FLAG (0x400000) +#define BUTTON_INPUT_FLAG (0x800000) #define POLL_READ (0x0000) #define POLL_WRITE (0x0100) @@ -90,22 +91,40 @@ 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_get_event(); + } else if (iface == INPUT_IFACE) { + uint32_t evt; +#ifdef USE_BUTTON + evt = button_get_event(); + 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_get_event(); if (evt) { // ignore TOUCH_MOVE events if they are too frequent if ((evt & TOUCH_MOVE) == 0 || (hal_ticks_ms() - last_touch_sample_time > 10)) { last_touch_sample_time = hal_ticks_ms(); - 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; @@ -132,6 +151,7 @@ STATIC mp_obj_t mod_trezorio_poll(mp_obj_t ifaces, mp_obj_t list_ref, 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) { @@ -140,27 +160,7 @@ STATIC mp_obj_t mod_trezorio_poll(mp_obj_t ifaces, mp_obj_t list_ref, ret->items[1] = usb_connected ? mp_const_true : mp_const_false; return mp_const_true; } - } -#endif -#if USE_BUTTON - else if (iface == BUTTON_IFACE) { - const uint32_t evt = button_get_event(); - 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 - else if (mode == POLL_READ) { + } else if (mode == POLL_READ) { if (sectrue == usb_hid_can_read(iface)) { uint8_t buf[64] = {0}; int len = usb_hid_read(iface, buf, sizeof(buf)); diff --git a/core/embed/extmod/modtrezorio/modtrezorio.c b/core/embed/extmod/modtrezorio/modtrezorio.c index 75a5501c5e..a3cf678ca7 100644 --- a/core/embed/extmod/modtrezorio/modtrezorio.c +++ b/core/embed/extmod/modtrezorio/modtrezorio.c @@ -62,12 +62,12 @@ uint32_t last_touch_sample_time = 0; /// 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 @@ -90,17 +90,18 @@ STATIC const mp_rom_map_elem_t mp_module_trezorio_globals_table[] = { #endif #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 89a8ed3df3..19bfbf5b4e 100644 --- a/core/embed/extmod/modtrezorutils/modtrezorutils.c +++ b/core/embed/extmod/modtrezorutils/modtrezorutils.c @@ -380,6 +380,8 @@ STATIC mp_obj_tuple_t mod_trezorutils_version_obj = { /// """Git commit hash of the firmware.""" /// VERSION: VersionTuple /// """Firmware version as a tuple (major, minor, patch, build).""" +/// USE_BUTTON: bool +/// """Whether the hardware supports button.""" /// USE_SD_CARD: bool /// """Whether the hardware supports SD card.""" /// USE_BACKLIGHT: bool @@ -388,6 +390,8 @@ STATIC mp_obj_tuple_t mod_trezorutils_version_obj = { /// """Whether the hardware supports haptic feedback.""" /// USE_OPTIGA: bool /// """Whether the hardware supports Optiga secure element.""" +/// USE_TOUCH: bool +/// """Whether the hardware supports touch screen.""" /// MODEL: str /// """Model name.""" /// MODEL_FULL_NAME: str @@ -439,6 +443,16 @@ STATIC const mp_rom_map_elem_t mp_module_trezorutils_globals_table[] = { #else {MP_ROM_QSTR(MP_QSTR_USE_SD_CARD), 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/touch.rs b/core/embed/rust/src/ui/event/touch.rs index b99310ebd2..54227fb68a 100644 --- a/core/embed/rust/src/ui/event/touch.rs +++ b/core/embed/rust/src/ui/event/touch.rs @@ -19,7 +19,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/mocks/generated/trezorio/__init__.pyi b/core/mocks/generated/trezorio/__init__.pyi index d60c9f2efb..2d273cc172 100644 --- a/core/mocks/generated/trezorio/__init__.pyi +++ b/core/mocks/generated/trezorio/__init__.pyi @@ -152,11 +152,11 @@ from . import fatfs, haptic, sdcard 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 5c497046ba..5a4f7796a2 100644 --- a/core/mocks/generated/trezorutils.pyi +++ b/core/mocks/generated/trezorutils.pyi @@ -122,6 +122,8 @@ SCM_REVISION: bytes """Git commit hash of the firmware.""" VERSION: VersionTuple """Firmware version as a tuple (major, minor, patch, build).""" +USE_BUTTON: bool +"""Whether the hardware supports button.""" USE_SD_CARD: bool """Whether the hardware supports SD card.""" USE_BACKLIGHT: bool @@ -130,6 +132,8 @@ USE_HAPTIC: bool """Whether the hardware supports haptic feedback.""" USE_OPTIGA: bool """Whether the hardware supports Optiga secure element.""" +USE_TOUCH: bool +"""Whether the hardware supports touch screen.""" MODEL: str """Model name.""" MODEL_FULL_NAME: str diff --git a/core/src/trezor/ui/layouts/mercury/__init__.py b/core/src/trezor/ui/layouts/mercury/__init__.py index f926cf0e48..ba7a0f5242 100644 --- a/core/src/trezor/ui/layouts/mercury/__init__.py +++ b/core/src/trezor/ui/layouts/mercury/__init__.py @@ -222,16 +222,21 @@ class RustLayout(ui.Layout): def handle_input_and_rendering(self) -> loop.Task: 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) - self._send_button_request() + 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/ui/layouts/tr/__init__.py b/core/src/trezor/ui/layouts/tr/__init__.py index 037f43e675..14741b96fb 100644 --- a/core/src/trezor/ui/layouts/tr/__init__.py +++ b/core/src/trezor/ui/layouts/tr/__init__.py @@ -261,16 +261,21 @@ class RustLayout(LayoutParentType[T]): def handle_input_and_rendering(self) -> loop.Task: from trezor import workflow - button = loop.wait(io.BUTTON) + input = loop.wait(io.INPUT) self._first_paint() while True: # Using `yield` instead of `await` to avoid allocations. - event, button_num = yield button + event, p0, p1 = yield input workflow.idle_timer.touch() msg = None - if event in (io.BUTTON_PRESSED, io.BUTTON_RELEASED): - msg = self.layout.button_event(event, button_num) - self._send_button_request() + 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/ui/layouts/tt/__init__.py b/core/src/trezor/ui/layouts/tt/__init__.py index 363345df3f..2e0094dd68 100644 --- a/core/src/trezor/ui/layouts/tt/__init__.py +++ b/core/src/trezor/ui/layouts/tt/__init__.py @@ -225,16 +225,21 @@ class RustLayout(LayoutParentType[T]): def handle_input_and_rendering(self) -> loop.Task: 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) - self._send_button_request() + 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 134274db6c..7021759ba9 100644 --- a/core/src/trezor/utils.py +++ b/core/src/trezor/utils.py @@ -11,10 +11,12 @@ from trezorutils import ( # noqa: F401 SCM_REVISION, UI_LAYOUT, USE_BACKLIGHT, + USE_BUTTON, USE_HAPTIC, USE_OPTIGA, USE_SD_CARD, USE_THP, + USE_TOUCH, VERSION, bootloader_locked, check_firmware_header,