What changed, and why it matters
This is a large internal refactoring of the Trezor firmware's USB driver layer. It replaces direct USB class-specific read/write APIs (for HID, VCP, and WebUSB) with a unified 'system handle' API, centralizes USB interface setup in a new configuration module, and adjusts memory layout for one model. The commit is tagged as a refactor with no changelog and makes no direct claim of fixing a security bug. While the change touches security-relevant code paths (USB communication between the device and host), the diff itself shows a restructuring rather than a clear vulnerability fix or introduction.
Treat this as a high-risk refactor of the USB attack surface. Review the new `usb_configure()` and `usb_start()` paths for race conditions, lifetime issues with the fixed-size descriptor strings, and correct syshandle registration/unregistration. Verify that removing per-class syscall verifiers does not weaken the unprivileged-to-kernel isolation, and run regression tests for USB communication in bootloader, firmware, prodtest, and emulator builds. No immediate patch is indicated because the commit does not disclose a specific vulnerability.
Security signals we found
Large refactor of security-relevant USB stack and syscall boundary
Reduction of USB-specific syscalls and move to generic syshandle I/O may shrink attack surface, but also changes trust boundary semantics
Fixed-size string buffers introduced for USB descriptor strings (previously pointer-based)
usb_start now accepts runtime-modifiable serial number and landing parameters
No changelog entry and no vendor security disclosure in commit message
Evidence from the diff
The commit refactors the core USB subsystem across the Trezor firmware. Key changes include: (1) introducing a new usb_config.c module that centralizes device initialization and interface registration (wire, debug, WebAuthn/FIDO, VCP) behind feature flags; (2) changing usb_dev_info_t string fields from const char * pointers to fixed-size char arrays and adding usb_start_params_t so usb_start() can update serial number and USB 2.1 landing behavior; (3) removing per-class read/write/can-read/can-write/blocking functions from usb_hid.h, usb_vcp.h, and usb_webusb.h, moving that I/O into generic syshandle_read/syshandle_write calls backed by VMT read/write callbacks; (4) updating syscall numbers and dispatch/verifiers to expose SYSCALL_SYSHANDLE_READ/SYSCALL_SYSHANDLE_WRITE and a reduced USB syscall surface; (5) updating bootloader, bootloader_ci, kernel, prodtest, and unix projects to call usb_configure() and usb_start() instead of open-coding USB setup; (6) increasing MAIN_RAM_SIZE and decreasing AUX2_RAM_SIZE for T3T1. The diff does not contain an explicit security fix, CVE reference, or advisory.
Changed components
core/embed/io/usb (USB HAL driver)core/embed/sys/syscall (system call dispatch and verifiers)core/embed/sys/task/sysevent (system handle event framework)core/embed/projects/bootloader (USB wire interface)core/embed/projects/bootloader_cicore/embed/projects/kernelcore/embed/projects/prodtest (VCP console)core/embed/projects/unixcore/embed/upymod/modtrezorio (MicroPython USB module bindings)core/embed/models/T3T1 memory layoutInspect captured patch +1341 / −2556
diff --git a/core/SConscript.bootloader b/core/SConscript.bootloader
index 7e6dcc4e..2c5a1794 100644
--- a/core/SConscript.bootloader
+++ b/core/SConscript.bootloader
@@ -27,6 +27,7 @@ FEATURES_WANTED = [
"secure_mode",
"suspend",
"usb",
+ "usb_iface_wire",
]
if TREZOR_MODEL in ('T3W1', ):
diff --git a/core/SConscript.bootloader_ci b/core/SConscript.bootloader_ci
index 0e5b4c35..d057e0ac 100644
--- a/core/SConscript.bootloader_ci
+++ b/core/SConscript.bootloader_ci
@@ -18,6 +18,7 @@ FEATURES_WANTED = [
"secure_domain",
"secure_mode",
"usb",
+ "usb_iface_wire",
]
CCFLAGS_MOD = ''
diff --git a/core/SConscript.bootloader_emu b/core/SConscript.bootloader_emu
index a4a5d01e..6a33b6ce 100644
--- a/core/SConscript.bootloader_emu
+++ b/core/SConscript.bootloader_emu
@@ -29,6 +29,8 @@ FEATURES_WANTED = [
"power_manager",
"rgb_led",
"secure_mode",
+ "usb",
+ "usb_iface_wire",
]
CCFLAGS_MOD = ''
diff --git a/core/SConscript.firmware b/core/SConscript.firmware
index f4b096fb..595e44df 100644
--- a/core/SConscript.firmware
+++ b/core/SConscript.firmware
@@ -64,6 +64,7 @@ FEATURES_WANTED = [
"suspend",
"tropic",
"usb",
+ "usb_iface_wire",
]
if DISABLE_OPTIGA:
diff --git a/core/SConscript.kernel b/core/SConscript.kernel
index d9c85f8c..7befdbcf 100644
--- a/core/SConscript.kernel
+++ b/core/SConscript.kernel
@@ -51,6 +51,18 @@ FEATURES_WANTED = [
"suspend",
"tropic",
"usb",
+ "usb_iface_wire",
+ ]
+
+if BITCOIN_ONLY == '0':
+ FEATURES_WANTED += [
+ "usb_iface_webauthn",
+ ]
+
+if PYOPT == '0':
+ FEATURES_WANTED += [
+ "usb_iface_debug",
+ "usb_iface_vcp",
]
if not TREZOR_MODEL in ['T3W1', 'D002']:
diff --git a/core/SConscript.prodtest b/core/SConscript.prodtest
index d421a285..f7c4a8ee 100644
--- a/core/SConscript.prodtest
+++ b/core/SConscript.prodtest
@@ -42,6 +42,7 @@ FEATURES_WANTED = [
"suspend",
"tropic",
"usb",
+ "usb_iface_vcp",
]
CCFLAGS_MOD = ''
diff --git a/core/SConscript.prodtest_emu b/core/SConscript.prodtest_emu
index 80d7e273..d7d03762 100644
--- a/core/SConscript.prodtest_emu
+++ b/core/SConscript.prodtest_emu
@@ -32,7 +32,8 @@ FEATURES_WANTED = [
"sd_card",
"secure_mode",
"tropic",
- "usb"
+ "usb",
+ "usb_iface_vcp",
]
CCFLAGS_MOD = ''
diff --git a/core/SConscript.unix b/core/SConscript.unix
index 644b741e..2ec2d3a3 100644
--- a/core/SConscript.unix
+++ b/core/SConscript.unix
@@ -34,6 +34,14 @@ FEATURES_WANTED = [
"sd_card",
"secure_mode",
"storage",
+ "usb",
+ "usb_iface_wire",
+ "usb_iface_debug",
+ ]
+
+if BITCOIN_ONLY == '0':
+ FEATURES_WANTED += [
+ "usb_iface_webauthn",
]
if not DISABLE_TROPIC:
diff --git a/core/embed/io/usb/inc/io/usb.h b/core/embed/io/usb/inc/io/usb.h
index 871eaf09..e8daeb92 100644
--- a/core/embed/io/usb/inc/io/usb.h
+++ b/core/embed/io/usb/inc/io/usb.h
@@ -17,15 +17,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef __TREZORHAL_USB_H__
-#define __TREZORHAL_USB_H__
+#pragma once
#include <trezor_types.h>
-#include <io/usb_hid.h>
-#include <io/usb_vcp.h>
-#include <io/usb_webusb.h>
-
#define USB_PACKET_LEN 64
typedef enum {
@@ -70,6 +65,8 @@ typedef union {
//
// clang-format on
+#define USB_MAX_STR_SIZE 62
+
typedef struct {
uint8_t device_class;
uint8_t device_subclass;
@@ -77,53 +74,69 @@ typedef struct {
uint16_t vendor_id;
uint16_t product_id;
uint16_t release_num;
- const char *manufacturer;
- const char *product;
- const char *serial_number;
- const char *interface;
+ char manufacturer[USB_MAX_STR_SIZE + 1];
+ char product[USB_MAX_STR_SIZE + 1];
+ char serial_number[USB_MAX_STR_SIZE + 1];
+ char interface[USB_MAX_STR_SIZE + 1];
secbool usb21_enabled;
secbool usb21_landing;
} usb_dev_info_t;
-// Initializes USB stack
-//
-// When the USB driver is initialized, class drivers can be registered.
-// After all class drivers are registered, `usb_start()` can be called.
-//
-// Returns `sectrue` if the initialization is successful.
+typedef struct {
+ char serial_number[USB_MAX_STR_SIZE + 1];
+ secbool usb21_landing;
+} usb_start_params_t;
+
+/**
+ * Initializes the USB stack driver.
+ *
+ * When the USB driver is initialized, class drivers can be registered using
+ * `usb_xxx_add()` functions. After all class drivers are registered,
+ * `usb_start` can be called.
+ *
+ * @param dev_info Pointer to USB device information structure.
+ * @return `sectrue` if the initialization is successful.
+ */
secbool usb_init(const usb_dev_info_t *dev_info);
-// Deinitialize USB stack
-//
-// This function completely deinitializes the USB driver and all class drivers.
-// After this function is called, `usb_init()` can be called again.
+/**
+ * Deinitializes the USB stack.
+ *
+ * This function completely deinitializes the USB driver and all class drivers.
+ * After this function is called, `usb_init` can be called again.
+ */
void usb_deinit(void);
-// Starts USB driver and its class drivers
-//
-// Initializes the USB stack (and hardware) and starts all registered class
-// drivers.
-//
-// This function can be called after all class drivers are registered or after
-// `usb_stop()` is called.
-//
-// Returns `sectrue` if the USB stack is started successfully.
-secbool usb_start(void);
+/**
+ * Starts the USB stack and registered class drivers.
+ *
+ * @param params Parameter that can be used to change some
+ * settings specified during USB stack initialization. May be `NULL`.
+ *
+ * @return `sectrue` if the USB stack is started successfully.
+ */
+secbool usb_start(const usb_start_params_t *params);
-// Stops USB driver and its class drivers
-//
-// Uninitializes the USB stack (and hardware) but leaves all configuration
-// intact, so it can be started again with `usb_start()`.
-//
-// When the USB stack is stopped, it does not respond to any USB events and
-// the CPU can go to stop/standby mode.
+/**
+ * Stops the USB stack but leaves all configuration intact,
+ * so it can be re-started again with @ref usb_start.
+ *
+ * When the USB stack is stopped, it does not respond to any USB events and
+ * the CPU can go to stop/standby mode.
+ */
void usb_stop(void);
-// Reads USB event
-// Return USB_EVENT_NONE if no event is available
+/**
+ * @brief Reads a USB event.
+ *
+ * @return USB_EVENT_NONE if no event is available.
+ */
usb_event_t usb_get_event(void);
-// Reads USB state into `state`
+/**
+ * @brief Reads the USB state into the provided structure.
+ *
+ * @param state Pointer to a @ref usb_state_t structure to receive the
+ * current state.
+ */
void usb_get_state(usb_state_t *state);
-
-#endif
diff --git a/core/embed/io/usb/inc/io/usb_config.h b/core/embed/io/usb/inc/io/usb_config.h
new file mode 100644
index 00000000..113199c1
--- /dev/null
+++ b/core/embed/io/usb/inc/io/usb_config.h
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <sys/sysevent.h>
+
+typedef void (*usb_vcp_intr_callback_t)(void);
+
+/**
+ * Initialize and configures USB stack and all enabled USB interfaces.
+ *
+ * @param vcp_intr_callback Optional callback to be called on VCP interrupt.
+ */
+secbool usb_configure(usb_vcp_intr_callback_t vcp_intr_callback);
diff --git a/core/embed/io/usb/inc/io/usb_hid.h b/core/embed/io/usb/inc/io/usb_hid.h
index 6ab8f644..692c86b3 100644
--- a/core/embed/io/usb/inc/io/usb_hid.h
+++ b/core/embed/io/usb/inc/io/usb_hid.h
@@ -17,15 +17,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef TREZORHAL_USB_CLASS_HID_H
-#define TREZORHAL_USB_CLASS_HID_H
+#pragma once
#include <trezor_types.h>
+#include <sys/sysevent.h>
+
/* usb_hid_info_t contains all information for setting up a HID interface. All
* passed pointers need to live at least until the interface is disabled
* (usb_stop is called). */
typedef struct {
+ syshandle_t handle;
const uint8_t *report_desc; // With length of report_desc_len bytes
uint8_t *rx_buffer; // With length of max_packet_len bytes
uint8_t iface_num; // Address of this HID interface
@@ -43,15 +45,3 @@ typedef struct {
} usb_hid_info_t;
secbool __wur usb_hid_add(const usb_hid_info_t *hid_info);
-secbool __wur usb_hid_can_read(uint8_t iface_num);
-secbool __wur usb_hid_can_write(uint8_t iface_num);
-int __wur usb_hid_read(uint8_t iface_num, uint8_t *buf, uint32_t len);
-int __wur usb_hid_write(uint8_t iface_num, const uint8_t *buf, uint32_t len);
-
-int __wur usb_hid_read_select(uint32_t timeout);
-int __wur usb_hid_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len,
- int timeout);
-int __wur usb_hid_write_blocking(uint8_t iface_num, const uint8_t *buf,
- uint32_t len, int timeout);
-
-#endif // TREZORHAL_USB_CLASS_HID_H
diff --git a/core/embed/io/usb/inc/io/usb_vcp.h b/core/embed/io/usb/inc/io/usb_vcp.h
index aeac05e9..f7abb6e9 100644
--- a/core/embed/io/usb/inc/io/usb_vcp.h
+++ b/core/embed/io/usb/inc/io/usb_vcp.h
@@ -17,15 +17,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef TREZORHAL_USB_CLASS_VCP_H
-#define TREZORHAL_USB_CLASS_VCP_H
+#pragma once
#include <trezor_types.h>
+#include <sys/sysevent.h>
+
/* usb_vcp_info_t contains all information for setting up a VCP interface. All
* passed pointers need to live at least until the interface is disabled
* (usb_stop is called). */
typedef struct {
+ syshandle_t handle;
uint8_t *tx_packet; // Buffer for one packet, with length of at least
// max_packet_len bytes
uint8_t *tx_buffer; // Buffer for IN EP ring buffer, with length of at least
@@ -55,14 +57,3 @@ typedef struct {
} usb_vcp_info_t;
secbool __wur usb_vcp_add(const usb_vcp_info_t *vcp_info);
-secbool __wur usb_vcp_can_read(uint8_t iface_num);
-secbool __wur usb_vcp_can_write(uint8_t iface_num);
-int __wur usb_vcp_read(uint8_t iface_num, uint8_t *buf, uint32_t len);
-int __wur usb_vcp_write(uint8_t iface_num, const uint8_t *buf, uint32_t len);
-
-int __wur usb_vcp_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len,
- int timeout);
-int __wur usb_vcp_write_blocking(uint8_t iface_num, const uint8_t *buf,
- uint32_t len, int timeout);
-
-#endif // TREZORHAL_USB_CLASS_VCP_H
diff --git a/core/embed/io/usb/inc/io/usb_webusb.h b/core/embed/io/usb/inc/io/usb_webusb.h
index 0cc873f0..1cffd7aa 100644
--- a/core/embed/io/usb/inc/io/usb_webusb.h
+++ b/core/embed/io/usb/inc/io/usb_webusb.h
@@ -17,15 +17,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef TREZORHAL_USB_CLASS_WEBUSB_H
-#define TREZORHAL_USB_CLASS_WEBUSB_H
+#pragma once
#include <trezor_types.h>
+#include <sys/sysevent.h>
+
/* usb_webusb_info_t contains all information for setting up a WebUSB interface.
* All passed pointers need to live at least until the interface is disabled
* (usb_stop is called). */
typedef struct {
+ syshandle_t handle;
uint8_t *rx_buffer; // With length of max_packet_len bytes
uint8_t iface_num; // Address of this WebUSB interface
#ifdef TREZOR_EMULATOR
@@ -41,15 +43,3 @@ typedef struct {
} usb_webusb_info_t;
secbool __wur usb_webusb_add(const usb_webusb_info_t *webusb_info);
-secbool __wur usb_webusb_can_read(uint8_t iface_num);
-secbool __wur usb_webusb_can_write(uint8_t iface_num);
-int __wur usb_webusb_read(uint8_t iface_num, uint8_t *buf, uint32_t len);
-int __wur usb_webusb_write(uint8_t iface_num, const uint8_t *buf, uint32_t len);
-
-int __wur usb_webusb_read_select(uint32_t timeout);
-int __wur usb_webusb_read_blocking(uint8_t iface_num, uint8_t *buf,
- uint32_t len, int timeout);
-int __wur usb_webusb_write_blocking(uint8_t iface_num, const uint8_t *buf,
- uint32_t len, int timeout);
-
-#endif // TREZORHAL_USB_CLASS_WEBUSB_H
diff --git a/core/embed/io/usb/stm32/usb.c b/core/embed/io/usb/stm32/usb.c
index 30a355a7..1586e5ba 100644
--- a/core/embed/io/usb/stm32/usb.c
+++ b/core/embed/io/usb/stm32/usb.c
@@ -30,7 +30,6 @@
#include "usb_internal.h"
#define USB_MAX_CONFIG_DESC_SIZE 256
-#define USB_MAX_STR_SIZE 62
#define USB_MAX_STR_DESC_SIZE (USB_MAX_STR_SIZE * 2 + 2)
#if defined(USE_USB_FS)
@@ -44,10 +43,10 @@
#endif
typedef struct {
- const char *manufacturer;
- const char *product;
- const char *serial_number;
- const char *interface;
+ char manufacturer[USB_MAX_STR_SIZE + 1];
+ char product[USB_MAX_STR_SIZE + 1];
+ char serial_number[USB_MAX_STR_SIZE + 1];
+ char interface[USB_MAX_STR_SIZE + 1];
} usb_dev_string_table_t;
typedef struct {
@@ -105,12 +104,6 @@ static const USBD_ClassTypeDef usb_class;
static const USBD_DescriptorsTypeDef usb_descriptors;
static const syshandle_vmt_t g_usb_handle_vmt;
-static secbool __wur check_desc_str(const char *s) {
- if (NULL == s) return secfalse;
- if (strlen(s) > USB_MAX_STR_SIZE) return secfalse;
- return sectrue;
-}
-
secbool usb_init(const usb_dev_info_t *dev_info) {
usb_driver_t *drv = &g_usb_driver;
@@ -146,23 +139,12 @@ secbool usb_init(const usb_dev_info_t *dev_info) {
drv->dev_desc.bNumConfigurations = 1;
// String table
- if (sectrue != check_desc_str(dev_info->manufacturer)) {
- return secfalse;
- }
- if (sectrue != check_desc_str(dev_info->product)) {
- return secfalse;
- }
- if (sectrue != check_desc_str(dev_info->serial_number)) {
- return secfalse;
- }
- if (sectrue != check_desc_str(dev_info->interface)) {
- return secfalse;
- }
-
- drv->str_table.manufacturer = dev_info->manufacturer;
- drv->str_table.product = dev_info->product;
- drv->str_table.serial_number = dev_info->serial_number;
- drv->str_table.interface = dev_info->interface;
+ strncpy(drv->str_table.manufacturer, dev_info->manufacturer,
+ USB_MAX_STR_SIZE);
+ strncpy(drv->str_table.product, dev_info->product, USB_MAX_STR_SIZE);
+ strncpy(drv->str_table.serial_number, dev_info->serial_number,
+ USB_MAX_STR_SIZE);
+ strncpy(drv->str_table.interface, dev_info->interface, USB_MAX_STR_SIZE);
drv->config_desc = (usb_config_descriptor_t *)(drv->desc_buffer);
@@ -205,7 +187,7 @@ void usb_deinit(void) {
drv->initialized = secfalse;
}
-secbool usb_start(void) {
+secbool usb_start(const usb_start_params_t *params) {
usb_driver_t *drv = &g_usb_driver;
if (drv->initialized != sectrue) {
@@ -215,7 +197,23 @@ secbool usb_start(void) {
if (drv->dev_handle.dev_state != USBD_STATE_UNINITIALIZED) {
// The driver has been started already
- return sectrue;
+ if (params != NULL &&
+ (drv->usb21_landing != params->usb21_landing ||
+ strncmp(drv->str_table.serial_number, params->serial_number,
+ USB_MAX_STR_SIZE) != 0)) {
+ // If the USB 2.1 landing or serial number has changed, we need to stop
+ // and restart the driver.
+ usb_stop();
+ } else {
+ // The driver is already started and the settings are the same.
+ return sectrue;
+ }
+ }
+
+ if (params != NULL) {
+ drv->usb21_landing = params->usb21_landing;
+ strncpy(drv->str_table.serial_number, params->serial_number,
+ USB_MAX_STR_SIZE);
}
drv->was_ready = secfalse;
diff --git a/core/embed/io/usb/stm32/usb_class_hid.c b/core/embed/io/usb/stm32/usb_class_hid.c
index 4337bc85..ac13879a 100644
--- a/core/embed/io/usb/stm32/usb_class_hid.c
+++ b/core/embed/io/usb/stm32/usb_class_hid.c
@@ -60,6 +60,7 @@ typedef struct __attribute__((packed)) {
* fields. */
typedef struct {
+ syshandle_t handle;
USBD_HandleTypeDef *dev_handle;
const usb_hid_descriptor_block_t *desc_block;
const uint8_t *report_desc;
@@ -83,9 +84,6 @@ static const USBD_ClassTypeDef usb_hid_class;
static const syshandle_vmt_t usb_hid_handle_vmt;
-#define usb_get_hid_state(iface_num) \
- ((usb_hid_state_t *)usb_get_iface_state(iface_num, &usb_hid_class))
-
/* usb_hid_add adds and configures new USB HID interface according to
* configuration options passed in `info`. */
secbool usb_hid_add(const usb_hid_info_t *info) {
@@ -152,6 +150,7 @@ secbool usb_hid_add(const usb_hid_info_t *info) {
d->ep_out.bInterval = info->polling_interval;
// Interface state
+ state->handle = info->handle;
state->desc_block = d;
state->report_desc = info->report_desc;
state->rx_buffer = info->rx_buffer;
@@ -170,129 +169,30 @@ secbool usb_hid_add(const usb_hid_info_t *info) {
return sectrue;
}
-secbool usb_hid_can_read(uint8_t iface_num) {
- usb_hid_state_t *state = usb_get_hid_state(iface_num);
-
- if (state == NULL) {
- return secfalse; // Invalid interface number
- }
+static bool usb_hid_can_read(usb_hid_state_t *state) {
if (state->dev_handle == NULL) {
- return secfalse; // Class driver not initialized
+ return false; // Class driver not initialized
}
if (state->last_read_len == 0) {
- return secfalse; // Nothing in the receiving buffer
+ return false; // Nothing in the receiving buffer
}
if (state->dev_handle->dev_state != USBD_STATE_CONFIGURED) {
- return secfalse; // Device is not configured
+ return false; // Device is not configured
}
- return sectrue;
+ return true;
}
-secbool usb_hid_can_write(uint8_t iface_num) {
- usb_hid_state_t *state = usb_get_hid_state(iface_num);
- if (state == NULL) {
- return secfalse; // Invalid interface number
- }
+static bool usb_hid_can_write(usb_hid_state_t *state) {
if (state->dev_handle == NULL) {
- return secfalse; // Class driver not initialized
+ return false; // Class driver not initialized
}
if (state->ep_in_is_idle == 0) {
- return secfalse; // Last transmission is not over yet
+ return false; // Last transmission is not over yet
}
if (state->dev_handle->dev_state != USBD_STATE_CONFIGURED) {
- return secfalse; // Device is not configured
+ return false; // Device is not configured
}
- return sectrue;
-}
-
-int usb_hid_read(uint8_t iface_num, uint8_t *buf, uint32_t len) {
- volatile usb_hid_state_t *state = usb_get_hid_state(iface_num);
-
- if (state == NULL) {
- return -1; // Invalid interface number
- }
-
- if (state->dev_handle == NULL) {
- return -1; // Class driver not initialized
- }
-
- // Copy maximum possible amount of data
- uint32_t last_read_len = state->last_read_len;
- if (len < last_read_len) {
- return 0; // Not enough data in the read buffer
- }
- memcpy(buf, state->rx_buffer, last_read_len);
-
- // Reset the length to indicate we are ready to read next packet
- state->last_read_len = 0;
-
- // Prepare the OUT EP to receive next packet
- USBD_LL_PrepareReceive(state->dev_handle, state->ep_out, state->rx_buffer,
- state->max_packet_len);
-
- return last_read_len;
-}
-
-int usb_hid_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) {
- volatile usb_hid_state_t *state = usb_get_hid_state(iface_num);
-
- if (state == NULL) {
- return -1; // Invalid interface number
- }
-
- if (state->dev_handle == NULL) {
- return -1; // Class driver not initialized
- }
-
- if (state->ep_in_is_idle == 0) {
- return 0; // Last transmission is not over yet
- }
-
- state->ep_in_is_idle = 0;
- USBD_LL_Transmit(state->dev_handle, state->ep_in, UNCONST(buf),
- (uint16_t)len);
-
- return len;
-}
-
-int usb_hid_read_select(uint32_t timeout) {
- const uint32_t start = HAL_GetTick();
- for (;;) {
- for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) {
- if (sectrue == usb_hid_can_read(i)) {
- return i;
- }
- }
- if (HAL_GetTick() - start >= timeout) {
- break;
- }
- __WFI(); // Enter sleep mode, waiting for interrupt
- }
- return -1; // Timeout
-}
-
-int usb_hid_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len,
- int timeout) {
- const uint32_t start = HAL_GetTick();
- while (sectrue != usb_hid_can_read(iface_num)) {
- if (timeout >= 0 && HAL_GetTick() - start >= timeout) {
- return 0; // Timeout
- }
- __WFI(); // Enter sleep mode, waiting for interrupt
- }
- return usb_hid_read(iface_num, buf, len);
-}
-
-int usb_hid_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len,
- int timeout) {
- const uint32_t start = HAL_GetTick();
- while (sectrue != usb_hid_can_write(iface_num)) {
- if (timeout >= 0 && HAL_GetTick() - start >= timeout) {
- return 0; // Timeout
- }
- __WFI(); // Enter sleep mode, waiting for interrupt
- }
- return usb_hid_write(iface_num, buf, len);
+ return true;
}
static uint8_t usb_hid_class_init(USBD_HandleTypeDef *dev, uint8_t cfg_idx) {
@@ -315,10 +215,7 @@ static uint8_t usb_hid_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_hid_handle_vmt, state)) {
+ if (!syshandle_register(state->handle, &usb_hid_handle_vmt, state)) {
return USBD_FAIL;
}
@@ -328,8 +225,7 @@ static uint8_t usb_hid_class_init(USBD_HandleTypeDef *dev, uint8_t cfg_idx) {
static uint8_t usb_hid_class_deinit(USBD_HandleTypeDef *dev, uint8_t cfg_idx) {
usb_hid_state_t *state = (usb_hid_state_t *)dev->pUserData;
- uint8_t iface_num = state->desc_block->iface.bInterfaceNumber;
- syshandle_unregister(SYSHANDLE_USB_IFACE_0 + iface_num);
+ syshandle_unregister(state->handle);
// Flush endpoints
USBD_LL_FlushEP(dev, state->ep_in);
@@ -465,42 +361,79 @@ static void on_event_poll(void *context, bool read_awaited,
bool write_awaited) {
usb_hid_state_t *state = (usb_hid_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_hid_can_read(iface_num)) {
- syshandle_signal_read_ready(handle, NULL);
+ if (read_awaited && usb_hid_can_read(state)) {
+ syshandle_signal_read_ready(state->handle, NULL);
}
- if (write_awaited && usb_hid_can_write(iface_num)) {
- syshandle_signal_write_ready(handle, NULL);
+ if (write_awaited && usb_hid_can_write(state)) {
+ syshandle_signal_write_ready(state->handle, NULL);
}
}
static bool on_check_read_ready(void *context, systask_id_t task_id,
void *param) {
usb_hid_state_t *state = (usb_hid_state_t *)context;
- uint8_t iface_num = state->desc_block->iface.bInterfaceNumber;
UNUSED(task_id);
UNUSED(param);
- return usb_hid_can_read(iface_num);
+ return usb_hid_can_read(state);
}
static bool on_check_write_ready(void *context, systask_id_t task_id,
void *param) {
usb_hid_state_t *state = (usb_hid_state_t *)context;
- uint8_t iface_num = state->desc_block->iface.bInterfaceNumber;
UNUSED(task_id);
UNUSED(param);
- return usb_hid_can_write(iface_num);
+ return usb_hid_can_write(state);
+}
+
+static ssize_t on_read(void *context, void *buffer, size_t buffer_size) {
+ usb_hid_state_t *state = (usb_hid_state_t *)context;
+
+ if (state->dev_handle == NULL) {
+ return -1; // Class driver not initialized
+ }
+
+ // Copy maximum possible amount of data
+ uint32_t last_read_len = state->last_read_len;
+ if (buffer_size < last_read_len) {
+ return 0; // Not enough data in the read buffer
+ }
+ memcpy(buffer, state->rx_buffer, last_read_len);
+
+ // Reset the length to indicate we are ready to read next packet
+ state->last_read_len = 0;
+
+ // Prepare the OUT EP to receive next packet
+ USBD_LL_PrepareReceive(state->dev_handle, state->ep_out, state->rx_buffer,
+ state->max_packet_len);
+
+ return last_read_len;
+}
+
+static ssize_t on_write(void *context, const void *data, size_t data_size) {
+ usb_hid_state_t *state = (usb_hid_state_t *)context;
+
+ if (state->dev_handle == NULL) {
+ return -1; // Class driver not initialized
+ }
+
+ if (state->ep_in_is_idle == 0) {
+ return 0; // Last transmission is not over yet
+ }
+
+ state->ep_in_is_idle = 0;
+ USBD_LL_Transmit(state->dev_handle, state->ep_in, UNCONST(data),
+ (uint16_t)data_size);
+
+ return data_size;
}
static const syshandle_vmt_t usb_hid_handle_vmt = {
@@ -509,6 +442,8 @@ static const syshandle_vmt_t usb_hid_handle_vmt = {
.check_read_ready = on_check_read_ready,
.check_write_ready = on_check_write_ready,
.poll = on_event_poll,
+ .read = on_read,
+ .write = on_write,
};
#endif // KERNEL_MODE
diff --git a/core/embed/io/usb/stm32/usb_class_vcp.c b/core/embed/io/usb/stm32/usb_class_vcp.c
index 5d667802..f2b102bb 100644
--- a/core/embed/io/usb/stm32/usb_class_vcp.c
+++ b/core/embed/io/usb/stm32/usb_class_vcp.c
@@ -141,6 +141,7 @@ typedef struct {
* usb_vcp_class_init. See usb_vcp_info_t for details of the configuration
* fields. */
typedef struct {
+ syshandle_t handle;
USBD_HandleTypeDef *dev_handle;
const usb_vcp_descriptor_block_t *desc_block;
usb_rbuf_t rx_ring;
@@ -165,9 +166,6 @@ static const USBD_ClassTypeDef usb_vcp_data_class;
static const syshandle_vmt_t usb_vcp_handle_vmt;
-#define usb_get_vcp_state(iface_num) \
- ((usb_vcp_state_t *)usb_get_iface_state(iface_num, &usb_vcp_class))
-
/* usb_vcp_add adds and configures new USB VCP interface according to
* configuration options passed in `info`. */
secbool usb_vcp_add(const usb_vcp_info_t *info) {
@@ -303,6 +301,7 @@ secbool usb_vcp_add(const usb_vcp_info_t *info) {
d->ep_in.bInterval = 0;
// Interface state
+ state->handle = info->handle;
state->desc_block = d;
state->rx_ring.buf = info->rx_buffer;
@@ -339,97 +338,45 @@ secbool usb_vcp_add(const usb_vcp_info_t *info) {
static inline size_t ring_length(usb_rbuf_t *b) { return (b->write - b->read); }
-static inline int ring_empty(usb_rbuf_t *b) { return ring_length(b) == 0; }
+static inline bool ring_empty(usb_rbuf_t *b) { return ring_length(b) == 0; }
-static inline int ring_full(usb_rbuf_t *b) { return ring_length(b) == b->cap; }
+static inline bool ring_full(usb_rbuf_t *b) { return ring_length(b) == b->cap; }
-secbool usb_vcp_can_read(uint8_t iface_num) {
- usb_vcp_state_t *state = usb_get_vcp_state(iface_num);
- if (state == NULL) {
- return secfalse; // Invalid interface number
- }
- if (ring_empty(&state->rx_ring)) {
- return secfalse; // Nothing in the rx buffer
- }
- return sectrue;
+static bool usb_vcp_can_read(usb_vcp_state_t *state) {
+ return !ring_empty(&state->rx_ring);
}
-secbool usb_vcp_can_write(uint8_t iface_num) {
- usb_vcp_state_t *state = usb_get_vcp_state(iface_num);
- if (state == NULL) {
- return secfalse; // Invalid interface number
- }
- if (ring_full(&state->tx_ring)) {
- return secfalse; // Tx ring buffer is full
- }
- return sectrue;
+static bool usb_vcp_can_write(usb_vcp_state_t *state) {
+ return !ring_full(&state->tx_ring);
}
-int usb_vcp_read(uint8_t iface_num, uint8_t *buf, uint32_t len) {
- usb_vcp_state_t *state = usb_get_vcp_state(iface_num);
- if (state == NULL) {
- return -1; // Invalid interface number
- }
-
+static ssize_t usb_vcp_read(usb_vcp_state_t *state, uint8_t *buffer,
+ uint32_t buffer_size) {
// Read from the rx ring buffer
usb_rbuf_t *b = &state->rx_ring;
size_t mask = b->cap - 1;
size_t i;
- for (i = 0; (i < len) && !ring_empty(b); i++) {
- buf[i] = b->buf[b->read & mask];
+ for (i = 0; (i < buffer_size) && !ring_empty(b); i++) {
+ buffer[i] = b->buf[b->read & mask];
b->read++;
}
return i;
}
-int usb_vcp_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) {
- usb_vcp_state_t *state = usb_get_vcp_state(iface_num);
- if (state == NULL) {
- return -1; // Invalid interface number
- }
-
+static ssize_t usb_vcp_write(usb_vcp_state_t *state, const uint8_t *data,
+ size_t data_size) {
// Write into the tx ring buffer
usb_rbuf_t *b = &state->tx_ring;
size_t mask = b->cap - 1;
size_t i;
- for (i = 0; (i < len) && !ring_full(b); i++) {
- b->buf[b->write & mask] = buf[i];
+ for (i = 0; (i < data_size) && !ring_full(b); i++) {
+ b->buf[b->write & mask] = data[i];
b->write++;
}
return i;
}
-int usb_vcp_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len,
- int timeout) {
- uint32_t start = HAL_GetTick();
- while (sectrue != usb_vcp_can_read(iface_num)) {
- if (timeout >= 0 && HAL_GetTick() - start >= timeout) {
- return 0; // Timeout
- }
- __WFI(); // Enter sleep mode, waiting for interrupt
- }
- return usb_vcp_read(iface_num, buf, len);
-}
-
-int usb_vcp_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len,
- int timeout) {
- uint32_t start = HAL_GetTick();
- uint32_t i = 0;
- while (i < len) {
- while (sectrue != usb_vcp_can_write(iface_num)) {
- if (timeout >= 0 && HAL_GetTick() - start >= timeout) {
- return i; // Timeout
- }
- __WFI(); // Enter sleep mode, waiting for interrupt
- }
- int ret = usb_vcp_write(iface_num, buf + i, len - i);
- if (ret < 0) return ret;
- i += ret;
- }
- return i;
-}
-
static uint8_t usb_vcp_class_init(USBD_HandleTypeDef *dev, uint8_t cfg_idx) {
usb_vcp_state_t *state = (usb_vcp_state_t *)dev->pUserData;
@@ -452,9 +399,7 @@ static uint8_t usb_vcp_class_init(USBD_HandleTypeDef *dev, uint8_t cfg_idx) {
USBD_LL_PrepareReceive(dev, state->ep_out, state->rx_packet,
state->max_packet_len);
- uint8_t iface_num = state->desc_block->iface_cdc.bInterfaceNumber;
- syshandle_t handle = SYSHANDLE_USB_IFACE_0 + iface_num;
- if (!syshandle_register(handle, &usb_vcp_handle_vmt, state)) {
+ if (!syshandle_register(state->handle, &usb_vcp_handle_vmt, state)) {
return USBD_FAIL;
}
@@ -464,9 +409,7 @@ static uint8_t usb_vcp_class_init(USBD_HandleTypeDef *dev, uint8_t cfg_idx) {
static uint8_t usb_vcp_class_deinit(USBD_HandleTypeDef *dev, uint8_t cfg_idx) {
usb_vcp_state_t *state = (usb_vcp_state_t *)dev->pUserData;
- uint8_t iface_num = state->desc_block->iface_cdc.bInterfaceNumber;
- syshandle_t handle = SYSHANDLE_USB_IFACE_0 + iface_num;
- syshandle_unregister(handle);
+ syshandle_unregister(state->handle);
// Flush endpoints
USBD_LL_FlushEP(dev, state->ep_in);
@@ -607,42 +550,49 @@ static void on_event_poll(void *context, bool read_awaited,
bool write_awaited) {
usb_vcp_state_t *state = (usb_vcp_state_t *)context;
- uint8_t iface_num = state->desc_block->iface_cdc.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_vcp_can_read(iface_num)) {
- syshandle_signal_read_ready(handle, NULL);
+ if (read_awaited && usb_vcp_can_read(state)) {
+ syshandle_signal_read_ready(state->handle, NULL);
}
- if (write_awaited && usb_vcp_can_write(iface_num)) {
- syshandle_signal_write_ready(handle, NULL);
+ if (write_awaited && usb_vcp_can_write(state)) {
+ syshandle_signal_write_ready(state->handle, NULL);
}
}
static bool on_check_read_ready(void *context, systask_id_t task_id,
void *param) {
usb_vcp_state_t *state = (usb_vcp_state_t *)context;
- uint8_t iface_num = state->desc_block->iface_cdc.bInterfaceNumber;
UNUSED(task_id);
UNUSED(param);
- return usb_vcp_can_read(iface_num);
+ return usb_vcp_can_read(state);
}
static bool on_check_write_ready(void *context, systask_id_t task_id,
void *param) {
usb_vcp_state_t *state = (usb_vcp_state_t *)context;
- uint8_t iface_num = state->desc_block->iface_cdc.bInterfaceNumber;
UNUSED(task_id);
UNUSED(param);
- return usb_vcp_can_write(iface_num);
+ return usb_vcp_can_write(state);
+}
+
+static ssize_t on_read(void *context, void *buffer, size_t buffer_size) {
+ usb_vcp_state_t *state = (usb_vcp_state_t *)context;
+
+ return usb_vcp_read(state, (uint8_t *)buffer, buffer_size);
+}
+
+static ssize_t on_write(void *context, const void *data, size_t data_size) {
+ usb_vcp_state_t *state = (usb_vcp_state_t *)context;
+
+ return usb_vcp_write(state, (const uint8_t *)data, data_size);
}
static const syshandle_vmt_t usb_vcp_handle_vmt = {
@@ -651,6 +601,8 @@ static const syshandle_vmt_t usb_vcp_handle_vmt = {
.check_read_ready = on_check_read_ready,
.check_write_ready = on_check_write_ready,
.poll = on_event_poll,
+ .read = on_read,
+ .write = on_write,
};
#endif // KERNEL_MODE
diff --git a/core/embed/io/usb/stm32/usb_class_webusb.c b/core/embed/io/usb/stm32/usb_class_webusb.c
index 53b95040..f234842c 100644
--- a/core/embed/io/usb/stm32/usb_class_webusb.c
+++ b/core/embed/io/usb/stm32/usb_class_webusb.c
@@ -40,6 +40,7 @@ typedef struct __attribute__((packed)) {
* usb_webusb_class_init. See usb_webusb_info_t for details of the
* configuration fields. */
typedef struct {
+ syshandle_t handle;
USBD_HandleTypeDef *dev_handle;
const usb_webusb_descriptor_block_t *desc_block;
uint8_t *rx_buffer;
@@ -58,9 +59,6 @@ _Static_assert(sizeof(usb_webusb_state_t) <= USBD_CLASS_STATE_MAX_SIZE);
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))
-
/* usb_webusb_add adds and configures new USB WebUSB interface according to
* configuration options passed in `info`. */
secbool usb_webusb_add(const usb_webusb_info_t *info) {
@@ -116,6 +114,7 @@ secbool usb_webusb_add(const usb_webusb_info_t *info) {
d->ep_out.bInterval = info->polling_interval;
// Interface state
+ state->handle = info->handle;
state->desc_block = d;
state->rx_buffer = info->rx_buffer;
state->ep_in = info->ep_in | USB_EP_DIR_IN;
@@ -130,123 +129,30 @@ secbool usb_webusb_add(const usb_webusb_info_t *info) {
return sectrue;
}
-secbool usb_webusb_can_read(uint8_t iface_num) {
- usb_webusb_state_t *state = usb_get_webusb_state(iface_num);
-
- if (state == NULL) {
- return secfalse; // Invalid interface number
- }
+bool usb_webusb_can_read(usb_webusb_state_t *state) {
if (state->dev_handle == NULL) {
- return secfalse; // Class driver not initialized
+ return false; // Class driver not initialized
}
if (state->last_read_len == 0) {
- return secfalse; // Nothing in the receiving buffer
+ return false; // Nothing in the receiving buffer
}
if (state->dev_handle->dev_state != USBD_STATE_CONFIGURED) {
- return secfalse; // Device is not configured
+ return false; // Device is not configured
}
- return sectrue;
+ return true;
}
-secbool usb_webusb_can_write(uint8_t iface_num) {
- usb_webusb_state_t *state = usb_get_webusb_state(iface_num);
- if (state == NULL) {
- return secfalse; // Invalid interface number
- }
+bool usb_webusb_can_write(usb_webusb_state_t *state) {
if (state->dev_handle == NULL) {
- return secfalse; // Class driver not initialized
+ return false; // Class driver not initialized
}
if (state->ep_in_is_idle == 0) {
- return secfalse; // Last transmission is not over yet
+ return false; // Last transmission is not over yet
}
if (state->dev_handle->dev_state != USBD_STATE_CONFIGURED) {
- return secfalse; // Device is not configured
- }
- return sectrue;
-}
-
-int usb_webusb_read(uint8_t iface_num, uint8_t *buf, uint32_t len) {
- volatile usb_webusb_state_t *state = usb_get_webusb_state(iface_num);
- if (state == NULL) {
- return -1; // Invalid interface number
- }
-
- if (state->dev_handle == NULL) {
- return -1; // Class driver not initialized
- }
-
- // Copy maximum possible amount of data
- uint32_t last_read_len = state->last_read_len;
- if (len < last_read_len) {
- return 0; // Not enough data in the read buffer
- }
- memcpy(buf, state->rx_buffer, last_read_len);
-
- // Reset the length to indicate we are ready to read next packet
- state->last_read_len = 0;
-
- // Prepare the OUT EP to receive next packet
- USBD_LL_PrepareReceive(state->dev_handle, state->ep_out, state->rx_buffer,
- state->max_packet_len);
-
- return last_read_len;
-}
-
-int usb_webusb_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) {
- volatile usb_webusb_state_t *state = usb_get_webusb_state(iface_num);
- if (state == NULL) {
- return -1; // Invalid interface number
+ return false; // Device is not configured
}
-
- if (state->dev_handle == NULL) {
- return -1; // Class driver not initialized
- }
-
- state->ep_in_is_idle = 0;
- USBD_LL_Transmit(state->dev_handle, state->ep_in, UNCONST(buf),
- (uint16_t)len);
-
- return len;
-}
-
-int usb_webusb_read_select(uint32_t timeout) {
- const uint32_t start = HAL_GetTick();
- for (;;) {
- for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) {
- if (sectrue == usb_webusb_can_read(i)) {
- return i;
- }
- }
- if (HAL_GetTick() - start >= timeout) {
- break;
- }
- __WFI(); // Enter sleep mode, waiting for interrupt
- }
- return -1; // Timeout
-}
-
-int usb_webusb_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len,
- int timeout) {
- const uint32_t start = HAL_GetTick();
- while (sectrue != usb_webusb_can_read(iface_num)) {
- if (timeout >= 0 && HAL_GetTick() - start >= timeout) {
- return 0; // Timeout
- }
- __WFI(); // Enter sleep mode, waiting for interrupt
- }
- return usb_webusb_read(iface_num, buf, len);
-}
-
-int usb_webusb_write_blocking(uint8_t iface_num, const uint8_t *buf,
- uint32_t len, int timeout) {
- const uint32_t start = HAL_GetTick();
- while (sectrue != usb_webusb_can_write(iface_num)) {
- if (timeout >= 0 && HAL_GetTick() - start >= timeout) {
- return 0; // Timeout
- }
- __WFI(); // Enter sleep mode, waiting for interrupt
- }
- return usb_webusb_write(iface_num, buf, len);
+ return true;
}
static uint8_t usb_webusb_class_init(USBD_HandleTypeDef *dev, uint8_t cfg_idx) {
@@ -267,9 +173,7 @@ 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)) {
+ if (!syshandle_register(state->handle, &usb_webusb_handle_vmt, state)) {
return USBD_FAIL;
}
@@ -280,9 +184,7 @@ 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);
+ syshandle_unregister(state->handle);
// Flush endpoints
USBD_LL_FlushEP(dev, state->ep_in);
@@ -374,42 +276,79 @@ 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 (read_awaited && usb_webusb_can_read(state)) {
+ syshandle_signal_read_ready(state->handle, NULL);
}
- if (write_awaited && usb_webusb_can_write(iface_num)) {
- syshandle_signal_write_ready(handle, NULL);
+ if (write_awaited && usb_webusb_can_write(state)) {
+ syshandle_signal_write_ready(state->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);
+ return usb_webusb_can_read(state);
}
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);
+ return usb_webusb_can_write(state);
+}
+
+static ssize_t on_read(void *context, void *buffer, size_t buffer_size) {
+ usb_webusb_state_t *state = (usb_webusb_state_t *)context;
+
+ if (state->dev_handle == NULL) {
+ return -1; // Class driver not initialized
+ }
+
+ // Copy maximum possible amount of data
+ uint32_t last_read_len = state->last_read_len;
+ if (buffer_size < last_read_len) {
+ return 0; // Not enough data in the read buffer
+ }
+ memcpy(buffer, state->rx_buffer, last_read_len);
+
+ // Reset the length to indicate we are ready to read next packet
+ state->last_read_len = 0;
+
+ // Prepare the OUT EP to receive next packet
+ USBD_LL_PrepareReceive(state->dev_handle, state->ep_out, state->rx_buffer,
+ state->max_packet_len);
+
+ return last_read_len;
+}
+
+static ssize_t on_write(void *context, const void *data, size_t data_size) {
+ usb_webusb_state_t *state = (usb_webusb_state_t *)context;
+
+ if (state->dev_handle == NULL) {
+ return -1; // Class driver not initialized
+ }
+
+ if (state->ep_in_is_idle == 0) {
+ return 0; // Last transmission is not over yet
+ }
+
+ state->ep_in_is_idle = 0;
+ USBD_LL_Transmit(state->dev_handle, state->ep_in, UNCONST(data),
+ (uint16_t)data_size);
+
+ return data_size;
}
static const syshandle_vmt_t usb_webusb_handle_vmt = {
@@ -418,6 +357,8 @@ static const syshandle_vmt_t usb_webusb_handle_vmt = {
.check_read_ready = on_check_read_ready,
.check_write_ready = on_check_write_ready,
.poll = on_event_poll,
+ .read = on_read,
+ .write = on_write,
};
#endif // KERNEL_MODE
diff --git a/core/embed/io/usb/stm32/usb_internal.h b/core/embed/io/usb/stm32/usb_internal.h
index 2fa548a2..c103c487 100644
--- a/core/embed/io/usb/stm32/usb_internal.h
+++ b/core/embed/io/usb/stm32/usb_internal.h
@@ -17,8 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef TREZORHAL_USBD_INTERNAL_H
-#define TREZORHAL_USBD_INTERNAL_H
+#pragma once
#include <trezor_types.h>
@@ -126,5 +125,3 @@ void usb_set_iface_class(uint8_t iface_num, const USBD_ClassTypeDef *class);
// The function checks if the remaining space is enough and
// returns NULL if not.
void *usb_alloc_class_descriptors(size_t desc_len);
-
-#endif // TREZORHAL_USBD_INTERNAL_H
diff --git a/core/embed/io/usb/unix/usb.c b/core/embed/io/usb/unix/usb.c
index b0e20cd1..658d82fc 100644
--- a/core/embed/io/usb/unix/usb.c
+++ b/core/embed/io/usb/unix/usb.c
@@ -29,13 +29,14 @@
#include <unistd.h>
#include <io/usb.h>
+#include <io/usb_hid.h>
+#include <io/usb_vcp.h>
+#include <io/usb_webusb.h>
+
#include "profile.h"
#include "memzero.h"
-// emulator opens UDP server and emulates HID/WebUSB interfaces
-// gracefully ignores all other USB interfaces
-
#define USBD_MAX_NUM_INTERFACES 8
typedef enum {
@@ -65,7 +66,7 @@ secbool usb_init(const usb_dev_info_t *dev_info) {
UNUSED(dev_info);
for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) {
usb_iface_t *iface = &usb_ifaces[i];
- iface->handle = SYSHANDLE_USB_IFACE_0 + i;
+ iface->handle = 0;
iface->type = USB_IFACE_TYPE_DISABLED;
iface->port = 0;
iface->sock = -1;
@@ -80,7 +81,7 @@ secbool usb_init(const usb_dev_info_t *dev_info) {
void usb_deinit(void) { usb_stop(); }
-secbool usb_start(void) {
+secbool usb_start(const usb_start_params_t *params) {
const char *ip = getenv("TREZOR_UDP_IP");
// iterate interfaces
@@ -110,8 +111,8 @@ secbool usb_start(void) {
sizeof(struct sockaddr_in))),
NULL);
- ensure(sectrue * syshandle_register(SYSHANDLE_USB_IFACE_0 + i,
- &usb_iface_handle_vmt, iface),
+ ensure(sectrue *
+ syshandle_register(iface->handle, &usb_iface_handle_vmt, iface),
NULL);
}
@@ -124,36 +125,48 @@ void usb_stop(void) {
if (iface->sock >= 0) {
close(iface->sock);
iface->sock = -1;
- syshandle_unregister(SYSHANDLE_USB_IFACE_0 + i);
+ syshandle_unregister(iface->handle);
}
}
}
secbool usb_hid_add(const usb_hid_info_t *info) {
- if (info->iface_num < USBD_MAX_NUM_INTERFACES &&
- usb_ifaces[info->iface_num].type == USB_IFACE_TYPE_DISABLED) {
- usb_ifaces[info->iface_num].type = USB_IFACE_TYPE_HID;
- usb_ifaces[info->iface_num].port = info->emu_port;
+ if (info->iface_num < USBD_MAX_NUM_INTERFACES) {
+ usb_iface_t *iface = &usb_ifaces[info->iface_num];
+ if (iface->type == USB_IFACE_TYPE_DISABLED) {
+ iface->type = USB_IFACE_TYPE_HID;
+ iface->port = info->emu_port;
+ iface->handle = info->handle;
+ return sectrue;
+ }
}
- return sectrue;
+ return secfalse;
}
secbool usb_webusb_add(const usb_webusb_info_t *info) {
- if (info->iface_num < USBD_MAX_NUM_INTERFACES &&
- usb_ifaces[info->iface_num].type == USB_IFACE_TYPE_DISABLED) {
- usb_ifaces[info->iface_num].type = USB_IFACE_TYPE_WEBUSB;
- usb_ifaces[info->iface_num].port = info->emu_port;
+ if (info->iface_num < USBD_MAX_NUM_INTERFACES) {
+ usb_iface_t *iface = &usb_ifaces[info->iface_num];
+ if (iface->type == USB_IFACE_TYPE_DISABLED) {
+ iface->type = USB_IFACE_TYPE_WEBUSB;
+ iface->port = info->emu_port;
+ iface->handle = info->handle;
+ return sectrue;
+ }
}
- return sectrue;
+ return secfalse;
}
secbool usb_vcp_add(const usb_vcp_info_t *info) {
- if (info->iface_num < USBD_MAX_NUM_INTERFACES &&
- usb_ifaces[info->iface_num].type == USB_IFACE_TYPE_DISABLED) {
- usb_ifaces[info->iface_num].type = USB_IFACE_TYPE_VCP;
- usb_ifaces[info->iface_num].port = info->emu_port;
+ if (info->iface_num < USBD_MAX_NUM_INTERFACES) {
+ usb_iface_t *iface = &usb_ifaces[info->iface_num];
+ if (iface->type == USB_IFACE_TYPE_DISABLED) {
+ iface->type = USB_IFACE_TYPE_VCP;
+ iface->port = info->emu_port;
+ iface->handle = info->handle;
+ return sectrue;
+ }
}
- return sectrue;
+ return secfalse;
}
static secbool usb_emulated_poll_read(usb_iface_t *iface) {
@@ -229,164 +242,6 @@ static int usb_emulated_write(usb_iface_t *iface, const uint8_t *buf,
return r;
}
-secbool usb_hid_can_read(uint8_t iface_num) {
- if (iface_num >= USBD_MAX_NUM_INTERFACES ||
- usb_ifaces[iface_num].type != USB_IFACE_TYPE_HID) {
- return secfalse;
- }
- return usb_emulated_poll_read(&usb_ifaces[iface_num]);
-}
-
-secbool usb_webusb_can_read(uint8_t iface_num) {
- if (iface_num >= USBD_MAX_NUM_INTERFACES ||
- usb_ifaces[iface_num].type != USB_IFACE_TYPE_WEBUSB) {
- return secfalse;
- }
- return usb_emulated_poll_read(&usb_ifaces[iface_num]);
-}
-
-secbool usb_hid_can_write(uint8_t iface_num) {
- if (iface_num >= USBD_MAX_NUM_INTERFACES ||
- usb_ifaces[iface_num].type != USB_IFACE_TYPE_HID) {
- return secfalse;
- }
- return usb_emulated_poll_write(&usb_ifaces[iface_num]);
-}
-
-secbool usb_webusb_can_write(uint8_t iface_num) {
- if (iface_num >= USBD_MAX_NUM_INTERFACES ||
- usb_ifaces[iface_num].type != USB_IFACE_TYPE_WEBUSB) {
- return secfalse;
- }
- return usb_emulated_poll_write(&usb_ifaces[iface_num]);
-}
-
-int usb_hid_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_HID) {
- return -1;
- }
- return usb_emulated_read(&usb_ifaces[iface_num], buf, len);
-}
-
-int usb_webusb_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_WEBUSB) {
- return -1;
- }
- return usb_emulated_read(&usb_ifaces[iface_num], buf, len);
-}
-
-int usb_webusb_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len,
- int timeout) {
- const uint32_t start = clock();
- while (sectrue != usb_webusb_can_read(iface_num)) {
- if (timeout >= 0 &&
- (1000 * (clock() - start)) / CLOCKS_PER_SEC >= timeout) {
- return -1; // Timeout
- }
- }
- return usb_webusb_read(iface_num, buf, len);
-}
-
-int usb_hid_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_HID) {
- return -1;
- }
- return usb_emulated_write(&usb_ifaces[iface_num], buf, len);
-}
-
-int usb_hid_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len,
- int timeout) {
- const uint32_t start = clock();
- while (sectrue != usb_hid_can_write(iface_num)) {
- if (timeout >= 0 &&
- (1000 * (clock() - start)) / CLOCKS_PER_SEC >= timeout) {
- return -1; // Timeout
- }
- }
- return usb_hid_write(iface_num, buf, len);
-}
-
-int usb_webusb_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_WEBUSB) {
- return -1;
- }
- return usb_emulated_write(&usb_ifaces[iface_num], buf, len);
-}
-
-int usb_webusb_write_blocking(uint8_t iface_num, const uint8_t *buf,
- uint32_t len, int timeout) {
- const uint32_t start = clock();
- while (sectrue != usb_webusb_can_write(iface_num)) {
- if (timeout >= 0 &&
- (1000 * (clock() - start)) / CLOCKS_PER_SEC >= timeout) {
- return -1; // Timeout
- }
- }
- 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 -1;
- }
- 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 -1; // 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 -1;
- }
- 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 -1; // Timeout
- }
- }
- return usb_vcp_write(iface_num, buf, len);
-}
-
-void mp_hal_set_vcp_iface(int iface_num) {}
-
secbool usb_configured(void) {
if (access(profile_usb_disconnect_path(), F_OK) == 0) {
return secfalse;
@@ -442,10 +297,24 @@ static bool on_check_write_ready(void *context, systask_id_t task_id,
return usb_emulated_poll_write(iface);
}
+static ssize_t on_read(void *context, void *buffer, size_t buffer_size) {
+ usb_iface_t *iface = (usb_iface_t *)context;
+
+ return usb_emulated_read(iface, (uint8_t *)buffer, buffer_size);
+}
+
+static ssize_t on_write(void *context, const void *data, size_t data_size) {
+ usb_iface_t *iface = (usb_iface_t *)context;
+
+ return usb_emulated_write(iface, (const uint8_t *)data, data_size);
+}
+
static const syshandle_vmt_t usb_iface_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,
+ .read = on_read,
+ .write = on_write,
};
diff --git a/core/embed/io/usb/usb_config.c b/core/embed/io/usb/usb_config.c
new file mode 100644
index 00000000..512e6379
--- /dev/null
+++ b/core/embed/io/usb/usb_config.c
@@ -0,0 +1,309 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef KERNEL_MODE
+
+#include <trezor_bsp.h>
+#include <trezor_model.h>
+#include <trezor_rtl.h>
+
+#include <io/usb.h>
+#include <io/usb_config.h>
+#include <io/usb_hid.h>
+#include <io/usb_vcp.h>
+#include <io/usb_webusb.h>
+
+#ifdef TREZOR_EMULATOR
+#include <stdlib.h>
+#endif
+
+#define USB_IFACE_BASE_PORT 21324
+
+#define USB_IFACE_WIRE_PORT_OFFSET 0
+#define USB_IFACE_DEBUG_PORT_OFFSET 1
+#define USB_IFACE_WEBAUTHN_PORT_OFFSET 2
+#define USB_IFACE_VCP_PORT_OFFSET 3
+
+static secbool usb_device_init(void) {
+#if defined(BOOTLOADER)
+ usb_dev_info_t dev_info_default = {
+ .device_class = 0x00,
+ .device_subclass = 0x00,
+ .device_protocol = 0x00,
+ .vendor_id = 0x1209,
+ .product_id = 0x53C0,
+ .release_num = 0x0200,
+ .manufacturer = MODEL_USB_MANUFACTURER,
+ .product = MODEL_USB_PRODUCT,
+ .serial_number = "000000000000000000000000",
+ .interface = "TREZOR Interface",
+ .usb21_enabled = sectrue,
+ .usb21_landing = secfalse,
+ };
+#elif defined(PRODTEST)
+ static const usb_dev_info_t dev_info_default = {
+ .device_class = 0xEF, // Composite Device Class
+ .device_subclass = 0x02, // Common Class
+ .device_protocol = 0x01, // Interface Association Descriptor
+ .vendor_id = 0x1209,
+ .product_id = 0x53C1,
+ .release_num = 0x0400,
+ .manufacturer = MODEL_USB_MANUFACTURER,
+ .product = MODEL_USB_PRODUCT,
+ .serial_number = "000000000000",
+ .interface = "TREZOR Interface",
+ .usb21_enabled = secfalse,
+ .usb21_landing = secfalse,
+ };
+#else
+ static const usb_dev_info_t dev_info_default = {
+ .device_class = 0x00,
+ .device_subclass = 0x00,
+ .device_protocol = 0x00,
+ .vendor_id = 0x1209,
+ .product_id = 0x53C1,
+ .release_num = 0x0200,
+ .manufacturer = MODEL_USB_MANUFACTURER,
+ .product = MODEL_USB_PRODUCT,
+ .serial_number = "000000000000000000000000",
+ .interface = "TREZOR Interface",
+ .usb21_enabled = sectrue,
+ .usb21_landing = secfalse,
+ };
+#endif
+
+ usb_dev_info_t dev_info = dev_info_default;
+
+ return usb_init(&dev_info);
+}
+
+#ifdef TREZOR_EMULATOR
+static uint16_t usb_emu_port(uint16_t port_offset) {
+ const char *base_port = getenv("TREZOR_UDP_PORT");
+ return port_offset + (base_port ? atoi(base_port) : USB_IFACE_BASE_PORT);
+}
+#endif
+
+// ----------------------------------------------------------------
+
+#ifdef USE_USB_IFACE_WIRE
+static secbool usb_wire_iface_init(uint8_t *iface_num) {
+ static uint8_t wire_iface_buffer[USB_PACKET_LEN];
+
+ const usb_webusb_info_t wire_iface = {
+ .handle = SYSHANDLE_USB_WIRE,
+ .rx_buffer = wire_iface_buffer,
+ .iface_num = *iface_num,
+#ifdef TREZOR_EMULATOR
+ .emu_port = usb_emu_port(USB_IFACE_WIRE_PORT_OFFSET),
+#else
+ .ep_in = 0x01 + *iface_num,
+ .ep_out = 0x01 + *iface_num,
+#endif
+ .subclass = 0x00,
+ .protocol = 0x00,
+ .polling_interval = 1,
+ .max_packet_len = sizeof(wire_iface_buffer),
+ };
+
+ if (sectrue != usb_webusb_add(&wire_iface)) {
+ return secfalse;
+ }
+
+ *iface_num += 1;
+
+ return sectrue;
+}
+#endif // USE_USB_IFACE_WIRE
+
+#ifdef USE_USB_IFACE_DEBUG
+static secbool usb_debug_iface_init(uint8_t *iface_num) {
+ static uint8_t debug_iface_buffer[USB_PACKET_LEN];
+
+ const usb_webusb_info_t debug_iface = {
+ .handle = SYSHANDLE_USB_DEBUG,
+ .rx_buffer = debug_iface_buffer,
+ .iface_num = *iface_num,
+#ifdef TREZOR_EMULATOR
+ .emu_port = usb_emu_port(USB_IFACE_DEBUG_PORT_OFFSET),
+#else
+ .ep_in = 0x01 + *iface_num,
+ .ep_out = 0x01 + *iface_num,
+#endif
+ .subclass = 0x00,
+ .protocol = 0x00,
+ .polling_interval = 1,
+ .max_packet_len = sizeof(debug_iface_buffer),
+ };
+
+ if (sectrue != usb_webusb_add(&debug_iface)) {
+ return secfalse;
+ }
+
+ *iface_num += 1;
+
+ return sectrue;
+}
+#endif // USE_USB_IFACE_DEBUG
+
+#ifdef USE_USB_IFACE_WEBAUTHN
+static secbool usb_webauthn_iface_init(uint8_t *iface_num) {
+ static const uint8_t webauthn_report_map[] = {
+ 0x06, 0xd0, 0xf1, // USAGE_PAGE (FIDO Alliance)
+ 0x09, 0x01, // USAGE (U2F HID Authenticator Device)
+ 0xa1, 0x01, // COLLECTION (Application)
+ 0x09, 0x20, // USAGE (Input Report Data)
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
+ 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x95, 0x40, // REPORT_COUNT (64)
+ 0x81, 0x02, // INPUT (Data,Var,Abs)
+ 0x09, 0x21, // USAGE (Output Report Data)
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
+ 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x95, 0x40, // REPORT_COUNT (64)
+ 0x91, 0x02, // OUTPUT (Data,Var,Abs)
+ 0xc0, // END_COLLECTION
+ };
+
+ static uint8_t webauthn_iface_buffer[USB_PACKET_LEN];
+
+ const usb_hid_info_t webauthn_iface = {
+ .handle = SYSHANDLE_USB_WEBAUTHN,
+ .report_desc = webauthn_report_map,
+ .report_desc_len = sizeof(webauthn_report_map),
+ .rx_buffer = webauthn_iface_buffer,
+ .max_packet_len = sizeof(webauthn_iface_buffer),
+ .iface_num = *iface_num,
+#ifdef TREZOR_EMULATOR
+ .emu_port = usb_emu_port(USB_IFACE_WEBAUTHN_PORT_OFFSET),
+#else
+ .ep_in = 0x01 + *iface_num,
+ .ep_out = 0x01 + *iface_num,
+#endif
+ .subclass = 0x00,
+ .protocol = 0x00,
+ .polling_interval = 1,
+ };
+
+ if (sectrue != usb_hid_add(&webauthn_iface)) {
+ return secfalse;
+ }
+
+ *iface_num += 1;
+
+ return sectrue;
+}
+#endif // USE_USB_IFACE_WEBAUTHN
+
+#if defined(USE_USB_HS)
+#define VCP_PACKET_LEN 512
+#elif defined(USE_USB_FS)
+#define VCP_PACKET_LEN 64
+#elif defined(TREZOR_EMULATOR)
+#define VCP_PACKET_LEN 64
+#else
+#error "USB type not defined"
+#endif
+
+#define VCP_TX_BUFFER_LEN 2048
+#define VCP_RX_BUFFER_LEN 2048
+
+#ifdef USE_USB_IFACE_VCP
+static secbool usb_vcp_iface_init(uint8_t *iface_num,
+ usb_vcp_intr_callback_t vcp_intr_callback) {
+ static uint8_t vcp_tx_packet[VCP_PACKET_LEN];
+ static uint8_t vcp_tx_buffer[VCP_TX_BUFFER_LEN];
+ static uint8_t vcp_rx_packet[VCP_PACKET_LEN];
+ static uint8_t vcp_rx_buffer[VCP_RX_BUFFER_LEN];
+
+ const usb_vcp_info_t vcp_info = {
+ .handle = SYSHANDLE_USB_VCP,
+ .tx_packet = vcp_tx_packet,
+ .tx_buffer = vcp_tx_buffer,
+ .rx_packet = vcp_rx_packet,
+ .rx_buffer = vcp_rx_buffer,
+ .tx_buffer_len = sizeof(vcp_tx_buffer),
+ .rx_buffer_len = sizeof(vcp_rx_buffer),
+ .max_packet_len = VCP_PACKET_LEN,
+ .rx_intr_fn = vcp_intr_callback,
+ .rx_intr_byte = 3, // Ctrl-C
+ .iface_num = *iface_num,
+ .data_iface_num = *iface_num + 1,
+#ifdef TREZOR_EMULATOR
+ .emu_port = usb_emu_port(USB_IFACE_VCP_PORT_OFFSET),
+#else
+ .ep_cmd = 0x01 + *iface_num + 1,
+ .ep_in = 0x01 + *iface_num,
+ .ep_out = 0x01 + *iface_num,
+#endif
+ .polling_interval = 10,
+ };
+
+ if (sectrue != usb_vcp_add(&vcp_info)) {
+ return secfalse;
+ }
+
+ *iface_num += 2; // increment by data iface
+
+ return sectrue;
+}
+#endif // USE_USB_IFACE_VCP
+
+secbool usb_configure(usb_vcp_intr_callback_t vcp_intr_callback) {
+ if (sectrue != usb_device_init()) {
+ goto cleanup;
+ }
+
+ uint8_t iface_num = 0;
+
+#ifdef USE_USB_IFACE_WIRE
+ if (sectrue != usb_wire_iface_init(&iface_num)) {
+ goto cleanup;
+ }
+#endif
+
+#ifdef USE_USB_IFACE_DEBUG
+ if (sectrue != usb_debug_iface_init(&iface_num)) {
+ goto cleanup;
+ }
+#endif
+
+#ifdef USE_USB_IFACE_WEBAUTHN
+ if (sectrue != usb_webauthn_iface_init(&iface_num)) {
+ goto cleanup;
+ }
+#endif
+
+#ifdef USE_USB_IFACE_VCP
+ if (sectrue != usb_vcp_iface_init(&iface_num, vcp_intr_callback)) {
+ goto cleanup;
+ }
+#endif
+
+ return sectrue;
+
+cleanup:
+
+ usb_deinit();
+ return secfalse;
+}
+
+#endif // KERNEL_MODE
diff --git a/core/embed/models/T3T1/memory.h b/core/embed/models/T3T1/memory.h
index c7688e7c..d3ef680f 100644
--- a/core/embed/models/T3T1/memory.h
+++ b/core/embed/models/T3T1/memory.h
@@ -78,10 +78,10 @@
#define BOOTARGS_SIZE 0x100
#define MAIN_RAM_START 0x30030000
-#define MAIN_RAM_SIZE (24 * 1024)
+#define MAIN_RAM_SIZE (28 * 1024)
-#define AUX2_RAM_START 0x30036000
-#define AUX2_RAM_SIZE (327 * 1024)
+#define AUX2_RAM_START 0x30037000
+#define AUX2_RAM_SIZE (323 * 1024)
#define FB1_RAM_START 0x30087C00
#define FB1_RAM_SIZE (115200)
diff --git a/core/embed/models/T3T1/memory.ld b/core/embed/models/T3T1/memory.ld
index e869c252..18d6c895 100644
--- a/core/embed/models/T3T1/memory.ld
+++ b/core/embed/models/T3T1/memory.ld
@@ -40,9 +40,9 @@ AUX1_RAM_SIZE = 0x2fe00;
BOOTARGS_START = 0x3002ff00;
BOOTARGS_SIZE = 0x100;
MAIN_RAM_START = 0x30030000;
-MAIN_RAM_SIZE = 0x6000;
-AUX2_RAM_START = 0x30036000;
-AUX2_RAM_SIZE = 0x51c00;
+MAIN_RAM_SIZE = 0x7000;
+AUX2_RAM_START = 0x30037000;
+AUX2_RAM_SIZE = 0x50c00;
FB1_RAM_START = 0x30087c00;
FB1_RAM_SIZE = 0x1c200;
FB2_RAM_START = 0x300a3e00;
diff --git a/core/embed/projects/bootloader/main.c b/core/embed/projects/bootloader/main.c
index 91b2f60e..fa08e244 100644
--- a/core/embed/projects/bootloader/main.c
+++ b/core/embed/projects/bootloader/main.c
@@ -22,6 +22,7 @@
#include <io/display.h>
#include <io/display_utils.h>
+#include <io/usb_config.h>
#include <sec/random_delays.h>
#include <sec/secret.h>
#include <sys/bootargs.h>
@@ -295,6 +296,8 @@ static void drivers_init(secbool manufacturing_mode,
consumption_mask_init();
#endif
+ usb_configure(NULL);
+
#ifdef USE_BLE
ble_init();
#endif
diff --git a/core/embed/projects/bootloader/wire/wire_iface_usb.c b/core/embed/projects/bootloader/wire/wire_iface_usb.c
index 86fae4a5..50bcf064 100644
--- a/core/embed/projects/bootloader/wire/wire_iface_usb.c
+++ b/core/embed/projects/bootloader/wire/wire_iface_usb.c
@@ -37,8 +37,8 @@ static bool usb_write(uint8_t* data, size_t size) {
return false;
}
- int r =
- usb_webusb_write_blocking(SYSHANDLE_USB_IFACE_0, data, size, USB_TIMEOUT);
+ ssize_t r =
+ syshandle_write_blocking(SYSHANDLE_USB_WIRE, data, size, USB_TIMEOUT);
return r == size;
}
@@ -48,8 +48,8 @@ static int usb_read(uint8_t* buffer, size_t buffer_size) {
return -1;
}
- int r = usb_webusb_read_blocking(SYSHANDLE_USB_IFACE_0, buffer,
- USB_PACKET_SIZE, USB_TIMEOUT);
+ ssize_t r = syshandle_read_blocking(SYSHANDLE_USB_WIRE, buffer, buffer_size,
+ USB_TIMEOUT);
return r;
}
@@ -59,46 +59,6 @@ static void usb_error(void) {
"Error reading from USB. Try different USB cable.", NULL);
}
-static void usb_init_all(secbool usb21_landing) {
- usb_dev_info_t dev_info = {
- .device_class = 0x00,
- .device_subclass = 0x00,
- .device_protocol = 0x00,
- .vendor_id = 0x1209,
- .product_id = 0x53C0,
- .release_num = 0x0200,
- .manufacturer = MODEL_USB_MANUFACTURER,
- .product = MODEL_USB_PRODUCT,
- .serial_number = "000000000000000000000000",
- .interface = "TREZOR Interface",
- .usb21_enabled = sectrue,
- .usb21_landing = usb21_landing,
- };
-
- static uint8_t rx_buffer[USB_PACKET_SIZE];
-
- static const usb_webusb_info_t webusb_info = {
- .iface_num = SYSHANDLE_USB_IFACE_0,
-#ifdef TREZOR_EMULATOR
- .emu_port = 21324,
-#else
- .ep_in = 0x01,
- .ep_out = 0x01,
-#endif
- .subclass = 0,
- .protocol = 0,
- .max_packet_len = sizeof(rx_buffer),
- .rx_buffer = rx_buffer,
- .polling_interval = 1,
- };
-
- ensure(usb_init(&dev_info), NULL);
-
- ensure(usb_webusb_add(&webusb_info), NULL);
-
- ensure(usb_start(), NULL);
-}
-
wire_iface_t* usb_iface_init(secbool usb21_landing) {
wire_iface_t* iface = &g_usb_iface;
@@ -106,11 +66,16 @@ wire_iface_t* usb_iface_init(secbool usb21_landing) {
return iface;
}
- usb_init_all(usb21_landing);
+ usb_start_params_t params = {
+ .serial_number = "000000000000000000000000",
+ .usb21_landing = usb21_landing,
+ };
+
+ usb_start(¶ms);
memset(iface, 0, sizeof(wire_iface_t));
- iface->poll_iface_id = SYSHANDLE_USB_IFACE_0;
+ iface->poll_iface_id = SYSHANDLE_USB_WIRE;
iface->tx_packet_size = USB_PACKET_SIZE;
iface->rx_packet_size = USB_PACKET_SIZE;
iface->write = &usb_write;
@@ -129,5 +94,5 @@ void usb_iface_deinit(void) {
}
memset(iface, 0, sizeof(wire_iface_t));
- usb_deinit();
+ usb_stop();
}
diff --git a/core/embed/projects/bootloader_ci/main.c b/core/embed/projects/bootloader_ci/main.c
index ed7b7473..abe2e625 100644
--- a/core/embed/projects/bootloader_ci/main.c
+++ b/core/embed/projects/bootloader_ci/main.c
@@ -25,12 +25,14 @@
#include <gfx/gfx_draw.h>
#include <io/display.h>
#include <io/usb.h>
+#include <io/usb_config.h>
#include <rtl/mini_printf.h>
#include <sec/random_delays.h>
#include <sec/rng.h>
#include <sys/bootargs.h>
#include <sys/bootutils.h>
#include <sys/mpu.h>
+#include <sys/sysevent.h>
#include <sys/system.h>
#include <sys/systick.h>
#include <util/flash_otp.h>
@@ -47,7 +49,7 @@
#include <sec/hash_processor.h>
#endif
-#define USB_IFACE_NUM 0
+#define USB_IFACE_NUM SYSHANDLE_USB_WIRE
static void drivers_init(void) {
display_init(DISPLAY_RESET_CONTENT);
@@ -66,39 +68,14 @@ static void drivers_deinit(void) {
}
static void usb_init_all(secbool usb21_landing) {
- usb_dev_info_t dev_info = {
- .device_class = 0x00,
- .device_subclass = 0x00,
- .device_protocol = 0x00,
- .vendor_id = 0x1209,
- .product_id = 0x53C0,
- .release_num = 0x0200,
- .manufacturer = MODEL_USB_MANUFACTURER,
- .product = MODEL_USB_PRODUCT,
+ ensure(usb_configure(NULL), NULL);
+
+ usb_start_params_t params = {
.serial_number = "000000000000000000000000",
- .interface = "TREZOR Interface",
- .usb21_enabled = sectrue,
.usb21_landing = usb21_landing,
};
- static uint8_t rx_buffer[USB_PACKET_SIZE];
-
- static const usb_webusb_info_t webusb_info = {
- .iface_num = USB_IFACE_NUM,
- .ep_in = 0x01,
- .ep_out = 0x01,
- .subclass = 0,
- .protocol = 0,
- .max_packet_len = sizeof(rx_buffer),
- .rx_buffer = rx_buffer,
- .polling_interval = 1,
- };
-
- ensure(usb_init(&dev_info), NULL);
-
- ensure(usb_webusb_add(&webusb_info), NULL);
-
- ensure(usb_start(), NULL);
+ ensure(usb_start(¶ms), NULL);
}
static secbool bootloader_usb_loop(const vendor_header *const vhdr,
@@ -110,8 +87,8 @@ static secbool bootloader_usb_loop(const vendor_header *const vhdr,
uint8_t buf[USB_PACKET_SIZE];
for (;;) {
- int r = usb_webusb_read_blocking(USB_IFACE_NUM, buf, USB_PACKET_SIZE,
- USB_TIMEOUT);
+ int r = syshandle_read_blocking(USB_IFACE_NUM, buf, USB_PACKET_SIZE,
+ USB_TIMEOUT);
if (r != USB_PACKET_SIZE) {
continue;
}
diff --git a/core/embed/projects/bootloader_ci/messages.c b/core/embed/projects/bootloader_ci/messages.c
index 206e85b4..e204cd6d 100644
--- a/core/embed/projects/bootloader_ci/messages.c
+++ b/core/embed/projects/bootloader_ci/messages.c
@@ -26,6 +26,7 @@
#include "pb/messages.pb.h"
#include <io/usb.h>
+#include <sys/sysevent.h>
#include <util/flash.h>
#include <util/flash_utils.h>
#include <util/image.h>
@@ -79,8 +80,8 @@ static bool _usb_write(pb_ostream_t *stream, const pb_byte_t *buf,
USB_PACKET_SIZE - state->packet_pos);
written += USB_PACKET_SIZE - state->packet_pos;
// send packet
- int r = usb_webusb_write_blocking(state->iface_num, state->buf,
- USB_PACKET_SIZE, USB_TIMEOUT);
+ int r = syshandle_write_blocking(state->iface_num, state->buf,
+ USB_PACKET_SIZE, USB_TIMEOUT);
ensure(sectrue * (r == USB_PACKET_SIZE), NULL);
// prepare new packet
state->packet_index++;
@@ -101,8 +102,8 @@ static void _usb_write_flush(usb_write_state *state) {
USB_PACKET_SIZE - state->packet_pos);
}
// send packet
- int r = usb_webusb_write_blocking(state->iface_num, state->buf,
- USB_PACKET_SIZE, USB_TIMEOUT);
+ int r = syshandle_write_blocking(state->iface_num, state->buf,
+ USB_PACKET_SIZE, USB_TIMEOUT);
ensure(sectrue * (r == USB_PACKET_SIZE), NULL);
}
@@ -193,7 +194,7 @@ typedef struct {
static void _usb_webusb_read_retry(uint8_t iface_num, uint8_t *buf) {
for (int retry = 0;; retry++) {
int r =
- usb_webusb_read_blocking(iface_num, buf, USB_PACKET_SIZE, USB_TIMEOUT);
+ syshandle_read_blocking(iface_num, buf, USB_PACKET_SIZE, USB_TIMEOUT);
if (r != USB_PACKET_SIZE) { // reading failed
if (r == 0 && retry < 10) {
// only timeout => let's try again
diff --git a/core/embed/projects/firmware/mphalport.c b/core/embed/projects/firmware/mphalport.c
index f95042ee..e38f2a43 100644
--- a/core/embed/projects/firmware/mphalport.c
+++ b/core/embed/projects/firmware/mphalport.c
@@ -21,31 +21,24 @@
#include "py/mphal.h"
-#include <io/usb.h>
+#include <io/usb_config.h>
#include <sys/systick.h>
-static int vcp_iface_num = -1;
-
int mp_hal_stdin_rx_chr(void) {
- ensure(sectrue * (vcp_iface_num >= 0), "vcp stdio is not configured");
uint8_t c = 0;
- int r = usb_vcp_read_blocking(vcp_iface_num, &c, 1, -1);
+ int r = syshandle_read(SYSHANDLE_USB_VCP, &c, sizeof(c));
(void)r;
return c;
}
void mp_hal_stdout_tx_strn(const char *str, size_t len) {
- if (vcp_iface_num >= 0) {
- // The write timeout defaults to 0, because otherwise when the VCP receive
- // buffer on the host gets full, the timeout will block device operation.
- int r = usb_vcp_write_blocking(vcp_iface_num, (const uint8_t *)str, len,
+ // The write timeout defaults to 0, because otherwise when the VCP receive
+ // buffer on the host gets full, the timeout will block device operation.
+ int r = syshandle_write_blocking(SYSHANDLE_USB_VCP, (const uint8_t *)str, len,
BLOCK_ON_VCP ? 1000 : 0);
- (void)r;
- }
+ (void)r;
}
-void mp_hal_set_vcp_iface(int iface_num) { vcp_iface_num = iface_num; }
-
// Dummy implementation required by ports/stm32/gccollect.c.
// The normal version requires MICROPY_ENABLE_SCHEDULER which we don't use.
void soft_timer_gc_mark_all(void) {}
diff --git a/core/embed/projects/firmware/mphalport.h b/core/embed/projects/firmware/mphalport.h
index 8954eec6..d1bb5cbb 100644
--- a/core/embed/projects/firmware/mphalport.h
+++ b/core/embed/projects/firmware/mphalport.h
@@ -20,5 +20,3 @@
#include "shared/runtime/interrupt_char.h"
static inline mp_uint_t mp_hal_ticks_cpu(void) { return 0; }
-
-void mp_hal_set_vcp_iface(int iface_num);
diff --git a/core/embed/projects/kernel/main.c b/core/embed/projects/kernel/main.c
index 1ca91e69..f739cc1c 100644
--- a/core/embed/projects/kernel/main.c
+++ b/core/embed/projects/kernel/main.c
@@ -98,6 +98,11 @@
#include <io/touch.h>
#endif
+#ifdef USE_USB
+#include <io/usb.h>
+#include <io/usb_config.h>
+#endif
+
void drivers_init() {
#ifdef SECURE_MODE
parse_boardloader_capabilities();
@@ -184,6 +189,10 @@ void drivers_init() {
tropic_init();
#endif
#endif // SECURE_MODE
+
+#ifdef USE_USB
+ usb_configure(NULL);
+#endif
}
// Kernel task main loop
diff --git a/core/embed/projects/prodtest/cmd/prodtest_ble.c b/core/embed/projects/prodtest/cmd/prodtest_ble.c
index 976c2347..987d0401 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_ble.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_ble.c
@@ -26,6 +26,7 @@
#include <io/nrf.h>
#include <io/usb.h>
#include <rtl/cli.h>
+#include <sys/sysevent.h>
#include <sys/systick.h>
#include <sys/systimer.h>
@@ -363,7 +364,7 @@ static void prodtest_ble_radio_test_cmd(cli_t* cli) {
}
// Read byte from the command line and pass it to NRF UART;
- if (usb_vcp_read(0, &cmd_line_byte, 1) > 0) {
+ if (syshandle_read(SYSHANDLE_USB_VCP, &cmd_line_byte, 1) > 0) {
HAL_UART_Transmit(&huart, &cmd_line_byte, 1, 100);
}
@@ -380,7 +381,9 @@ static void prodtest_ble_radio_test_cmd(cli_t* cli) {
cli_ok(cli, "");
}
-void dtm_rx_callback(uint8_t byte) { (void)!usb_vcp_write(0, &byte, 1); }
+void dtm_rx_callback(uint8_t byte) {
+ syshandle_write(SYSHANDLE_USB_VCP, &byte, sizeof(byte));
+}
void prodtest_ble_direct_test_mode_cmd(cli_t* cli) {
if (cli_arg_count(cli) > 0) {
@@ -405,7 +408,7 @@ void prodtest_ble_direct_test_mode_cmd(cli_t* cli) {
// }
// Read byte from the command line and pass it to NRF UART;
- if (usb_vcp_read(0, &cmd_line_byte, 1) > 0) {
+ if (syshandle_read(SYSHANDLE_USB_VCP, &cmd_line_byte, 1) > 0) {
nrf_dtm_send_data(&cmd_line_byte, 1);
}
}
diff --git a/core/embed/projects/prodtest/emulator.c b/core/embed/projects/prodtest/emulator.c
index 4e30d3c6..bc9a0984 100644
--- a/core/embed/projects/prodtest/emulator.c
+++ b/core/embed/projects/prodtest/emulator.c
@@ -20,7 +20,7 @@ void usage(void) {
"socat' in Ubuntu)\n");
printf(
"Bind the UDP with 'socat -d -d "
- "pty,link=/dev/ttyVCP0,mode=666,raw,echo=0 UDP:127.0.0.1:21424'\n");
+ "pty,link=/dev/ttyVCP0,mode=666,raw,echo=0 UDP:127.0.0.1:21327'\n");
printf("Then you can connect with you terminal to /dev/ttyVCP0\n");
printf(" -h show this help\n");
}
diff --git a/core/embed/projects/prodtest/main.c b/core/embed/projects/prodtest/main.c
index 5c0f3b31..5488b441 100644
--- a/core/embed/projects/prodtest/main.c
+++ b/core/embed/projects/prodtest/main.c
@@ -24,6 +24,7 @@
#include <io/display.h>
#include <io/usb.h>
+#include <io/usb_config.h>
#include <rtl/cli.h>
#include <sys/system.h>
#include <sys/systick.h>
@@ -123,77 +124,15 @@ struct {
bool set;
} g_layout __attribute__((aligned(4))) = {0};
-#define VCP_IFACE 0
-
-static size_t console_read(void *context, char *buf, size_t size) {
- return usb_vcp_read(VCP_IFACE, (uint8_t *)buf, size);
+static ssize_t console_read(void *context, char *buf, size_t size) {
+ return syshandle_read(SYSHANDLE_USB_VCP, buf, size);
}
-static size_t console_write(void *context, const char *buf, size_t size) {
- return usb_vcp_write_blocking(VCP_IFACE, (const uint8_t *)buf, size, 100);
+static ssize_t console_write(void *context, const char *buf, size_t size) {
+ return syshandle_write_blocking(SYSHANDLE_USB_VCP, buf, size, 100);
}
-static void vcp_intr(void) { cli_abort(&g_cli); }
-
-#if defined(USE_USB_HS)
-#define VCP_PACKET_LEN 512
-#elif defined(USE_USB_FS)
-#define VCP_PACKET_LEN 64
-#elif defined(TREZOR_EMULATOR)
-#define VCP_PACKET_LEN 64
-#else
-#error "USB type not defined"
-#endif
-
-#define VCP_BUFFER_LEN 2048
-
-static void usb_init_all(void) {
- static const usb_dev_info_t dev_info = {
- .device_class = 0xEF, // Composite Device Class
- .device_subclass = 0x02, // Common Class
- .device_protocol = 0x01, // Interface Association Descriptor
- .vendor_id = 0x1209,
- .product_id = 0x53C1,
- .release_num = 0x0400,
- .manufacturer = MODEL_USB_MANUFACTURER,
- .product = MODEL_USB_PRODUCT,
- .serial_number = "000000000000",
- .interface = "TREZOR Interface",
- .usb21_enabled = secfalse,
- .usb21_landing = secfalse,
- };
-
- static uint8_t tx_packet[VCP_PACKET_LEN];
- static uint8_t tx_buffer[VCP_BUFFER_LEN];
- static uint8_t rx_packet[VCP_PACKET_LEN];
- static uint8_t rx_buffer[VCP_BUFFER_LEN];
-
- static const usb_vcp_info_t vcp_info = {
- .tx_packet = tx_packet,
- .tx_buffer = tx_buffer,
- .rx_packet = rx_packet,
- .rx_buffer = rx_buffer,
- .tx_buffer_len = VCP_BUFFER_LEN,
- .rx_buffer_len = VCP_BUFFER_LEN,
- .rx_intr_fn = vcp_intr,
- .rx_intr_byte = 3, // Ctrl-C
- .iface_num = VCP_IFACE,
- .data_iface_num = 0x01,
-#ifdef TREZOR_EMULATOR
- .emu_port = 21424,
-#else
- .ep_cmd = 0x02,
- .ep_in = 0x01,
- .ep_out = 0x01,
-#endif
- .polling_interval = 10,
- .max_packet_len = VCP_PACKET_LEN,
- };
-
- ensure(usb_init(&dev_info), NULL);
- ensure(usb_vcp_add(&vcp_info), "usb_vcp_add");
- ensure(usb_start(), NULL);
-}
+static void usb_vcp_intr_callback(void) { cli_abort(&g_cli); }
// Set if the RGB LED must not be controlled by the main loop
static bool g_rgbled_control_disabled = false;
@@ -278,7 +217,10 @@ int prodtest_main(void) {
system_init(&rsod_panic_handler);
drivers_init();
- usb_init_all();
+
+ ensure(usb_configure(&usb_vcp_intr_callback), "usb_configure failed");
+
+ ensure(usb_start(NULL), "usb_start failed");
// Initialize command line interface
cli_init(&g_cli, console_read, console_write, NULL);
@@ -309,7 +251,7 @@ int prodtest_main(void) {
while (true) {
sysevents_t awaited = {0};
- awaited.read_ready |= 1 << VCP_IFACE;
+ awaited.read_ready |= 1 << SYSHANDLE_USB_VCP;
#ifdef USE_BUTTON
awaited.read_ready |= 1 << SYSHANDLE_BUTTON;
#endif
@@ -322,7 +264,7 @@ int prodtest_main(void) {
sysevents_t signalled = {0};
sysevents_poll(&awaited, &signalled, ticks_timeout(100));
- if (signalled.read_ready & (1 << VCP_IFACE)) {
+ if (signalled.read_ready & (1 << SYSHANDLE_USB_VCP)) {
const cli_command_t *cmd = cli_process_io(&g_cli);
if (cmd != NULL) {
diff --git a/core/embed/projects/unix/main.c b/core/embed/projects/unix/main.c
index 6d3d61aa..58882b46 100644
--- a/core/embed/projects/unix/main.c
+++ b/core/embed/projects/unix/main.c
@@ -37,6 +37,7 @@
#include <unistd.h>
#include <io/display.h>
+#include <io/usb_config.h>
#include <sec/secret.h>
#include <sys/system.h>
#include <sys/systimer.h>
@@ -522,6 +523,8 @@ void drivers_init() {
#ifdef USE_TROPIC
tropic_init();
#endif
+
+ usb_configure(NULL);
}
// Initialize the system and drivers for running tests in the Rust code.
diff --git a/core/embed/rtl/cli.c b/core/embed/rtl/cli.c
index 6f061f91..2e0d0416 100644
--- a/core/embed/rtl/cli.c
+++ b/core/embed/rtl/cli.c
@@ -277,7 +277,7 @@ static int cli_readch(cli_t* cli) {
for (;;) {
char ch;
- size_t len = cli->read(cli->callback_context, &ch, 1);
+ ssize_t len = cli->read(cli->callback_context, &ch, 1);
if (len != 1) {
return 0;
diff --git a/core/embed/rtl/inc/rtl/cli.h b/core/embed/rtl/inc/rtl/cli.h
index 1d70cf1a..6c36d1d6 100644
--- a/core/embed/rtl/inc/rtl/cli.h
+++ b/core/embed/rtl/inc/rtl/cli.h
@@ -85,9 +85,9 @@ typedef struct {
#endif
// Callback for writing characters to console output
-typedef size_t (*cli_write_cb_t)(void* ctx, const char* buf, size_t len);
+typedef ssize_t (*cli_write_cb_t)(void* ctx, const char* buf, size_t len);
// Callback for reading characters from console input
-typedef size_t (*cli_read_cb_t)(void* ctx, char* buf, size_t len);
+typedef ssize_t (*cli_read_cb_t)(void* ctx, char* buf, size_t len);
struct cli {
// I/O callbacks
diff --git a/core/embed/rtl/inc/trezor_types.h b/core/embed/rtl/inc/trezor_types.h
index a4e8a83e..044bf743 100644
--- a/core/embed/rtl/inc/trezor_types.h
+++ b/core/embed/rtl/inc/trezor_types.h
@@ -17,8 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef TREZOR_TYPES_H
-#define TREZOR_TYPES_H
+#pragma once
// `trezor_types.h` consolidates commonly needed includes for interface
// header files and provides essential types required in most files.
@@ -29,7 +28,6 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
+#include <sys/types.h>
#include "rtl/secbool.h"
-
-#endif // TREZOR_TYPES_H
diff --git a/core/embed/sys/suspend/stm32u5/suspend_io.c b/core/embed/sys/suspend/stm32u5/suspend_io.c
index 37793fc6..79ad2885 100644
--- a/core/embed/sys/suspend/stm32u5/suspend_io.c
+++ b/core/embed/sys/suspend/stm32u5/suspend_io.c
@@ -155,7 +155,7 @@ void resume_drivers(const power_save_wakeup_params_t *wakeup_params) {
rgb_led_init();
#endif
#ifdef USE_USB
- usb_start();
+ usb_start(NULL);
#endif
#ifdef USE_BLE
ble_resume(&wakeup_params->ble);
diff --git a/core/embed/sys/syscall/inc/sys/syscall_numbers.h b/core/embed/sys/syscall/inc/sys/syscall_numbers.h
index 86c7e621..e3fe19c6 100644
--- a/core/embed/sys/syscall/inc/sys/syscall_numbers.h
+++ b/core/embed/sys/syscall/inc/sys/syscall_numbers.h
@@ -41,6 +41,8 @@ typedef enum {
SYSCALL_SYSTICK_US_TO_CYCLES,
SYSCALL_SYSEVENTS_POLL,
+ SYSCALL_SYSHANDLE_READ,
+ SYSCALL_SYSHANDLE_WRITE,
SYSCALL_BOOT_IMAGE_CHECK,
SYSCALL_BOOT_IMAGE_REPLACE,
@@ -59,37 +61,11 @@ typedef enum {
SYSCALL_DISPLAY_FILL,
SYSCALL_DISPLAY_COPY_RGB565,
- SYSCALL_USB_INIT,
- SYSCALL_USB_DEINIT,
SYSCALL_USB_START,
SYSCALL_USB_STOP,
SYSCALL_USB_GET_EVENT,
SYSCALL_USB_GET_STATE,
- SYSCALL_USB_HID_ADD,
- SYSCALL_USB_HID_CAN_READ,
- SYSCALL_USB_HID_CAN_WRITE,
- SYSCALL_USB_HID_READ,
- SYSCALL_USB_HID_WRITE,
- SYSCALL_USB_HID_READ_SELECT,
- SYSCALL_USB_HID_READ_BLOCKING,
- SYSCALL_USB_HID_WRITE_BLOCKING,
- SYSCALL_USB_VCP_ADD,
- SYSCALL_USB_VCP_CAN_READ,
- SYSCALL_USB_VCP_CAN_WRITE,
- SYSCALL_USB_VCP_READ,
- SYSCALL_USB_VCP_WRITE,
- SYSCALL_USB_VCP_READ_BLOCKING,
- SYSCALL_USB_VCP_WRITE_BLOCKING,
- SYSCALL_USB_WEBUSB_ADD,
- SYSCALL_USB_WEBUSB_CAN_READ,
- SYSCALL_USB_WEBUSB_CAN_WRITE,
- SYSCALL_USB_WEBUSB_READ,
- SYSCALL_USB_WEBUSB_WRITE,
- SYSCALL_USB_WEBUSB_READ_SELECT,
- SYSCALL_USB_WEBUSB_READ_BLOCKING,
- SYSCALL_USB_WEBUSB_WRITE_BLOCKING,
-
SYSCALL_SDCARD_POWER_ON,
SYSCALL_SDCARD_POWER_OFF,
SYSCALL_SDCARD_IS_PRESENT,
diff --git a/core/embed/sys/syscall/stm32/syscall_dispatch.c b/core/embed/sys/syscall/stm32/syscall_dispatch.c
index 4b022527..95d42128 100644
--- a/core/embed/sys/syscall/stm32/syscall_dispatch.c
+++ b/core/embed/sys/syscall/stm32/syscall_dispatch.c
@@ -24,9 +24,6 @@
#include <gfx/dma2d_bitblt.h>
#include <io/display.h>
#include <io/usb.h>
-#include <io/usb_hid.h>
-#include <io/usb_vcp.h>
-#include <io/usb_webusb.h>
#include <sec/rng.h>
#include <sec/secret.h>
#include <sys/bootutils.h>
@@ -156,6 +153,20 @@ __attribute((no_stack_protector)) void syscall_handler(uint32_t *args,
}
} break;
+ case SYSCALL_SYSHANDLE_READ: {
+ syshandle_t handle = (syshandle_t)args[0];
+ void *buffer = (void *)args[1];
+ size_t buffer_size = (size_t)args[2];
+ args[0] = syshandle_read__verified(handle, buffer, buffer_size);
+ } break;
+
+ case SYSCALL_SYSHANDLE_WRITE: {
+ syshandle_t handle = (syshandle_t)args[0];
+ const void *data = (const void *)args[1];
+ size_t data_size = (size_t)args[2];
+ args[0] = syshandle_write__verified(handle, data, data_size);
+ } break;
+
case SYSCALL_BOOT_IMAGE_CHECK: {
const boot_image_t *image = (const boot_image_t *)args[0];
args[0] = boot_image_check__verified(image);
@@ -224,17 +235,9 @@ __attribute((no_stack_protector)) void syscall_handler(uint32_t *args,
display_refresh();
} break;
- case SYSCALL_USB_INIT: {
- const usb_dev_info_t *dev_info = (const usb_dev_info_t *)args[0];
- args[0] = usb_init(dev_info);
- } break;
-
- case SYSCALL_USB_DEINIT: {
- usb_deinit();
- } break;
-
case SYSCALL_USB_START: {
- args[0] = usb_start();
+ const usb_start_params_t *params = (const usb_start_params_t *)args[0];
+ args[0] = usb_start__verified(params);
} break;
case SYSCALL_USB_STOP: {
@@ -250,153 +253,6 @@ __attribute((no_stack_protector)) void syscall_handler(uint32_t *args,
usb_get_state__verified(state);
} break;
- case SYSCALL_USB_HID_ADD: {
- const usb_hid_info_t *hid_info = (const usb_hid_info_t *)args[0];
- args[0] = usb_hid_add(hid_info);
- } break;
-
- case SYSCALL_USB_HID_CAN_READ: {
- uint8_t iface_num = (uint8_t)args[0];
- args[0] = usb_hid_can_read(iface_num);
- } break;
-
- case SYSCALL_USB_HID_CAN_WRITE: {
- uint8_t iface_num = (uint8_t)args[0];
- args[0] = usb_hid_can_write(iface_num);
- } break;
-
- case SYSCALL_USB_HID_READ: {
- uint8_t iface_num = (uint8_t)args[0];
- uint8_t *buf = (uint8_t *)args[1];
- uint32_t len = args[2];
- args[0] = usb_hid_read__verified(iface_num, buf, len);
- } break;
-
- case SYSCALL_USB_HID_WRITE: {
- uint8_t iface_num = (uint8_t)args[0];
- const uint8_t *buf = (const uint8_t *)args[1];
- uint32_t len = args[2];
- args[0] = usb_hid_write__verified(iface_num, buf, len);
- } break;
-
- case SYSCALL_USB_HID_READ_SELECT: {
- uint32_t timeout = args[0];
- args[0] = usb_hid_read_select(timeout);
- } break;
-
- case SYSCALL_USB_HID_READ_BLOCKING: {
- uint8_t iface_num = (uint8_t)args[0];
- uint8_t *buf = (uint8_t *)args[1];
- uint32_t len = args[2];
- int timeout = (int)args[3];
- args[0] = usb_hid_read_blocking__verified(iface_num, buf, len, timeout);
- } break;
-
- case SYSCALL_USB_HID_WRITE_BLOCKING: {
- uint8_t iface_num = (uint8_t)args[0];
- const uint8_t *buf = (const uint8_t *)args[1];
- uint32_t len = args[2];
- int timeout = (int)args[3];
- args[0] = usb_hid_write_blocking__verified(iface_num, buf, len, timeout);
- } break;
-
- case SYSCALL_USB_VCP_ADD: {
- const usb_vcp_info_t *vcp_info = (const usb_vcp_info_t *)args[0];
- args[0] = usb_vcp_add(vcp_info);
- } break;
-
- case SYSCALL_USB_VCP_CAN_READ: {
- uint8_t iface_num = (uint8_t)args[0];
- args[0] = usb_vcp_can_read(iface_num);
- } break;
-
- case SYSCALL_USB_VCP_CAN_WRITE: {
- uint8_t iface_num = (uint8_t)args[0];
- args[0] = usb_vcp_can_write(iface_num);
- } break;
-
- case SYSCALL_USB_VCP_READ: {
- uint8_t iface_num = (uint8_t)args[0];
- uint8_t *buf = (uint8_t *)args[1];
- uint32_t len = args[2];
- args[0] = usb_vcp_read__verified(iface_num, buf, len);
- } break;
-
- case SYSCALL_USB_VCP_WRITE: {
- uint8_t iface_num = (uint8_t)args[0];
- const uint8_t *buf = (const uint8_t *)args[1];
- uint32_t len = args[2];
- args[0] = usb_vcp_write__verified(iface_num, buf, len);
- } break;
-
- case SYSCALL_USB_VCP_READ_BLOCKING: {
- uint8_t iface_num = (uint8_t)args[0];
- uint8_t *buf = (uint8_t *)args[1];
- uint32_t len = args[2];
- int timeout = (int)args[3];
- args[0] = usb_vcp_read_blocking__verified(iface_num, buf, len, timeout);
- } break;
-
- case SYSCALL_USB_VCP_WRITE_BLOCKING: {
- uint8_t iface_num = (uint8_t)args[0];
- const uint8_t *buf = (const uint8_t *)args[1];
- uint32_t len = args[2];
- int timeout = (int)args[3];
- args[0] = usb_vcp_write_blocking__verified(iface_num, buf, len, timeout);
- } break;
-
- case SYSCALL_USB_WEBUSB_ADD: {
- const usb_webusb_info_t *webusb_info = (const usb_webusb_info_t *)args[0];
- args[0] = usb_webusb_add(webusb_info);
- } break;
-
- case SYSCALL_USB_WEBUSB_CAN_READ: {
- uint8_t iface_num = (uint8_t)args[0];
- args[0] = usb_webusb_can_read(iface_num);
- } break;
-
- case SYSCALL_USB_WEBUSB_CAN_WRITE: {
- uint8_t iface_num = (uint8_t)args[0];
- args[0] = usb_webusb_can_write(iface_num);
- } break;
-
- case SYSCALL_USB_WEBUSB_READ: {
- uint8_t iface_num = (uint8_t)args[0];
- uint8_t *buf = (uint8_t *)args[1];
- uint32_t len = args[2];
- args[0] = usb_webusb_read__verified(iface_num, buf, len);
- } break;
-
- case SYSCALL_USB_WEBUSB_WRITE: {
- uint8_t iface_num = (uint8_t)args[0];
- const uint8_t *buf = (const uint8_t *)args[1];
- uint32_t len = args[2];
- args[0] = usb_webusb_write__verified(iface_num, buf, len);
- } break;
-
- case SYSCALL_USB_WEBUSB_READ_SELECT: {
- uint32_t timeout = args[0];
- args[0] = usb_webusb_read_select(timeout);
- } break;
-
- case SYSCALL_USB_WEBUSB_READ_BLOCKING: {
- uint8_t iface_num = (uint8_t)args[0];
- uint8_t *buf = (uint8_t *)args[1];
- uint32_t len = args[2];
- int timeout = (int)args[3];
- args[0] =
- usb_webusb_read_blocking__verified(iface_num, buf, len, timeout);
- } break;
-
- case SYSCALL_USB_WEBUSB_WRITE_BLOCKING: {
- uint8_t iface_num = (uint8_t)args[0];
- const uint8_t *buf = (const uint8_t *)args[1];
- uint32_t len = args[2];
- int timeout = (int)args[3];
- args[0] =
- usb_webusb_write_blocking__verified(iface_num, buf, len, timeout);
- } break;
-
#ifdef USE_SD_CARD
case SYSCALL_SDCARD_POWER_ON: {
args[0] = sdcard_power_on();
diff --git a/core/embed/sys/syscall/stm32/syscall_stubs.c b/core/embed/sys/syscall/stm32/syscall_stubs.c
index 514b3886..00a78296 100644
--- a/core/embed/sys/syscall/stm32/syscall_stubs.c
+++ b/core/embed/sys/syscall/stm32/syscall_stubs.c
@@ -84,6 +84,17 @@ void sysevents_poll(const sysevents_t *awaited, sysevents_t *signalled,
SYSCALL_SYSEVENTS_POLL);
}
+ssize_t syshandle_read(syshandle_t handle, void *buffer, size_t buffer_size) {
+ return syscall_invoke3((uint32_t)handle, (uint32_t)buffer, buffer_size,
+ SYSCALL_SYSHANDLE_READ);
+}
+
+ssize_t syshandle_write(syshandle_t handle, const void *data,
+ size_t data_size) {
+ return syscall_invoke3((uint32_t)handle, (uint32_t)data, data_size,
+ SYSCALL_SYSHANDLE_WRITE);
+}
+
// =============================================================================
// boot_image.h
// =============================================================================
@@ -174,14 +185,10 @@ void display_refresh(void) { syscall_invoke0(SYSCALL_DISPLAY_REFRESH); }
#include <io/usb.h>
-secbool usb_init(const usb_dev_info_t *dev_info) {
- return (secbool)syscall_invoke1((uint32_t)dev_info, SYSCALL_USB_INIT);
+secbool usb_start(const usb_start_params_t *params) {
+ return (secbool)syscall_invoke1((uint32_t)params, SYSCALL_USB_START);
}
-void usb_deinit(void) { syscall_invoke0(SYSCALL_USB_DEINIT); }
-
-secbool usb_start(void) { return (secbool)syscall_invoke0(SYSCALL_USB_START); }
-
void usb_stop(void) { syscall_invoke0(SYSCALL_USB_STOP); }
usb_event_t usb_get_event(void) {
@@ -192,141 +199,6 @@ void usb_get_state(usb_state_t *state) {
syscall_invoke1((uint32_t)state, SYSCALL_USB_GET_STATE);
}
-// =============================================================================
-// usb_hid.h
-// =============================================================================
-
-#include <io/usb_hid.h>
-
-secbool usb_hid_add(const usb_hid_info_t *hid_info) {
- return (secbool)syscall_invoke1((uint32_t)hid_info, SYSCALL_USB_HID_ADD);
-}
-
-secbool usb_hid_can_read(uint8_t iface_num) {
- return (secbool)syscall_invoke1((uint32_t)iface_num,
- SYSCALL_USB_HID_CAN_READ);
-}
-
-secbool usb_hid_can_write(uint8_t iface_num) {
- return (secbool)syscall_invoke1((uint32_t)iface_num,
- SYSCALL_USB_HID_CAN_WRITE);
-}
-
-int usb_hid_read(uint8_t iface_num, uint8_t *buf, uint32_t len) {
- return (int)syscall_invoke3((uint32_t)iface_num, (uint32_t)buf, len,
- SYSCALL_USB_HID_READ);
-}
-
-int usb_hid_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) {
- return (int)syscall_invoke3((uint32_t)iface_num, (uint32_t)buf, len,
- SYSCALL_USB_HID_WRITE);
-}
-
-int usb_hid_read_select(uint32_t timeout) {
- return (int)syscall_invoke1(timeout, SYSCALL_USB_HID_READ_SELECT);
-}
-
-int usb_hid_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len,
- int timeout) {
- return (int)syscall_invoke4((uint32_t)iface_num, (uint32_t)buf, len, timeout,
- SYSCALL_USB_HID_READ_BLOCKING);
-}
-
-int usb_hid_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len,
- int timeout) {
- return (int)syscall_invoke4((uint32_t)iface_num, (uint32_t)buf, len, timeout,
- SYSCALL_USB_HID_WRITE_BLOCKING);
-}
-
-// =============================================================================
-// usb_vcp.h
-// =============================================================================
-
-#include <io/usb_vcp.h>
-
-secbool usb_vcp_add(const usb_vcp_info_t *vcp_info) {
- return (secbool)syscall_invoke1((uint32_t)vcp_info, SYSCALL_USB_VCP_ADD);
-}
-
-secbool usb_vcp_can_read(uint8_t iface_num) {
- return (secbool)syscall_invoke1((uint32_t)iface_num,
- SYSCALL_USB_VCP_CAN_READ);
-}
-
-secbool usb_vcp_can_write(uint8_t iface_num) {
- return (secbool)syscall_invoke1((uint32_t)iface_num,
- SYSCALL_USB_VCP_CAN_WRITE);
-}
-
-int usb_vcp_read(uint8_t iface_num, uint8_t *buf, uint32_t len) {
- return (int)syscall_invoke3((uint32_t)iface_num, (uint32_t)buf, len,
- SYSCALL_USB_VCP_READ);
-}
-
-int usb_vcp_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) {
- return (int)syscall_invoke3((uint32_t)iface_num, (uint32_t)buf, len,
- SYSCALL_USB_VCP_WRITE);
-}
-
-int usb_vcp_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len,
- int timeout) {
- return (int)syscall_invoke4((uint32_t)iface_num, (uint32_t)buf, len, timeout,
- SYSCALL_USB_VCP_READ_BLOCKING);
-}
-
-int usb_vcp_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len,
- int timeout) {
- return (int)syscall_invoke4((uint32_t)iface_num, (uint32_t)buf, len, timeout,
- SYSCALL_USB_VCP_WRITE_BLOCKING);
-}
-
-// =============================================================================
-// usb_webusb.h
-// =============================================================================
-
-#include <io/usb_webusb.h>
-
-secbool usb_webusb_add(const usb_webusb_info_t *webusb_info) {
- return (secbool)syscall_invoke1((uint32_t)webusb_info,
- SYSCALL_USB_WEBUSB_ADD);
-}
-
-secbool usb_webusb_can_read(uint8_t iface_num) {
- return (secbool)syscall_invoke1((uint32_t)iface_num,
- SYSCALL_USB_WEBUSB_CAN_READ);
-}
-
-secbool usb_webusb_can_write(uint8_t iface_num) {
- return (secbool)syscall_invoke1((uint32_t)iface_num,
- SYSCALL_USB_WEBUSB_CAN_WRITE);
-}
-
-int usb_webusb_read(uint8_t iface_num, uint8_t *buf, uint32_t len) {
- return (int)syscall_invoke3((uint32_t)iface_num, (uint32_t)buf, len,
- SYSCALL_USB_WEBUSB_READ);
-}
-
-int usb_webusb_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) {
- return (int)syscall_invoke3((uint32_t)iface_num, (uint32_t)buf, len,
- SYSCALL_USB_WEBUSB_WRITE);
-}
-
-int usb_webusb_read_select(uint32_t timeout) {
- return (int)syscall_invoke1(timeout, SYSCALL_USB_WEBUSB_READ_SELECT);
-}
-
-int usb_webusb_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len,
- int timeout) {
- return (int)syscall_invoke4((uint32_t)iface_num, (uint32_t)buf, len, timeout,
- SYSCALL_USB_WEBUSB_READ_BLOCKING);
-}
-
-int usb_webusb_write_blocking(uint8_t iface_num, const uint8_t *buf,
- uint32_t len, int timeout) {
- return (int)syscall_invoke4((uint32_t)iface_num, (uint32_t)buf, len, timeout,
- SYSCALL_USB_WEBUSB_WRITE_BLOCKING);
-}
-
// =============================================================================
// sdcard.h
// =============================================================================
diff --git a/core/embed/sys/syscall/stm32/syscall_verifiers.c b/core/embed/sys/syscall/stm32/syscall_verifiers.c
index 233a16ff..2b4ccfff 100644
--- a/core/embed/sys/syscall/stm32/syscall_verifiers.c
+++ b/core/embed/sys/syscall/stm32/syscall_verifiers.c
@@ -62,6 +62,32 @@ access_violation:
apptask_access_violation();
}
+ssize_t syshandle_read__verified(syshandle_t handle, void *buffer,
+ size_t buffer_size) {
+ if (!probe_write_access(buffer, buffer_size)) {
+ goto access_violation;
+ }
+
+ return syshandle_read(handle, buffer, buffer_size);
+
+access_violation:
+ apptask_access_violation();
+ return -1;
+}
+
+ssize_t syshandle_write__verified(syshandle_t handle, const void *data,
+ size_t data_size) {
+ if (!probe_read_access(data, data_size)) {
+ goto access_violation;
+ }
+
+ return syshandle_write(handle, data, data_size);
+
+access_violation:
+ apptask_access_violation();
+ return -1;
+}
+
// ---------------------------------------------------------------------
bool boot_image_check__verified(const boot_image_t *image) {
@@ -265,161 +291,16 @@ access_violation:
apptask_access_violation();
}
-int usb_hid_read__verified(uint8_t iface_num, uint8_t *buf, uint32_t len) {
- if (!probe_write_access(buf, len)) {
- goto access_violation;
- }
-
- return usb_hid_read(iface_num, buf, len);
-
-access_violation:
- apptask_access_violation();
- return 0;
-}
-
-int usb_hid_write__verified(uint8_t iface_num, const uint8_t *buf,
- uint32_t len) {
- if (!probe_read_access(buf, len)) {
- goto access_violation;
- }
-
- return usb_hid_write(iface_num, buf, len);
-
-access_violation:
- apptask_access_violation();
- return 0;
-}
-
-int usb_hid_read_blocking__verified(uint8_t iface_num, uint8_t *buf,
- uint32_t len, int timeout) {
- if (!probe_write_access(buf, len)) {
- goto access_violation;
- }
-
- return usb_hid_read_blocking(iface_num, buf, len, timeout);
-
-access_violation:
- apptask_access_violation();
- return 0;
-}
-
-int usb_hid_write_blocking__verified(uint8_t iface_num, const uint8_t *buf,
- uint32_t len, int timeout) {
- if (!probe_read_access(buf, len)) {
+secbool usb_start__verified(const usb_start_params_t *params) {
+ if (!probe_read_access(params, sizeof(*params))) {
goto access_violation;
}
- return usb_hid_write_blocking(iface_num, buf, len, timeout);
+ return usb_start(params);
access_violation:
apptask_access_violation();
- return 0;
-}
-
-// ---------------------------------------------------------------------
-
-int usb_vcp_read__verified(uint8_t iface_num, uint8_t *buf, uint32_t len) {
- if (!probe_write_access(buf, len)) {
- goto access_violation;
- }
-
- return usb_vcp_read(iface_num, buf, len);
-
-access_violation:
- apptask_access_violation();
- return 0;
-}
-
-int usb_vcp_write__verified(uint8_t iface_num, const uint8_t *buf,
- uint32_t len) {
- if (!probe_read_access(buf, len)) {
- goto access_violation;
- }
-
- return usb_vcp_write(iface_num, buf, len);
-
-access_violation:
- apptask_access_violation();
- return 0;
-}
-
-int usb_vcp_read_blocking__verified(uint8_t iface_num, uint8_t *buf,
- uint32_t len, int timeout) {
- if (!probe_write_access(buf, len)) {
- goto access_violation;
- }
-
- return usb_vcp_read_blocking(iface_num, buf, len, timeout);
-
-access_violation:
- apptask_access_violation();
- return 0;
-}
-
-int usb_vcp_write_blocking__verified(uint8_t iface_num, const uint8_t *buf,
- uint32_t len, int timeout) {
- if (!probe_read_access(buf, len)) {
- goto access_violation;
- }
-
- return usb_vcp_write_blocking(iface_num, buf, len, timeout);
-
-access_violation:
- apptask_access_violation();
- return 0;
-}
-
-// ---------------------------------------------------------------------
-
-int usb_webusb_read__verified(uint8_t iface_num, uint8_t *buf, uint32_t len) {
- if (!probe_write_access(buf, len)) {
- goto access_violation;
- }
-
- return usb_webusb_read(iface_num, buf, len);
-
-access_violation:
- apptask_access_violation();
- return 0;
-}
-
-int usb_webusb_write__verified(uint8_t iface_num, const uint8_t *buf,
- uint32_t len) {
- if (!probe_read_access(buf, len)) {
- goto access_violation;
- }
-
- return usb_webusb_write(iface_num, buf, len);
-
-access_violation:
- apptask_access_violation();
- return 0;
-}
-
-int usb_webusb_read_blocking__verified(uint8_t iface_num, uint8_t *buf,
- uint32_t len, int timeout) {
- if (!probe_write_access(buf, len)) {
- goto access_violation;
- }
-
- return usb_webusb_read_blocking(iface_num, buf, len, timeout);
-
-access_violation:
- apptask_access_violation();
- return 0;
-}
-
-int usb_webusb_write_blocking__verified(uint8_t iface_num, const uint8_t *buf,
- uint32_t len, int timeout) {
- if (!probe_read_access(buf, len)) {
- goto access_violation;
- }
-
- return usb_webusb_write_blocking(iface_num, buf, len, timeout);
-
-access_violation:
- apptask_access_violation();
- return 0;
+ return secfalse;
}
// ---------------------------------------------------------------------
diff --git a/core/embed/sys/syscall/stm32/syscall_verifiers.h b/core/embed/sys/syscall/stm32/syscall_verifiers.h
index a0ba00b1..a33fd73d 100644
--- a/core/embed/sys/syscall/stm32/syscall_verifiers.h
+++ b/core/embed/sys/syscall/stm32/syscall_verifiers.h
@@ -27,6 +27,12 @@
void sysevents_poll__verified(const sysevents_t *awaited,
sysevents_t *signalled, uint32_t deadline);
+ssize_t syshandle_read__verified(syshandle_t handle, void *buffer,
+ size_t buffer_size);
+
+ssize_t syshandle_write__verified(syshandle_t handle, const void *data,
+ size_t data_size);
+
// ---------------------------------------------------------------------
#include <sys/systask.h>
@@ -65,46 +71,10 @@ void display_copy_rgb565__verified(const gfx_bitblt_t *bb);
// ---------------------------------------------------------------------
#include <io/usb.h>
-void usb_get_state__verified(usb_state_t *state);
-
-// ---------------------------------------------------------------------
-#include <io/usb_hid.h>
-int usb_hid_read__verified(uint8_t iface_num, uint8_t *buf, uint32_t len);
-
-int usb_hid_write__verified(uint8_t iface_num, const uint8_t *buf,
- uint32_t len);
-
-int usb_hid_read_blocking__verified(uint8_t iface_num, uint8_t *buf,
- uint32_t len, int timeout);
-int usb_hid_write_blocking__verified(uint8_t iface_num, const uint8_t *buf,
- uint32_t len, int timeout);
-
-// ---------------------------------------------------------------------
-#include <io/usb_vcp.h>
-
-int usb_vcp_read__verified(uint8_t iface_num, uint8_t *buf, uint32_t len);
-
-int usb_vcp_write__verified(uint8_t iface_num, const uint8_t *buf,
- uint32_t len);
-
-int usb_vcp_read_blocking__verified(uint8_t iface_num, uint8_t *buf,
- uint32_t len, int timeout);
-int usb_vcp_write_blocking__verified(uint8_t iface_num, const uint8_t *buf,
- uint32_t len, int timeout);
-
-// ---------------------------------------------------------------------
-#include <io/usb_webusb.h>
-
-int usb_webusb_read__verified(uint8_t iface_num, uint8_t *buf, uint32_t len);
-
-int usb_webusb_write__verified(uint8_t iface_num, const uint8_t *buf,
- uint32_t len);
+void usb_get_state__verified(usb_state_t *state);
-int usb_webusb_read_blocking__verified(uint8_t iface_num, uint8_t *buf,
- uint32_t len, int timeout);
-int usb_webusb_write_blocking__verified(uint8_t iface_num, const uint8_t *buf,
- uint32_t len, int timeout);
+secbool usb_start__verified(const usb_start_params_t *params);
// ---------------------------------------------------------------------
diff --git a/core/embed/sys/task/inc/sys/sysevent.h b/core/embed/sys/task/inc/sys/sysevent.h
index ea3aeeb1..770c64fd 100644
--- a/core/embed/sys/task/inc/sys/sysevent.h
+++ b/core/embed/sys/task/inc/sys/sysevent.h
@@ -21,10 +21,12 @@
#include <trezor_types.h>
-// Event sources that can be signaled by the system or device drivers
+/** System handles registered by system or device drivers */
typedef enum {
- SYSHANDLE_USB_IFACE_0,
- SYSHANDLE_USB_IFACE_7 = SYSHANDLE_USB_IFACE_0 + 7,
+ SYSHANDLE_USB_WIRE,
+ SYSHANDLE_USB_DEBUG,
+ SYSHANDLE_USB_WEBAUTHN,
+ SYSHANDLE_USB_VCP,
SYSHANDLE_BLE_IFACE_0,
// SYSHANDLE_BLE_IFACE_N = SYSHANDLE_BLE_IFACE_0 + N - 1,
SYSHANDLE_POWER_MANAGER,
@@ -36,22 +38,87 @@ typedef enum {
SYSHANDLE_COUNT,
} syshandle_t;
-// Bitmask of event sources
+#define SYSHANDLE_USB_IFACE_MIN SYSHANDLE_USB_WIRE
+#define SYSHANDLE_USB_IFACE_MAX SYSHANDLE_USB_VCP
+
+/**
+ * @brief Reads data from the specified device
+ *
+ * This function is non-blocking and returns immediately.
+ *
+ * @param handle Handle of the device to read from
+ * @param buffer Pointer to the buffer where the read data will be stored
+ * @param buffer_size Size of the buffer in bytes
+ *
+ * @return Number of bytes read, or negative value on error.
+ */
+ssize_t syshandle_read(syshandle_t handle, void* buffer, size_t buffer_size);
+
+/**
+ * @brief Writes data to the specified device
+ *
+ * This function is non-blocking and returns immediately.
+ *
+ * @param handle Handle of the device to write to
+ * @param data Pointer to the data to write
+ * @param data_size Size of the data in bytes
+ *
+ * @return Number of bytes written, or negative value on error.
+ */
+ssize_t syshandle_write(syshandle_t handle, const void* data, size_t data_size);
+
+/**
+ * @brief Reads data from the specified device, blocks until data is available
+ * or timeout expires.
+ *
+ * If the timeout is 0, the function behaves like `syshandle_read`.
+ *
+ * @param handle Handle of the device to read from
+ * @param buffer Pointer to the buffer where the read data will be stored
+ * @param buffer_size Size of the buffer in bytes
+ * @param timeout Timeout in milliseconds, 0 means no timeout
+ *
+ * @return Number of bytes read, or negative value on error.
+ */
+ssize_t syshandle_read_blocking(syshandle_t handle, void* buffer,
+ size_t buffer_size, uint32_t timeout);
+
+/**
+ * @brief Writes data to the specified device, blocks until data is written
+ * or timeout expires.
+ *
+ * If the timeout is 0, the function behaves like `syshandle_write`.
+ *
+ * @param handle Handle of the device to write to
+ * @param data Pointer to the data to write
+ * @param data_size Size of the data in bytes
+ * @param timeout Timeout in milliseconds, 0 means no timeout
+ */
+ssize_t syshandle_write_blocking(syshandle_t handle, const void* data,
+ size_t data_size, uint32_t timeout);
+
+/** Bitmask of event handles */
typedef uint32_t syshandle_mask_t;
typedef struct {
- // Bitmask of handles ready for reading
+ /** Bitmask of handles ready for reading */
syshandle_mask_t read_ready;
- // Bitmask of handles ready for writing
+ /** Bitmask of handles ready for writing */
syshandle_mask_t write_ready;
-} sysevents_t; // sys_events_t
-
-// Polls for the specified events. The function blocks until at least
-// one event is signaled or deadline expires.
-//
-// Multiple events may be signaled simultaneously.
-//
-// Returns the events that were signaled. If the timeout expires, both
-// fields in the result are set to 0.
+} sysevents_t;
+
+/**
+ * @brief Polls for the specified device events. The function blocks until at
+ * least one event is signaled or deadline expires.
+ *
+ * Multiple events may be signaled simultaneously.
+ *
+ * @param awaited Pointer to the structure specifying which events to wait for.
+ * @param signalled Pointer to the structure where the signaled events will be
+ * stored.
+ *
+ * @return The events that were signaled. If the deadline expires, the function
+ * returns without signaling any events in the `signalled` structure.
+ */
void sysevents_poll(const sysevents_t* awaited, sysevents_t* signalled,
uint32_t deadline);
diff --git a/core/embed/sys/task/inc/sys/sysevent_source.h b/core/embed/sys/task/inc/sys/sysevent_source.h
index 9dbb9012..28b64e12 100644
--- a/core/embed/sys/task/inc/sys/sysevent_source.h
+++ b/core/embed/sys/task/inc/sys/sysevent_source.h
@@ -54,6 +54,12 @@ typedef void (*syshandle_poll_cb_t)(void *context, bool read_awaited,
typedef bool (*syshandle_check_cb_t)(void *context, systask_id_t task_id,
void *param);
+typedef ssize_t (*syshandle_read_cb_t)(void *context, void *buffer,
+ size_t buffer_size);
+
+typedef ssize_t (*syshandle_write_cb_t)(void *context, const void *data,
+ size_t data_size);
+
// System handle virtual method table
typedef struct {
syshandle_task_created_cb_t task_created;
@@ -61,6 +67,8 @@ typedef struct {
syshandle_poll_cb_t poll;
syshandle_check_cb_t check_read_ready;
syshandle_check_cb_t check_write_ready;
+ syshandle_read_cb_t read;
+ syshandle_write_cb_t write;
} syshandle_vmt_t;
// ----------------------------------------------------------------------
diff --git a/core/embed/sys/task/sysevent.c b/core/embed/sys/task/sysevent.c
index b79eec43..6dc89f13 100644
--- a/core/embed/sys/task/sysevent.c
+++ b/core/embed/sys/task/sysevent.c
@@ -17,14 +17,16 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifdef KERNEL_MODE
-
-#include <trezor_bsp.h>
#include <trezor_rtl.h>
+#include <sys/sysevent.h>
+#include <sys/systick.h>
+
+#ifdef KERNEL_MODE
+
#include <sys/sysevent_source.h>
#include <sys/systask.h>
-#include <sys/systick.h>
+#include <trezor_bsp.h>
#ifdef TREZOR_EMULATOR
#include <sys/unix/sdl_event.h>
@@ -81,6 +83,39 @@ void syshandle_unregister(syshandle_t handle) {
}
}
+ssize_t syshandle_read(syshandle_t handle, void *buffer, size_t buffer_size) {
+ if (handle >= SYSHANDLE_COUNT) {
+ return -1;
+ }
+
+ sysevent_dispatcher_t *dispatcher = &g_sysevent_dispatcher;
+
+ const sysevent_source_t *source = &dispatcher->sources[handle];
+
+ if (source->vmt == NULL || source->vmt->read == NULL) {
+ return -1;
+ }
+
+ return source->vmt->read(source->context, buffer, buffer_size);
+}
+
+ssize_t syshandle_write(syshandle_t handle, const void *data,
+ size_t data_size) {
+ if (handle >= SYSHANDLE_COUNT) {
+ return false;
+ }
+
+ sysevent_dispatcher_t *dispatcher = &g_sysevent_dispatcher;
+
+ const sysevent_source_t *source = &dispatcher->sources[handle];
+
+ if (source->vmt == NULL || source->vmt->write == NULL) {
+ return -1;
+ }
+
+ return source->vmt->write(source->context, data, data_size);
+}
+
void syshandle_signal_read_ready(syshandle_t handle, void *param) {
if (handle >= SYSHANDLE_COUNT) {
return;
@@ -277,3 +312,23 @@ void sysevents_notify_task_killed(systask_t *task) {
}
#endif // KERNEL_MODE
+
+ssize_t syshandle_read_blocking(syshandle_t handle, void *buffer,
+ size_t buffer_size, uint32_t timeout) {
+ if (timeout > 0) {
+ sysevents_t awaited = {.read_ready = 1 << handle};
+ sysevents_t signalled = {0};
+ sysevents_poll(&awaited, &signalled, ticks_timeout(timeout));
+ }
+ return syshandle_read(handle, buffer, buffer_size);
+}
+
+ssize_t syshandle_write_blocking(syshandle_t handle, const void *data,
+ size_t data_size, uint32_t timeout) {
+ if (timeout > 0) {
+ sysevents_t awaited = {.write_ready = 1 << handle};
+ sysevents_t signalled = {0};
+ sysevents_poll(&awaited, &signalled, ticks_timeout(timeout));
+ }
+ return syshandle_write(handle, data, data_size);
+}
diff --git a/core/embed/upymod/modtrezorio/modtrezorio-hid.h b/core/embed/upymod/modtrezorio/modtrezorio-hid.h
deleted file mode 100644
index f58da3f7..00000000
--- a/core/embed/upymod/modtrezorio/modtrezorio-hid.h
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "embed/upymod/trezorobj.h"
-
-/// package: trezorio.__init__
-
-/// class HID:
-/// """
-/// USB HID interface configuration.
-/// """
-typedef struct _mp_obj_HID_t {
- mp_obj_base_t base;
- usb_hid_info_t info;
-} mp_obj_HID_t;
-
-/// def __init__(
-/// self,
-/// iface_num: int,
-/// ep_in: int,
-/// ep_out: int,
-/// emu_port: int,
-/// report_desc: bytes,
-/// subclass: int = 0,
-/// protocol: int = 0,
-/// polling_interval: int = 1,
-/// max_packet_len: int = 64,
-/// ) -> None:
-/// """
-/// """
-STATIC mp_obj_t mod_trezorio_HID_make_new(const mp_obj_type_t *type,
- size_t n_args, size_t n_kw,
- const mp_obj_t *args) {
- STATIC const mp_arg_t allowed_args[] = {
- {MP_QSTR_iface_num,
- MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
- {.u_int = 0}},
- {MP_QSTR_ep_in,
- MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
- {.u_int = 0}},
- {MP_QSTR_ep_out,
- MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
- {.u_int = 0}},
- {MP_QSTR_emu_port,
- MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
- {.u_int = 0}},
- {MP_QSTR_subclass, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}},
- {MP_QSTR_protocol, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}},
- {MP_QSTR_polling_interval, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1}},
- {MP_QSTR_max_packet_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64}},
- {MP_QSTR_report_desc,
- MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ,
- {.u_obj = MP_OBJ_NULL}},
- };
- mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)] = {0};
- mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args),
- allowed_args, vals);
-
- const mp_int_t iface_num = vals[0].u_int;
- const mp_int_t ep_in = vals[1].u_int;
- const mp_int_t ep_out = vals[2].u_int;
- const mp_int_t emu_port = vals[3].u_int;
- const mp_int_t subclass = vals[4].u_int;
- const mp_int_t protocol = vals[5].u_int;
- const mp_int_t polling_interval = vals[6].u_int;
- const mp_int_t max_packet_len = vals[7].u_int;
- mp_buffer_info_t report_desc = {0};
- mp_get_buffer_raise(vals[8].u_obj, &report_desc, MP_BUFFER_READ);
-
- if (report_desc.buf == NULL || report_desc.len == 0 ||
- report_desc.len > 255) {
- mp_raise_ValueError(MP_ERROR_TEXT("report_desc is invalid"));
- }
- CHECK_PARAM_RANGE(iface_num, 0, 32)
- CHECK_PARAM_RANGE(ep_in, 0, 255)
- CHECK_PARAM_RANGE(ep_out, 0, 255)
- CHECK_PARAM_RANGE(emu_port, 0, 65535)
- CHECK_PARAM_RANGE(subclass, 0, 255)
- CHECK_PARAM_RANGE(protocol, 0, 255)
- CHECK_PARAM_RANGE(polling_interval, 1, 255)
- CHECK_PARAM_RANGE(max_packet_len, 64, 64)
-
- mp_obj_HID_t *o = mp_obj_malloc(mp_obj_HID_t, type);
-
- o->info.rx_buffer = m_new(uint8_t, max_packet_len);
- o->info.report_desc = report_desc.buf;
- o->info.iface_num = (uint8_t)(iface_num);
-#ifdef TREZOR_EMULATOR
- o->info.emu_port = (uint16_t)(emu_port);
-#else
- o->info.ep_in = (uint8_t)(ep_in);
- o->info.ep_out = (uint8_t)(ep_out);
-#endif
- o->info.subclass = (uint8_t)(subclass);
- o->info.protocol = (uint8_t)(protocol);
- o->info.polling_interval = (uint8_t)(polling_interval);
- o->info.max_packet_len = (uint8_t)(max_packet_len);
- o->info.report_desc_len = (uint8_t)(report_desc.len);
-
- return MP_OBJ_FROM_PTR(o);
-}
-
-/// def iface_num(self) -> int:
-/// """
-/// Returns the configured number of this interface.
-/// """
-STATIC mp_obj_t mod_trezorio_HID_iface_num(mp_obj_t self) {
- mp_obj_HID_t *o = MP_OBJ_TO_PTR(self);
- return MP_OBJ_NEW_SMALL_INT(o->info.iface_num);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_HID_iface_num_obj,
- mod_trezorio_HID_iface_num);
-
-/// def write(self, msg: bytes) -> int:
-/// """
-/// Sends message using USB HID (device) or UDP (emulator).
-/// """
-STATIC mp_obj_t mod_trezorio_HID_write(mp_obj_t self, mp_obj_t msg) {
- mp_obj_HID_t *o = MP_OBJ_TO_PTR(self);
- mp_buffer_info_t buf = {0};
- mp_get_buffer_raise(msg, &buf, MP_BUFFER_READ);
- ssize_t r = usb_hid_write(o->info.iface_num, buf.buf, buf.len);
- return MP_OBJ_NEW_SMALL_INT(r);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_HID_write_obj,
- mod_trezorio_HID_write);
-
-/// def read(self, buf: bytearray, offset: int = 0) -> int:
-/// """
-/// Reads message using USB HID (device) or UDP (emulator).
-/// """
-STATIC mp_obj_t mod_trezorio_HID_read(size_t n_args, const mp_obj_t *args) {
- mp_obj_HID_t *o = MP_OBJ_TO_PTR(args[0]);
- mp_buffer_info_t buf = {0};
- mp_get_buffer_raise(args[1], &buf, MP_BUFFER_WRITE);
-
- int offset = 0;
- if (n_args >= 2) {
- offset = mp_obj_get_int(args[2]);
- }
-
- if (offset < 0) {
- mp_raise_ValueError(MP_ERROR_TEXT("Negative offset not allowed"));
- }
-
- if (offset > buf.len) {
- mp_raise_ValueError(MP_ERROR_TEXT("Offset out of bounds"));
- }
-
- uint32_t buffer_space = buf.len - offset;
-
- if (buffer_space < USB_PACKET_LEN) {
- mp_raise_ValueError(MP_ERROR_TEXT("Buffer too small"));
- }
-
- ssize_t r = usb_hid_read(o->info.iface_num, &((uint8_t *)buf.buf)[offset],
- USB_PACKET_LEN);
-
- if (r != USB_PACKET_LEN) {
- mp_raise_msg(&mp_type_RuntimeError,
- MP_ERROR_TEXT("Unexpected read length"));
- }
-
- return MP_OBJ_NEW_SMALL_INT(r);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorio_HID_read_obj, 2, 3,
- mod_trezorio_HID_read);
-
-/// def write_blocking(self, msg: bytes, timeout_ms: int) -> int:
-/// """
-/// Sends message using USB HID (device) or UDP (emulator).
-/// """
-STATIC mp_obj_t mod_trezorio_HID_write_blocking(mp_obj_t self, mp_obj_t msg,
- mp_obj_t timeout_ms) {
- mp_obj_HID_t *o = MP_OBJ_TO_PTR(self);
- mp_buffer_info_t buf = {0};
- mp_get_buffer_raise(msg, &buf, MP_BUFFER_READ);
- uint32_t timeout = trezor_obj_get_uint(timeout_ms);
- ssize_t r =
- usb_hid_write_blocking(o->info.iface_num, buf.buf, buf.len, timeout);
- return MP_OBJ_NEW_SMALL_INT(r);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorio_HID_write_blocking_obj,
- mod_trezorio_HID_write_blocking);
-
-/// RX_PACKET_LEN: ClassVar[int]
-/// """Length of one USB RX packet."""
-
-/// TX_PACKET_LEN: ClassVar[int]
-/// """Length of one USB TX packet."""
-
-STATIC const mp_rom_map_elem_t mod_trezorio_HID_locals_dict_table[] = {
- {MP_ROM_QSTR(MP_QSTR_iface_num),
- MP_ROM_PTR(&mod_trezorio_HID_iface_num_obj)},
- {MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mod_trezorio_HID_write_obj)},
- {MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mod_trezorio_HID_read_obj)},
- {MP_ROM_QSTR(MP_QSTR_write_blocking),
- MP_ROM_PTR(&mod_trezorio_HID_write_blocking_obj)},
- {MP_ROM_QSTR(MP_QSTR_RX_PACKET_LEN), MP_ROM_INT(USB_PACKET_LEN)},
- {MP_ROM_QSTR(MP_QSTR_TX_PACKET_LEN), MP_ROM_INT(USB_PACKET_LEN)},
-};
-STATIC MP_DEFINE_CONST_DICT(mod_trezorio_HID_locals_dict,
- mod_trezorio_HID_locals_dict_table);
-
-STATIC const mp_obj_type_t mod_trezorio_HID_type = {
- {&mp_type_type},
- .name = MP_QSTR_HID,
- .make_new = mod_trezorio_HID_make_new,
- .locals_dict = (void *)&mod_trezorio_HID_locals_dict,
-};
diff --git a/core/embed/upymod/modtrezorio/modtrezorio-poll.h b/core/embed/upymod/modtrezorio/modtrezorio-poll.h
index 923dd6f5..9a50b18f 100644
--- a/core/embed/upymod/modtrezorio/modtrezorio-poll.h
+++ b/core/embed/upymod/modtrezorio/modtrezorio-poll.h
@@ -236,7 +236,7 @@ STATIC mp_obj_t mod_trezorio_poll(mp_obj_t ifaces, mp_obj_t list_ref,
return mp_const_true;
}
- for (syshandle_t h = SYSHANDLE_USB_IFACE_0; h <= SYSHANDLE_USB_IFACE_7;
+ for (syshandle_t h = SYSHANDLE_USB_IFACE_MIN; h <= SYSHANDLE_USB_IFACE_MAX;
h++) {
if (signalled.read_ready & (1 << h)) {
ret->items[0] = MP_OBJ_NEW_SMALL_INT(h);
diff --git a/core/embed/upymod/modtrezorio/modtrezorio-usb-if.h b/core/embed/upymod/modtrezorio/modtrezorio-usb-if.h
new file mode 100644
index 00000000..9e34e1ca
--- /dev/null
+++ b/core/embed/upymod/modtrezorio/modtrezorio-usb-if.h
@@ -0,0 +1,184 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/// package: trezorio.__init__
+
+/// class USBIF:
+/// """
+/// USB USBIF interface configuration.
+/// """
+typedef struct _mp_obj_USBIF_t {
+ mp_obj_base_t base;
+ mp_int_t handle;
+} mp_obj_USBIF_t;
+
+/// def __init__(
+/// self,
+/// handle: int,
+/// ) -> None:
+/// """
+/// """
+STATIC mp_obj_t mod_trezorio_USBIF_make_new(const mp_obj_type_t *type,
+ size_t n_args, size_t n_kw,
+ const mp_obj_t *args) {
+ STATIC const mp_arg_t allowed_args[] = {
+ {MP_QSTR_handle,
+ MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
+ {.u_int = 0}},
+ };
+ mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)] = {0};
+ mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args),
+ allowed_args, vals);
+
+ const mp_int_t handle = vals[0].u_int;
+
+ CHECK_PARAM_RANGE(handle, 0, 32)
+
+ mp_obj_USBIF_t *o = mp_obj_malloc(mp_obj_USBIF_t, type);
+
+ o->handle = handle;
+
+ return MP_OBJ_FROM_PTR(o);
+}
+
+/// def iface_num(self) -> int:
+/// """
+/// Returns the configured number of this interface.
+/// """
+STATIC mp_obj_t mod_trezorio_USBIF_iface_num(mp_obj_t self) {
+ mp_obj_USBIF_t *o = MP_OBJ_TO_PTR(self);
+ return MP_OBJ_NEW_SMALL_INT(o->handle);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_USBIF_iface_num_obj,
+ mod_trezorio_USBIF_iface_num);
+
+/// def write(self, msg: bytes) -> int:
+/// """
+/// Sends message using USB interface.
+/// """
+STATIC mp_obj_t mod_trezorio_USBIF_write(mp_obj_t self, mp_obj_t msg) {
+ mp_obj_USBIF_t *o = MP_OBJ_TO_PTR(self);
+ mp_buffer_info_t buf = {0};
+ mp_get_buffer_raise(msg, &buf, MP_BUFFER_READ);
+
+ if (buf.len != USB_PACKET_LEN) {
+ mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Invalid buffer length"));
+ }
+
+ ssize_t r = syshandle_write(o->handle, buf.buf, buf.len);
+
+ // !@# should we have this test here?
+ if (r != buf.len) {
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Write failed"));
+ }
+
+ return MP_OBJ_NEW_SMALL_INT(r);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_USBIF_write_obj,
+ mod_trezorio_USBIF_write);
+
+/// def write_blocking(self, msg: bytes, timeout_ms: int) -> int:
+/// """
+/// Sends message using USB interface.
+/// """
+STATIC mp_obj_t mod_trezorio_USBIF_write_blocking(mp_obj_t self, mp_obj_t msg,
+ mp_obj_t timeout_ms) {
+ mp_obj_USBIF_t *o = MP_OBJ_TO_PTR(self);
+ mp_buffer_info_t buf = {0};
+ mp_get_buffer_raise(msg, &buf, MP_BUFFER_READ);
+
+ if (buf.len != USB_PACKET_LEN) {
+ mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Invalid buffer length"));
+ }
+
+ uint32_t timeout = trezor_obj_get_uint(timeout_ms);
+
+ ssize_t r = syshandle_write_blocking(o->handle, buf.buf, buf.len, timeout);
+
+ return MP_OBJ_NEW_SMALL_INT(r);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorio_USBIF_write_blocking_obj,
+ mod_trezorio_USBIF_write_blocking);
+
+/// def read(self, buf: bytearray, offset: int = 0) -> int:
+/// """
+/// Reads message using USB interface
+/// """
+STATIC mp_obj_t mod_trezorio_USBIF_read(size_t n_args, const mp_obj_t *args) {
+ mp_obj_USBIF_t *o = MP_OBJ_TO_PTR(args[0]);
+ mp_buffer_info_t buf = {0};
+ mp_get_buffer_raise(args[1], &buf, MP_BUFFER_WRITE);
+
+ int offset = 0;
+ if (n_args >= 2) {
+ offset = mp_obj_get_int(args[2]);
+ }
+
+ if (offset < 0) {
+ mp_raise_ValueError(MP_ERROR_TEXT("Negative offset not allowed"));
+ }
+
+ if (offset > buf.len) {
+ mp_raise_ValueError(MP_ERROR_TEXT("Offset out of bounds"));
+ }
+
+ uint32_t buffer_space = buf.len - offset;
+
+ if (buffer_space < USB_PACKET_LEN) {
+ mp_raise_ValueError(MP_ERROR_TEXT("Buffer too small"));
+ }
+
+ ssize_t r =
+ syshandle_read(o->handle, &((uint8_t *)buf.buf)[offset], USB_PACKET_LEN);
+
+ if (r != USB_PACKET_LEN) {
+ mp_raise_msg(&mp_type_RuntimeError,
+ MP_ERROR_TEXT("Unexpected read length"));
+ }
+
+ return MP_OBJ_NEW_SMALL_INT(r);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorio_USBIF_read_obj, 2, 3,
+ mod_trezorio_USBIF_read);
+
+/// RX_PACKET_LEN: ClassVar[int]
+/// """Length of one USB RX packet."""
+
+/// TX_PACKET_LEN: ClassVar[int]
+/// """Length of one USB TX packet."""
+
+STATIC const mp_rom_map_elem_t mod_trezorio_USBIF_locals_dict_table[] = {
+ {MP_ROM_QSTR(MP_QSTR_iface_num),
+ MP_ROM_PTR(&mod_trezorio_USBIF_iface_num_obj)},
+ {MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mod_trezorio_USBIF_write_obj)},
+ {MP_ROM_QSTR(MP_QSTR_write_blocking),
+ MP_ROM_PTR(&mod_trezorio_USBIF_write_blocking_obj)},
+ {MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mod_trezorio_USBIF_read_obj)},
+ {MP_ROM_QSTR(MP_QSTR_RX_PACKET_LEN), MP_ROM_INT(USB_PACKET_LEN)},
+ {MP_ROM_QSTR(MP_QSTR_TX_PACKET_LEN), MP_ROM_INT(USB_PACKET_LEN)},
+};
+STATIC MP_DEFINE_CONST_DICT(mod_trezorio_USBIF_locals_dict,
+ mod_trezorio_USBIF_locals_dict_table);
+
+STATIC const mp_obj_type_t mod_trezorio_USBIF_type = {
+ {&mp_type_type},
+ .name = MP_QSTR_USBIF,
+ .make_new = mod_trezorio_USBIF_make_new,
+ .locals_dict = (void *)&mod_trezorio_USBIF_locals_dict,
+};
diff --git a/core/embed/upymod/modtrezorio/modtrezorio-usb.h b/core/embed/upymod/modtrezorio/modtrezorio-usb.h
index 9d72f85d..77c6b564 100644
--- a/core/embed/upymod/modtrezorio/modtrezorio-usb.h
+++ b/core/embed/upymod/modtrezorio/modtrezorio-usb.h
@@ -17,13 +17,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-void mp_hal_set_vcp_iface(int iface_num);
-
-enum {
- USB_CLOSED = 0,
- USB_OPENED = 1,
-};
-
/// package: trezorio.__init__
/// class USB:
@@ -32,9 +25,6 @@ enum {
/// """
typedef struct _mp_obj_USB_t {
mp_obj_base_t base;
- mp_obj_list_t ifaces;
- usb_dev_info_t info;
- mp_int_t state;
} mp_obj_USB_t;
static const char *get_0str(mp_obj_t o, size_t min_len, size_t max_len) {
@@ -53,193 +43,41 @@ static const char *get_0str(mp_obj_t o, size_t min_len, size_t max_len) {
/// def __init__(
/// self,
-/// vendor_id: int,
-/// product_id: int,
-/// release_num: int,
-/// device_class: int = 0,
-/// device_subclass: int = 0,
-/// device_protocol: int = 0,
-/// manufacturer: str = "",
-/// product: str = "",
-/// interface: str = "",
-/// usb21_enabled: bool = True,
-/// usb21_landing: bool = True,
/// ) -> None:
/// """
/// """
STATIC mp_obj_t mod_trezorio_USB_make_new(const mp_obj_type_t *type,
size_t n_args, size_t n_kw,
const mp_obj_t *args) {
- STATIC const mp_arg_t allowed_args[] = {
- {MP_QSTR_device_class, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}},
- {MP_QSTR_device_subclass, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}},
- {MP_QSTR_device_protocol, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}},
- {MP_QSTR_vendor_id,
- MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
- {.u_int = 0}},
- {MP_QSTR_product_id,
- MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
- {.u_int = 0}},
- {MP_QSTR_release_num,
- MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
- {.u_int = 0}},
- {MP_QSTR_manufacturer,
- MP_ARG_KW_ONLY | MP_ARG_OBJ,
- {.u_obj = mp_const_empty_bytes}},
- {MP_QSTR_product,
- MP_ARG_KW_ONLY | MP_ARG_OBJ,
- {.u_obj = mp_const_empty_bytes}},
- {MP_QSTR_interface,
- MP_ARG_KW_ONLY | MP_ARG_OBJ,
- {.u_obj = mp_const_empty_bytes}},
- {MP_QSTR_usb21_enabled, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true}},
- {MP_QSTR_usb21_landing, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true}},
- };
- mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)] = {0};
- mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args),
- allowed_args, vals);
-
- const mp_int_t device_class = vals[0].u_int;
- const mp_int_t device_subclass = vals[1].u_int;
- const mp_int_t device_protocol = vals[2].u_int;
- const mp_int_t vendor_id = vals[3].u_int;
- const mp_int_t product_id = vals[4].u_int;
- const mp_int_t release_num = vals[5].u_int;
- const char *manufacturer = get_0str(vals[6].u_obj, 0, 32);
- const char *product = get_0str(vals[7].u_obj, 0, 32);
- const char *interface = get_0str(vals[8].u_obj, 0, 32);
- const secbool usb21_enabled = vals[9].u_bool ? sectrue : secfalse;
- const secbool usb21_landing = vals[10].u_bool ? sectrue : secfalse;
-
- CHECK_PARAM_RANGE(device_class, 0, 255)
- CHECK_PARAM_RANGE(device_subclass, 0, 255)
- CHECK_PARAM_RANGE(device_protocol, 0, 255)
- CHECK_PARAM_RANGE(vendor_id, 0, 65535)
- CHECK_PARAM_RANGE(product_id, 0, 65535)
- CHECK_PARAM_RANGE(release_num, 0, 65535)
- if (manufacturer == NULL) {
- mp_raise_ValueError(MP_ERROR_TEXT("manufacturer is invalid"));
- }
- if (product == NULL) {
- mp_raise_ValueError(MP_ERROR_TEXT("product is invalid"));
- }
- if (interface == NULL) {
- mp_raise_ValueError(MP_ERROR_TEXT("interface is invalid"));
- }
-
mp_obj_USB_t *o = m_new_obj_with_finaliser(mp_obj_USB_t);
o->base.type = type;
- o->state = USB_CLOSED;
-
- o->info.device_class = (uint8_t)(device_class);
- o->info.device_subclass = (uint8_t)(device_subclass);
- o->info.device_protocol = (uint8_t)(device_protocol);
- o->info.vendor_id = (uint16_t)(vendor_id);
- o->info.product_id = (uint16_t)(product_id);
- o->info.release_num = (uint16_t)(release_num);
- o->info.manufacturer = manufacturer;
- o->info.product = product;
- o->info.serial_number = NULL;
- o->info.interface = interface;
- o->info.usb21_enabled = usb21_enabled;
- o->info.usb21_landing = usb21_landing;
-
- mp_obj_list_init(&o->ifaces, 0);
-
return MP_OBJ_FROM_PTR(o);
}
-/// def add(self, iface: HID | VCP | WebUSB) -> None:
-/// """
-/// Registers passed interface into the USB stack.
-/// """
-STATIC mp_obj_t mod_trezorio_USB_add(mp_obj_t self, mp_obj_t iface) {
- mp_obj_USB_t *o = MP_OBJ_TO_PTR(self);
-
- if (o->state != USB_CLOSED) {
- mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("already initialized"));
- }
- mp_obj_list_append(MP_OBJ_FROM_PTR(&o->ifaces), iface);
-
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_USB_add_obj,
- mod_trezorio_USB_add);
-
/// def open(self, serial_number: str) -> None:
/// """
/// Initializes the USB stack.
/// """
STATIC mp_obj_t mod_trezorio_USB_open(mp_obj_t self,
mp_obj_t serial_number_obj) {
- mp_obj_USB_t *o = MP_OBJ_TO_PTR(self);
-
- if (o->state != USB_CLOSED) {
- mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("already initialized"));
- }
-
- const char *serial_number = get_0str(serial_number_obj, 0, 32);
+ const char *serial_number = get_0str(serial_number_obj, 0, USB_MAX_STR_SIZE);
if (serial_number == NULL) {
mp_raise_ValueError(MP_ERROR_TEXT("serial_number is invalid"));
}
- o->info.serial_number = serial_number;
-
- size_t iface_cnt = 0;
- mp_obj_t *iface_objs = NULL;
- mp_obj_get_array(MP_OBJ_FROM_PTR(&o->ifaces), &iface_cnt, &iface_objs);
-
- // Initialize the USB stack
- if (sectrue != usb_init(&o->info)) {
- mp_raise_msg(&mp_type_RuntimeError,
- MP_ERROR_TEXT("failed to initialize usb driver"));
- }
-
- int vcp_iface_num = -1;
- // Add all interfaces
- for (size_t i = 0; i < iface_cnt; i++) {
- mp_obj_t iface = iface_objs[i];
+ usb_start_params_t params = {
+ .serial_number = "",
+ .usb21_landing = secfalse,
+ };
- if (MP_OBJ_IS_TYPE(iface, &mod_trezorio_HID_type)) {
- mp_obj_HID_t *hid = MP_OBJ_TO_PTR(iface);
- if (sectrue != usb_hid_add(&hid->info)) {
- usb_deinit();
- mp_raise_msg(&mp_type_RuntimeError,
- MP_ERROR_TEXT("failed to add HID interface"));
- }
- } else if (MP_OBJ_IS_TYPE(iface, &mod_trezorio_WebUSB_type)) {
- mp_obj_WebUSB_t *webusb = MP_OBJ_TO_PTR(iface);
- if (sectrue != usb_webusb_add(&webusb->info)) {
- usb_deinit();
- mp_raise_msg(&mp_type_RuntimeError,
- MP_ERROR_TEXT("failed to add WebUSB interface"));
- }
- } else if (MP_OBJ_IS_TYPE(iface, &mod_trezorio_VCP_type)) {
- mp_obj_VCP_t *vcp = MP_OBJ_TO_PTR(iface);
- if (sectrue != usb_vcp_add(&vcp->info)) {
- usb_deinit();
- mp_raise_msg(&mp_type_RuntimeError,
- MP_ERROR_TEXT("failed to add VCP interface"));
- }
- vcp_iface_num = vcp->info.iface_num;
- } else {
- usb_deinit();
- mp_raise_TypeError(MP_ERROR_TEXT("expected HID, WebUSB or VCP type"));
- }
- }
+ strncpy(params.serial_number, serial_number, USB_MAX_STR_SIZE);
// Start the USB stack
- if (sectrue != usb_start()) {
- usb_deinit();
+ if (sectrue != usb_start(¶ms)) {
mp_raise_msg(&mp_type_RuntimeError,
MP_ERROR_TEXT("failed to start usb driver"));
}
- o->state = USB_OPENED;
-
- // If we found any VCP interfaces, use the last one for stdio,
- // otherwise disable the stdio support
- mp_hal_set_vcp_iface(vcp_iface_num);
return mp_const_none;
}
@@ -251,40 +89,20 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_USB_open_obj,
/// Cleans up the USB stack.
/// """
STATIC mp_obj_t mod_trezorio_USB_close(mp_obj_t self) {
- mp_obj_USB_t *o = MP_OBJ_TO_PTR(self);
-
- if (o->state != USB_OPENED) {
- mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("not initialized"));
- }
- usb_deinit();
- mp_obj_list_set_len(MP_OBJ_FROM_PTR(&o->ifaces), 0);
- mp_seq_clear(o->ifaces.items, 0, o->ifaces.alloc, sizeof(*o->ifaces.items));
- o->info.vendor_id = 0;
- o->info.product_id = 0;
- o->info.release_num = 0;
- o->info.manufacturer = NULL;
- o->info.product = NULL;
- o->info.serial_number = NULL;
- o->state = USB_CLOSED;
-
+ usb_stop();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_USB_close_obj,
mod_trezorio_USB_close);
STATIC mp_obj_t mod_trezorio_USB___del__(mp_obj_t self) {
- mp_obj_USB_t *o = MP_OBJ_TO_PTR(self);
- if (o->state != USB_CLOSED) {
- usb_deinit();
- o->state = USB_CLOSED;
- }
+ usb_stop();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_USB___del___obj,
mod_trezorio_USB___del__);
STATIC const mp_rom_map_elem_t mod_trezorio_USB_locals_dict_table[] = {
- {MP_ROM_QSTR(MP_QSTR_add), MP_ROM_PTR(&mod_trezorio_USB_add_obj)},
{MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mod_trezorio_USB_open_obj)},
{MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mod_trezorio_USB_close_obj)},
{MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorio_USB___del___obj)},
diff --git a/core/embed/upymod/modtrezorio/modtrezorio-vcp.h b/core/embed/upymod/modtrezorio/modtrezorio-vcp.h
deleted file mode 100644
index fc9ae526..00000000
--- a/core/embed/upymod/modtrezorio/modtrezorio-vcp.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/// package: trezorio.__init__
-
-/// class VCP:
-/// """
-/// USB VCP interface configuration.
-/// """
-typedef struct _mp_obj_VCP_t {
- mp_obj_base_t base;
- usb_vcp_info_t info;
-} mp_obj_VCP_t;
-
-/// def __init__(
-/// self,
-/// iface_num: int,
-/// data_iface_num: int,
-/// ep_in: int,
-/// ep_out: int,
-/// ep_cmd: int,
-/// emu_port: int,
-/// ) -> None:
-/// """
-/// """
-STATIC mp_obj_t mod_trezorio_VCP_make_new(const mp_obj_type_t *type,
- size_t n_args, size_t n_kw,
- const mp_obj_t *args) {
- STATIC const mp_arg_t allowed_args[] = {
- {MP_QSTR_iface_num,
- MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
- {.u_int = 0}},
- {MP_QSTR_data_iface_num,
- MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
- {.u_int = 0}},
- {MP_QSTR_ep_in,
- MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
- {.u_int = 0}},
- {MP_QSTR_ep_out,
- MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
- {.u_int = 0}},
- {MP_QSTR_ep_cmd,
- MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
- {.u_int = 0}},
- {MP_QSTR_emu_port,
- MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
- {.u_int = 0}},
- };
- mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)] = {0};
- mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args),
- allowed_args, vals);
-
- const mp_int_t iface_num = vals[0].u_int;
- const mp_int_t data_iface_num = vals[1].u_int;
- const mp_int_t ep_in = vals[2].u_int;
- const mp_int_t ep_out = vals[3].u_int;
- const mp_int_t ep_cmd = vals[4].u_int;
- const mp_int_t emu_port = vals[5].u_int;
-
- CHECK_PARAM_RANGE(iface_num, 0, 32)
- CHECK_PARAM_RANGE(data_iface_num, 0, 32)
- CHECK_PARAM_RANGE(ep_in, 0, 255)
- CHECK_PARAM_RANGE(ep_out, 0, 255)
- CHECK_PARAM_RANGE(ep_cmd, 0, 255)
- CHECK_PARAM_RANGE(emu_port, 0, 65535)
-
- const size_t vcp_buffer_len = 1024;
- const size_t vcp_packet_len = 64;
-
- mp_obj_VCP_t *o = mp_obj_malloc(mp_obj_VCP_t, type);
-
- o->info.tx_packet = m_new(uint8_t, vcp_packet_len);
- o->info.tx_buffer = m_new(uint8_t, vcp_buffer_len);
- o->info.rx_packet = m_new(uint8_t, vcp_packet_len);
- o->info.rx_buffer = m_new(uint8_t, vcp_buffer_len);
- o->info.tx_buffer_len = vcp_buffer_len;
- o->info.rx_buffer_len = vcp_buffer_len;
- o->info.rx_intr_fn = NULL;
- o->info.rx_intr_byte = 3; // Ctrl-C
- o->info.iface_num = (uint8_t)(iface_num);
- o->info.data_iface_num = (uint8_t)(data_iface_num);
-#ifdef TREZOR_EMULATOR
- o->info.emu_port = (uint16_t)(emu_port);
-#else
- o->info.ep_cmd = (uint8_t)(ep_cmd);
- o->info.ep_in = (uint8_t)(ep_in);
- o->info.ep_out = (uint8_t)(ep_out);
-#endif
- o->info.polling_interval = 10;
- o->info.max_packet_len = (uint8_t)(vcp_packet_len);
-
- return MP_OBJ_FROM_PTR(o);
-}
-
-/// def iface_num(self) -> int:
-/// """
-/// Returns the configured number of this interface.
-/// """
-STATIC mp_obj_t mod_trezorio_VCP_iface_num(mp_obj_t self) {
- mp_obj_VCP_t *o = MP_OBJ_TO_PTR(self);
- return MP_OBJ_NEW_SMALL_INT(o->info.iface_num);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_VCP_iface_num_obj,
- mod_trezorio_VCP_iface_num);
-
-STATIC const mp_rom_map_elem_t mod_trezorio_VCP_locals_dict_table[] = {
- {MP_ROM_QSTR(MP_QSTR_iface_num),
- MP_ROM_PTR(&mod_trezorio_VCP_iface_num_obj)},
-};
-STATIC MP_DEFINE_CONST_DICT(mod_trezorio_VCP_locals_dict,
- mod_trezorio_VCP_locals_dict_table);
-
-STATIC const mp_obj_type_t mod_trezorio_VCP_type = {
- {&mp_type_type},
- .name = MP_QSTR_VCP,
- .make_new = mod_trezorio_VCP_make_new,
- .locals_dict = (void *)&mod_trezorio_VCP_locals_dict,
-};
diff --git a/core/embed/upymod/modtrezorio/modtrezorio-webusb.h b/core/embed/upymod/modtrezorio/modtrezorio-webusb.h
deleted file mode 100644
index ed1f3075..00000000
--- a/core/embed/upymod/modtrezorio/modtrezorio-webusb.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/// package: trezorio.__init__
-
-/// class WebUSB:
-/// """
-/// USB WebUSB interface configuration.
-/// """
-typedef struct _mp_obj_WebUSB_t {
- mp_obj_base_t base;
- usb_webusb_info_t info;
-} mp_obj_WebUSB_t;
-
-/// def __init__(
-/// self,
-/// iface_num: int,
-/// ep_in: int,
-/// ep_out: int,
-/// emu_port: int,
-/// subclass: int = 0,
-/// protocol: int = 0,
-/// polling_interval: int = 1,
-/// max_packet_len: int = 64,
-/// ) -> None:
-/// """
-/// """
-STATIC mp_obj_t mod_trezorio_WebUSB_make_new(const mp_obj_type_t *type,
- size_t n_args, size_t n_kw,
- const mp_obj_t *args) {
- STATIC const mp_arg_t allowed_args[] = {
- {MP_QSTR_iface_num,
- MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
- {.u_int = 0}},
- {MP_QSTR_ep_in,
- MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
- {.u_int = 0}},
- {MP_QSTR_ep_out,
- MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
- {.u_int = 0}},
- {MP_QSTR_emu_port,
- MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
- {.u_int = 0}},
- {MP_QSTR_subclass, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}},
- {MP_QSTR_protocol, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}},
- {MP_QSTR_polling_interval, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1}},
- {MP_QSTR_max_packet_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64}},
- };
- mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)] = {0};
- mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args),
- allowed_args, vals);
-
- const mp_int_t iface_num = vals[0].u_int;
- const mp_int_t ep_in = vals[1].u_int;
- const mp_int_t ep_out = vals[2].u_int;
- const mp_int_t emu_port = vals[3].u_int;
- const mp_int_t subclass = vals[4].u_int;
- const mp_int_t protocol = vals[5].u_int;
- const mp_int_t polling_interval = vals[6].u_int;
- const mp_int_t max_packet_len = vals[7].u_int;
-
- CHECK_PARAM_RANGE(iface_num, 0, 32)
- CHECK_PARAM_RANGE(ep_in, 0, 255)
- CHECK_PARAM_RANGE(ep_out, 0, 255)
- CHECK_PARAM_RANGE(emu_port, 0, 65535)
- CHECK_PARAM_RANGE(subclass, 0, 255)
- CHECK_PARAM_RANGE(protocol, 0, 255)
- CHECK_PARAM_RANGE(polling_interval, 1, 255)
- CHECK_PARAM_RANGE(max_packet_len, 64, 64)
-
- mp_obj_WebUSB_t *o = mp_obj_malloc(mp_obj_WebUSB_t, type);
-
- o->info.rx_buffer = m_new(uint8_t, max_packet_len);
- o->info.iface_num = (uint8_t)(iface_num);
-#ifdef TREZOR_EMULATOR
- o->info.emu_port = (uint16_t)(emu_port);
-#else
- o->info.ep_in = (uint8_t)(ep_in);
- o->info.ep_out = (uint8_t)(ep_out);
-#endif
- o->info.subclass = (uint8_t)(subclass);
- o->info.protocol = (uint8_t)(protocol);
- o->info.polling_interval = (uint8_t)(polling_interval);
- o->info.max_packet_len = (uint8_t)(max_packet_len);
-
- return MP_OBJ_FROM_PTR(o);
-}
-
-/// def iface_num(self) -> int:
-/// """
-/// Returns the configured number of this interface.
-/// """
-STATIC mp_obj_t mod_trezorio_WebUSB_iface_num(mp_obj_t self) {
- mp_obj_WebUSB_t *o = MP_OBJ_TO_PTR(self);
- return MP_OBJ_NEW_SMALL_INT(o->info.iface_num);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_WebUSB_iface_num_obj,
- mod_trezorio_WebUSB_iface_num);
-
-/// def write(self, msg: bytes) -> int:
-/// """
-/// Sends message using USB WebUSB (device) or UDP (emulator).
-/// """
-STATIC mp_obj_t mod_trezorio_WebUSB_write(mp_obj_t self, mp_obj_t msg) {
- mp_obj_WebUSB_t *o = MP_OBJ_TO_PTR(self);
- mp_buffer_info_t buf = {0};
- mp_get_buffer_raise(msg, &buf, MP_BUFFER_READ);
-
- if (buf.len != USB_PACKET_LEN) {
- mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Invalid buffer length"));
- }
-
- ssize_t r = usb_webusb_write(o->info.iface_num, buf.buf, buf.len);
-
- if (r != buf.len) {
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Write failed"));
- }
-
- return MP_OBJ_NEW_SMALL_INT(r);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_WebUSB_write_obj,
- mod_trezorio_WebUSB_write);
-
-/// def read(self, buf: bytearray, offset: int = 0) -> int:
-/// """
-/// Reads message using USB WebUSB (device) or UDP (emulator).
-/// """
-STATIC mp_obj_t mod_trezorio_WebUSB_read(size_t n_args, const mp_obj_t *args) {
- mp_obj_WebUSB_t *o = MP_OBJ_TO_PTR(args[0]);
- mp_buffer_info_t buf = {0};
- mp_get_buffer_raise(args[1], &buf, MP_BUFFER_WRITE);
-
- int offset = 0;
- if (n_args >= 2) {
- offset = mp_obj_get_int(args[2]);
- }
-
- if (offset < 0) {
- mp_raise_ValueError(MP_ERROR_TEXT("Negative offset not allowed"));
- }
-
- if (offset > buf.len) {
- mp_raise_ValueError(MP_ERROR_TEXT("Offset out of bounds"));
- }
-
- uint32_t buffer_space = buf.len - offset;
-
- if (buffer_space < USB_PACKET_LEN) {
- mp_raise_ValueError(MP_ERROR_TEXT("Buffer too small"));
- }
-
- ssize_t r = usb_webusb_read(o->info.iface_num, &((uint8_t *)buf.buf)[offset],
- USB_PACKET_LEN);
-
- if (r != USB_PACKET_LEN) {
- mp_raise_msg(&mp_type_RuntimeError,
- MP_ERROR_TEXT("Unexpected read length"));
- }
-
- return MP_OBJ_NEW_SMALL_INT(r);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorio_WebUSB_read_obj, 2, 3,
- mod_trezorio_WebUSB_read);
-
-/// RX_PACKET_LEN: ClassVar[int]
-/// """Length of one USB RX packet."""
-
-/// TX_PACKET_LEN: ClassVar[int]
-/// """Length of one USB TX packet."""
-
-STATIC const mp_rom_map_elem_t mod_trezorio_WebUSB_locals_dict_table[] = {
- {MP_ROM_QSTR(MP_QSTR_iface_num),
- MP_ROM_PTR(&mod_trezorio_WebUSB_iface_num_obj)},
- {MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mod_trezorio_WebUSB_write_obj)},
- {MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mod_trezorio_WebUSB_read_obj)},
- {MP_ROM_QSTR(MP_QSTR_RX_PACKET_LEN), MP_ROM_INT(USB_PACKET_LEN)},
- {MP_ROM_QSTR(MP_QSTR_TX_PACKET_LEN), MP_ROM_INT(USB_PACKET_LEN)},
-};
-STATIC MP_DEFINE_CONST_DICT(mod_trezorio_WebUSB_locals_dict,
- mod_trezorio_WebUSB_locals_dict_table);
-
-STATIC const mp_obj_type_t mod_trezorio_WebUSB_type = {
- {&mp_type_type},
- .name = MP_QSTR_WebUSB,
- .make_new = mod_trezorio_WebUSB_make_new,
- .locals_dict = (void *)&mod_trezorio_WebUSB_locals_dict,
-};
diff --git a/core/embed/upymod/modtrezorio/modtrezorio.c b/core/embed/upymod/modtrezorio/modtrezorio.c
index 479a58a4..48435ec2 100644
--- a/core/embed/upymod/modtrezorio/modtrezorio.c
+++ b/core/embed/upymod/modtrezorio/modtrezorio.c
@@ -46,11 +46,9 @@ uint32_t last_touch_sample_time = 0;
}
// clang-format off
-#include "modtrezorio-hid.h"
#include "modtrezorio-poll.h"
-#include "modtrezorio-vcp.h"
-#include "modtrezorio-webusb.h"
#include "modtrezorio-usb.h"
+#include "modtrezorio-usb-if.h"
// clang-format on
#ifdef USE_SD_CARD
#include "modtrezorio-fatfs.h"
@@ -90,7 +88,10 @@ uint32_t last_touch_sample_time = 0;
/// USB_EVENT: int # interface id for USB events
-/// WireInterface = Union[HID, WebUSB, BleInterface]
+/// WireInterface = Union[USBIF, BleInterface]
+/// USBIF_WIRE: int # interface id of the USB wire interface
+/// USBIF_DEBUG: int # interface id of the USB debug interface
+/// USBIF_WEBAUTHN: int # interface id of the USB WebAuthn
STATIC const mp_rom_map_elem_t mp_module_trezorio_globals_table[] = {
{MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_trezorio)},
@@ -130,9 +131,10 @@ STATIC const mp_rom_map_elem_t mp_module_trezorio_globals_table[] = {
#endif
{MP_ROM_QSTR(MP_QSTR_USB), MP_ROM_PTR(&mod_trezorio_USB_type)},
- {MP_ROM_QSTR(MP_QSTR_HID), MP_ROM_PTR(&mod_trezorio_HID_type)},
- {MP_ROM_QSTR(MP_QSTR_VCP), MP_ROM_PTR(&mod_trezorio_VCP_type)},
- {MP_ROM_QSTR(MP_QSTR_WebUSB), MP_ROM_PTR(&mod_trezorio_WebUSB_type)},
+ {MP_ROM_QSTR(MP_QSTR_USBIF), MP_ROM_PTR(&mod_trezorio_USBIF_type)},
+ {MP_ROM_QSTR(MP_QSTR_USBIF_WIRE), MP_ROM_INT(SYSHANDLE_USB_WIRE)},
+ {MP_ROM_QSTR(MP_QSTR_USBIF_DEBUG), MP_ROM_INT(SYSHANDLE_USB_DEBUG)},
+ {MP_ROM_QSTR(MP_QSTR_USBIF_WEBAUTHN), MP_ROM_INT(SYSHANDLE_USB_WEBAUTHN)},
{MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&mod_trezorio_poll_obj)},
{MP_ROM_QSTR(MP_QSTR_POLL_READ), MP_ROM_INT(POLL_READ)},
diff --git a/core/embed/upymod/modtrezorutils/modtrezorutils-meminfo.h b/core/embed/upymod/modtrezorutils/modtrezorutils-meminfo.h
index 98ad80d6..d632fa80 100644
--- a/core/embed/upymod/modtrezorutils/modtrezorutils-meminfo.h
+++ b/core/embed/upymod/modtrezorutils/modtrezorutils-meminfo.h
@@ -307,27 +307,10 @@ typedef struct _mp_obj_closure_t {
extern const mp_obj_type_t mp_type_bound_meth;
extern const mp_obj_type_t mp_type_closure;
extern const mp_obj_type_t mp_type_cell;
-extern const mp_obj_type_t mod_trezorio_WebUSB_type;
extern const mp_obj_type_t mod_trezorio_USB_type;
-extern const mp_obj_type_t mod_trezorio_VCP_type;
-extern const mp_obj_type_t mod_trezorio_HID_type;
+extern const mp_obj_type_t mod_trezorio_USBIF_type;
extern const mp_obj_type_t mod_trezorui_Display_type;
-typedef struct _mp_obj_WebUSB_t {
- mp_obj_base_t base;
- usb_webusb_info_t info;
-} mp_obj_WebUSB_t;
-
-typedef struct _mp_obj_VCP_t {
- mp_obj_base_t base;
- usb_vcp_info_t info;
-} mp_obj_VCP_t;
-
-typedef struct _mp_obj_HID_t {
- mp_obj_base_t base;
- usb_hid_info_t info;
-} mp_obj_HID_t;
-
typedef struct _mp_obj_protomsg_t {
mp_obj_base_t base;
mp_map_t map;
@@ -496,36 +479,6 @@ void dump_set(FILE *out, const mp_obj_set_t *set) {
}
}
-void dump_trezor_hid(FILE *out, const mp_obj_HID_t *hid) {
- print_type(out, "trezor-hid", NULL, hid, false);
- fprintf(out, ",\n\"rx_buffer\": \"%p\"},\n", hid->info.rx_buffer);
- print_type(out, "rawbuffer", NULL, hid->info.rx_buffer, true);
- fprintf(out, ",\n");
-}
-
-void dump_trezor_webusb(FILE *out, const mp_obj_WebUSB_t *webusb) {
- print_type(out, "trezor-webusb", NULL, webusb, false);
- fprintf(out, ",\n\"rx_buffer\": \"%p\"},\n", webusb->info.rx_buffer);
- print_type(out, "rawbuffer", NULL, webusb->info.rx_buffer, true);
- fprintf(out, ",\n");
-}
-
-void dump_trezor_vcp(FILE *out, const mp_obj_VCP_t *vcp) {
- print_type(out, "trezor-vcp", NULL, vcp, false);
- fprintf(out, ",\n\"tx_packet\": \"%p\"", vcp->info.tx_packet);
- fprintf(out, ",\n\"tx_buffer\": \"%p\"", vcp->info.tx_buffer);
- fprintf(out, ",\n\"rx_packet\": \"%p\"", vcp->info.rx_packet);
- fprintf(out, ",\n\"rx_buffer\": \"%p\"},\n", vcp->info.rx_buffer);
- print_type(out, "rawbuffer", NULL, vcp->info.tx_packet, true);
- fprintf(out, ",\n");
- print_type(out, "rawbuffer", NULL, vcp->info.tx_buffer, true);
- fprintf(out, ",\n");
- print_type(out, "rawbuffer", NULL, vcp->info.rx_packet, true);
- fprintf(out, ",\n");
- print_type(out, "rawbuffer", NULL, vcp->info.rx_buffer, true);
- fprintf(out, ",\n");
-}
-
void dump_protomsg(FILE *out, const mp_obj_protomsg_t *value) {
mp_obj_t name[2] = {MP_OBJ_NULL, MP_OBJ_NULL};
mp_obj_type_t *type = protobuf_debug_msg_type();
@@ -654,19 +607,8 @@ void dump_value_opt(FILE *out, mp_const_obj_t value, bool eval_short) {
dump_generator(out, value);
}
- else if (mp_obj_is_type(value, &mod_trezorio_WebUSB_type)) {
- dump_trezor_webusb(out, value);
- }
-
- else if (mp_obj_is_type(value, &mod_trezorio_VCP_type)) {
- dump_trezor_vcp(out, value);
- }
-
- else if (mp_obj_is_type(value, &mod_trezorio_HID_type)) {
- dump_trezor_hid(out, value);
- }
-
else if (mp_obj_is_type(value, &mod_trezorio_USB_type) ||
+ mp_obj_is_type(value, &mod_trezorio_USBIF_type) ||
mp_obj_is_type(value, &mod_trezorui_Display_type)) {
print_type(out, "trezor", NULL, value, true);
fprintf(out, ",\n");
diff --git a/core/mocks/generated/trezorio/__init__.pyi b/core/mocks/generated/trezorio/__init__.pyi
index 1c136e10..6b54e610 100644
--- a/core/mocks/generated/trezorio/__init__.pyi
+++ b/core/mocks/generated/trezorio/__init__.pyi
@@ -1,52 +1,6 @@
from typing import *
-# upymod/modtrezorio/modtrezorio-hid.h
-class HID:
- """
- USB HID interface configuration.
- """
-
- def __init__(
- self,
- iface_num: int,
- ep_in: int,
- ep_out: int,
- emu_port: int,
- report_desc: bytes,
- subclass: int = 0,
- protocol: int = 0,
- polling_interval: int = 1,
- max_packet_len: int = 64,
- ) -> None:
- """
- """
-
- def iface_num(self) -> int:
- """
- Returns the configured number of this interface.
- """
-
- def write(self, msg: bytes) -> int:
- """
- Sends message using USB HID (device) or UDP (emulator).
- """
-
- def read(self, buf: bytearray, offset: int = 0) -> int:
- """
- Reads message using USB HID (device) or UDP (emulator).
- """
-
- def write_blocking(self, msg: bytes, timeout_ms: int) -> int:
- """
- Sends message using USB HID (device) or UDP (emulator).
- """
- RX_PACKET_LEN: ClassVar[int]
- """Length of one USB RX packet."""
- TX_PACKET_LEN: ClassVar[int]
- """Length of one USB TX packet."""
-
-
# upymod/modtrezorio/modtrezorio-poll.h
def poll(ifaces: Iterable[int], list_ref: list, timeout_ms: int) -> bool:
"""
@@ -65,107 +19,65 @@ def poll(ifaces: Iterable[int], list_ref: list, timeout_ms: int) -> bool:
"""
-# upymod/modtrezorio/modtrezorio-usb.h
-class USB:
+# upymod/modtrezorio/modtrezorio-usb-if.h
+class USBIF:
"""
- USB device configuration.
+ USB USBIF interface configuration.
"""
def __init__(
self,
- vendor_id: int,
- product_id: int,
- release_num: int,
- device_class: int = 0,
- device_subclass: int = 0,
- device_protocol: int = 0,
- manufacturer: str = "",
- product: str = "",
- interface: str = "",
- usb21_enabled: bool = True,
- usb21_landing: bool = True,
+ handle: int,
) -> None:
"""
"""
- def add(self, iface: HID | VCP | WebUSB) -> None:
- """
- Registers passed interface into the USB stack.
- """
-
- def open(self, serial_number: str) -> None:
+ def iface_num(self) -> int:
"""
- Initializes the USB stack.
+ Returns the configured number of this interface.
"""
- def close(self) -> None:
+ def write(self, msg: bytes) -> int:
"""
- Cleans up the USB stack.
+ Sends message using USB interface.
"""
-
-# upymod/modtrezorio/modtrezorio-vcp.h
-class VCP:
- """
- USB VCP interface configuration.
- """
-
- def __init__(
- self,
- iface_num: int,
- data_iface_num: int,
- ep_in: int,
- ep_out: int,
- ep_cmd: int,
- emu_port: int,
- ) -> None:
+ def write_blocking(self, msg: bytes, timeout_ms: int) -> int:
"""
+ Sends message using USB interface.
"""
- def iface_num(self) -> int:
+ def read(self, buf: bytearray, offset: int = 0) -> int:
"""
- Returns the configured number of this interface.
+ Reads message using USB interface
"""
+ RX_PACKET_LEN: ClassVar[int]
+ """Length of one USB RX packet."""
+ TX_PACKET_LEN: ClassVar[int]
+ """Length of one USB TX packet."""
-# upymod/modtrezorio/modtrezorio-webusb.h
-class WebUSB:
+# upymod/modtrezorio/modtrezorio-usb.h
+class USB:
"""
- USB WebUSB interface configuration.
+ USB device configuration.
"""
def __init__(
self,
- iface_num: int,
- ep_in: int,
- ep_out: int,
- emu_port: int,
- subclass: int = 0,
- protocol: int = 0,
- polling_interval: int = 1,
- max_packet_len: int = 64,
) -> None:
"""
"""
- def iface_num(self) -> int:
- """
- Returns the configured number of this interface.
- """
-
- def write(self, msg: bytes) -> int:
+ def open(self, serial_number: str) -> None:
"""
- Sends message using USB WebUSB (device) or UDP (emulator).
+ Initializes the USB stack.
"""
- def read(self, buf: bytearray, offset: int = 0) -> int:
+ def close(self) -> None:
"""
- Reads message using USB WebUSB (device) or UDP (emulator).
+ Cleans up the USB stack.
"""
- RX_PACKET_LEN: ClassVar[int]
- """Length of one USB RX packet."""
- TX_PACKET_LEN: ClassVar[int]
- """Length of one USB TX packet."""
from . import fatfs, haptic, sdcard, ble, pm, rgb_led
POLL_READ: int # wait until interface is readable and return read data
POLL_WRITE: int # wait until interface is writable
@@ -185,4 +97,7 @@ BUTTON_RELEASED: int # button up event
BUTTON_LEFT: int # button number of left button
BUTTON_RIGHT: int # button number of right button
USB_EVENT: int # interface id for USB events
-WireInterface = Union[HID, WebUSB, BleInterface]
+WireInterface = Union[USBIF, BleInterface]
+USBIF_WIRE: int # interface id of the USB wire interface
+USBIF_DEBUG: int # interface id of the USB debug interface
+USBIF_WEBAUTHN: int # interface id of the USB WebAuthn
diff --git a/core/site_scons/models/D001/discovery.py b/core/site_scons/models/D001/discovery.py
index 2721bf04..ef147666 100644
--- a/core/site_scons/models/D001/discovery.py
+++ b/core/site_scons/models/D001/discovery.py
@@ -18,7 +18,9 @@ def configure(
mcu = "STM32F429xx"
- stm32f4_common_files(env, defines, sources, paths)
+ features_available += stm32f4_common_files(
+ env, features_wanted, defines, sources, paths
+ )
env.get("ENV")[
"CPU_ASFLAGS"
@@ -84,22 +86,6 @@ def configure(
("USE_I2C", "1"),
]
- if "usb" in features_wanted:
- sources += [
- "embed/io/usb/stm32/usb_class_hid.c",
- "embed/io/usb/stm32/usb_class_vcp.c",
- "embed/io/usb/stm32/usb_class_webusb.c",
- "embed/io/usb/stm32/usb.c",
- "embed/io/usb/stm32/usbd_conf.c",
- "embed/io/usb/stm32/usbd_core.c",
- "embed/io/usb/stm32/usbd_ctlreq.c",
- "embed/io/usb/stm32/usbd_ioreq.c",
- "vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c",
- ]
- features_available.append("usb")
- paths += ["embed/io/usb/inc"]
- defines += [("USE_USB", "1")]
-
defines += [("USE_PVD", "1")]
return features_available
diff --git a/core/site_scons/models/D002/discovery2.py b/core/site_scons/models/D002/discovery2.py
index 1aada31a..74d4d5b4 100644
--- a/core/site_scons/models/D002/discovery2.py
+++ b/core/site_scons/models/D002/discovery2.py
@@ -20,7 +20,9 @@ def configure(
linker_script = """embed/sys/linker/stm32u5g/{target}.ld"""
memory_layout = "memory.ld"
- stm32u5_common_files(env, features_wanted, defines, sources, paths)
+ features_available += stm32u5_common_files(
+ env, features_wanted, defines, sources, paths
+ )
env.get("ENV")[
"CPU_ASFLAGS"
@@ -86,22 +88,6 @@ def configure(
("USE_I2C", "1"),
]
- if "usb" in features_wanted:
- sources += [
- "embed/io/usb/stm32/usb_class_hid.c",
- "embed/io/usb/stm32/usb_class_vcp.c",
- "embed/io/usb/stm32/usb_class_webusb.c",
- "embed/io/usb/stm32/usb.c",
- "embed/io/usb/stm32/usbd_conf.c",
- "embed/io/usb/stm32/usbd_core.c",
- "embed/io/usb/stm32/usbd_ctlreq.c",
- "embed/io/usb/stm32/usbd_ioreq.c",
- "vendor/stm32u5xx_hal_driver/Src/stm32u5xx_ll_usb.c",
- ]
- features_available.append("usb")
- paths += ["embed/io/usb/inc"]
- defines += [("USE_USB", "1")]
-
defines += [
"FRAMEBUFFER",
"DISPLAY_RGBA8888",
diff --git a/core/site_scons/models/T2B1/emulator.py b/core/site_scons/models/T2B1/emulator.py
index e955a37a..150ff854 100644
--- a/core/site_scons/models/T2B1/emulator.py
+++ b/core/site_scons/models/T2B1/emulator.py
@@ -18,7 +18,9 @@ def configure(
hw_revision = 0
mcu = "STM32F427xx"
- unix_common_files(env, defines, sources, paths)
+ features_available += unix_common_files(
+ env, features_wanted, defines, sources, paths
+ )
defines += [
"FRAMEBUFFER",
diff --git a/core/site_scons/models/T2B1/trezor_r_v10.py b/core/site_scons/models/T2B1/trezor_r_v10.py
index 39fab83b..47d14444 100644
--- a/core/site_scons/models/T2B1/trezor_r_v10.py
+++ b/core/site_scons/models/T2B1/trezor_r_v10.py
@@ -27,7 +27,9 @@ def configure(
mcu = "STM32F427xx"
- stm32f4_common_files(env, defines, sources, paths)
+ features_available += stm32f4_common_files(
+ env, features_wanted, defines, sources, paths
+ )
env.get("ENV")[
"CPU_ASFLAGS"
@@ -72,22 +74,6 @@ def configure(
paths += ["embed/sec/consumption_mask/inc"]
defines += [("USE_CONSUMPTION_MASK", "1")]
- if "usb" in features_wanted:
- sources += [
- "embed/io/usb/stm32/usb_class_hid.c",
- "embed/io/usb/stm32/usb_class_vcp.c",
- "embed/io/usb/stm32/usb_class_webusb.c",
- "embed/io/usb/stm32/usb.c",
- "embed/io/usb/stm32/usbd_conf.c",
- "embed/io/usb/stm32/usbd_core.c",
- "embed/io/usb/stm32/usbd_ctlreq.c",
- "embed/io/usb/stm32/usbd_ioreq.c",
- "vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c",
- ]
- features_available.append("usb")
- paths += ["embed/io/usb/inc"]
- defines += [("USE_USB", "1")]
-
if "optiga" in features_wanted:
sources += ["embed/io/i2c_bus/stm32f4/i2c_bus.c"]
sources += ["embed/sec/optiga/stm32/optiga_hal.c"]
diff --git a/core/site_scons/models/T2T1/emulator.py b/core/site_scons/models/T2T1/emulator.py
index 73bf2bc6..9cca37bd 100644
--- a/core/site_scons/models/T2T1/emulator.py
+++ b/core/site_scons/models/T2T1/emulator.py
@@ -18,7 +18,9 @@ def configure(
hw_revision = 0
mcu = "STM32F427xx"
- unix_common_files(env, defines, sources, paths)
+ features_available += unix_common_files(
+ env, features_wanted, defines, sources, paths
+ )
features_available.append("display_rgb565")
defines += [
diff --git a/core/site_scons/models/T2T1/trezor_t.py b/core/site_scons/models/T2T1/trezor_t.py
index cbc0c950..5eec1654 100644
--- a/core/site_scons/models/T2T1/trezor_t.py
+++ b/core/site_scons/models/T2T1/trezor_t.py
@@ -26,7 +26,9 @@ def configure(
mcu = "STM32F427xx"
- stm32f4_common_files(env, defines, sources, paths)
+ features_available += stm32f4_common_files(
+ env, features_wanted, defines, sources, paths
+ )
env.get("ENV")[
"CPU_ASFLAGS"
@@ -89,22 +91,6 @@ def configure(
features_available.append("sbu")
defines += [("USE_SBU", "1")]
- if "usb" in features_wanted:
- sources += [
- "embed/io/usb/stm32/usb_class_hid.c",
- "embed/io/usb/stm32/usb_class_vcp.c",
- "embed/io/usb/stm32/usb_class_webusb.c",
- "embed/io/usb/stm32/usb.c",
- "embed/io/usb/stm32/usbd_conf.c",
- "embed/io/usb/stm32/usbd_core.c",
- "embed/io/usb/stm32/usbd_ctlreq.c",
- "embed/io/usb/stm32/usbd_ioreq.c",
- "vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c",
- ]
- features_available.append("usb")
- paths += ["embed/io/usb/inc"]
- defines += [("USE_USB", "1")]
-
if "dma2d" in features_wanted:
defines += ["USE_DMA2D"]
sources += ["embed/gfx/bitblt/stm32/dma2d_bitblt.c"]
diff --git a/core/site_scons/models/T3B1/emulator.py b/core/site_scons/models/T3B1/emulator.py
index 5fc5c8fd..e144cdb7 100644
--- a/core/site_scons/models/T3B1/emulator.py
+++ b/core/site_scons/models/T3B1/emulator.py
@@ -18,7 +18,9 @@ def configure(
hw_revision = 0
mcu = "STM32U585xx"
- unix_common_files(env, defines, sources, paths)
+ features_available += unix_common_files(
+ env, features_wanted, defines, sources, paths
+ )
defines += [
"FRAMEBUFFER",
diff --git a/core/site_scons/models/T3B1/trezor_t3b1_revB.py b/core/site_scons/models/T3B1/trezor_t3b1_revB.py
index 7c2e4fde..7b96d7b8 100644
--- a/core/site_scons/models/T3B1/trezor_t3b1_revB.py
+++ b/core/site_scons/models/T3B1/trezor_t3b1_revB.py
@@ -29,7 +29,9 @@ def configure(
linker_script = """embed/sys/linker/stm32u58/{target}.ld"""
memory_layout = "memory.ld"
- stm32u5_common_files(env, features_wanted, defines, sources, paths)
+ features_available += stm32u5_common_files(
+ env, features_wanted, defines, sources, paths
+ )
env.get("ENV")[
"CPU_ASFLAGS"
@@ -64,22 +66,6 @@ def configure(
features_available.append("sbu")
defines += [("USE_SBU", "1")]
- if "usb" in features_wanted:
- sources += [
- "embed/io/usb/stm32/usb_class_hid.c",
- "embed/io/usb/stm32/usb_class_vcp.c",
- "embed/io/usb/stm32/usb_class_webusb.c",
- "embed/io/usb/stm32/usb.c",
- "embed/io/usb/stm32/usbd_conf.c",
- "embed/io/usb/stm32/usbd_core.c",
- "embed/io/usb/stm32/usbd_ctlreq.c",
- "embed/io/usb/stm32/usbd_ioreq.c",
- "vendor/stm32u5xx_hal_driver/Src/stm32u5xx_ll_usb.c",
- ]
- features_available.append("usb")
- paths += ["embed/io/usb/inc"]
- defines += [("USE_USB", "1")]
-
if "optiga" in features_wanted:
sources += ["embed/io/i2c_bus/stm32u5/i2c_bus.c"]
sources += ["embed/sec/optiga/stm32/optiga_hal.c"]
diff --git a/core/site_scons/models/T3T1/emulator.py b/core/site_scons/models/T3T1/emulator.py
index 2b005959..cd757521 100644
--- a/core/site_scons/models/T3T1/emulator.py
+++ b/core/site_scons/models/T3T1/emulator.py
@@ -18,7 +18,9 @@ def configure(
hw_revision = 0
mcu = "STM32U585xx"
- unix_common_files(env, defines, sources, paths)
+ features_available += unix_common_files(
+ env, features_wanted, defines, sources, paths
+ )
features_available.append("framebuffer")
features_available.append("display_rgb565")
diff --git a/core/site_scons/models/T3T1/trezor_t3t1_revE.py b/core/site_scons/models/T3T1/trezor_t3t1_revE.py
index 0661d2e2..d103e397 100644
--- a/core/site_scons/models/T3T1/trezor_t3t1_revE.py
+++ b/core/site_scons/models/T3T1/trezor_t3t1_revE.py
@@ -31,7 +31,9 @@ def configure(
linker_script = """embed/sys/linker/stm32u58/{target}.ld"""
memory_layout = "memory.ld"
- stm32u5_common_files(env, features_wanted, defines, sources, paths)
+ features_available += stm32u5_common_files(
+ env, features_wanted, defines, sources, paths
+ )
env.get("ENV")[
"CPU_ASFLAGS"
@@ -102,22 +104,6 @@ def configure(
features_available.append("sbu")
defines += [("USE_SBU", "1")]
- if "usb" in features_wanted:
- sources += [
- "embed/io/usb/stm32/usb_class_hid.c",
- "embed/io/usb/stm32/usb_class_vcp.c",
- "embed/io/usb/stm32/usb_class_webusb.c",
- "embed/io/usb/stm32/usb.c",
- "embed/io/usb/stm32/usbd_conf.c",
- "embed/io/usb/stm32/usbd_core.c",
- "embed/io/usb/stm32/usbd_ctlreq.c",
- "embed/io/usb/stm32/usbd_ioreq.c",
- "vendor/stm32u5xx_hal_driver/Src/stm32u5xx_ll_usb.c",
- ]
- features_available.append("usb")
- paths += ["embed/io/usb/inc"]
- defines += [("USE_USB", "1")]
-
if "dma2d" in features_wanted:
defines += [("USE_DMA2D", "1")]
sources += ["embed/gfx/bitblt/stm32/dma2d_bitblt.c"]
diff --git a/core/site_scons/models/T3W1/emulator.py b/core/site_scons/models/T3W1/emulator.py
index 8b5afc1c..9ed196ef 100644
--- a/core/site_scons/models/T3W1/emulator.py
+++ b/core/site_scons/models/T3W1/emulator.py
@@ -18,7 +18,9 @@ def configure(
hw_revision = 0
mcu = "STM32U5G9xx"
- unix_common_files(env, defines, sources, paths)
+ features_available += unix_common_files(
+ env, features_wanted, defines, sources, paths
+ )
defines += [
"FRAMEBUFFER",
diff --git a/core/site_scons/models/T3W1/trezor_t3w1_revA.py b/core/site_scons/models/T3W1/trezor_t3w1_revA.py
index aff4c291..329c2b38 100644
--- a/core/site_scons/models/T3W1/trezor_t3w1_revA.py
+++ b/core/site_scons/models/T3W1/trezor_t3w1_revA.py
@@ -20,7 +20,9 @@ def configure(
linker_script = """embed/sys/linker/stm32u5g/{target}.ld"""
memory_layout = "memory.ld"
- stm32u5_common_files(env, features_wanted, defines, sources, paths)
+ features_available += stm32u5_common_files(
+ env, features_wanted, defines, sources, paths
+ )
env.get("ENV")[
"CPU_ASFLAGS"
@@ -233,22 +235,6 @@ def configure(
features_available.append("rgb_led")
defines += [("USE_RGB_LED", "1")]
- if "usb" in features_wanted:
- sources += [
- "embed/io/usb/stm32/usb_class_hid.c",
- "embed/io/usb/stm32/usb_class_vcp.c",
- "embed/io/usb/stm32/usb_class_webusb.c",
- "embed/io/usb/stm32/usb.c",
- "embed/io/usb/stm32/usbd_conf.c",
- "embed/io/usb/stm32/usbd_core.c",
- "embed/io/usb/stm32/usbd_ctlreq.c",
- "embed/io/usb/stm32/usbd_ioreq.c",
- "vendor/stm32u5xx_hal_driver/Src/stm32u5xx_ll_usb.c",
- ]
- features_available.append("usb")
- paths += ["embed/io/usb/inc"]
- defines += [("USE_USB", "1")]
-
defines += [
"FRAMEBUFFER",
"DISPLAY_RGBA8888",
diff --git a/core/site_scons/models/T3W1/trezor_t3w1_revB.py b/core/site_scons/models/T3W1/trezor_t3w1_revB.py
index a11fed29..6c0625bb 100644
--- a/core/site_scons/models/T3W1/trezor_t3w1_revB.py
+++ b/core/site_scons/models/T3W1/trezor_t3w1_revB.py
@@ -20,7 +20,9 @@ def configure(
linker_script = """embed/sys/linker/stm32u5g/{target}.ld"""
memory_layout = "memory.ld"
- stm32u5_common_files(env, features_wanted, defines, sources, paths)
+ features_available += stm32u5_common_files(
+ env, features_wanted, defines, sources, paths
+ )
env.get("ENV")[
"CPU_ASFLAGS"
@@ -234,22 +236,6 @@ def configure(
features_available.append("rgb_led")
defines += [("USE_RGB_LED", "1")]
- if "usb" in features_wanted:
- sources += [
- "embed/io/usb/stm32/usb_class_hid.c",
- "embed/io/usb/stm32/usb_class_vcp.c",
- "embed/io/usb/stm32/usb_class_webusb.c",
- "embed/io/usb/stm32/usb.c",
- "embed/io/usb/stm32/usbd_conf.c",
- "embed/io/usb/stm32/usbd_core.c",
- "embed/io/usb/stm32/usbd_ctlreq.c",
- "embed/io/usb/stm32/usbd_ioreq.c",
- "vendor/stm32u5xx_hal_driver/Src/stm32u5xx_ll_usb.c",
- ]
- features_available.append("usb")
- paths += ["embed/io/usb/inc"]
- defines += [("USE_USB", "1")]
-
if "hw_revision" in features_wanted:
defines += [("USE_HW_REVISION", "1")]
paths += ["embed/util/hw_revision/inc"]
diff --git a/core/site_scons/models/T3W1/trezor_t3w1_revC.py b/core/site_scons/models/T3W1/trezor_t3w1_revC.py
index 1b1feda5..f901e5d0 100644
--- a/core/site_scons/models/T3W1/trezor_t3w1_revC.py
+++ b/core/site_scons/models/T3W1/trezor_t3w1_revC.py
@@ -20,7 +20,9 @@ def configure(
linker_script = """embed/sys/linker/stm32u5g/{target}.ld"""
memory_layout = "memory.ld"
- stm32u5_common_files(env, features_wanted, defines, sources, paths)
+ features_available += stm32u5_common_files(
+ env, features_wanted, defines, sources, paths
+ )
env.get("ENV")[
"CPU_ASFLAGS"
@@ -233,22 +235,6 @@ def configure(
features_available.append("rgb_led")
defines += [("USE_RGB_LED", "1")]
- if "usb" in features_wanted:
- sources += [
- "embed/io/usb/stm32/usb_class_hid.c",
- "embed/io/usb/stm32/usb_class_vcp.c",
- "embed/io/usb/stm32/usb_class_webusb.c",
- "embed/io/usb/stm32/usb.c",
- "embed/io/usb/stm32/usbd_conf.c",
- "embed/io/usb/stm32/usbd_core.c",
- "embed/io/usb/stm32/usbd_ctlreq.c",
- "embed/io/usb/stm32/usbd_ioreq.c",
- "vendor/stm32u5xx_hal_driver/Src/stm32u5xx_ll_usb.c",
- ]
- features_available.append("usb")
- paths += ["embed/io/usb/inc"]
- defines += [("USE_USB", "1")]
-
if "hw_revision" in features_wanted:
defines += [("USE_HW_REVISION", "1")]
paths += ["embed/util/hw_revision/inc"]
diff --git a/core/site_scons/models/stm32f4_common.py b/core/site_scons/models/stm32f4_common.py
index c6b7238d..e7cea83a 100644
--- a/core/site_scons/models/stm32f4_common.py
+++ b/core/site_scons/models/stm32f4_common.py
@@ -1,7 +1,9 @@
from __future__ import annotations
-def stm32f4_common_files(env, defines, sources, paths):
+def stm32f4_common_files(env, features_wanted, defines, sources, paths):
+ features_available: list[str] = []
+
defines += [
("STM32_HAL_H", "<stm32f4xx.h>"),
("FLASH_BLOCK_WORDS", "1"),
@@ -104,6 +106,34 @@ def stm32f4_common_files(env, defines, sources, paths):
"embed/util/unit_properties/stm32/unit_properties.c",
]
+ if "usb" in features_wanted:
+ sources += [
+ "embed/io/usb/stm32/usb_class_hid.c",
+ "embed/io/usb/stm32/usb_class_vcp.c",
+ "embed/io/usb/stm32/usb_class_webusb.c",
+ "embed/io/usb/stm32/usb.c",
+ "embed/io/usb/stm32/usbd_conf.c",
+ "embed/io/usb/stm32/usbd_core.c",
+ "embed/io/usb/stm32/usbd_ctlreq.c",
+ "embed/io/usb/stm32/usbd_ioreq.c",
+ "embed/io/usb/usb_config.c",
+ "vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c",
+ ]
+ features_available.append("usb")
+ paths += ["embed/io/usb/inc"]
+ defines += [("USE_USB", "1")]
+
+ if "usb_iface_wire" in features_wanted:
+ defines += [("USE_USB_IFACE_WIRE", "1")]
+ if "usb_iface_debug" in features_wanted:
+ defines += [("USE_USB_IFACE_DEBUG", "1")]
+ if "usb_iface_webauthn" in features_wanted:
+ defines += [("USE_USB_IFACE_WEBAUTHN", "1")]
+ if "usb_iface_vcp" in features_wanted:
+ defines += [("USE_USB_IFACE_VCP", "1")]
+
env.get("ENV")["SUFFIX"] = "stm32f4"
env.get("ENV")["LINKER_SCRIPT"] = """embed/sys/linker/stm32f4/{target}.ld"""
env.get("ENV")["MEMORY_LAYOUT"] = "memory.ld"
+
+ return features_available
diff --git a/core/site_scons/models/stm32u5_common.py b/core/site_scons/models/stm32u5_common.py
index a8697252..cb402033 100644
--- a/core/site_scons/models/stm32u5_common.py
+++ b/core/site_scons/models/stm32u5_common.py
@@ -2,6 +2,8 @@ from __future__ import annotations
def stm32u5_common_files(env, features_wanted, defines, sources, paths):
+ features_available: list[str] = []
+
defines += [
("STM32_HAL_H", "<stm32u5xx.h>"),
("FLASH_BLOCK_WORDS", "4"),
@@ -133,4 +135,33 @@ def stm32u5_common_files(env, features_wanted, defines, sources, paths):
if "applet" in features_wanted:
sources += ["embed/sys/task/stm32/applet.c"]
+ if "usb" in features_wanted:
+ sources += [
+ "embed/io/usb/stm32/usb_class_hid.c",
+ "embed/io/usb/stm32/usb_class_vcp.c",
+ "embed/io/usb/stm32/usb_class_webusb.c",
+ "embed/io/usb/stm32/usb.c",
+ "embed/io/usb/stm32/usbd_conf.c",
+ "embed/io/usb/stm32/usbd_core.c",
+ "embed/io/usb/stm32/usbd_ctlreq.c",
+ "embed/io/usb/stm32/usbd_ioreq.c",
+ "embed/io/usb/usb_config.c",
+ "vendor/stm32u5xx_hal_driver/Src/stm32u5xx_ll_usb.c",
+ ]
+
+ features_available.append("usb")
+ paths += ["embed/io/usb/inc"]
+ defines += [("USE_USB", "1")]
+
+ if "usb_iface_wire" in features_wanted:
+ defines += [("USE_USB_IFACE_WIRE", "1")]
+ if "usb_iface_debug" in features_wanted:
+ defines += [("USE_USB_IFACE_DEBUG", "1")]
+ if "usb_iface_webauthn" in features_wanted:
+ defines += [("USE_USB_IFACE_WEBAUTHN", "1")]
+ if "usb_iface_vcp" in features_wanted:
+ defines += [("USE_USB_IFACE_VCP", "1")]
+
env.get("ENV")["SUFFIX"] = "stm32u5"
+
+ return features_available
diff --git a/core/site_scons/models/unix_common.py b/core/site_scons/models/unix_common.py
index e875d6fb..7567058f 100644
--- a/core/site_scons/models/unix_common.py
+++ b/core/site_scons/models/unix_common.py
@@ -1,7 +1,9 @@
from __future__ import annotations
-def unix_common_files(env, defines, sources, paths):
+def unix_common_files(env, features_wanted, defines, sources, paths):
+ features_available: list[str] = []
+
defines += [
("FLASH_BLOCK_WORDS", "1"),
("FLASH_BIT_ACCESS", "1"),
@@ -10,7 +12,6 @@ def unix_common_files(env, defines, sources, paths):
paths += [
"embed/io/display/inc",
- "embed/io/usb/inc",
"embed/sec/random_delays/inc",
"embed/sec/time_estimate/inc",
"embed/sys/bsp/inc",
@@ -31,7 +32,6 @@ def unix_common_files(env, defines, sources, paths):
sources += [
"embed/io/display/unix/display_driver.c",
- "embed/io/usb/unix/usb.c",
"embed/sec/random_delays/unix/random_delays.c",
"embed/sec/secret/unix/secret.c",
"embed/sec/secret/unix/secret_keys.c",
@@ -54,3 +54,23 @@ def unix_common_files(env, defines, sources, paths):
"embed/util/fwutils/fwutils.c",
"embed/util/unit_properties/unix/unit_properties.c",
]
+
+ if "usb" in features_wanted:
+ sources += [
+ "embed/io/usb/unix/usb.c",
+ "embed/io/usb/usb_config.c",
+ ]
+ features_available.append("usb")
+ paths += ["embed/io/usb/inc"]
+ defines += [("USE_USB", "1")]
+
+ if "usb_iface_wire" in features_wanted:
+ defines += [("USE_USB_IFACE_WIRE", "1")]
+ if "usb_iface_debug" in features_wanted:
+ defines += [("USE_USB_IFACE_DEBUG", "1")]
+ if "usb_iface_webauthn" in features_wanted:
+ defines += [("USE_USB_IFACE_WEBAUTHN", "1")]
+ if "usb_iface_vcp" in features_wanted:
+ defines += [("USE_USB_IFACE_VCP", "1")]
+
+ return features_available
diff --git a/core/src/apps/webauthn/fido2.py b/core/src/apps/webauthn/fido2.py
index b55f5628..864878fe 100644
--- a/core/src/apps/webauthn/fido2.py
+++ b/core/src/apps/webauthn/fido2.py
@@ -22,7 +22,7 @@ if TYPE_CHECKING:
from .credential import U2fCredential
- HID = io.HID
+ HID = io.USBIF
_CID_BROADCAST = const(0xFFFF_FFFF) # broadcast channel id
diff --git a/core/src/usb.py b/core/src/usb.py
index cd60dcb6..ebb10590 100644
--- a/core/src/usb.py
+++ b/core/src/usb.py
@@ -1,107 +1,9 @@
-from micropython import const
-
from trezor import io, utils
-bus = io.USB(
- vendor_id=0x1209,
- product_id=0x53C1,
- release_num=0x0200,
- manufacturer=utils.MODEL_USB_MANUFACTURER,
- product=utils.MODEL_USB_PRODUCT,
- interface="TREZOR Interface",
- usb21_landing=False,
-)
-
-UDP_PORT = 0
-_WIRE_PORT_OFFSET = const(0)
-_DEBUGLINK_PORT_OFFSET = const(1)
-_WEBAUTHN_PORT_OFFSET = const(2)
-_VCP_PORT_OFFSET = const(3)
-
-if utils.EMULATOR:
- import uos
-
- UDP_PORT = int(uos.getenv("TREZOR_UDP_PORT") or "21324")
-
-_iface_iter = iter(range(5))
+bus = io.USB()
-ENABLE_IFACE_DEBUG = __debug__
ENABLE_IFACE_WEBAUTHN = not utils.BITCOIN_ONLY
-ENABLE_IFACE_VCP = __debug__ and not utils.EMULATOR
-
-# interface used for trezor wire protocol
-id_wire = next(_iface_iter)
-iface_wire = io.WebUSB(
- iface_num=id_wire,
- ep_in=0x01 + id_wire,
- ep_out=0x01 + id_wire,
- emu_port=UDP_PORT + _WIRE_PORT_OFFSET,
-)
-bus.add(iface_wire)
-
-# XXXXXXXXXXXXXXXXXXX
-#
-# We want the following branches present only in their respective firmwares. To achieve
-# that, we are taking advantage of the upy compiler static optimization: when an
-# if-expression statically evaluates to False, the branch is excluded from the bytecode.
-# This works magically for the __debug__ builtin, and `utils.BITCOIN_ONLY` is replaced
-# by a literal True/False by us in the build step.
-#
-# Therefore, each of the following needs to include the respective static expression
-# so that it can be correctly excluded from the resulting build.
-
-if __debug__ and ENABLE_IFACE_DEBUG:
- # interface used for debug messages with trezor wire protocol
- id_debug = next(_iface_iter)
- iface_debug = io.WebUSB(
- iface_num=id_debug,
- ep_in=0x01 + id_debug,
- ep_out=0x01 + id_debug,
- emu_port=UDP_PORT + _DEBUGLINK_PORT_OFFSET,
- )
- bus.add(iface_debug)
-
-if not utils.BITCOIN_ONLY and ENABLE_IFACE_WEBAUTHN:
- # interface used for FIDO/U2F and FIDO2/WebAuthn HID transport
- id_webauthn = next(_iface_iter)
- iface_webauthn = io.HID(
- iface_num=id_webauthn,
- ep_in=0x01 + id_webauthn,
- ep_out=0x01 + id_webauthn,
- emu_port=UDP_PORT + _WEBAUTHN_PORT_OFFSET,
- # fmt: off
- report_desc=bytes([
- 0x06, 0xd0, 0xf1, # USAGE_PAGE (FIDO Alliance)
- 0x09, 0x01, # USAGE (U2F HID Authenticator Device)
- 0xa1, 0x01, # COLLECTION (Application)
- 0x09, 0x20, # USAGE (Input Report Data)
- 0x15, 0x00, # LOGICAL_MINIMUM (0)
- 0x26, 0xff, 0x00, # LOGICAL_MAXIMUM (255)
- 0x75, 0x08, # REPORT_SIZE (8)
- 0x95, 0x40, # REPORT_COUNT (64)
- 0x81, 0x02, # INPUT (Data,Var,Abs)
- 0x09, 0x21, # USAGE (Output Report Data)
- 0x15, 0x00, # LOGICAL_MINIMUM (0)
- 0x26, 0xff, 0x00, # LOGICAL_MAXIMUM (255)
- 0x75, 0x08, # REPORT_SIZE (8)
- 0x95, 0x40, # REPORT_COUNT (64)
- 0x91, 0x02, # OUTPUT (Data,Var,Abs)
- 0xc0, # END_COLLECTION
- ]),
- # fmt: on
- )
- bus.add(iface_webauthn)
-if __debug__ and ENABLE_IFACE_VCP:
- # interface used for cdc/vcp console emulation (debug messages)
- id_vcp = next(_iface_iter)
- id_vcp_data = next(_iface_iter)
- iface_vcp = io.VCP(
- iface_num=id_vcp,
- data_iface_num=id_vcp_data,
- ep_in=0x01 + id_vcp,
- ep_out=0x01 + id_vcp,
- ep_cmd=0x01 + id_vcp_data,
- emu_port=UDP_PORT + _VCP_PORT_OFFSET,
- )
- bus.add(iface_vcp)
+iface_wire = io.USBIF(handle=io.USBIF_WIRE)
+iface_debug = io.USBIF(handle=io.USBIF_DEBUG)
+iface_webauthn = io.USBIF(handle=io.USBIF_WEBAUTHN)
Why this scored 34/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.