refactor(core): unify touch and button handling, enable usage of both in one model

[no changelog]
mmilata/ble-rebased
tychovrahe 1 year ago committed by Martin Milata
parent b074d0dd7e
commit b71b4cdc82

@ -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();

@ -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

@ -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

@ -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<Self, error::Error> {
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),

@ -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

@ -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

@ -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

@ -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)
)

@ -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:

@ -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.

@ -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()

@ -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,

@ -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()

Loading…
Cancel
Save