1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-03-03 08:46:05 +00:00

refactor(core/embed): refactor usb driver

[no changelog]
This commit is contained in:
cepetr 2024-05-29 10:22:54 +02:00 committed by cepetr
parent 8e429b0352
commit 0bc1d1f706
26 changed files with 944 additions and 683 deletions

View File

@ -112,8 +112,8 @@ static void usb_init_all(secbool usb21_landing) {
#ifdef TREZOR_EMULATOR
.emu_port = 21324,
#else
.ep_in = USB_EP_DIR_IN | 0x01,
.ep_out = USB_EP_DIR_OUT | 0x01,
.ep_in = 0x01,
.ep_out = 0x01,
#endif
.subclass = 0,
.protocol = 0,

View File

@ -69,8 +69,8 @@ static void usb_init_all(secbool usb21_landing) {
static const usb_webusb_info_t webusb_info = {
.iface_num = USB_IFACE_NUM,
.ep_in = USB_EP_DIR_IN | 0x01,
.ep_out = USB_EP_DIR_OUT | 0x01,
.ep_in = 0x01,
.ep_out = 0x01,
.subclass = 0,
.protocol = 0,
.max_packet_len = sizeof(rx_buffer),

View File

@ -148,8 +148,8 @@ static void usb_init_all(void) {
.rx_intr_byte = 3, // Ctrl-C
.iface_num = VCP_IFACE,
.data_iface_num = 0x01,
.ep_cmd = 0x82,
.ep_in = 0x81,
.ep_cmd = 0x02,
.ep_in = 0x01,
.ep_out = 0x01,
.polling_interval = 10,
.max_packet_len = VCP_PACKET_LEN,

View File

@ -19,10 +19,12 @@
#include STM32_HAL_H
#include "usb.h"
#include "common.h"
#include "random_delays.h"
#include "secbool.h"
#include "usb.h"
#include "usbd_core.h"
#include "usbd_internal.h"
#define USB_MAX_CONFIG_DESC_SIZE 256
#define USB_MAX_STR_SIZE 62
@ -38,39 +40,49 @@
#error Unable to determine proper USB_PHY_ID to use
#endif
#define USB_WINUSB_VENDOR_CODE \
'!' // arbitrary, but must be equivalent to the last character in extra
// string
#define USB_WINUSB_EXTRA_STRING \
'M', 0x00, 'S', 0x00, 'F', 0x00, 'T', 0x00, '1', 0x00, '0', 0x00, '0', 0x00, \
USB_WINUSB_VENDOR_CODE, 0x00 // MSFT100!
#define USB_WINUSB_EXTRA_STRING_INDEX 0xEE
#define USB_WINUSB_REQ_GET_COMPATIBLE_ID_FEATURE_DESCRIPTOR 0x04
#define USB_WINUSB_REQ_GET_EXTENDED_PROPERTIES_OS_FEATURE_DESCRIPTOR 0x05
typedef struct {
const char *manufacturer;
const char *product;
const char *serial_number;
const char *interface;
} usb_dev_string_table_t;
#define UNCONST(X) ((uint8_t *)(X))
typedef struct {
// USB class dispatch table
const USBD_ClassTypeDef *class;
// Internal state for USB class driver
uint8_t state[USBD_CLASS_STATE_MAX_SIZE] __attribute__((aligned(8)));
} usb_iface_t;
static usb_device_descriptor_t usb_dev_desc;
typedef struct {
// Handle to the USB device (lower layer driver)
USBD_HandleTypeDef dev_handle;
// Device descriptor
usb_device_descriptor_t dev_desc;
// Device string descriptors
usb_dev_string_table_t str_table;
// Interfaces of registered class drivers
// (each class driver must add 1 or more interfaces)
usb_iface_t ifaces[USBD_MAX_NUM_INTERFACES];
// Buffer for configuration descriptor and additional descriptors
// (interface, endpoint, ..) added by registered class drivers
uint8_t desc_buffer[USB_MAX_CONFIG_DESC_SIZE] __attribute__((aligned(4)));
// Configuration descriptor (located at the beginning of the desc_buffer)
usb_config_descriptor_t *config_desc;
// Temporary buffer for unicode strings
uint8_t str_buf[USB_MAX_STR_DESC_SIZE] __attribute__((aligned(4)));
// Config descriptor
static uint8_t usb_config_buf[USB_MAX_CONFIG_DESC_SIZE]
__attribute__((aligned(4)));
static usb_config_descriptor_t *usb_config_desc =
(usb_config_descriptor_t *)(usb_config_buf);
static usb_interface_descriptor_t *usb_next_iface_desc;
secbool usb21_enabled;
secbool usb21_landing;
// String descriptor
static uint8_t usb_str_buf[USB_MAX_STR_DESC_SIZE] __attribute__((aligned(4)));
static usb_dev_string_table_t usb_str_table;
} usb_driver_t;
static usb_iface_t usb_ifaces[USBD_MAX_NUM_INTERFACES];
// USB driver instance
static usb_driver_t g_usb_driver;
static USBD_HandleTypeDef usb_dev_handle;
static const USBD_DescriptorsTypeDef usb_descriptors;
// forward declarations of dispatch functions
static const USBD_ClassTypeDef usb_class;
static secbool usb21_enabled = secfalse;
static secbool usb21_landing = secfalse;
static const USBD_DescriptorsTypeDef usb_descriptors;
static secbool __wur check_desc_str(const char *s) {
if (NULL == s) return secfalse;
@ -79,28 +91,30 @@ static secbool __wur check_desc_str(const char *s) {
}
void usb_init(const usb_dev_info_t *dev_info) {
usb_driver_t *usb = &g_usb_driver;
// enable/disable USB 2.1 features
usb21_enabled = dev_info->usb21_enabled;
usb21_landing = dev_info->usb21_landing;
usb->usb21_enabled = dev_info->usb21_enabled;
usb->usb21_landing = dev_info->usb21_landing;
// Device descriptor
usb_dev_desc.bLength = sizeof(usb_device_descriptor_t);
usb_dev_desc.bDescriptorType = USB_DESC_TYPE_DEVICE;
usb_dev_desc.bcdUSB =
(sectrue == usb21_enabled) ? 0x0210 : 0x0200; // USB 2.1 or USB 2.0
usb_dev_desc.bDeviceClass = dev_info->device_class;
usb_dev_desc.bDeviceSubClass = dev_info->device_subclass;
usb_dev_desc.bDeviceProtocol = dev_info->device_protocol;
usb_dev_desc.bMaxPacketSize0 = USB_MAX_EP0_SIZE;
usb_dev_desc.idVendor = dev_info->vendor_id;
usb_dev_desc.idProduct = dev_info->product_id;
usb_dev_desc.bcdDevice = dev_info->release_num;
usb_dev_desc.iManufacturer =
USBD_IDX_MFC_STR; // Index of manufacturer string
usb_dev_desc.iProduct = USBD_IDX_PRODUCT_STR; // Index of product string
usb_dev_desc.iSerialNumber =
usb->dev_desc.bLength = sizeof(usb_device_descriptor_t);
usb->dev_desc.bDescriptorType = USB_DESC_TYPE_DEVICE;
usb->dev_desc.bcdUSB =
(sectrue == usb->usb21_enabled) ? 0x0210 : 0x0200; // USB 2.1 or USB 2.0
usb->dev_desc.bDeviceClass = dev_info->device_class;
usb->dev_desc.bDeviceSubClass = dev_info->device_subclass;
usb->dev_desc.bDeviceProtocol = dev_info->device_protocol;
usb->dev_desc.bMaxPacketSize0 = USB_MAX_EP0_SIZE;
usb->dev_desc.idVendor = dev_info->vendor_id;
usb->dev_desc.idProduct = dev_info->product_id;
usb->dev_desc.bcdDevice = dev_info->release_num;
usb->dev_desc.iManufacturer =
USBD_IDX_MFC_STR; // Index of manufacturer string
usb->dev_desc.iProduct = USBD_IDX_PRODUCT_STR; // Index of product string
usb->dev_desc.iSerialNumber =
USBD_IDX_SERIAL_STR; // Index of serial number string
usb_dev_desc.bNumConfigurations = 1;
usb->dev_desc.bNumConfigurations = 1;
// String table
ensure(check_desc_str(dev_info->manufacturer), NULL);
@ -108,57 +122,66 @@ void usb_init(const usb_dev_info_t *dev_info) {
ensure(check_desc_str(dev_info->serial_number), NULL);
ensure(check_desc_str(dev_info->interface), NULL);
usb_str_table.manufacturer = dev_info->manufacturer;
usb_str_table.product = dev_info->product;
usb_str_table.serial_number = dev_info->serial_number;
usb_str_table.interface = dev_info->interface;
usb->str_table.manufacturer = dev_info->manufacturer;
usb->str_table.product = dev_info->product;
usb->str_table.serial_number = dev_info->serial_number;
usb->str_table.interface = dev_info->interface;
usb->config_desc = (usb_config_descriptor_t *)(usb->desc_buffer);
// Configuration descriptor
usb_config_desc->bLength = sizeof(usb_config_descriptor_t);
usb_config_desc->bDescriptorType = USB_DESC_TYPE_CONFIGURATION;
usb_config_desc->wTotalLength =
usb->config_desc->bLength = sizeof(usb_config_descriptor_t);
usb->config_desc->bDescriptorType = USB_DESC_TYPE_CONFIGURATION;
usb->config_desc->wTotalLength =
sizeof(usb_config_descriptor_t); // will be updated later via
// usb_desc_add_iface()
usb_config_desc->bNumInterfaces =
0; // will be updated later via usb_desc_add_iface()
usb_config_desc->bConfigurationValue = 0x01;
usb_config_desc->iConfiguration = 0;
usb_config_desc->bmAttributes =
0x80; // 0x80 = bus powered; 0xC0 = self powered
usb_config_desc->bMaxPower = 0x32; // Maximum Power Consumption in 2mA units
// Pointer to interface descriptor data
usb_next_iface_desc =
(usb_interface_descriptor_t *)(usb_config_buf +
usb_config_desc->wTotalLength);
// usb_alloc_class_descriptors()
usb->config_desc->bNumInterfaces =
0; // will be updated later via usb_set_iface_class()
usb->config_desc->bConfigurationValue = 0x01;
usb->config_desc->iConfiguration = 0;
usb->config_desc->bmAttributes =
0x80; // 0x80 = bus powered; 0xC0 = self powered
usb->config_desc->bMaxPower = 0x32; // Maximum Power Consumption in 2mA units
ensure(sectrue *
(USBD_OK == USBD_Init(&usb_dev_handle,
(USBD_OK == USBD_Init(&usb->dev_handle,
(USBD_DescriptorsTypeDef *)&usb_descriptors,
USB_PHY_ID)),
NULL);
ensure(sectrue *
(USBD_OK == USBD_RegisterClass(&usb_dev_handle,
(USBD_OK == USBD_RegisterClass(&usb->dev_handle,
(USBD_ClassTypeDef *)&usb_class)),
NULL);
}
void usb_deinit(void) {
USBD_DeInit(&usb_dev_handle);
usb_driver_t *usb = &g_usb_driver;
USBD_DeInit(&usb->dev_handle);
for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) {
usb_ifaces[i].type = USB_IFACE_TYPE_DISABLED;
usb->ifaces[i].class = NULL;
}
}
void usb_start(void) { USBD_Start(&usb_dev_handle); }
void usb_start(void) {
usb_driver_t *usb = &g_usb_driver;
void usb_stop(void) { USBD_Stop(&usb_dev_handle); }
USBD_Start(&usb->dev_handle);
}
void usb_stop(void) {
usb_driver_t *usb = &g_usb_driver;
USBD_Stop(&usb->dev_handle);
}
secbool usb_configured(void) {
usb_driver_t *usb = &g_usb_driver;
static uint32_t usb_configured_last_ok = 0;
uint32_t ticks = hal_ticks_ms();
const USBD_HandleTypeDef *pdev = &usb_dev_handle;
const USBD_HandleTypeDef *pdev = &usb->dev_handle;
if (pdev->dev_state == USBD_STATE_CONFIGURED) {
usb_configured_last_ok = hal_ticks_ms();
return sectrue;
@ -189,50 +212,65 @@ secbool usb_configured(void) {
return secfalse;
}
/*
* Utility functions for USB interfaces
*/
// ==========================================================================
// Utility functions for USB class drivers
// ==========================================================================
void *usb_get_iface_state(uint8_t iface_num, const USBD_ClassTypeDef *class) {
usb_driver_t *usb = &g_usb_driver;
static usb_iface_t *usb_get_iface(uint8_t iface_num) {
if (iface_num < USBD_MAX_NUM_INTERFACES) {
return &usb_ifaces[iface_num];
} else {
return NULL; // Invalid interface number
usb_iface_t *iface = &usb->ifaces[iface_num];
if (iface->class == class) {
return &iface->state;
}
}
// Invalid interface number or type
return NULL;
}
void usb_set_iface_class(uint8_t iface_num, const USBD_ClassTypeDef *class) {
usb_driver_t *usb = &g_usb_driver;
if (iface_num < USBD_MAX_NUM_INTERFACES) {
if (usb->ifaces[iface_num].class == NULL && class != NULL) {
usb->config_desc->bNumInterfaces++;
}
usb->ifaces[iface_num].class = class;
}
}
static void *usb_desc_alloc_iface(size_t desc_len) {
if (usb_config_desc->wTotalLength + desc_len < USB_MAX_CONFIG_DESC_SIZE) {
return usb_next_iface_desc;
USBD_HandleTypeDef *usb_get_dev_handle(void) {
usb_driver_t *usb = &g_usb_driver;
return &usb->dev_handle;
}
void *usb_alloc_class_descriptors(size_t desc_len) {
usb_driver_t *usb = &g_usb_driver;
if (usb->config_desc->wTotalLength + desc_len < USB_MAX_CONFIG_DESC_SIZE) {
void *retval = &usb->desc_buffer[usb->config_desc->wTotalLength];
usb->config_desc->wTotalLength += desc_len;
return retval;
} else {
return NULL; // Not enough space in the descriptor
}
}
static void usb_desc_add_iface(size_t desc_len) {
usb_config_desc->bNumInterfaces++;
usb_config_desc->wTotalLength += desc_len;
usb_next_iface_desc =
(usb_interface_descriptor_t *)(usb_config_buf +
usb_config_desc->wTotalLength);
}
/*
* USB interface implementations
*/
#include "usb_hid-impl.h"
#include "usb_vcp-impl.h"
#include "usb_webusb-impl.h"
/*
* USB configuration (device & string descriptors)
*/
// ==========================================================================
// USB configuration (device & string descriptors)
// ==========================================================================
static uint8_t *usb_get_dev_descriptor(USBD_SpeedTypeDef speed,
uint16_t *length) {
*length = sizeof(usb_dev_desc);
return (uint8_t *)(&usb_dev_desc);
usb_driver_t *usb = &g_usb_driver;
*length = sizeof(usb->dev_desc);
return (uint8_t *)(&usb->dev_desc);
}
static uint8_t *usb_get_langid_str_descriptor(USBD_SpeedTypeDef speed,
@ -248,37 +286,49 @@ static uint8_t *usb_get_langid_str_descriptor(USBD_SpeedTypeDef speed,
static uint8_t *usb_get_manufacturer_str_descriptor(USBD_SpeedTypeDef speed,
uint16_t *length) {
USBD_GetString((uint8_t *)usb_str_table.manufacturer, usb_str_buf, length);
return usb_str_buf;
usb_driver_t *usb = &g_usb_driver;
USBD_GetString((uint8_t *)usb->str_table.manufacturer, usb->str_buf, length);
return usb->str_buf;
}
static uint8_t *usb_get_product_str_descriptor(USBD_SpeedTypeDef speed,
uint16_t *length) {
USBD_GetString((uint8_t *)usb_str_table.product, usb_str_buf, length);
return usb_str_buf;
usb_driver_t *usb = &g_usb_driver;
USBD_GetString((uint8_t *)usb->str_table.product, usb->str_buf, length);
return usb->str_buf;
}
static uint8_t *usb_get_serial_str_descriptor(USBD_SpeedTypeDef speed,
uint16_t *length) {
USBD_GetString((uint8_t *)usb_str_table.serial_number, usb_str_buf, length);
return usb_str_buf;
usb_driver_t *usb = &g_usb_driver;
USBD_GetString((uint8_t *)usb->str_table.serial_number, usb->str_buf, length);
return usb->str_buf;
}
static uint8_t *usb_get_configuration_str_descriptor(USBD_SpeedTypeDef speed,
uint16_t *length) {
USBD_GetString((uint8_t *)"", usb_str_buf, length);
return usb_str_buf;
usb_driver_t *usb = &g_usb_driver;
USBD_GetString((uint8_t *)"", usb->str_buf, length);
return usb->str_buf;
}
static uint8_t *usb_get_interface_str_descriptor(USBD_SpeedTypeDef speed,
uint16_t *length) {
USBD_GetString((uint8_t *)usb_str_table.interface, usb_str_buf, length);
return usb_str_buf;
usb_driver_t *usb = &g_usb_driver;
USBD_GetString((uint8_t *)usb->str_table.interface, usb->str_buf, length);
return usb->str_buf;
}
static uint8_t *usb_get_bos_descriptor(USBD_SpeedTypeDef speed,
uint16_t *length) {
if (sectrue == usb21_enabled) {
usb_driver_t *usb = &g_usb_driver;
if (sectrue == usb->usb21_enabled) {
static uint8_t bos[] = {
// usb_bos_descriptor {
0x05, // uint8_t bLength
@ -298,7 +348,7 @@ static uint8_t *usb_get_bos_descriptor(USBD_SpeedTypeDef speed,
USB_WEBUSB_LANDING_PAGE, // uint8_t iLandingPage
// }
};
bos[28] = (sectrue == usb21_landing) ? USB_WEBUSB_LANDING_PAGE : 0;
bos[28] = (sectrue == usb->usb21_landing) ? USB_WEBUSB_LANDING_PAGE : 0;
*length = sizeof(bos);
return UNCONST(bos);
} else {
@ -318,45 +368,49 @@ static const USBD_DescriptorsTypeDef usb_descriptors = {
.GetBOSDescriptor = usb_get_bos_descriptor,
};
/*
* USB class (interface dispatch, configuration descriptor)
*/
// ==========================================================================
// USB class (interface dispatch, configuration descriptor)
// ==========================================================================
#define USB_WINUSB_VENDOR_CODE \
'!' // arbitrary, but must be equivalent to the last character in extra
// string
#define USB_WINUSB_EXTRA_STRING \
'M', 0x00, 'S', 0x00, 'F', 0x00, 'T', 0x00, '1', 0x00, '0', 0x00, '0', 0x00, \
USB_WINUSB_VENDOR_CODE, 0x00 // MSFT100!
#define USB_WINUSB_EXTRA_STRING_INDEX 0xEE
#define USB_WINUSB_REQ_GET_COMPATIBLE_ID_FEATURE_DESCRIPTOR 0x04
#define USB_WINUSB_REQ_GET_EXTENDED_PROPERTIES_OS_FEATURE_DESCRIPTOR 0x05
static uint8_t usb_class_init(USBD_HandleTypeDef *dev, uint8_t cfg_idx) {
usb_driver_t *usb = &g_usb_driver;
for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) {
switch (usb_ifaces[i].type) {
case USB_IFACE_TYPE_HID:
usb_hid_class_init(dev, &usb_ifaces[i].hid, cfg_idx);
break;
case USB_IFACE_TYPE_VCP:
usb_vcp_class_init(dev, &usb_ifaces[i].vcp, cfg_idx);
break;
case USB_IFACE_TYPE_WEBUSB:
usb_webusb_class_init(dev, &usb_ifaces[i].webusb, cfg_idx);
break;
default:
break;
usb_iface_t *iface = &usb->ifaces[i];
if (iface->class != NULL && iface->class->Init != NULL) {
dev->pUserData = iface->state;
iface->class->Init(dev, cfg_idx);
}
}
dev->pUserData = NULL;
return USBD_OK;
}
static uint8_t usb_class_deinit(USBD_HandleTypeDef *dev, uint8_t cfg_idx) {
usb_driver_t *usb = &g_usb_driver;
for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) {
switch (usb_ifaces[i].type) {
case USB_IFACE_TYPE_HID:
usb_hid_class_deinit(dev, &usb_ifaces[i].hid, cfg_idx);
break;
case USB_IFACE_TYPE_VCP:
usb_vcp_class_deinit(dev, &usb_ifaces[i].vcp, cfg_idx);
break;
case USB_IFACE_TYPE_WEBUSB:
usb_webusb_class_deinit(dev, &usb_ifaces[i].webusb, cfg_idx);
break;
default:
break;
usb_iface_t *iface = &usb->ifaces[i];
if (iface->class != NULL && iface->class->DeInit != NULL) {
dev->pUserData = iface->state;
iface->class->DeInit(dev, cfg_idx);
}
}
dev->pUserData = NULL;
return USBD_OK;
}
@ -367,6 +421,8 @@ static uint8_t usb_class_deinit(USBD_HandleTypeDef *dev, uint8_t cfg_idx) {
static uint8_t usb_class_setup(USBD_HandleTypeDef *dev,
USBD_SetupReqTypedef *req) {
usb_driver_t *usb = &g_usb_driver;
if (((req->bmRequest & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_CLASS) &&
((req->bmRequest & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_STANDARD) &&
((req->bmRequest & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_VENDOR)) {
@ -375,7 +431,8 @@ static uint8_t usb_class_setup(USBD_HandleTypeDef *dev,
if ((req->bmRequest & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_VENDOR) {
if ((req->bmRequest & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE) {
if (sectrue == usb21_enabled && req->bRequest == USB_WEBUSB_VENDOR_CODE) {
if (sectrue == usb->usb21_enabled &&
req->bRequest == USB_WEBUSB_VENDOR_CODE) {
if (req->wIndex == USB_WEBUSB_REQ_GET_URL &&
req->wValue == USB_WEBUSB_LANDING_PAGE) {
static const char webusb_url[] = {
@ -407,7 +464,7 @@ static uint8_t usb_class_setup(USBD_HandleTypeDef *dev,
USBD_CtlError(dev, req);
return USBD_FAIL;
}
} else if (sectrue == usb21_enabled &&
} else if (sectrue == usb->usb21_enabled &&
req->bRequest == USB_WINUSB_VENDOR_CODE) {
if (req->wIndex ==
USB_WINUSB_REQ_GET_COMPATIBLE_ID_FEATURE_DESCRIPTOR) {
@ -440,7 +497,8 @@ static uint8_t usb_class_setup(USBD_HandleTypeDef *dev,
}
if ((req->bmRequest & USB_REQ_RECIPIENT_MASK) ==
USB_REQ_RECIPIENT_INTERFACE) {
if (sectrue == usb21_enabled && req->bRequest == USB_WINUSB_VENDOR_CODE) {
if (sectrue == usb->usb21_enabled &&
req->bRequest == USB_WINUSB_VENDOR_CODE) {
if (req->wIndex ==
USB_WINUSB_REQ_GET_EXTENDED_PROPERTIES_OS_FEATURE_DESCRIPTOR &&
(req->wValue & 0xFF) == 0) { // reply only if interface is 0
@ -485,88 +543,89 @@ static uint8_t usb_class_setup(USBD_HandleTypeDef *dev,
USBD_CtlError(dev, req);
return USBD_FAIL;
}
switch (usb_ifaces[req->wIndex].type) {
case USB_IFACE_TYPE_HID:
return usb_hid_class_setup(dev, &usb_ifaces[req->wIndex].hid, req);
case USB_IFACE_TYPE_VCP:
return usb_vcp_class_setup(dev, &usb_ifaces[req->wIndex].vcp, req);
case USB_IFACE_TYPE_WEBUSB:
return usb_webusb_class_setup(dev, &usb_ifaces[req->wIndex].webusb,
req);
default:
wait_random();
USBD_CtlError(dev, req);
return USBD_FAIL;
usb_iface_t *iface = &usb->ifaces[req->wIndex];
if (iface->class != NULL && iface->class->Setup != NULL) {
dev->pUserData = iface->state;
iface->class->Setup(dev, req);
dev->pUserData = NULL;
} else {
wait_random();
USBD_CtlError(dev, req);
return USBD_FAIL;
}
}
return USBD_OK;
}
static uint8_t usb_class_data_in(USBD_HandleTypeDef *dev, uint8_t ep_num) {
usb_driver_t *usb = &g_usb_driver;
#ifdef RDI
rdi_refresh_session_delay();
#endif
for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) {
switch (usb_ifaces[i].type) {
case USB_IFACE_TYPE_HID:
usb_hid_class_data_in(dev, &usb_ifaces[i].hid, ep_num);
break;
case USB_IFACE_TYPE_VCP:
usb_vcp_class_data_in(dev, &usb_ifaces[i].vcp, ep_num);
break;
case USB_IFACE_TYPE_WEBUSB:
usb_webusb_class_data_in(dev, &usb_ifaces[i].webusb, ep_num);
break;
default:
break;
usb_iface_t *iface = &usb->ifaces[i];
if (iface->class != NULL && iface->class->DataIn != NULL) {
dev->pUserData = iface->state;
iface->class->DataIn(dev, ep_num);
}
}
dev->pUserData = NULL;
return USBD_OK;
}
static uint8_t usb_class_data_out(USBD_HandleTypeDef *dev, uint8_t ep_num) {
usb_driver_t *usb = &g_usb_driver;
#ifdef RDI
rdi_refresh_session_delay();
#endif
for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) {
switch (usb_ifaces[i].type) {
case USB_IFACE_TYPE_HID:
usb_hid_class_data_out(dev, &usb_ifaces[i].hid, ep_num);
break;
case USB_IFACE_TYPE_VCP:
usb_vcp_class_data_out(dev, &usb_ifaces[i].vcp, ep_num);
break;
case USB_IFACE_TYPE_WEBUSB:
usb_webusb_class_data_out(dev, &usb_ifaces[i].webusb, ep_num);
break;
default:
break;
usb_iface_t *iface = &usb->ifaces[i];
if (iface->class != NULL && iface->class->DataOut != NULL) {
dev->pUserData = iface->state;
iface->class->DataOut(dev, ep_num);
}
}
dev->pUserData = NULL;
return USBD_OK;
}
static uint8_t usb_class_sof(USBD_HandleTypeDef *dev) {
usb_driver_t *usb = &g_usb_driver;
for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) {
switch (usb_ifaces[i].type) {
case USB_IFACE_TYPE_VCP:
usb_vcp_class_sof(dev, &usb_ifaces[i].vcp);
break;
default:
break;
usb_iface_t *iface = &usb->ifaces[i];
if (iface->class != NULL && iface->class->SOF != NULL) {
dev->pUserData = iface->state;
iface->class->SOF(dev);
}
}
dev->pUserData = NULL;
return USBD_OK;
}
static uint8_t *usb_class_get_cfg_desc(uint16_t *length) {
*length = usb_config_desc->wTotalLength;
return usb_config_buf;
usb_driver_t *usb = &g_usb_driver;
*length = usb->config_desc->wTotalLength;
return usb->desc_buffer;
}
static uint8_t *usb_class_get_usrstr_desc(USBD_HandleTypeDef *dev,
uint8_t index, uint16_t *length) {
if (sectrue == usb21_enabled && index == USB_WINUSB_EXTRA_STRING_INDEX) {
usb_driver_t *usb = &g_usb_driver;
if (sectrue == usb->usb21_enabled && index == USB_WINUSB_EXTRA_STRING_INDEX) {
static const uint8_t winusb_string_descriptor[] = {
0x12, // bLength
USB_DESC_TYPE_STRING, // bDescriptorType

View File

@ -17,6 +17,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common.h"
#include "random_delays.h"
#include "usbd_core.h"
#include "usbd_internal.h"
#include "usb_hid.h"
#define USB_CLASS_HID 0x03
#define USB_DESC_TYPE_HID 0x21
@ -27,37 +35,81 @@
#define USB_HID_REQ_SET_IDLE 0x0A
#define USB_HID_REQ_GET_IDLE 0x02
typedef struct __attribute__((packed)) {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdHID;
uint8_t bCountryCode;
uint8_t bNumDescriptors;
uint8_t bReportDescriptorType;
uint16_t wReportDescriptorLength;
} usb_hid_descriptor_t;
typedef struct __attribute__((packed)) {
usb_interface_descriptor_t iface;
usb_hid_descriptor_t hid;
usb_endpoint_descriptor_t ep_in;
usb_endpoint_descriptor_t ep_out;
} usb_hid_descriptor_block_t;
/* usb_hid_state_t encapsulates all state used by enabled HID interface. It
* needs to be completely initialized in usb_hid_add and reset in
* usb_hid_class_init. See usb_hid_info_t for details of the configuration
* fields. */
typedef struct {
USBD_HandleTypeDef *dev_handle;
const usb_hid_descriptor_block_t *desc_block;
const uint8_t *report_desc;
uint8_t *rx_buffer;
uint8_t ep_in;
uint8_t ep_out;
uint8_t max_packet_len;
uint8_t report_desc_len;
uint8_t protocol; // For SET_PROTOCOL/GET_PROTOCOL setup reqs
uint8_t idle_rate; // For SET_IDLE/GET_IDLE setup reqs
uint8_t alt_setting; // For SET_INTERFACE/GET_INTERFACE setup reqs
uint8_t last_read_len; // Length of data read into rx_buffer
uint8_t ep_in_is_idle; // Set to 1 after IN endpoint gets idle
} usb_hid_state_t;
_Static_assert(sizeof(usb_hid_state_t) <= USBD_CLASS_STATE_MAX_SIZE);
// interface dispatch functions
static const USBD_ClassTypeDef usb_hid_class;
#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) {
usb_iface_t *iface = usb_get_iface(info->iface_num);
usb_hid_state_t *state = usb_get_iface_state(info->iface_num, NULL);
if (iface == NULL) {
if (state == NULL) {
return secfalse; // Invalid interface number
}
if (iface->type != USB_IFACE_TYPE_DISABLED) {
return secfalse; // Interface is already enabled
}
usb_hid_descriptor_block_t *d =
usb_desc_alloc_iface(sizeof(usb_hid_descriptor_block_t));
usb_alloc_class_descriptors(sizeof(usb_hid_descriptor_block_t));
if (d == NULL) {
return secfalse; // Not enough space in the configuration descriptor
}
if ((info->ep_in & USB_EP_DIR_MASK) != USB_EP_DIR_IN) {
return secfalse; // IN EP is invalid
}
if ((info->ep_out & USB_EP_DIR_MASK) != USB_EP_DIR_OUT) {
return secfalse; // OUT EP is invalid
}
if (info->rx_buffer == NULL) {
return secfalse;
}
if (info->report_desc == NULL) {
return secfalse;
}
if (info->ep_in >= USBD_MAX_NUM_INTERFACES) {
return secfalse;
}
if (info->ep_out >= USBD_MAX_NUM_INTERFACES) {
return secfalse;
}
// Interface descriptor
d->iface.bLength = sizeof(usb_interface_descriptor_t);
@ -82,7 +134,7 @@ secbool usb_hid_add(const usb_hid_info_t *info) {
// IN endpoint (sending)
d->ep_in.bLength = sizeof(usb_endpoint_descriptor_t);
d->ep_in.bDescriptorType = USB_DESC_TYPE_ENDPOINT;
d->ep_in.bEndpointAddress = info->ep_in;
d->ep_in.bEndpointAddress = info->ep_in | USB_EP_DIR_IN;
d->ep_in.bmAttributes = USBD_EP_TYPE_INTR;
d->ep_in.wMaxPacketSize = info->max_packet_len;
d->ep_in.bInterval = info->polling_interval;
@ -90,75 +142,67 @@ secbool usb_hid_add(const usb_hid_info_t *info) {
// OUT endpoint (receiving)
d->ep_out.bLength = sizeof(usb_endpoint_descriptor_t);
d->ep_out.bDescriptorType = USB_DESC_TYPE_ENDPOINT;
d->ep_out.bEndpointAddress = info->ep_out;
d->ep_out.bEndpointAddress = info->ep_out | USB_EP_DIR_OUT;
d->ep_out.bmAttributes = USBD_EP_TYPE_INTR;
d->ep_out.wMaxPacketSize = info->max_packet_len;
d->ep_out.bInterval = info->polling_interval;
// Config descriptor
usb_desc_add_iface(sizeof(usb_hid_descriptor_block_t));
// Interface state
iface->type = USB_IFACE_TYPE_HID;
iface->hid.desc_block = d;
iface->hid.report_desc = info->report_desc;
iface->hid.rx_buffer = info->rx_buffer;
iface->hid.ep_in = info->ep_in;
iface->hid.ep_out = info->ep_out;
iface->hid.max_packet_len = info->max_packet_len;
iface->hid.report_desc_len = info->report_desc_len;
iface->hid.protocol = 0;
iface->hid.idle_rate = 0;
iface->hid.alt_setting = 0;
iface->hid.last_read_len = 0;
iface->hid.ep_in_is_idle = 1;
state->dev_handle = usb_get_dev_handle();
state->desc_block = d;
state->report_desc = info->report_desc;
state->rx_buffer = info->rx_buffer;
state->ep_in = info->ep_in | USB_EP_DIR_IN;
state->ep_out = info->ep_out | USB_EP_DIR_OUT;
state->max_packet_len = info->max_packet_len;
state->report_desc_len = info->report_desc_len;
state->protocol = 0;
state->idle_rate = 0;
state->alt_setting = 0;
state->last_read_len = 0;
state->ep_in_is_idle = 1;
usb_set_iface_class(info->iface_num, &usb_hid_class);
return sectrue;
}
secbool usb_hid_can_read(uint8_t iface_num) {
usb_iface_t *iface = usb_get_iface(iface_num);
if (iface == NULL) {
usb_hid_state_t *state = usb_get_hid_state(iface_num);
if (state == NULL) {
return secfalse; // Invalid interface number
}
if (iface->type != USB_IFACE_TYPE_HID) {
return secfalse; // Invalid interface type
}
if (iface->hid.last_read_len == 0) {
if (state->last_read_len == 0) {
return secfalse; // Nothing in the receiving buffer
}
if (usb_dev_handle.dev_state != USBD_STATE_CONFIGURED) {
if (state->dev_handle->dev_state != USBD_STATE_CONFIGURED) {
return secfalse; // Device is not configured
}
return sectrue;
}
secbool usb_hid_can_write(uint8_t iface_num) {
usb_iface_t *iface = usb_get_iface(iface_num);
if (iface == NULL) {
usb_hid_state_t *state = usb_get_hid_state(iface_num);
if (state == NULL) {
return secfalse; // Invalid interface number
}
if (iface->type != USB_IFACE_TYPE_HID) {
return secfalse; // Invalid interface type
}
if (iface->hid.ep_in_is_idle == 0) {
if (state->ep_in_is_idle == 0) {
return secfalse; // Last transmission is not over yet
}
if (usb_dev_handle.dev_state != USBD_STATE_CONFIGURED) {
if (state->dev_handle->dev_state != USBD_STATE_CONFIGURED) {
return secfalse; // Device is not configured
}
return sectrue;
}
int usb_hid_read(uint8_t iface_num, uint8_t *buf, uint32_t len) {
usb_iface_t *iface = usb_get_iface(iface_num);
if (iface == NULL) {
volatile usb_hid_state_t *state = usb_get_hid_state(iface_num);
if (state == NULL) {
return -1; // Invalid interface number
}
if (iface->type != USB_IFACE_TYPE_HID) {
return -2; // Invalid interface type
}
volatile usb_hid_state_t *state = &iface->hid;
// Copy maximum possible amount of data
uint32_t last_read_len = state->last_read_len;
@ -171,28 +215,26 @@ int usb_hid_read(uint8_t iface_num, uint8_t *buf, uint32_t len) {
state->last_read_len = 0;
// Prepare the OUT EP to receive next packet
USBD_LL_PrepareReceive(&usb_dev_handle, state->ep_out, state->rx_buffer,
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) {
usb_iface_t *iface = usb_get_iface(iface_num);
if (iface == NULL) {
volatile usb_hid_state_t *state = usb_get_hid_state(iface_num);
if (state == NULL) {
return -1; // Invalid interface number
}
if (iface->type != USB_IFACE_TYPE_HID) {
return -2; // Invalid interface type
}
volatile usb_hid_state_t *state = &iface->hid;
if (state->ep_in_is_idle == 0) {
return 0; // Last transmission is not over yet
}
state->ep_in_is_idle = 0;
USBD_LL_Transmit(&usb_dev_handle, state->ep_in, UNCONST(buf), (uint16_t)len);
USBD_LL_Transmit(state->dev_handle, state->ep_in, UNCONST(buf),
(uint16_t)len);
return len;
}
@ -237,8 +279,9 @@ int usb_hid_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len,
return usb_hid_write(iface_num, buf, len);
}
static void usb_hid_class_init(USBD_HandleTypeDef *dev, usb_hid_state_t *state,
uint8_t cfg_idx) {
static uint8_t usb_hid_class_init(USBD_HandleTypeDef *dev, uint8_t cfg_idx) {
usb_hid_state_t *state = (usb_hid_state_t *)dev->pUserData;
// Open endpoints
USBD_LL_OpenEP(dev, state->ep_in, USBD_EP_TYPE_INTR, state->max_packet_len);
USBD_LL_OpenEP(dev, state->ep_out, USBD_EP_TYPE_INTR, state->max_packet_len);
@ -253,20 +296,27 @@ static void usb_hid_class_init(USBD_HandleTypeDef *dev, usb_hid_state_t *state,
// Prepare the OUT EP to receive next packet
USBD_LL_PrepareReceive(dev, state->ep_out, state->rx_buffer,
state->max_packet_len);
return USBD_OK;
}
static void usb_hid_class_deinit(USBD_HandleTypeDef *dev,
usb_hid_state_t *state, 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;
// Flush endpoints
USBD_LL_FlushEP(dev, state->ep_in);
USBD_LL_FlushEP(dev, state->ep_out);
// Close endpoints
USBD_LL_CloseEP(dev, state->ep_in);
USBD_LL_CloseEP(dev, state->ep_out);
return USBD_OK;
}
static int usb_hid_class_setup(USBD_HandleTypeDef *dev, usb_hid_state_t *state,
USBD_SetupReqTypedef *req) {
static uint8_t usb_hid_class_setup(USBD_HandleTypeDef *dev,
USBD_SetupReqTypedef *req) {
usb_hid_state_t *state = (usb_hid_state_t *)dev->pUserData;
wait_random();
switch (req->bmRequest & USB_REQ_TYPE_MASK) {
@ -339,20 +389,44 @@ static int usb_hid_class_setup(USBD_HandleTypeDef *dev, usb_hid_state_t *state,
return USBD_OK;
}
static void usb_hid_class_data_in(USBD_HandleTypeDef *dev,
usb_hid_state_t *state, uint8_t ep_num) {
static uint8_t usb_hid_class_data_in(USBD_HandleTypeDef *dev, uint8_t ep_num) {
usb_hid_state_t *state = (usb_hid_state_t *)dev->pUserData;
if ((ep_num | USB_EP_DIR_IN) == state->ep_in) {
wait_random();
state->ep_in_is_idle = 1;
}
return USBD_OK;
}
static void usb_hid_class_data_out(USBD_HandleTypeDef *dev,
usb_hid_state_t *state, uint8_t ep_num) {
static uint8_t usb_hid_class_data_out(USBD_HandleTypeDef *dev, uint8_t ep_num) {
usb_hid_state_t *state = (usb_hid_state_t *)dev->pUserData;
if (ep_num == state->ep_out) {
wait_random();
// Save the report length to indicate we have read something, but don't
// schedule next reading until user reads this one
state->last_read_len = USBD_LL_GetRxDataSize(dev, ep_num);
}
return USBD_OK;
}
static const USBD_ClassTypeDef usb_hid_class = {
.Init = usb_hid_class_init,
.DeInit = usb_hid_class_deinit,
.Setup = usb_hid_class_setup,
.EP0_TxSent = NULL,
.EP0_RxReady = NULL,
.DataIn = usb_hid_class_data_in,
.DataOut = usb_hid_class_data_out,
.SOF = NULL,
.IsoINIncomplete = NULL,
.IsoOUTIncomplete = NULL,
.GetHSConfigDescriptor = NULL,
.GetFSConfigDescriptor = NULL,
.GetOtherSpeedConfigDescriptor = NULL,
.GetDeviceQualifierDescriptor = NULL,
.GetUsrStrDescriptor = NULL,
};

View File

@ -17,6 +17,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common.h"
#include "usbd_core.h"
#include "usbd_internal.h"
#include "usb_vcp.h"
// Communications Device Class Code (bFunctionClass, bInterfaceClass)
#define USB_CLASS_CDC 0x02
@ -50,34 +57,129 @@
#define USB_CDC_GET_LINE_CODING 0x21
#define USB_CDC_SET_CONTROL_LINE_STATE 0x22
typedef struct __attribute__((packed)) {
uint8_t bFunctionLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint16_t bcdCDC;
} usb_vcp_header_descriptor_t;
typedef struct __attribute__((packed)) {
uint8_t bFunctionLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint8_t bmCapabilities;
uint8_t bDataInterface;
} usb_vcp_cm_descriptor_t;
typedef struct __attribute__((packed)) {
uint8_t bFunctionLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint8_t bmCapabilities;
} usb_vcp_acm_descriptor_t;
typedef struct __attribute__((packed)) {
uint8_t bFunctionLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint8_t bControlInterface;
uint8_t bSubordinateInterface0;
} usb_vcp_union_descriptor_t;
typedef struct __attribute__((packed)) {
usb_interface_assoc_descriptor_t assoc;
usb_interface_descriptor_t iface_cdc;
usb_vcp_header_descriptor_t
fheader; // Class-Specific Descriptor Header Format
usb_vcp_cm_descriptor_t fcm; // Call Management Functional Descriptor
usb_vcp_acm_descriptor_t
facm; // Abstract Control Management Functional Descriptor
usb_vcp_union_descriptor_t funion; // Union Interface Functional Descriptor
usb_endpoint_descriptor_t ep_cmd;
usb_interface_descriptor_t iface_data;
usb_endpoint_descriptor_t ep_in;
usb_endpoint_descriptor_t ep_out;
} usb_vcp_descriptor_block_t;
typedef struct __attribute__((packed)) {
uint32_t dwDTERate;
uint8_t bCharFormat; // usb_cdc_line_coding_bCharFormat_t
uint8_t bParityType; // usb_cdc_line_coding_bParityType_t
uint8_t bDataBits;
} usb_cdc_line_coding_t;
typedef enum {
USB_CDC_1_STOP_BITS = 0,
USB_CDC_1_5_STOP_BITS = 1,
USB_CDC_2_STOP_BITS = 2,
} usb_cdc_line_coding_bCharFormat_t;
typedef enum {
USB_CDC_NO_PARITY = 0,
USB_CDC_ODD_PARITY = 1,
USB_CDC_EVEN_PARITY = 2,
USB_CDC_MARK_PARITY = 3,
USB_CDC_SPACE_PARITY = 4,
} usb_cdc_line_coding_bParityType_t;
/* usb_rbuf_t is used internally for the RX/TX buffering. */
typedef struct {
size_t cap;
volatile size_t read;
volatile size_t write;
uint8_t *buf;
} usb_rbuf_t;
// Maximal length of packets on IN CMD EP
#define USB_CDC_MAX_CMD_PACKET_LEN 0x08
/* usb_vcp_state_t encapsulates all state used by enabled VCP interface. It
* needs to be completely initialized in usb_vcp_add and reset in
* usb_vcp_class_init. See usb_vcp_info_t for details of the configuration
* fields. */
typedef struct {
USBD_HandleTypeDef *dev_handle;
const usb_vcp_descriptor_block_t *desc_block;
usb_rbuf_t rx_ring;
usb_rbuf_t tx_ring;
uint8_t *rx_packet;
uint8_t *tx_packet;
void (*rx_intr_fn)(void);
uint8_t rx_intr_byte;
uint8_t ep_cmd;
uint8_t ep_in;
uint8_t ep_out;
uint8_t max_packet_len;
uint8_t ep_in_is_idle; // Set to 1 after IN endpoint gets idle
uint8_t cmd_buffer[USB_CDC_MAX_CMD_PACKET_LEN];
} usb_vcp_state_t;
_Static_assert(sizeof(usb_vcp_state_t) <= USBD_CLASS_STATE_MAX_SIZE);
// interface dispatch functions
static const USBD_ClassTypeDef usb_vcp_class;
static const USBD_ClassTypeDef usb_vcp_data_class;
#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) {
usb_iface_t *iface = usb_get_iface(info->iface_num);
usb_vcp_state_t *state = usb_get_iface_state(info->iface_num, NULL);
if (iface == NULL) {
if (state == NULL) {
return secfalse; // Invalid interface number
}
if (iface->type != USB_IFACE_TYPE_DISABLED) {
return secfalse; // Interface is already enabled
}
usb_vcp_descriptor_block_t *d =
usb_desc_alloc_iface(sizeof(usb_vcp_descriptor_block_t));
usb_alloc_class_descriptors(sizeof(usb_vcp_descriptor_block_t));
if (d == NULL) {
return secfalse; // Not enough space in the configuration descriptor
}
if ((info->ep_cmd & USB_EP_DIR_MASK) != USB_EP_DIR_IN) {
return secfalse; // IN CMD EP is invalid
}
if ((info->ep_in & USB_EP_DIR_MASK) != USB_EP_DIR_IN) {
return secfalse; // IN EP is invalid
}
if ((info->ep_out & USB_EP_DIR_MASK) != USB_EP_DIR_OUT) {
return secfalse; // OUT EP is invalid
}
if ((info->rx_buffer_len == 0) ||
(info->rx_buffer_len & (info->rx_buffer_len - 1)) != 0) {
return secfalse; // Capacity needs to be a power of 2
@ -98,6 +200,15 @@ secbool usb_vcp_add(const usb_vcp_info_t *info) {
if (info->tx_packet == NULL) {
return secfalse;
}
if (info->ep_in >= USBD_MAX_NUM_INTERFACES) {
return secfalse;
}
if (info->ep_out >= USBD_MAX_NUM_INTERFACES) {
return secfalse;
}
if (info->ep_cmd >= USBD_MAX_NUM_INTERFACES) {
return secfalse;
}
// Interface association descriptor
d->assoc.bLength = sizeof(usb_interface_assoc_descriptor_t);
@ -155,7 +266,7 @@ secbool usb_vcp_add(const usb_vcp_info_t *info) {
// IN CMD endpoint (control)
d->ep_cmd.bLength = sizeof(usb_endpoint_descriptor_t);
d->ep_cmd.bDescriptorType = USB_DESC_TYPE_ENDPOINT;
d->ep_cmd.bEndpointAddress = info->ep_cmd;
d->ep_cmd.bEndpointAddress = info->ep_cmd | USB_EP_DIR_IN;
d->ep_cmd.bmAttributes = USBD_EP_TYPE_INTR;
d->ep_cmd.wMaxPacketSize = USB_CDC_MAX_CMD_PACKET_LEN;
d->ep_cmd.bInterval = info->polling_interval;
@ -174,7 +285,7 @@ secbool usb_vcp_add(const usb_vcp_info_t *info) {
// OUT endpoint (receiving)
d->ep_out.bLength = sizeof(usb_endpoint_descriptor_t);
d->ep_out.bDescriptorType = USB_DESC_TYPE_ENDPOINT;
d->ep_out.bEndpointAddress = info->ep_out;
d->ep_out.bEndpointAddress = info->ep_out | USB_EP_DIR_OUT;
d->ep_out.bmAttributes = USBD_EP_TYPE_BULK;
d->ep_out.wMaxPacketSize = info->max_packet_len;
d->ep_out.bInterval = 0;
@ -182,43 +293,43 @@ secbool usb_vcp_add(const usb_vcp_info_t *info) {
// IN endpoint (sending)
d->ep_in.bLength = sizeof(usb_endpoint_descriptor_t);
d->ep_in.bDescriptorType = USB_DESC_TYPE_ENDPOINT;
d->ep_in.bEndpointAddress = info->ep_in;
d->ep_in.bEndpointAddress = info->ep_in | USB_EP_DIR_IN;
d->ep_in.bmAttributes = USBD_EP_TYPE_BULK;
d->ep_in.wMaxPacketSize = info->max_packet_len;
d->ep_in.bInterval = 0;
// Config descriptor
usb_desc_add_iface(sizeof(usb_vcp_descriptor_block_t));
usb_config_desc
->bNumInterfaces++; // usb_vcp_descriptor_block_t contains 2 interfaces
// Interface state
state->dev_handle = usb_get_dev_handle();
state->desc_block = d;
iface->type = USB_IFACE_TYPE_VCP;
iface->vcp.desc_block = d;
state->rx_ring.buf = info->rx_buffer;
state->rx_ring.cap = info->rx_buffer_len;
state->rx_ring.read = 0;
state->rx_ring.write = 0;
iface->vcp.rx_ring.buf = info->rx_buffer;
iface->vcp.rx_ring.cap = info->rx_buffer_len;
iface->vcp.rx_ring.read = 0;
iface->vcp.rx_ring.write = 0;
state->tx_ring.buf = info->tx_buffer;
state->tx_ring.cap = info->tx_buffer_len;
state->tx_ring.read = 0;
state->tx_ring.write = 0;
iface->vcp.tx_ring.buf = info->tx_buffer;
iface->vcp.tx_ring.cap = info->tx_buffer_len;
iface->vcp.tx_ring.read = 0;
iface->vcp.tx_ring.write = 0;
state->rx_packet = info->rx_packet;
state->tx_packet = info->tx_packet;
iface->vcp.rx_packet = info->rx_packet;
iface->vcp.tx_packet = info->tx_packet;
state->rx_intr_fn = info->rx_intr_fn;
state->rx_intr_byte = info->rx_intr_byte;
iface->vcp.rx_intr_fn = info->rx_intr_fn;
iface->vcp.rx_intr_byte = info->rx_intr_byte;
state->ep_cmd = info->ep_cmd | USB_EP_DIR_IN;
state->ep_in = info->ep_in | USB_EP_DIR_IN;
state->ep_out = info->ep_out | USB_EP_DIR_OUT;
state->max_packet_len = info->max_packet_len;
iface->vcp.ep_cmd = info->ep_cmd;
iface->vcp.ep_in = info->ep_in;
iface->vcp.ep_out = info->ep_out;
iface->vcp.max_packet_len = info->max_packet_len;
state->ep_in_is_idle = 1;
iface->vcp.ep_in_is_idle = 1;
usb_set_iface_class(info->iface_num, &usb_vcp_class);
// This just make the data interface slot occupied so it can't be reused
// by another class driver. Data interface dispatch functiona are not used.
usb_set_iface_class(info->data_iface_num, &usb_vcp_data_class);
return sectrue;
}
@ -230,42 +341,32 @@ static inline int 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; }
secbool usb_vcp_can_read(uint8_t iface_num) {
usb_iface_t *iface = usb_get_iface(iface_num);
if (iface == NULL) {
usb_vcp_state_t *state = usb_get_vcp_state(iface_num);
if (state == NULL) {
return secfalse; // Invalid interface number
}
if (iface->type != USB_IFACE_TYPE_VCP) {
return secfalse; // Invalid interface type
}
if (ring_empty(&iface->vcp.rx_ring)) {
if (ring_empty(&state->rx_ring)) {
return secfalse; // Nothing in the rx buffer
}
return sectrue;
}
secbool usb_vcp_can_write(uint8_t iface_num) {
usb_iface_t *iface = usb_get_iface(iface_num);
if (iface == NULL) {
usb_vcp_state_t *state = usb_get_vcp_state(iface_num);
if (state == NULL) {
return secfalse; // Invalid interface number
}
if (iface->type != USB_IFACE_TYPE_VCP) {
return secfalse; // Invalid interface type
}
if (ring_full(&iface->vcp.tx_ring)) {
if (ring_full(&state->tx_ring)) {
return secfalse; // Tx ring buffer is full
}
return sectrue;
}
int usb_vcp_read(uint8_t iface_num, uint8_t *buf, uint32_t len) {
usb_iface_t *iface = usb_get_iface(iface_num);
if (iface == NULL) {
usb_vcp_state_t *state = usb_get_vcp_state(iface_num);
if (state == NULL) {
return -1; // Invalid interface number
}
if (iface->type != USB_IFACE_TYPE_VCP) {
return -2; // Invalid interface type
}
usb_vcp_state_t *state = &iface->vcp;
// Read from the rx ring buffer
usb_rbuf_t *b = &state->rx_ring;
@ -279,14 +380,10 @@ int usb_vcp_read(uint8_t iface_num, uint8_t *buf, uint32_t len) {
}
int usb_vcp_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) {
usb_iface_t *iface = usb_get_iface(iface_num);
if (iface == NULL) {
usb_vcp_state_t *state = usb_get_vcp_state(iface_num);
if (state == NULL) {
return -1; // Invalid interface number
}
if (iface->type != USB_IFACE_TYPE_VCP) {
return -2; // Invalid interface type
}
usb_vcp_state_t *state = &iface->vcp;
// Write into the tx ring buffer
usb_rbuf_t *b = &state->tx_ring;
@ -330,8 +427,9 @@ int usb_vcp_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len,
return i;
}
static void usb_vcp_class_init(USBD_HandleTypeDef *dev, usb_vcp_state_t *state,
uint8_t cfg_idx) {
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;
// Open endpoints
USBD_LL_OpenEP(dev, state->ep_in, USBD_EP_TYPE_BULK, state->max_packet_len);
USBD_LL_OpenEP(dev, state->ep_out, USBD_EP_TYPE_BULK, state->max_packet_len);
@ -348,10 +446,13 @@ static void usb_vcp_class_init(USBD_HandleTypeDef *dev, usb_vcp_state_t *state,
// Prepare the OUT EP to receive next packet
USBD_LL_PrepareReceive(dev, state->ep_out, state->rx_packet,
state->max_packet_len);
return USBD_OK;
}
static void usb_vcp_class_deinit(USBD_HandleTypeDef *dev,
usb_vcp_state_t *state, 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;
// Flush endpoints
USBD_LL_FlushEP(dev, state->ep_in);
USBD_LL_FlushEP(dev, state->ep_out);
@ -360,10 +461,14 @@ static void usb_vcp_class_deinit(USBD_HandleTypeDef *dev,
USBD_LL_CloseEP(dev, state->ep_in);
USBD_LL_CloseEP(dev, state->ep_out);
USBD_LL_CloseEP(dev, state->ep_cmd);
return USBD_OK;
}
static int usb_vcp_class_setup(USBD_HandleTypeDef *dev, usb_vcp_state_t *state,
USBD_SetupReqTypedef *req) {
static uint8_t usb_vcp_class_setup(USBD_HandleTypeDef *dev,
USBD_SetupReqTypedef *req) {
usb_vcp_state_t *state = (usb_vcp_state_t *)dev->pUserData;
static const usb_cdc_line_coding_t line_coding = {
.dwDTERate = 115200,
.bCharFormat = USB_CDC_1_STOP_BITS,
@ -393,15 +498,19 @@ static int usb_vcp_class_setup(USBD_HandleTypeDef *dev, usb_vcp_state_t *state,
return USBD_OK;
}
static void usb_vcp_class_data_in(USBD_HandleTypeDef *dev,
usb_vcp_state_t *state, uint8_t ep_num) {
static uint8_t usb_vcp_class_data_in(USBD_HandleTypeDef *dev, uint8_t ep_num) {
usb_vcp_state_t *state = (usb_vcp_state_t *)dev->pUserData;
if ((ep_num | USB_EP_DIR_IN) == state->ep_in) {
state->ep_in_is_idle = 1;
}
return USBD_OK;
}
static void usb_vcp_class_data_out(USBD_HandleTypeDef *dev,
usb_vcp_state_t *state, uint8_t ep_num) {
static uint8_t usb_vcp_class_data_out(USBD_HandleTypeDef *dev, uint8_t ep_num) {
usb_vcp_state_t *state = (usb_vcp_state_t *)dev->pUserData;
if (ep_num == state->ep_out) {
uint32_t len = USBD_LL_GetRxDataSize(dev, ep_num);
@ -425,11 +534,15 @@ static void usb_vcp_class_data_out(USBD_HandleTypeDef *dev,
USBD_LL_PrepareReceive(dev, state->ep_out, state->rx_packet,
state->max_packet_len);
}
return USBD_OK;
}
static void usb_vcp_class_sof(USBD_HandleTypeDef *dev, usb_vcp_state_t *state) {
static uint8_t usb_vcp_class_sof(USBD_HandleTypeDef *dev) {
usb_vcp_state_t *state = (usb_vcp_state_t *)dev->pUserData;
if (!state->ep_in_is_idle) {
return;
return USBD_OK;
}
// Read from the tx ring buffer
@ -447,6 +560,28 @@ static void usb_vcp_class_sof(USBD_HandleTypeDef *dev, usb_vcp_state_t *state) {
if (i > 0) {
state->ep_in_is_idle = 0;
USBD_LL_Transmit(&usb_dev_handle, state->ep_in, buf, (uint16_t)i);
USBD_LL_Transmit(dev, state->ep_in, buf, (uint16_t)i);
}
return USBD_OK;
}
static const USBD_ClassTypeDef usb_vcp_class = {
.Init = usb_vcp_class_init,
.DeInit = usb_vcp_class_deinit,
.Setup = usb_vcp_class_setup,
.EP0_TxSent = NULL,
.EP0_RxReady = NULL,
.DataIn = usb_vcp_class_data_in,
.DataOut = usb_vcp_class_data_out,
.SOF = usb_vcp_class_sof,
.IsoINIncomplete = NULL,
.IsoOUTIncomplete = NULL,
.GetHSConfigDescriptor = NULL,
.GetFSConfigDescriptor = NULL,
.GetOtherSpeedConfigDescriptor = NULL,
.GetDeviceQualifierDescriptor = NULL,
.GetUsrStrDescriptor = NULL,
};
static const USBD_ClassTypeDef usb_vcp_data_class = {};

View File

@ -17,36 +17,73 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common.h"
#include "random_delays.h"
#include "usbd_core.h"
#include "usbd_internal.h"
#include "usb_webusb.h"
#define USB_CLASS_WEBUSB 0xFF
typedef struct __attribute__((packed)) {
usb_interface_descriptor_t iface;
usb_endpoint_descriptor_t ep_in;
usb_endpoint_descriptor_t ep_out;
} usb_webusb_descriptor_block_t;
/* usb_webusb_state_t encapsulates all state used by enabled WebUSB interface.
* It needs to be completely initialized in usb_webusb_add and reset in
* usb_webusb_class_init. See usb_webusb_info_t for details of the
* configuration fields. */
typedef struct {
USBD_HandleTypeDef *dev_handle;
const usb_webusb_descriptor_block_t *desc_block;
uint8_t *rx_buffer;
uint8_t ep_in;
uint8_t ep_out;
uint8_t max_packet_len;
uint8_t alt_setting; // For SET_INTERFACE/GET_INTERFACE setup reqs
uint8_t last_read_len; // Length of data read into rx_buffer
uint8_t ep_in_is_idle; // Set to 1 after IN endpoint gets idle
} usb_webusb_state_t;
_Static_assert(sizeof(usb_webusb_state_t) <= USBD_CLASS_STATE_MAX_SIZE);
// interface dispatch functions
static const USBD_ClassTypeDef usb_webusb_class;
#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) {
usb_iface_t *iface = usb_get_iface(info->iface_num);
usb_webusb_state_t *state =
(usb_webusb_state_t *)usb_get_iface_state(info->iface_num, NULL);
if (iface == NULL) {
if (state == NULL) {
return secfalse; // Invalid interface number
}
if (iface->type != USB_IFACE_TYPE_DISABLED) {
return secfalse; // Interface is already enabled
}
usb_webusb_descriptor_block_t *d =
usb_desc_alloc_iface(sizeof(usb_webusb_descriptor_block_t));
usb_alloc_class_descriptors(sizeof(usb_webusb_descriptor_block_t));
if (d == NULL) {
return secfalse; // Not enough space in the configuration descriptor
}
if ((info->ep_in & USB_EP_DIR_MASK) != USB_EP_DIR_IN) {
return secfalse; // IN EP is invalid
}
if ((info->ep_out & USB_EP_DIR_MASK) != USB_EP_DIR_OUT) {
return secfalse; // OUT EP is invalid
}
if (info->rx_buffer == NULL) {
return secfalse;
}
if (info->ep_in >= USBD_MAX_NUM_INTERFACES) {
return secfalse;
}
if (info->ep_out >= USBD_MAX_NUM_INTERFACES) {
return secfalse;
}
// Interface descriptor
d->iface.bLength = sizeof(usb_interface_descriptor_t);
@ -62,7 +99,7 @@ secbool usb_webusb_add(const usb_webusb_info_t *info) {
// IN endpoint (sending)
d->ep_in.bLength = sizeof(usb_endpoint_descriptor_t);
d->ep_in.bDescriptorType = USB_DESC_TYPE_ENDPOINT;
d->ep_in.bEndpointAddress = info->ep_in;
d->ep_in.bEndpointAddress = info->ep_in | USB_EP_DIR_IN;
d->ep_in.bmAttributes = USBD_EP_TYPE_INTR;
d->ep_in.wMaxPacketSize = info->max_packet_len;
d->ep_in.bInterval = info->polling_interval;
@ -70,71 +107,60 @@ secbool usb_webusb_add(const usb_webusb_info_t *info) {
// OUT endpoint (receiving)
d->ep_out.bLength = sizeof(usb_endpoint_descriptor_t);
d->ep_out.bDescriptorType = USB_DESC_TYPE_ENDPOINT;
d->ep_out.bEndpointAddress = info->ep_out;
d->ep_out.bEndpointAddress = info->ep_out | USB_EP_DIR_OUT;
d->ep_out.bmAttributes = USBD_EP_TYPE_INTR;
d->ep_out.wMaxPacketSize = info->max_packet_len;
d->ep_out.bInterval = info->polling_interval;
// Config descriptor
usb_desc_add_iface(sizeof(usb_webusb_descriptor_block_t));
// Interface state
iface->type = USB_IFACE_TYPE_WEBUSB;
iface->webusb.desc_block = d;
iface->webusb.rx_buffer = info->rx_buffer;
iface->webusb.ep_in = info->ep_in;
iface->webusb.ep_out = info->ep_out;
iface->webusb.max_packet_len = info->max_packet_len;
iface->webusb.alt_setting = 0;
iface->webusb.last_read_len = 0;
iface->webusb.ep_in_is_idle = 1;
state->dev_handle = usb_get_dev_handle();
state->desc_block = d;
state->rx_buffer = info->rx_buffer;
state->ep_in = info->ep_in | USB_EP_DIR_IN;
state->ep_out = info->ep_out | USB_EP_DIR_OUT;
state->max_packet_len = info->max_packet_len;
state->alt_setting = 0;
state->last_read_len = 0;
state->ep_in_is_idle = 1;
usb_set_iface_class(info->iface_num, &usb_webusb_class);
return sectrue;
}
secbool usb_webusb_can_read(uint8_t iface_num) {
usb_iface_t *iface = usb_get_iface(iface_num);
if (iface == NULL) {
usb_webusb_state_t *state = usb_get_webusb_state(iface_num);
if (state == NULL) {
return secfalse; // Invalid interface number
}
if (iface->type != USB_IFACE_TYPE_WEBUSB) {
return secfalse; // Invalid interface type
}
if (iface->webusb.last_read_len == 0) {
if (state->last_read_len == 0) {
return secfalse; // Nothing in the receiving buffer
}
if (usb_dev_handle.dev_state != USBD_STATE_CONFIGURED) {
if (state->dev_handle->dev_state != USBD_STATE_CONFIGURED) {
return secfalse; // Device is not configured
}
return sectrue;
}
secbool usb_webusb_can_write(uint8_t iface_num) {
usb_iface_t *iface = usb_get_iface(iface_num);
if (iface == NULL) {
usb_webusb_state_t *state = usb_get_webusb_state(iface_num);
if (state == NULL) {
return secfalse; // Invalid interface number
}
if (iface->type != USB_IFACE_TYPE_WEBUSB) {
return secfalse; // Invalid interface type
}
if (iface->webusb.ep_in_is_idle == 0) {
if (state->ep_in_is_idle == 0) {
return secfalse; // Last transmission is not over yet
}
if (usb_dev_handle.dev_state != USBD_STATE_CONFIGURED) {
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) {
usb_iface_t *iface = usb_get_iface(iface_num);
if (iface == NULL) {
volatile usb_webusb_state_t *state = usb_get_webusb_state(iface_num);
if (state == NULL) {
return -1; // Invalid interface number
}
if (iface->type != USB_IFACE_TYPE_WEBUSB) {
return -2; // Invalid interface type
}
volatile usb_webusb_state_t *state = &iface->webusb;
// Copy maximum possible amount of data
uint32_t last_read_len = state->last_read_len;
@ -147,24 +173,21 @@ int usb_webusb_read(uint8_t iface_num, uint8_t *buf, uint32_t len) {
state->last_read_len = 0;
// Prepare the OUT EP to receive next packet
USBD_LL_PrepareReceive(&usb_dev_handle, state->ep_out, state->rx_buffer,
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) {
usb_iface_t *iface = usb_get_iface(iface_num);
if (iface == NULL) {
volatile usb_webusb_state_t *state = usb_get_webusb_state(iface_num);
if (state == NULL) {
return -1; // Invalid interface number
}
if (iface->type != USB_IFACE_TYPE_WEBUSB) {
return -2; // Invalid interface type
}
volatile usb_webusb_state_t *state = &iface->webusb;
state->ep_in_is_idle = 0;
USBD_LL_Transmit(&usb_dev_handle, state->ep_in, UNCONST(buf), (uint16_t)len);
USBD_LL_Transmit(state->dev_handle, state->ep_in, UNCONST(buf),
(uint16_t)len);
return len;
}
@ -209,8 +232,9 @@ int usb_webusb_write_blocking(uint8_t iface_num, const uint8_t *buf,
return usb_webusb_write(iface_num, buf, len);
}
static void usb_webusb_class_init(USBD_HandleTypeDef *dev,
usb_webusb_state_t *state, uint8_t cfg_idx) {
static uint8_t usb_webusb_class_init(USBD_HandleTypeDef *dev, uint8_t cfg_idx) {
usb_webusb_state_t *state = (usb_webusb_state_t *)dev->pUserData;
// Open endpoints
USBD_LL_OpenEP(dev, state->ep_in, USBD_EP_TYPE_INTR, state->max_packet_len);
USBD_LL_OpenEP(dev, state->ep_out, USBD_EP_TYPE_INTR, state->max_packet_len);
@ -223,22 +247,30 @@ static void usb_webusb_class_init(USBD_HandleTypeDef *dev,
// Prepare the OUT EP to receive next packet
USBD_LL_PrepareReceive(dev, state->ep_out, state->rx_buffer,
state->max_packet_len);
return USBD_OK;
}
static void usb_webusb_class_deinit(USBD_HandleTypeDef *dev,
usb_webusb_state_t *state,
uint8_t cfg_idx) {
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;
// Flush endpoints
USBD_LL_FlushEP(dev, state->ep_in);
USBD_LL_FlushEP(dev, state->ep_out);
// Close endpoints
USBD_LL_CloseEP(dev, state->ep_in);
USBD_LL_CloseEP(dev, state->ep_out);
return USBD_OK;
}
static int usb_webusb_class_setup(USBD_HandleTypeDef *dev,
usb_webusb_state_t *state,
USBD_SetupReqTypedef *req) {
static uint8_t usb_webusb_class_setup(USBD_HandleTypeDef *dev,
USBD_SetupReqTypedef *req) {
usb_webusb_state_t *state = (usb_webusb_state_t *)dev->pUserData;
wait_random();
if ((req->bmRequest & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_STANDARD) {
return USBD_OK;
}
@ -259,24 +291,50 @@ static int usb_webusb_class_setup(USBD_HandleTypeDef *dev,
USBD_CtlError(dev, req);
return USBD_FAIL;
}
return USBD_OK;
}
static void usb_webusb_class_data_in(USBD_HandleTypeDef *dev,
usb_webusb_state_t *state,
uint8_t ep_num) {
static uint8_t usb_webusb_class_data_in(USBD_HandleTypeDef *dev,
uint8_t ep_num) {
usb_webusb_state_t *state = (usb_webusb_state_t *)dev->pUserData;
if ((ep_num | USB_EP_DIR_IN) == state->ep_in) {
wait_random();
state->ep_in_is_idle = 1;
}
return USBD_OK;
}
static void usb_webusb_class_data_out(USBD_HandleTypeDef *dev,
usb_webusb_state_t *state,
uint8_t ep_num) {
static uint8_t usb_webusb_class_data_out(USBD_HandleTypeDef *dev,
uint8_t ep_num) {
usb_webusb_state_t *state = (usb_webusb_state_t *)dev->pUserData;
if (ep_num == state->ep_out) {
wait_random();
// Save the report length to indicate we have read something, but don't
// schedule next reading until user reads this one
state->last_read_len = USBD_LL_GetRxDataSize(dev, ep_num);
}
return USBD_OK;
}
static const USBD_ClassTypeDef usb_webusb_class = {
.Init = usb_webusb_class_init,
.DeInit = usb_webusb_class_deinit,
.Setup = usb_webusb_class_setup,
.EP0_TxSent = NULL,
.EP0_RxReady = NULL,
.DataIn = usb_webusb_class_data_in,
.DataOut = usb_webusb_class_data_out,
.SOF = NULL,
.IsoINIncomplete = NULL,
.IsoOUTIncomplete = NULL,
.GetHSConfigDescriptor = NULL,
.GetFSConfigDescriptor = NULL,
.GetOtherSpeedConfigDescriptor = NULL,
.GetDeviceQualifierDescriptor = NULL,
.GetUsrStrDescriptor = NULL,
};

View File

@ -272,6 +272,8 @@ typedef struct _USBD_HandleTypeDef
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
#define UNCONST(X) ((uint8_t *)(X))
#if defined ( __GNUC__ )
#ifndef __weak
#define __weak __attribute__((weak))

View File

@ -0,0 +1,131 @@
/*
* 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/>.
*/
#ifndef TREZORHAL_USBD_INTERNAL_H
#define TREZORHAL_USBD_INTERNAL_H
#include <stdint.h>
#define USB_EP_DIR_MASK 0x80
#define USB_EP_DIR_OUT 0x00
#define USB_EP_DIR_IN 0x80
#define USB_WEBUSB_VENDOR_CODE 0x01 // arbitrary
#define USB_WEBUSB_LANDING_PAGE 0x01 // arbitrary
typedef struct __attribute__((packed)) {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdUSB;
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
uint8_t bMaxPacketSize0;
uint16_t idVendor;
uint16_t idProduct;
uint16_t bcdDevice;
uint8_t iManufacturer;
uint8_t iProduct;
uint8_t iSerialNumber;
uint8_t bNumConfigurations;
} usb_device_descriptor_t;
typedef struct __attribute__((packed)) {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wData;
} usb_langid_descriptor_t;
typedef enum {
USB_LANGID_ENGLISH_US = 0x409,
} usb_language_id_t;
typedef struct __attribute__((packed)) {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wTotalLength;
uint8_t bNumInterfaces;
uint8_t bConfigurationValue;
uint8_t iConfiguration;
uint8_t bmAttributes;
uint8_t bMaxPower;
} usb_config_descriptor_t;
typedef struct __attribute__((packed)) {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bInterfaceNumber;
uint8_t bAlternateSetting;
uint8_t bNumEndpoints;
uint8_t bInterfaceClass;
uint8_t bInterfaceSubClass;
uint8_t bInterfaceProtocol;
uint8_t iInterface;
} usb_interface_descriptor_t;
typedef struct __attribute__((packed)) {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bFirstInterface;
uint8_t bInterfaceCount;
uint8_t bFunctionClass;
uint8_t bFunctionSubClass;
uint8_t bFunctionProtocol;
uint8_t iFunction;
} usb_interface_assoc_descriptor_t;
typedef struct __attribute__((packed)) {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bEndpointAddress;
uint8_t bmAttributes;
uint16_t wMaxPacketSize;
uint8_t bInterval;
} usb_endpoint_descriptor_t;
// Number of reserved bytes for the state of each class.
#define USBD_CLASS_STATE_MAX_SIZE 128
// Returns the pointer to class state structure reserved for the
// specified interface number.
//
// The function checks if the interface number is valid and the type
// matches and returns NULL if not. If the `class` is NULL, the function
// returns the valid pointer only if the slot is empty.
//
// The returned array has `USBD_CLASS_STATE_MAX_SIZE` bytes
// and is aligned to 8-byte boundary.
void *usb_get_iface_state(uint8_t iface_num, const USBD_ClassTypeDef *class);
// Assigns the concrete class to the slot `iface_num`.
void usb_set_iface_class(uint8_t iface_num, const USBD_ClassTypeDef *class);
// Allocates the buffer for the class driver descriptors
// (interface, endpoint, ...) inside the USB device structure.
//
// The callee must fill the whole buffer with the descriptors.
//
// The function checks if the remaining space is enough and
// returns NULL if not.
void *usb_alloc_class_descriptors(size_t desc_len);
// Returns the global handle to the USB device.
USBD_HandleTypeDef *usb_get_dev_handle(void);
#endif // TREZORHAL_USBD_INTERNAL_H

View File

@ -38,6 +38,13 @@
#define USBD_MAX_NUM_INTERFACES 8
typedef enum {
USB_IFACE_TYPE_DISABLED = 0,
USB_IFACE_TYPE_VCP = 1,
USB_IFACE_TYPE_HID = 2,
USB_IFACE_TYPE_WEBUSB = 3,
} usb_iface_type_t;
static struct {
usb_iface_type_t type;
uint16_t port;

View File

@ -23,86 +23,9 @@
#include <stdint.h>
#include "secbool.h"
#define USB_EP_DIR_MASK 0x80
#define USB_EP_DIR_OUT 0x00
#define USB_EP_DIR_IN 0x80
typedef struct __attribute__((packed)) {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdUSB;
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
uint8_t bMaxPacketSize0;
uint16_t idVendor;
uint16_t idProduct;
uint16_t bcdDevice;
uint8_t iManufacturer;
uint8_t iProduct;
uint8_t iSerialNumber;
uint8_t bNumConfigurations;
} usb_device_descriptor_t;
typedef struct __attribute__((packed)) {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wData;
} usb_langid_descriptor_t;
typedef struct __attribute__((packed)) {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wTotalLength;
uint8_t bNumInterfaces;
uint8_t bConfigurationValue;
uint8_t iConfiguration;
uint8_t bmAttributes;
uint8_t bMaxPower;
} usb_config_descriptor_t;
typedef struct __attribute__((packed)) {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bInterfaceNumber;
uint8_t bAlternateSetting;
uint8_t bNumEndpoints;
uint8_t bInterfaceClass;
uint8_t bInterfaceSubClass;
uint8_t bInterfaceProtocol;
uint8_t iInterface;
} usb_interface_descriptor_t;
typedef struct __attribute__((packed)) {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bFirstInterface;
uint8_t bInterfaceCount;
uint8_t bFunctionClass;
uint8_t bFunctionSubClass;
uint8_t bFunctionProtocol;
uint8_t iFunction;
} usb_interface_assoc_descriptor_t;
typedef struct __attribute__((packed)) {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bEndpointAddress;
uint8_t bmAttributes;
uint16_t wMaxPacketSize;
uint8_t bInterval;
} usb_endpoint_descriptor_t;
typedef enum {
USB_LANGID_ENGLISH_US = 0x409,
} usb_language_id_t;
typedef struct {
const char *manufacturer;
const char *product;
const char *serial_number;
const char *interface;
} usb_dev_string_table_t;
#include "usb_hid.h"
#include "usb_vcp.h"
#include "usb_webusb.h"
typedef struct {
uint8_t device_class;
@ -119,26 +42,6 @@ typedef struct {
secbool usb21_landing;
} usb_dev_info_t;
typedef enum {
USB_IFACE_TYPE_DISABLED = 0,
USB_IFACE_TYPE_VCP = 1,
USB_IFACE_TYPE_HID = 2,
USB_IFACE_TYPE_WEBUSB = 3,
} usb_iface_type_t;
#include "usb_hid-defs.h"
#include "usb_vcp-defs.h"
#include "usb_webusb-defs.h"
typedef struct {
union {
usb_hid_state_t hid;
usb_vcp_state_t vcp;
usb_webusb_state_t webusb;
};
usb_iface_type_t type;
} usb_iface_t;
void usb_init(const usb_dev_info_t *dev_info);
void usb_deinit(void);
void usb_start(void);

View File

@ -17,22 +17,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
typedef struct __attribute__((packed)) {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdHID;
uint8_t bCountryCode;
uint8_t bNumDescriptors;
uint8_t bReportDescriptorType;
uint16_t wReportDescriptorLength;
} usb_hid_descriptor_t;
#ifndef TREZORHAL_USB_CLASS_HID_H
#define TREZORHAL_USB_CLASS_HID_H
typedef struct __attribute__((packed)) {
usb_interface_descriptor_t iface;
usb_hid_descriptor_t hid;
usb_endpoint_descriptor_t ep_in;
usb_endpoint_descriptor_t ep_out;
} usb_hid_descriptor_block_t;
#include <stdint.h>
#include "secbool.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
@ -54,26 +43,6 @@ typedef struct {
uint8_t report_desc_len; // Length of report_desc
} usb_hid_info_t;
/* usb_hid_state_t encapsulates all state used by enabled HID interface. It
* needs to be completely initialized in usb_hid_add and reset in
* usb_hid_class_init. See usb_hid_info_t for details of the configuration
* fields. */
typedef struct {
const usb_hid_descriptor_block_t *desc_block;
const uint8_t *report_desc;
uint8_t *rx_buffer;
uint8_t ep_in;
uint8_t ep_out;
uint8_t max_packet_len;
uint8_t report_desc_len;
uint8_t protocol; // For SET_PROTOCOL/GET_PROTOCOL setup reqs
uint8_t idle_rate; // For SET_IDLE/GET_IDLE setup reqs
uint8_t alt_setting; // For SET_INTERFACE/GET_INTERFACE setup reqs
uint8_t last_read_len; // Length of data read into rx_buffer
uint8_t ep_in_is_idle; // Set to 1 after IN endpoint gets idle
} usb_hid_state_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);
@ -85,3 +54,5 @@ 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

View File

@ -17,73 +17,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TREZORHAL_USB_CLASS_VCP_H
#define TREZORHAL_USB_CLASS_VCP_H
#include <stddef.h>
typedef struct __attribute__((packed)) {
uint8_t bFunctionLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint16_t bcdCDC;
} usb_vcp_header_descriptor_t;
typedef struct __attribute__((packed)) {
uint8_t bFunctionLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint8_t bmCapabilities;
uint8_t bDataInterface;
} usb_vcp_cm_descriptor_t;
typedef struct __attribute__((packed)) {
uint8_t bFunctionLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint8_t bmCapabilities;
} usb_vcp_acm_descriptor_t;
typedef struct __attribute__((packed)) {
uint8_t bFunctionLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
uint8_t bControlInterface;
uint8_t bSubordinateInterface0;
} usb_vcp_union_descriptor_t;
typedef struct __attribute__((packed)) {
usb_interface_assoc_descriptor_t assoc;
usb_interface_descriptor_t iface_cdc;
usb_vcp_header_descriptor_t
fheader; // Class-Specific Descriptor Header Format
usb_vcp_cm_descriptor_t fcm; // Call Management Functional Descriptor
usb_vcp_acm_descriptor_t
facm; // Abstract Control Management Functional Descriptor
usb_vcp_union_descriptor_t funion; // Union Interface Functional Descriptor
usb_endpoint_descriptor_t ep_cmd;
usb_interface_descriptor_t iface_data;
usb_endpoint_descriptor_t ep_in;
usb_endpoint_descriptor_t ep_out;
} usb_vcp_descriptor_block_t;
typedef struct __attribute__((packed)) {
uint32_t dwDTERate;
uint8_t bCharFormat; // usb_cdc_line_coding_bCharFormat_t
uint8_t bParityType; // usb_cdc_line_coding_bParityType_t
uint8_t bDataBits;
} usb_cdc_line_coding_t;
typedef enum {
USB_CDC_1_STOP_BITS = 0,
USB_CDC_1_5_STOP_BITS = 1,
USB_CDC_2_STOP_BITS = 2,
} usb_cdc_line_coding_bCharFormat_t;
typedef enum {
USB_CDC_NO_PARITY = 0,
USB_CDC_ODD_PARITY = 1,
USB_CDC_EVEN_PARITY = 2,
USB_CDC_MARK_PARITY = 3,
USB_CDC_SPACE_PARITY = 4,
} usb_cdc_line_coding_bParityType_t;
#include "secbool.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
@ -117,37 +55,6 @@ typedef struct {
// rx_packet
} usb_vcp_info_t;
/* usb_rbuf_t is used internally for the RX/TX buffering. */
typedef struct {
size_t cap;
volatile size_t read;
volatile size_t write;
uint8_t *buf;
} usb_rbuf_t;
// Maximal length of packets on IN CMD EP
#define USB_CDC_MAX_CMD_PACKET_LEN 0x08
/* usb_vcp_state_t encapsulates all state used by enabled VCP interface. It
* needs to be completely initialized in usb_vcp_add and reset in
* usb_vcp_class_init. See usb_vcp_info_t for details of the configuration
* fields. */
typedef struct {
const usb_vcp_descriptor_block_t *desc_block;
usb_rbuf_t rx_ring;
usb_rbuf_t tx_ring;
uint8_t *rx_packet;
uint8_t *tx_packet;
void (*rx_intr_fn)(void);
uint8_t rx_intr_byte;
uint8_t ep_cmd;
uint8_t ep_in;
uint8_t ep_out;
uint8_t max_packet_len;
uint8_t ep_in_is_idle; // Set to 1 after IN endpoint gets idle
uint8_t cmd_buffer[USB_CDC_MAX_CMD_PACKET_LEN];
} usb_vcp_state_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);
@ -158,3 +65,5 @@ 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

View File

@ -17,14 +17,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define USB_WEBUSB_VENDOR_CODE 0x01 // arbitrary
#define USB_WEBUSB_LANDING_PAGE 0x01 // arbitrary
#ifndef TREZORHAL_USB_CLASS_WEBUSB_H
#define TREZORHAL_USB_CLASS_WEBUSB_H
typedef struct __attribute__((packed)) {
usb_interface_descriptor_t iface;
usb_endpoint_descriptor_t ep_in;
usb_endpoint_descriptor_t ep_out;
} usb_webusb_descriptor_block_t;
#include "secbool.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
@ -44,22 +40,6 @@ typedef struct {
uint8_t max_packet_len; // Length of the biggest report and of rx_buffer
} usb_webusb_info_t;
/* usb_webusb_state_t encapsulates all state used by enabled WebUSB interface.
* It needs to be completely initialized in usb_webusb_add and reset in
* usb_webusb_class_init. See usb_webusb_info_t for details of the
* configuration fields. */
typedef struct {
const usb_webusb_descriptor_block_t *desc_block;
uint8_t *rx_buffer;
uint8_t ep_in;
uint8_t ep_out;
uint8_t max_packet_len;
uint8_t alt_setting; // For SET_INTERFACE/GET_INTERFACE setup reqs
uint8_t last_read_len; // Length of data read into rx_buffer
uint8_t ep_in_is_idle; // Set to 1 after IN endpoint gets idle
} usb_webusb_state_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);
@ -71,3 +51,5 @@ 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

View File

@ -76,11 +76,14 @@ def configure(
if "usb" in features_wanted:
sources += [
"embed/trezorhal/stm32f4/usb/usb.c",
"embed/trezorhal/stm32f4/usb/usbd_class_hid.c",
"embed/trezorhal/stm32f4/usb/usbd_class_vcp.c",
"embed/trezorhal/stm32f4/usb/usbd_class_webusb.c",
"embed/trezorhal/stm32f4/usb/usbd_conf.c",
"embed/trezorhal/stm32f4/usb/usbd_core.c",
"embed/trezorhal/stm32f4/usb/usbd_ctlreq.c",
"embed/trezorhal/stm32f4/usb/usbd_ioreq.c",
"embed/trezorhal/stm32f4/usb/usbd.c",
"vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c",
]
features_available.append("usb")

View File

@ -82,11 +82,14 @@ def configure(
if "usb" in features_wanted:
sources += [
"embed/trezorhal/stm32u5/usb/usb.c",
"embed/trezorhal/stm32u5/usb/usbd_class_hid.c",
"embed/trezorhal/stm32u5/usb/usbd_class_vcp.c",
"embed/trezorhal/stm32u5/usb/usbd_class_webusb.c",
"embed/trezorhal/stm32u5/usb/usbd_conf.c",
"embed/trezorhal/stm32u5/usb/usbd_core.c",
"embed/trezorhal/stm32u5/usb/usbd_ctlreq.c",
"embed/trezorhal/stm32u5/usb/usbd_ioreq.c",
"embed/trezorhal/stm32u5/usb/usbd.c",
"vendor/stm32u5xx_hal_driver/Src/stm32u5xx_ll_usb.c",
]
features_available.append("usb")

View File

@ -42,11 +42,14 @@ def configure(
if "usb" in features_wanted:
sources += [
"embed/trezorhal/stm32f4/usb/usb.c",
"embed/trezorhal/stm32f4/usb/usbd_class_hid.c",
"embed/trezorhal/stm32f4/usb/usbd_class_vcp.c",
"embed/trezorhal/stm32f4/usb/usbd_class_webusb.c",
"embed/trezorhal/stm32f4/usb/usbd_conf.c",
"embed/trezorhal/stm32f4/usb/usbd_core.c",
"embed/trezorhal/stm32f4/usb/usbd_ctlreq.c",
"embed/trezorhal/stm32f4/usb/usbd_ioreq.c",
"embed/trezorhal/stm32f4/usb/usbd.c",
"vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c",
]
features_available.append("usb")

View File

@ -65,11 +65,14 @@ def configure(
]
if "usb" in features_wanted:
sources += [
"embed/trezorhal/stm32f4/usb/usb.c",
"embed/trezorhal/stm32f4/usb/usbd_class_hid.c",
"embed/trezorhal/stm32f4/usb/usbd_class_vcp.c",
"embed/trezorhal/stm32f4/usb/usbd_class_webusb.c",
"embed/trezorhal/stm32f4/usb/usbd_conf.c",
"embed/trezorhal/stm32f4/usb/usbd_core.c",
"embed/trezorhal/stm32f4/usb/usbd_ctlreq.c",
"embed/trezorhal/stm32f4/usb/usbd_ioreq.c",
"embed/trezorhal/stm32f4/usb/usbd.c",
"vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c",
]
features_available.append("usb")

View File

@ -62,11 +62,14 @@ def configure(
if "usb" in features_wanted:
sources += [
"embed/trezorhal/stm32f4/usb/usb.c",
"embed/trezorhal/stm32f4/usb/usbd_class_hid.c",
"embed/trezorhal/stm32f4/usb/usbd_class_vcp.c",
"embed/trezorhal/stm32f4/usb/usbd_class_webusb.c",
"embed/trezorhal/stm32f4/usb/usbd_conf.c",
"embed/trezorhal/stm32f4/usb/usbd_core.c",
"embed/trezorhal/stm32f4/usb/usbd_ctlreq.c",
"embed/trezorhal/stm32f4/usb/usbd_ioreq.c",
"embed/trezorhal/stm32f4/usb/usbd.c",
"vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c",
]
features_available.append("usb")

View File

@ -58,11 +58,14 @@ def configure(
if "usb" in features_wanted:
sources += [
"embed/trezorhal/stm32f4/usb/usb.c",
"embed/trezorhal/stm32f4/usb/usbd_class_hid.c",
"embed/trezorhal/stm32f4/usb/usbd_class_vcp.c",
"embed/trezorhal/stm32f4/usb/usbd_class_webusb.c",
"embed/trezorhal/stm32f4/usb/usbd_conf.c",
"embed/trezorhal/stm32f4/usb/usbd_core.c",
"embed/trezorhal/stm32f4/usb/usbd_ctlreq.c",
"embed/trezorhal/stm32f4/usb/usbd_ioreq.c",
"embed/trezorhal/stm32f4/usb/usbd.c",
"vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c",
]
features_available.append("usb")

View File

@ -58,11 +58,14 @@ def configure(
if "usb" in features_wanted:
sources += [
"embed/trezorhal/stm32f4/usb/usb.c",
"embed/trezorhal/stm32f4/usb/usbd_class_hid.c",
"embed/trezorhal/stm32f4/usb/usbd_class_vcp.c",
"embed/trezorhal/stm32f4/usb/usbd_class_webusb.c",
"embed/trezorhal/stm32f4/usb/usbd_conf.c",
"embed/trezorhal/stm32f4/usb/usbd_core.c",
"embed/trezorhal/stm32f4/usb/usbd_ctlreq.c",
"embed/trezorhal/stm32f4/usb/usbd_ioreq.c",
"embed/trezorhal/stm32f4/usb/usbd.c",
"vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c",
]
features_available.append("usb")

View File

@ -100,11 +100,14 @@ def configure(
if "usb" in features_wanted:
sources += [
"embed/trezorhal/stm32f4/usb/usb.c",
"embed/trezorhal/stm32f4/usb/usbd_class_hid.c",
"embed/trezorhal/stm32f4/usb/usbd_class_vcp.c",
"embed/trezorhal/stm32f4/usb/usbd_class_webusb.c",
"embed/trezorhal/stm32f4/usb/usbd_conf.c",
"embed/trezorhal/stm32f4/usb/usbd_core.c",
"embed/trezorhal/stm32f4/usb/usbd_ctlreq.c",
"embed/trezorhal/stm32f4/usb/usbd_ioreq.c",
"embed/trezorhal/stm32f4/usb/usbd.c",
"vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c",
]
features_available.append("usb")

View File

@ -100,11 +100,14 @@ def configure(
if "usb" in features_wanted:
sources += [
"embed/trezorhal/stm32u5/usb/usb.c",
"embed/trezorhal/stm32u5/usb/usbd_class_hid.c",
"embed/trezorhal/stm32u5/usb/usbd_class_vcp.c",
"embed/trezorhal/stm32u5/usb/usbd_class_webusb.c",
"embed/trezorhal/stm32u5/usb/usbd_conf.c",
"embed/trezorhal/stm32u5/usb/usbd_core.c",
"embed/trezorhal/stm32u5/usb/usbd_ctlreq.c",
"embed/trezorhal/stm32u5/usb/usbd_ioreq.c",
"embed/trezorhal/stm32u5/usb/usbd.c",
"vendor/stm32u5xx_hal_driver/Src/stm32u5xx_ll_usb.c",
]
features_available.append("usb")

View File

@ -102,11 +102,14 @@ def configure(
if "usb" in features_wanted:
sources += [
"embed/trezorhal/stm32u5/usb/usb.c",
"embed/trezorhal/stm32u5/usb/usbd_class_hid.c",
"embed/trezorhal/stm32u5/usb/usbd_class_vcp.c",
"embed/trezorhal/stm32u5/usb/usbd_class_webusb.c",
"embed/trezorhal/stm32u5/usb/usbd_conf.c",
"embed/trezorhal/stm32u5/usb/usbd_core.c",
"embed/trezorhal/stm32u5/usb/usbd_ctlreq.c",
"embed/trezorhal/stm32u5/usb/usbd_ioreq.c",
"embed/trezorhal/stm32u5/usb/usbd.c",
"vendor/stm32u5xx_hal_driver/Src/stm32u5xx_ll_usb.c",
]
features_available.append("usb")

View File

@ -33,7 +33,7 @@ ENABLE_IFACE_VCP = __debug__
id_wire = next(_iface_iter)
iface_wire = io.WebUSB(
iface_num=id_wire,
ep_in=0x81 + id_wire,
ep_in=0x01 + id_wire,
ep_out=0x01 + id_wire,
emu_port=UDP_PORT + _WIRE_PORT_OFFSET,
)
@ -55,7 +55,7 @@ if __debug__ and ENABLE_IFACE_DEBUG:
id_debug = next(_iface_iter)
iface_debug = io.WebUSB(
iface_num=id_debug,
ep_in=0x81 + id_debug,
ep_in=0x01 + id_debug,
ep_out=0x01 + id_debug,
emu_port=UDP_PORT + _DEBUGLINK_PORT_OFFSET,
)
@ -66,7 +66,7 @@ if not utils.BITCOIN_ONLY and ENABLE_IFACE_WEBAUTHN:
id_webauthn = next(_iface_iter)
iface_webauthn = io.HID(
iface_num=id_webauthn,
ep_in=0x81 + id_webauthn,
ep_in=0x01 + id_webauthn,
ep_out=0x01 + id_webauthn,
emu_port=UDP_PORT + _WEBAUTHN_PORT_OFFSET,
# fmt: off
@ -99,9 +99,9 @@ if __debug__ and ENABLE_IFACE_VCP:
iface_vcp = io.VCP(
iface_num=id_vcp,
data_iface_num=id_vcp_data,
ep_in=0x81 + id_vcp,
ep_in=0x01 + id_vcp,
ep_out=0x01 + id_vcp,
ep_cmd=0x81 + id_vcp_data,
ep_cmd=0x01 + id_vcp_data,
emu_port=UDP_PORT + _VCP_PORT_OFFSET,
)
bus.add(iface_vcp)

View File

@ -5,9 +5,9 @@ import utime
usb_vcp = io.VCP(
iface_num=0x00,
data_iface_num=0x01,
ep_in=0x81,
ep_in=0x01,
ep_out=0x01,
ep_cmd=0x82,
ep_cmd=0x02,
)
usb = io.USB(