From 803baf7fcd23011610b0e6b0db5d55e7a360c289 Mon Sep 17 00:00:00 2001 From: tychovrahe Date: Fri, 16 May 2025 20:29:26 +0200 Subject: [PATCH] feat(core/unix): implement USB VCP emulation [no changelog] --- core/embed/io/usb/unix/usb.c | 59 +++++++++++++++++++++++++++++++++++- core/src/usb.py | 2 +- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/core/embed/io/usb/unix/usb.c b/core/embed/io/usb/unix/usb.c index d758ea72f8..e74b72a176 100644 --- a/core/embed/io/usb/unix/usb.c +++ b/core/embed/io/usb/unix/usb.c @@ -88,7 +88,8 @@ secbool usb_start(void) { usb_iface_t *iface = &usb_ifaces[i]; // skip if not HID or WebUSB interface if (iface->type != USB_IFACE_TYPE_HID && - iface->type != USB_IFACE_TYPE_WEBUSB) { + iface->type != USB_IFACE_TYPE_WEBUSB && + iface->type != USB_IFACE_TYPE_VCP) { continue; } @@ -328,6 +329,62 @@ int usb_webusb_write_blocking(uint8_t iface_num, const uint8_t *buf, return usb_webusb_write(iface_num, buf, len); } +secbool usb_vcp_can_read(uint8_t iface_num) { + if (iface_num >= USBD_MAX_NUM_INTERFACES || + usb_ifaces[iface_num].type != USB_IFACE_TYPE_VCP) { + return secfalse; + } + return usb_emulated_poll_read(&usb_ifaces[iface_num]); +} + +secbool usb_vcp_can_write(uint8_t iface_num) { + if (iface_num >= USBD_MAX_NUM_INTERFACES || + usb_ifaces[iface_num].type != USB_IFACE_TYPE_VCP) { + return secfalse; + } + return usb_emulated_poll_write(&usb_ifaces[iface_num]); +} + +int usb_vcp_read(uint8_t iface_num, uint8_t *buf, uint32_t len) { + if (iface_num >= USBD_MAX_NUM_INTERFACES || + usb_ifaces[iface_num].type != USB_IFACE_TYPE_VCP) { + return 0; + } + return usb_emulated_read(&usb_ifaces[iface_num], buf, len); +} + +int usb_vcp_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len, + int timeout) { + const uint32_t start = clock(); + while (sectrue != usb_vcp_can_read(iface_num)) { + if (timeout >= 0 && + (1000 * (clock() - start)) / CLOCKS_PER_SEC >= timeout) { + return 0; // Timeout + } + } + return usb_vcp_read(iface_num, buf, len); +} + +int usb_vcp_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) { + if (iface_num >= USBD_MAX_NUM_INTERFACES || + usb_ifaces[iface_num].type != USB_IFACE_TYPE_VCP) { + return 0; + } + return usb_emulated_write(&usb_ifaces[iface_num], buf, len); +} + +int usb_vcp_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len, + int timeout) { + const uint32_t start = clock(); + while (sectrue != usb_vcp_can_write(iface_num)) { + if (timeout >= 0 && + (1000 * (clock() - start)) / CLOCKS_PER_SEC >= timeout) { + return 0; // Timeout + } + } + return usb_vcp_write(iface_num, buf, len); +} + void mp_hal_set_vcp_iface(int iface_num) {} secbool usb_configured(void) { diff --git a/core/src/usb.py b/core/src/usb.py index 33d43f25ea..cd60dcb676 100644 --- a/core/src/usb.py +++ b/core/src/usb.py @@ -27,7 +27,7 @@ _iface_iter = iter(range(5)) ENABLE_IFACE_DEBUG = __debug__ ENABLE_IFACE_WEBAUTHN = not utils.BITCOIN_ONLY -ENABLE_IFACE_VCP = __debug__ +ENABLE_IFACE_VCP = __debug__ and not utils.EMULATOR # interface used for trezor wire protocol id_wire = next(_iface_iter)