mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-02-23 21:02:23 +00:00
trezorhal: minor usb cleanup
This commit is contained in:
parent
cc38f537d3
commit
df57f47aa9
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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****/
|
||||
|
Loading…
Reference in New Issue
Block a user