From f61da5777a2f6e5305d6ab855ec1b1f8126be37c Mon Sep 17 00:00:00 2001 From: cepetr Date: Tue, 1 Apr 2025 09:06:10 +0200 Subject: [PATCH] feat(core): add event polling to usb webusb driver [no changelog] --- core/embed/io/usb/stm32/usb_class_webusb.c | 62 ++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/core/embed/io/usb/stm32/usb_class_webusb.c b/core/embed/io/usb/stm32/usb_class_webusb.c index 4395e23ddb..53b95040ba 100644 --- a/core/embed/io/usb/stm32/usb_class_webusb.c +++ b/core/embed/io/usb/stm32/usb_class_webusb.c @@ -23,6 +23,7 @@ #include #include +#include #include "usb_internal.h" @@ -55,6 +56,7 @@ _Static_assert(sizeof(usb_webusb_state_t) <= USBD_CLASS_STATE_MAX_SIZE); // interface dispatch functions static const USBD_ClassTypeDef usb_webusb_class; +static const syshandle_vmt_t usb_webusb_handle_vmt; #define usb_get_webusb_state(iface_num) \ ((usb_webusb_state_t *)usb_get_iface_state(iface_num, &usb_webusb_class)) @@ -265,6 +267,12 @@ static uint8_t usb_webusb_class_init(USBD_HandleTypeDef *dev, uint8_t cfg_idx) { USBD_LL_PrepareReceive(dev, state->ep_out, state->rx_buffer, state->max_packet_len); + uint8_t iface_num = state->desc_block->iface.bInterfaceNumber; + syshandle_t handle = SYSHANDLE_USB_IFACE_0 + iface_num; + if (!syshandle_register(handle, &usb_webusb_handle_vmt, state)) { + return USBD_FAIL; + } + return USBD_OK; } @@ -272,6 +280,10 @@ static uint8_t usb_webusb_class_deinit(USBD_HandleTypeDef *dev, uint8_t cfg_idx) { usb_webusb_state_t *state = (usb_webusb_state_t *)dev->pUserData; + uint8_t iface_num = state->desc_block->iface.bInterfaceNumber; + syshandle_t handle = SYSHANDLE_USB_IFACE_0 + iface_num; + syshandle_unregister(handle); + // Flush endpoints USBD_LL_FlushEP(dev, state->ep_in); USBD_LL_FlushEP(dev, state->ep_out); @@ -358,4 +370,54 @@ static const USBD_ClassTypeDef usb_webusb_class = { .GetUsrStrDescriptor = NULL, }; +static void on_event_poll(void *context, bool read_awaited, + bool write_awaited) { + usb_webusb_state_t *state = (usb_webusb_state_t *)context; + + uint8_t iface_num = state->desc_block->iface.bInterfaceNumber; + syshandle_t handle = SYSHANDLE_USB_IFACE_0 + iface_num; + + // Only one task can read or write at a time. Therefore, we can + // assume that only one task is waiting for events and keep the + // logic simple. + + if (read_awaited && usb_webusb_can_read(iface_num)) { + syshandle_signal_read_ready(handle, NULL); + } + + if (write_awaited && usb_webusb_can_write(iface_num)) { + syshandle_signal_write_ready(handle, NULL); + } +} + +static bool on_check_read_ready(void *context, systask_id_t task_id, + void *param) { + usb_webusb_state_t *state = (usb_webusb_state_t *)context; + uint8_t iface_num = state->desc_block->iface.bInterfaceNumber; + + UNUSED(task_id); + UNUSED(param); + + return usb_webusb_can_read(iface_num); +} + +static bool on_check_write_ready(void *context, systask_id_t task_id, + void *param) { + usb_webusb_state_t *state = (usb_webusb_state_t *)context; + uint8_t iface_num = state->desc_block->iface.bInterfaceNumber; + + UNUSED(task_id); + UNUSED(param); + + return usb_webusb_can_write(iface_num); +} + +static const syshandle_vmt_t usb_webusb_handle_vmt = { + .task_created = NULL, + .task_killed = NULL, + .check_read_ready = on_check_read_ready, + .check_write_ready = on_check_write_ready, + .poll = on_event_poll, +}; + #endif // KERNEL_MODE