From df57f47aa9756a9e987a1ab7de382aaaf58422d1 Mon Sep 17 00:00:00 2001 From: Jan Pochyla Date: Fri, 7 Apr 2017 17:40:22 +0200 Subject: [PATCH] trezorhal: minor usb cleanup --- micropython/firmware/main.c | 1 - micropython/trezorhal/usb.c | 220 ++++++++++++--------------- micropython/trezorhal/usb.h | 14 +- micropython/trezorhal/usb_hid-defs.h | 7 + micropython/trezorhal/usb_hid-impl.h | 33 ++-- micropython/trezorhal/usb_vcp-defs.h | 37 +++-- micropython/trezorhal/usb_vcp-impl.h | 139 +++++++---------- micropython/trezorhal/usbd_conf.c | 65 +++++++- 8 files changed, 286 insertions(+), 230 deletions(-) diff --git a/micropython/firmware/main.c b/micropython/firmware/main.c index 3986f84e..ed7031b6 100644 --- a/micropython/firmware/main.c +++ b/micropython/firmware/main.c @@ -71,7 +71,6 @@ int usb_init_all(void) { .ep_in = USB_EP_DIR_IN | 0x03, .ep_out = USB_EP_DIR_OUT | 0x03, .polling_interval = 1, - .max_cmd_packet_len = 8, .max_data_packet_len = 64, }; diff --git a/micropython/trezorhal/usb.c b/micropython/trezorhal/usb.c index 28f21bce..42e6eb51 100644 --- a/micropython/trezorhal/usb.c +++ b/micropython/trezorhal/usb.c @@ -1,4 +1,9 @@ -// TODO: max size of user strings from dev_info +/* + * Copyright (c) Jan Pochyla, SatoshiLabs + * + * Licensed under TREZOR License + * see LICENSE file for details + */ #include STM32_HAL_H @@ -7,33 +12,39 @@ #define UNCONST(X) ((uint8_t *)(X)) -#define USB_MAX_CONFIG_DESC_SIZE 128 -#define USB_MAX_STR_DESC_SIZE 256 - -extern PCD_HandleTypeDef pcd_fs_handle; - -static USBD_HandleTypeDef usb_dev_handle; +#define USB_MAX_CONFIG_DESC_SIZE 128 +#define USB_MAX_STR_SIZE 62 +#define USB_MAX_STR_DESC_SIZE (USB_MAX_STR_SIZE * 2 + 2) static usb_device_descriptor_t usb_dev_desc; + +// Config descriptor static uint8_t usb_config_buf[USB_MAX_CONFIG_DESC_SIZE]; -static uint8_t usb_str_buf[USB_MAX_STR_DESC_SIZE]; -static const usb_string_descriptor_t usb_langid_str_desc = { - .bLength = USB_LEN_LANGID_STR_DESC, - .bDescriptorType = USB_DESC_TYPE_STRING, - .wData = USB_LANGID_ENGLISH_US, -}; static usb_config_descriptor_t *usb_config_desc = (usb_config_descriptor_t *)(usb_config_buf); static usb_interface_descriptor_t *usb_next_iface_desc; -static usb_string_table_t usb_str_table; + +// String descriptor +static uint8_t usb_str_buf[USB_MAX_STR_DESC_SIZE]; +static usb_dev_string_table_t usb_str_table; + static usb_iface_t usb_ifaces[USBD_MAX_NUM_INTERFACES]; +static USBD_HandleTypeDef usb_dev_handle; static const USBD_DescriptorsTypeDef usb_descriptors; static const USBD_ClassTypeDef usb_class; +static int check_desc_str(const uint8_t *s) { + if (!s || strlen((const char *)s) > USB_MAX_STR_SIZE) { + return 1; + } else { + return 0; + } +} + int usb_init(const usb_dev_info_t *dev_info) { // Device descriptor - usb_dev_desc.bLength = USB_LEN_DEV_DESC; + usb_dev_desc.bLength = sizeof(usb_device_descriptor_t); usb_dev_desc.bDescriptorType = USB_DESC_TYPE_DEVICE; usb_dev_desc.bcdUSB = 0x0200; usb_dev_desc.bDeviceClass = 0xef; // Composite Device Class @@ -46,9 +57,14 @@ int usb_init(const usb_dev_info_t *dev_info) { 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 = 0x01; + usb_dev_desc.bNumConfigurations = 1; // String table + if (0 != check_desc_str(dev_info->manufacturer_str)) return 1; + if (0 != check_desc_str(dev_info->product_str)) return 1; + if (0 != check_desc_str(dev_info->serial_number_str)) return 1; + if (0 != check_desc_str(dev_info->configuration_str)) return 1; + if (0 != check_desc_str(dev_info->interface_str)) return 1; usb_str_table.manufacturer_str = dev_info->manufacturer_str; usb_str_table.product_str = dev_info->product_str; usb_str_table.serial_str = dev_info->serial_number_str; @@ -56,16 +72,16 @@ int usb_init(const usb_dev_info_t *dev_info) { usb_str_table.interface_str = dev_info->interface_str; // Configuration descriptor - usb_config_desc->bLength = USB_LEN_CFG_DESC; + usb_config_desc->bLength = sizeof(usb_config_descriptor_t); usb_config_desc->bDescriptorType = USB_DESC_TYPE_CONFIGURATION; - usb_config_desc->wTotalLength = USB_LEN_CFG_DESC; + usb_config_desc->wTotalLength = sizeof(usb_config_descriptor_t); usb_config_desc->bNumInterfaces = 0x00; usb_config_desc->bConfigurationValue = 0x01; // Configuration value usb_config_desc->iConfiguration = 0x00; // Index of string descriptor describing the configuration usb_config_desc->bmAttributes = 0x80; // 0x80 = bus powered; 0xc0 = self powered usb_config_desc->bMaxPower = 0xfa; // In units of 2mA - // Pointer to interface descriptor data, see: usb_desc_alloc_iface, usb_desc_add_iface + // Reset pointer to interface descriptor data usb_next_iface_desc = (usb_interface_descriptor_t *)(usb_config_buf + usb_config_desc->wTotalLength); // Reset the iface state map @@ -93,50 +109,9 @@ int usb_stop(void) { return USBD_Stop(&usb_dev_handle); } -static uint8_t *usb_get_dev_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - *length = sizeof(usb_dev_desc); - return (uint8_t *)&usb_dev_desc; -} - -static uint8_t *usb_get_langid_str_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - *length = sizeof(usb_langid_str_desc); - return (uint8_t *)&usb_langid_str_desc; -} - -static uint8_t *usb_get_manufacturer_str_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - USBD_GetString(UNCONST(usb_str_table.manufacturer_str), usb_str_buf, length); - return usb_str_buf; -} - -static uint8_t *usb_get_product_str_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - USBD_GetString(UNCONST(usb_str_table.product_str), usb_str_buf, length); - return usb_str_buf; -} - -static uint8_t *usb_get_serial_str_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - USBD_GetString(UNCONST(usb_str_table.serial_str), usb_str_buf, length); - return usb_str_buf; -} - -static uint8_t *usb_get_config_str_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - USBD_GetString(UNCONST(usb_str_table.config_str), usb_str_buf, length); - return usb_str_buf; -} - -static uint8_t *usb_get_interface_str_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - USBD_GetString(UNCONST(usb_str_table.interface_str), usb_str_buf, length); - return usb_str_buf; -} - -static const USBD_DescriptorsTypeDef usb_descriptors = { - .GetDeviceDescriptor = usb_get_dev_descriptor, - .GetLangIDStrDescriptor = usb_get_langid_str_descriptor, - .GetManufacturerStrDescriptor = usb_get_manufacturer_str_descriptor, - .GetProductStrDescriptor = usb_get_product_str_descriptor, - .GetSerialStrDescriptor = usb_get_serial_str_descriptor, - .GetConfigurationStrDescriptor = usb_get_config_str_descriptor, - .GetInterfaceStrDescriptor = usb_get_interface_str_descriptor, -}; +/* + * Utility functions for USB interfaces + */ static usb_iface_t *usb_get_iface(uint8_t iface_num) { if (iface_num < USBD_MAX_NUM_INTERFACES) { @@ -174,9 +149,71 @@ static uint8_t usb_ep_clear_nak(USBD_HandleTypeDef *dev, uint8_t ep_num) { return USBD_OK; } +/* + * USB interface implementations + */ + #include "usb_hid-impl.h" #include "usb_vcp-impl.h" +/* + * 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); +} + +static uint8_t *usb_get_langid_str_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { + static const usb_langid_descriptor_t usb_langid_str_desc = { + .bLength = USB_LEN_LANGID_STR_DESC, + .bDescriptorType = USB_DESC_TYPE_STRING, + .wData = USB_LANGID_ENGLISH_US, + }; + *length = sizeof(usb_langid_str_desc); + return (uint8_t *)(&usb_langid_str_desc); +} + +static uint8_t *usb_get_manufacturer_str_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { + USBD_GetString(UNCONST(usb_str_table.manufacturer_str), usb_str_buf, length); + return usb_str_buf; +} + +static uint8_t *usb_get_product_str_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { + USBD_GetString(UNCONST(usb_str_table.product_str), usb_str_buf, length); + return usb_str_buf; +} + +static uint8_t *usb_get_serial_str_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { + USBD_GetString(UNCONST(usb_str_table.serial_str), usb_str_buf, length); + return usb_str_buf; +} + +static uint8_t *usb_get_config_str_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { + USBD_GetString(UNCONST(usb_str_table.config_str), usb_str_buf, length); + return usb_str_buf; +} + +static uint8_t *usb_get_interface_str_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { + USBD_GetString(UNCONST(usb_str_table.interface_str), usb_str_buf, length); + return usb_str_buf; +} + +static const USBD_DescriptorsTypeDef usb_descriptors = { + .GetDeviceDescriptor = usb_get_dev_descriptor, + .GetLangIDStrDescriptor = usb_get_langid_str_descriptor, + .GetManufacturerStrDescriptor = usb_get_manufacturer_str_descriptor, + .GetProductStrDescriptor = usb_get_product_str_descriptor, + .GetSerialStrDescriptor = usb_get_serial_str_descriptor, + .GetConfigurationStrDescriptor = usb_get_config_str_descriptor, + .GetInterfaceStrDescriptor = usb_get_interface_str_descriptor, +}; + +/* + * USB class (interface dispatch, configuration descriptor) + */ + static uint8_t usb_class_init(USBD_HandleTypeDef *dev, uint8_t cfg_idx) { for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { switch (usb_ifaces[i].type) { @@ -284,60 +321,3 @@ static const USBD_ClassTypeDef usb_class = { .GetOtherSpeedConfigDescriptor = usb_class_get_cfg_desc, .GetDeviceQualifierDescriptor = NULL, }; - -/** - * @brief This function handles USB-On-The-Go FS global interrupt request. - * @param None - * @retval None - */ -void OTG_FS_IRQHandler(void) { - HAL_PCD_IRQHandler(&pcd_fs_handle); -} - -/** - * @brief This function handles USB OTG Common FS/HS Wakeup functions. - * @param *pcd_handle for FS or HS - * @retval None - */ -static void OTG_CMD_WKUP_Handler(PCD_HandleTypeDef *pcd_handle) { - if (!(pcd_handle->Init.low_power_enable)) { - return; - } - - /* Reset SLEEPDEEP bit of Cortex System Control Register */ - SCB->SCR &= (uint32_t) ~((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); - - /* Configures system clock after wake-up from STOP: enable HSE, PLL and select - PLL as system clock source (HSE and PLL are disabled in STOP mode) */ - - __HAL_RCC_HSE_CONFIG(RCC_HSE_ON); - - /* Wait till HSE is ready */ - while (__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == RESET) {} - - /* Enable the main PLL. */ - __HAL_RCC_PLL_ENABLE(); - - /* Wait till PLL is ready */ - while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET) {} - - /* Select PLL as SYSCLK */ - MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_SYSCLKSOURCE_PLLCLK); - - while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL) {} - - /* ungate PHY clock */ - __HAL_PCD_UNGATE_PHYCLOCK(pcd_handle); -} - -/** - * @brief This function handles USB OTG FS Wakeup IRQ Handler. - * @param None - * @retval None - */ -void OTG_FS_WKUP_IRQHandler(void) { - OTG_CMD_WKUP_Handler(&pcd_fs_handle); - - /* Clear EXTI pending Bit*/ - __HAL_USB_FS_EXTI_CLEAR_FLAG(); -} diff --git a/micropython/trezorhal/usb.h b/micropython/trezorhal/usb.h index 57b61eef..e65c638c 100644 --- a/micropython/trezorhal/usb.h +++ b/micropython/trezorhal/usb.h @@ -1,3 +1,10 @@ +/* + * Copyright (c) Jan Pochyla, SatoshiLabs + * + * Licensed under TREZOR License + * see LICENSE file for details + */ + #ifndef __TREZORHAL_USB_H__ #define __TREZORHAL_USB_H__ @@ -26,7 +33,7 @@ typedef struct __attribute__((packed)) { uint8_t bLength; uint8_t bDescriptorType; uint16_t wData; -} usb_string_descriptor_t; +} usb_langid_descriptor_t; typedef struct __attribute__((packed)) { uint8_t bLength; @@ -81,7 +88,7 @@ typedef struct { const uint8_t *serial_str; const uint8_t *config_str; const uint8_t *interface_str; -} usb_string_table_t; +} usb_dev_string_table_t; typedef struct { uint16_t vendor_id; @@ -97,8 +104,7 @@ typedef struct { typedef enum { USB_IFACE_TYPE_DISABLED = 0, USB_IFACE_TYPE_VCP = 1, - // USB_IFACE_TYPE_MSC = 2, - USB_IFACE_TYPE_HID = 3, + USB_IFACE_TYPE_HID = 2, } usb_iface_type_t; #include "usb_hid-defs.h" diff --git a/micropython/trezorhal/usb_hid-defs.h b/micropython/trezorhal/usb_hid-defs.h index 7dbdb3d6..2d455fd4 100644 --- a/micropython/trezorhal/usb_hid-defs.h +++ b/micropython/trezorhal/usb_hid-defs.h @@ -1,3 +1,10 @@ +/* + * Copyright (c) Jan Pochyla, SatoshiLabs + * + * Licensed under TREZOR License + * see LICENSE file for details + */ + typedef struct __attribute__((packed)) { uint8_t bLength; uint8_t bDescriptorType; diff --git a/micropython/trezorhal/usb_hid-impl.h b/micropython/trezorhal/usb_hid-impl.h index cd9e48af..4961cfa1 100644 --- a/micropython/trezorhal/usb_hid-impl.h +++ b/micropython/trezorhal/usb_hid-impl.h @@ -1,10 +1,17 @@ -#define USB_DESC_TYPE_HID 0x21 -#define USB_DESC_TYPE_REPORT 0x22 +/* + * Copyright (c) Jan Pochyla, SatoshiLabs + * + * Licensed under TREZOR License + * see LICENSE file for details + */ -#define HID_REQ_SET_PROTOCOL 0x0b -#define HID_REQ_GET_PROTOCOL 0x03 -#define HID_REQ_SET_IDLE 0x0a -#define HID_REQ_GET_IDLE 0x02 +#define USB_DESC_TYPE_HID 0x21 +#define USB_DESC_TYPE_REPORT 0x22 + +#define USB_HID_REQ_SET_PROTOCOL 0x0b +#define USB_HID_REQ_GET_PROTOCOL 0x03 +#define USB_HID_REQ_SET_IDLE 0x0a +#define USB_HID_REQ_GET_IDLE 0x02 /* usb_hid_add adds and configures new USB HID interface according to * configuration options passed in `info`. */ @@ -39,7 +46,7 @@ int usb_hid_add(const usb_hid_info_t *info) { } // Interface descriptor - d->iface.bLength = USB_LEN_IF_DESC; + d->iface.bLength = sizeof(usb_interface_descriptor_t); d->iface.bDescriptorType = USB_DESC_TYPE_INTERFACE; d->iface.bInterfaceNumber = info->iface_num; d->iface.bAlternateSetting = 0x00; @@ -59,7 +66,7 @@ int usb_hid_add(const usb_hid_info_t *info) { d->hid.wReportDescriptorLength = info->report_desc_len; // IN endpoint (sending) - d->ep_in.bLength = USB_LEN_EP_DESC; + 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.bmAttributes = USBD_EP_TYPE_INTR; @@ -67,7 +74,7 @@ int usb_hid_add(const usb_hid_info_t *info) { d->ep_in.bInterval = info->polling_interval; // OUT endpoint (receiving) - d->ep_out.bLength = USB_LEN_EP_DESC; + 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.bmAttributes = USBD_EP_TYPE_INTR; @@ -234,19 +241,19 @@ static int usb_hid_class_setup(USBD_HandleTypeDef *dev, usb_hid_state_t *state, case USB_REQ_TYPE_CLASS: switch (req->bRequest) { - case HID_REQ_SET_PROTOCOL: + case USB_HID_REQ_SET_PROTOCOL: state->protocol = req->wValue; break; - case HID_REQ_GET_PROTOCOL: + case USB_HID_REQ_GET_PROTOCOL: USBD_CtlSendData(dev, &state->protocol, sizeof(state->protocol)); break; - case HID_REQ_SET_IDLE: + case USB_HID_REQ_SET_IDLE: state->idle_rate = req->wValue >> 8; break; - case HID_REQ_GET_IDLE: + case USB_HID_REQ_GET_IDLE: USBD_CtlSendData(dev, &state->idle_rate, sizeof(state->idle_rate)); break; diff --git a/micropython/trezorhal/usb_vcp-defs.h b/micropython/trezorhal/usb_vcp-defs.h index 8507f0a7..237f9edb 100644 --- a/micropython/trezorhal/usb_vcp-defs.h +++ b/micropython/trezorhal/usb_vcp-defs.h @@ -1,3 +1,10 @@ +/* + * Copyright (c) Jan Pochyla, SatoshiLabs + * + * Licensed under TREZOR License + * see LICENSE file for details + */ + typedef struct __attribute__((packed)) { uint8_t bFunctionLength; uint8_t bDescriptorType; @@ -41,6 +48,27 @@ typedef struct __attribute__((packed)) { 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; + typedef struct { uint8_t iface_num; // Address of this VCP interface uint8_t data_iface_num; // Address of data interface of the VCP interface association @@ -48,17 +76,9 @@ typedef struct { uint8_t ep_in; // Address of IN endpoint (with the highest bit set) uint8_t ep_out; // Address of OUT endpoint uint8_t polling_interval; // In units of 1ms - uint8_t max_cmd_packet_len; uint8_t max_data_packet_len; } usb_vcp_info_t; -// typedef struct { -// uint32_t cap; -// uint32_t read; -// uint32_t write; -// uint8_t *buf; -// } ring_buffer_t; - typedef struct { uint8_t is_connected; uint8_t in_idle; @@ -71,7 +91,6 @@ typedef struct { uint8_t ep_in; uint8_t ep_out; uint8_t polling_interval; - uint8_t max_cmd_packet_len; uint8_t max_data_packet_len; const usb_vcp_descriptor_block_t *desc_block; diff --git a/micropython/trezorhal/usb_vcp-impl.h b/micropython/trezorhal/usb_vcp-impl.h index b95acb96..7c0ea2b1 100644 --- a/micropython/trezorhal/usb_vcp-impl.h +++ b/micropython/trezorhal/usb_vcp-impl.h @@ -1,56 +1,38 @@ -#define USB_LEN_ASSOC_DESC 0x08 +/* + * Copyright (c) Jan Pochyla, SatoshiLabs + * + * Licensed under TREZOR License + * see LICENSE file for details + */ -#define USB_DESC_TYPE_ASSOCIATION 0x0b -#define USB_DESC_TYPE_HEADER 0x00 -#define USB_DESC_TYPE_CALL_MANAGEMENT 0x01 -#define USB_DESC_TYPE_ACM 0x02 -#define USB_DESC_TYPE_UNION 0x06 +// Communications Device Class Code (bFunctionClass, bInterfaceClass) +#define USB_CLASS_CDC 0x02 -#define CDC_GET_LINE_CODING 0x21 -#define CDC_SET_CONTROL_LINE_STATE 0x22 +// Data Interface Class Code (bInterfaceClass) +#define USB_CLASS_DATA 0x0A -// static int ring_init(ring_buffer_t *b, uint8_t *buf, size_t cap) { -// if (cap == 0 || (cap & (cap - 1)) != 0) { -// return 1; // Capacity needs to be a power of 2 -// } -// b->buf = buf; -// b->cap = cap; -// b->read = 0; -// b->write = 0; -// return 0; -// } +// Class Subclass Code (bFunctionSubClass, bInterfaceSubClass) +#define USB_CDC_SUBCLASS_ACM 0x02 -// static inline size_t ring_length(ring_buffer_t *b) { -// return (b->write - b->read); -// } +// Communications Interface Class Control Protocol Codes (bFunctionProtocol, bInterfaceProtocol) +#define USB_CDC_PROTOCOL_AT 0x01 -// static inline int ring_empty(ring_buffer_t *b) { -// return ring_length(b) == 0; -// } +// Descriptor Types (bDescriptorType) +#define USB_DESC_TYPE_ASSOCIATION 0x0b +#define USB_DESC_TYPE_CS_INTERACE 0x24 -// static inline int ring_full(ring_buffer_t *b) { -// return ring_length(b) == b->cap; -// } +// Descriptor SubTypes (bDescriptorSubtype) +#define USB_DESC_TYPE_HEADER 0x00 +#define USB_DESC_TYPE_CM 0x01 +#define USB_DESC_TYPE_ACM 0x02 +#define USB_DESC_TYPE_UNION 0x06 -// uint32_t ring_read(ring_buffer_t *b, uint8_t *buf, uint32_t len) { -// const uint32_t mask = b->cap - 1; -// uint32_t i; -// for (i = 0; (i < len) && !ring_empty(b); i++) { -// buf[i] = b->buf[b->read & mask]; -// b->read++; -// } -// return i; -// } +// Class-Specific Request Codes for PSTN subclasses +#define USB_CDC_GET_LINE_CODING 0x21 +#define USB_CDC_SET_CONTROL_LINE_STATE 0x22 -// uint32_t ring_write(ring_buffer_t *b, const uint8_t *buf, uint32_t len) { -// const uint32_t mask = b->cap - 1; -// uint32_t i; -// for (i = 0; (i < len) && !ring_full(b); i++) { -// b->buf[b->write & mask] = buf[i]; -// b->write++; -// } -// return i; -// } +// Maximal length of packets on IN CMD EP +#define USB_CDC_MAX_CMD_PACKET_LEN 0x08 /* usb_vcp_add adds and configures new USB VCP interface according to * configuration options passed in `info`. */ @@ -72,7 +54,7 @@ int usb_vcp_add(const usb_vcp_info_t *info) { } if ((info->ep_cmd & USB_EP_DIR_MSK) != USB_EP_DIR_IN) { - return 1; // CMD EP is invalid + return 1; // IN CMD EP is invalid } if ((info->ep_in & USB_EP_DIR_MSK) != USB_EP_DIR_IN) { return 1; // IN EP is invalid @@ -82,73 +64,73 @@ int usb_vcp_add(const usb_vcp_info_t *info) { } // Interface association descriptor - d->assoc.bLength = USB_LEN_ASSOC_DESC; + d->assoc.bLength = sizeof(usb_interface_assoc_descriptor_t); d->assoc.bDescriptorType = USB_DESC_TYPE_ASSOCIATION; d->assoc.bFirstInterface = info->iface_num; d->assoc.bInterfaceCount = 2; - d->assoc.bFunctionClass = 0x02; // Communication Interface Class - d->assoc.bFunctionSubClass = 0x02; // Abstract Control Model - d->assoc.bFunctionProtocol = 0x01; // Common AT commands + d->assoc.bFunctionClass = USB_CLASS_CDC; + d->assoc.bFunctionSubClass = USB_CDC_SUBCLASS_ACM; + d->assoc.bFunctionProtocol = USB_CDC_PROTOCOL_AT; d->assoc.iFunction = 0x00; // Index of string descriptor describing the function // Interface descriptor - d->iface_cdc.bLength = USB_LEN_IF_DESC; + d->iface_cdc.bLength = sizeof(usb_interface_descriptor_t); d->iface_cdc.bDescriptorType = USB_DESC_TYPE_INTERFACE; d->iface_cdc.bInterfaceNumber = info->iface_num; d->iface_cdc.bAlternateSetting = 0x00; d->iface_cdc.bNumEndpoints = 1; - d->iface_cdc.bInterfaceClass = 0x02; // Communication Interface Class - d->iface_cdc.bInterfaceSubClass = 0x02; // Abstract Control Model - d->iface_cdc.bInterfaceProtocol = 0x01; // Common AT commands + d->iface_cdc.bInterfaceClass = USB_CLASS_CDC; + d->iface_cdc.bInterfaceSubClass = USB_CDC_SUBCLASS_ACM; + d->iface_cdc.bInterfaceProtocol = USB_CDC_PROTOCOL_AT; d->iface_cdc.iInterface = 0x00; // Index of string descriptor describing the interface // Header Functional Descriptor d->fheader.bFunctionLength = sizeof(usb_vcp_header_descriptor_t); - d->fheader.bDescriptorType = 0x24; // CS_INTERFACE - d->fheader.bDescriptorSubtype = 0x00; // Header Func desc + d->fheader.bDescriptorType = USB_DESC_TYPE_CS_INTERACE; + d->fheader.bDescriptorSubtype = USB_DESC_TYPE_HEADER; d->fheader.bcdCDC = 0x1001; // Spec release number // Call Management Functional Descriptor d->fcm.bFunctionLength = sizeof(usb_vcp_cm_descriptor_t); - d->fcm.bDescriptorType = 0x24; // CS_INTERFACE - d->fcm.bDescriptorSubtype = 0x01; // Call Management Func desc + d->fcm.bDescriptorType = USB_DESC_TYPE_CS_INTERACE; + d->fcm.bDescriptorSubtype = USB_DESC_TYPE_CM; d->fcm.bmCapabilities = 0x00; // D0+D1 d->fcm.bDataInterface = info->data_iface_num; // ACM Functional Descriptor d->facm.bFunctionLength = sizeof(usb_vcp_acm_descriptor_t); - d->facm.bDescriptorType = 0x24; // CS_INTERFACE - d->facm.bDescriptorSubtype = 0x02; // Abstract Control Management desc + d->facm.bDescriptorType = USB_DESC_TYPE_CS_INTERACE; + d->facm.bDescriptorSubtype = USB_DESC_TYPE_ACM; d->facm.bmCapabilities = 0x02; // Union Functional Descriptor d->funion.bFunctionLength = sizeof(usb_vcp_union_descriptor_t); - d->funion.bDescriptorType = 0x24; // CS_INTERFACE - d->funion.bDescriptorSubtype = 0x06; // Union Func desc + d->funion.bDescriptorType = USB_DESC_TYPE_CS_INTERACE; + d->funion.bDescriptorSubtype = USB_DESC_TYPE_UNION; d->funion.bControlInterface = info->iface_num; d->funion.bSubordinateInterface0 = info->data_iface_num; // IN CMD endpoint (control) - d->ep_cmd.bLength = USB_LEN_EP_DESC; + 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.bmAttributes = USBD_EP_TYPE_INTR; - d->ep_cmd.wMaxPacketSize = info->max_cmd_packet_len; + d->ep_cmd.wMaxPacketSize = USB_CDC_MAX_CMD_PACKET_LEN; d->ep_cmd.bInterval = info->polling_interval; // Interface descriptor - d->iface_data.bLength = USB_LEN_IF_DESC; + d->iface_data.bLength = sizeof(usb_interface_descriptor_t); d->iface_data.bDescriptorType = USB_DESC_TYPE_INTERFACE; d->iface_data.bInterfaceNumber = info->data_iface_num; d->iface_data.bAlternateSetting = 0x00; d->iface_data.bNumEndpoints = 2; - d->iface_data.bInterfaceClass = 0x0A; // CDC + d->iface_data.bInterfaceClass = USB_CLASS_DATA; d->iface_data.bInterfaceSubClass = 0x00; d->iface_data.bInterfaceProtocol = 0x00; d->iface_data.iInterface = 0x00; // Index of string descriptor describing the interface // OUT endpoint (receiving) - d->ep_out.bLength = USB_LEN_EP_DESC; + 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.bmAttributes = USBD_EP_TYPE_BULK; @@ -156,7 +138,7 @@ int usb_vcp_add(const usb_vcp_info_t *info) { d->ep_out.bInterval = 0x00; // Ignored for bulk endpoints // IN endpoint (sending) - d->ep_in.bLength = USB_LEN_EP_DESC; + 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.bmAttributes = USBD_EP_TYPE_BULK; @@ -164,9 +146,8 @@ int usb_vcp_add(const usb_vcp_info_t *info) { d->ep_in.bInterval = 0x00; // Ignored for bulk endpoints // Config descriptor - // TODO: do this in a clean way usb_desc_add_iface(sizeof(usb_vcp_descriptor_block_t)); - usb_config_desc->bNumInterfaces++; + usb_config_desc->bNumInterfaces++; // usb_vcp_descriptor_block_t contains 2 interfaces // Interface state iface->type = USB_IFACE_TYPE_VCP; @@ -174,7 +155,6 @@ int usb_vcp_add(const usb_vcp_info_t *info) { iface->vcp.ep_cmd = info->ep_cmd; iface->vcp.ep_in = info->ep_in; iface->vcp.ep_out = info->ep_out; - iface->vcp.max_cmd_packet_len = info->max_cmd_packet_len; iface->vcp.max_data_packet_len = info->max_data_packet_len; iface->vcp.desc_block = d; @@ -262,7 +242,7 @@ static int usb_vcp_class_init(USBD_HandleTypeDef *dev, usb_vcp_state_t *state, u // Open endpoints USBD_LL_OpenEP(dev, state->ep_in, USBD_EP_TYPE_BULK, state->max_data_packet_len); USBD_LL_OpenEP(dev, state->ep_out, USBD_EP_TYPE_BULK, state->max_data_packet_len); - USBD_LL_OpenEP(dev, state->ep_cmd, USBD_EP_TYPE_INTR, state->max_cmd_packet_len); + USBD_LL_OpenEP(dev, state->ep_cmd, USBD_EP_TYPE_INTR, USB_CDC_MAX_CMD_PACKET_LEN); // Reset the state state->in_idle = 1; @@ -284,14 +264,11 @@ static int usb_vcp_class_deinit(USBD_HandleTypeDef *dev, usb_vcp_state_t *state, } static int usb_vcp_class_setup(USBD_HandleTypeDef *dev, usb_vcp_state_t *state, USBD_SetupReqTypedef *req) { - static const uint8_t line_coding[] = { - (uint8_t)(115200 >> 0), - (uint8_t)(115200 >> 8), - (uint8_t)(115200 >> 16), - (uint8_t)(115200 >> 24), - 0, // Stop bits - 0, // Parity - 8, // Number of bits + static const usb_cdc_line_coding_t line_coding = { + .dwDTERate = 115200, + .bCharFormat = USB_CDC_1_STOP_BITS, + .bParityType = USB_CDC_NO_PARITY, + .bDataBits = 8, }; switch (req->bmRequest & USB_REQ_TYPE_MASK) { @@ -301,7 +278,7 @@ static int usb_vcp_class_setup(USBD_HandleTypeDef *dev, usb_vcp_state_t *state, switch (req->bRequest) { case USB_CDC_GET_LINE_CODING: - USBD_CtlSendData(dev, UNCONST(line_coding), sizeof(line_coding)); + USBD_CtlSendData(dev, (uint8_t *)(&line_coding), sizeof(line_coding)); break; case USB_CDC_SET_CONTROL_LINE_STATE: diff --git a/micropython/trezorhal/usbd_conf.c b/micropython/trezorhal/usbd_conf.c index d3770d79..fb0af211 100644 --- a/micropython/trezorhal/usbd_conf.c +++ b/micropython/trezorhal/usbd_conf.c @@ -42,10 +42,10 @@ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ #ifdef USE_USB_FS -PCD_HandleTypeDef pcd_fs_handle; +static PCD_HandleTypeDef pcd_fs_handle; #endif #ifdef USE_USB_HS -PCD_HandleTypeDef pcd_hs_handle; +static PCD_HandleTypeDef pcd_hs_handle; #endif /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ @@ -685,4 +685,65 @@ void USBD_LL_Delay(uint32_t Delay) HAL_Delay(Delay); } +/******************************************************************************* + IRQ Handlers +*******************************************************************************/ + +/** + * @brief This function handles USB-On-The-Go FS global interrupt request. + * @param None + * @retval None + */ +void OTG_FS_IRQHandler(void) { + HAL_PCD_IRQHandler(&pcd_fs_handle); +} + +/** + * @brief This function handles USB OTG Common FS/HS Wakeup functions. + * @param *pcd_handle for FS or HS + * @retval None + */ +static void OTG_CMD_WKUP_Handler(PCD_HandleTypeDef *pcd_handle) { + if (!(pcd_handle->Init.low_power_enable)) { + return; + } + + /* Reset SLEEPDEEP bit of Cortex System Control Register */ + SCB->SCR &= (uint32_t) ~((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); + + /* Configures system clock after wake-up from STOP: enable HSE, PLL and select + PLL as system clock source (HSE and PLL are disabled in STOP mode) */ + + __HAL_RCC_HSE_CONFIG(RCC_HSE_ON); + + /* Wait till HSE is ready */ + while (__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == RESET) {} + + /* Enable the main PLL. */ + __HAL_RCC_PLL_ENABLE(); + + /* Wait till PLL is ready */ + while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET) {} + + /* Select PLL as SYSCLK */ + MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_SYSCLKSOURCE_PLLCLK); + + while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL) {} + + /* ungate PHY clock */ + __HAL_PCD_UNGATE_PHYCLOCK(pcd_handle); +} + +/** + * @brief This function handles USB OTG FS Wakeup IRQ Handler. + * @param None + * @retval None + */ +void OTG_FS_WKUP_IRQHandler(void) { + OTG_CMD_WKUP_Handler(&pcd_fs_handle); + + /* Clear EXTI pending Bit*/ + __HAL_USB_FS_EXTI_CLEAR_FLAG(); +} + /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/