diff --git a/micropython/trezorhal/usb.c b/micropython/trezorhal/usb.c index 42e6eb5132..8dd6fc4fe4 100644 --- a/micropython/trezorhal/usb.c +++ b/micropython/trezorhal/usb.c @@ -60,11 +60,13 @@ int usb_init(const usb_dev_info_t *dev_info) { 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; + if ((0 != check_desc_str(dev_info->manufacturer_str)) || + (0 != check_desc_str(dev_info->product_str)) || + (0 != check_desc_str(dev_info->serial_number_str)) || + (0 != check_desc_str(dev_info->configuration_str)) || + (0 != check_desc_str(dev_info->interface_str))) { + return 1; // Invalid descriptor string + } 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; @@ -265,6 +267,15 @@ static uint8_t usb_class_setup(USBD_HandleTypeDef *dev, USBD_SetupReqTypedef *re } static uint8_t usb_class_ep0_rx_ready(USBD_HandleTypeDef *dev) { + for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { + switch (usb_ifaces[i].type) { + case USB_IFACE_TYPE_VCP: + usb_vcp_class_ep0_rx_ready(dev, &usb_ifaces[i].vcp); + break; + default: + break; + } + } return USBD_OK; } diff --git a/micropython/trezorhal/usb_hid-defs.h b/micropython/trezorhal/usb_hid-defs.h index 2d455fd49d..566179fb55 100644 --- a/micropython/trezorhal/usb_hid-defs.h +++ b/micropython/trezorhal/usb_hid-defs.h @@ -39,11 +39,11 @@ typedef struct { uint8_t ep_out; // Address of OUT endpoint uint8_t subclass; // usb_iface_subclass_t uint8_t protocol; // usb_iface_protocol_t - uint8_t max_packet_len; // rx_buffer should be big enough uint8_t polling_interval; // In units of 1ms - uint8_t report_desc_len; - const uint8_t *report_desc; - uint8_t *rx_buffer; // Big enough for max_packet_len + uint8_t max_packet_len; // Length of the biggest report and of rx_buffer + uint8_t report_desc_len; // Length of report_desc + uint8_t *rx_buffer; // With length of max_packet_len bytes + const uint8_t *report_desc; // With length of report_desc_len bytes } usb_hid_info_t; typedef struct { @@ -51,9 +51,8 @@ typedef struct { 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 rx_buffer_len; // Length of data read into rx_buffer + uint8_t last_read_len; // Length of data read into rx_buffer - // Configuration (copied from usb_hid_info_t on init) uint8_t ep_in; uint8_t ep_out; uint8_t max_packet_len; diff --git a/micropython/trezorhal/usb_hid-impl.h b/micropython/trezorhal/usb_hid-impl.h index 4961cfa1d3..827dd1a488 100644 --- a/micropython/trezorhal/usb_hid-impl.h +++ b/micropython/trezorhal/usb_hid-impl.h @@ -5,6 +5,8 @@ * see LICENSE file for details */ +#define USB_CLASS_HID 0x03 + #define USB_DESC_TYPE_HID 0x21 #define USB_DESC_TYPE_REPORT 0x22 @@ -50,8 +52,8 @@ int usb_hid_add(const usb_hid_info_t *info) { d->iface.bDescriptorType = USB_DESC_TYPE_INTERFACE; d->iface.bInterfaceNumber = info->iface_num; d->iface.bAlternateSetting = 0x00; - d->iface.bNumEndpoints = 0x02; - d->iface.bInterfaceClass = 0x03; // HID Class + d->iface.bNumEndpoints = 2; + d->iface.bInterfaceClass = USB_CLASS_HID; d->iface.bInterfaceSubClass = info->subclass; d->iface.bInterfaceProtocol = info->protocol; d->iface.iInterface = 0x00; // Index of string descriptor describing the interface @@ -61,7 +63,7 @@ int usb_hid_add(const usb_hid_info_t *info) { d->hid.bDescriptorType = USB_DESC_TYPE_HID; d->hid.bcdHID = 0x1101; // HID Class Spec release number d->hid.bCountryCode = 0x00; // Hardware target country - d->hid.bNumDescriptors = 0x01; // Number of HID class descriptors to follow + d->hid.bNumDescriptors = 1; // Number of HID class descriptors d->hid.bReportDescriptorType = USB_DESC_TYPE_REPORT; d->hid.wReportDescriptorLength = info->report_desc_len; @@ -86,11 +88,15 @@ int usb_hid_add(const usb_hid_info_t *info) { // Interface state iface->type = USB_IFACE_TYPE_HID; + iface->hid.in_idle = 1; + iface->hid.protocol = 0; + iface->hid.idle_rate = 0; + iface->hid.alt_setting = 0; iface->hid.ep_in = info->ep_in; iface->hid.ep_out = info->ep_out; - iface->hid.rx_buffer = info->rx_buffer; iface->hid.max_packet_len = info->max_packet_len; iface->hid.report_desc_len = info->report_desc_len; + iface->hid.rx_buffer = info->rx_buffer; iface->hid.report_desc = info->report_desc; iface->hid.desc_block = d; @@ -105,7 +111,7 @@ int usb_hid_can_read(uint8_t iface_num) { if (iface->type != USB_IFACE_TYPE_HID) { return 0; // Invalid interface type } - if (iface->hid.rx_buffer_len == 0) { + if (iface->hid.last_read_len == 0) { return 0; // Nothing in the receiving buffer } if (usb_dev_handle.dev_state != USBD_STATE_CONFIGURED) { @@ -142,11 +148,11 @@ int usb_hid_read(uint8_t iface_num, uint8_t *buf, uint32_t len) { usb_hid_state_t *state = &iface->hid; // Copy maximum possible amount of data and truncate the buffer length - if (len < state->rx_buffer_len) { + if (len < state->last_read_len) { return 0; // Not enough data in the read buffer } - len = state->rx_buffer_len; - state->rx_buffer_len = 0; + len = state->last_read_len; + state->last_read_len = 0; memcpy(buf, state->rx_buffer, len); // Clear NAK to indicate we are ready to read more data @@ -302,14 +308,13 @@ static uint8_t usb_hid_class_data_in(USBD_HandleTypeDef *dev, usb_hid_state_t *s static uint8_t usb_hid_class_data_out(USBD_HandleTypeDef *dev, usb_hid_state_t *state, uint8_t ep_num) { if (ep_num == state->ep_out) { - // User should provide state->rx_buffer_len that is big - // enough for state->max_packet_len bytes. - state->rx_buffer_len = USBD_LL_GetRxDataSize(dev, ep_num); + state->last_read_len = USBD_LL_GetRxDataSize(dev, ep_num); // Prepare the OUT EP to receive next packet + // User should provide state->rx_buffer that is big enough for state->max_packet_len bytes USBD_LL_PrepareReceive(dev, ep_num, state->rx_buffer, state->max_packet_len); - if (state->rx_buffer_len > 0) { + if (state->last_read_len > 0) { // Block the OUT EP until we process received data usb_ep_set_nak(dev, ep_num); }