From 388360cc5adf9daafd37c9c45aa3250b95d64f3b Mon Sep 17 00:00:00 2001 From: Tomas Rezucha Date: Wed, 6 Dec 2023 17:47:16 +0100 Subject: [PATCH] fix(usb/host): Correctly parse MPS fields in HighSpeed EP descriptors Bits [11,12] in HighSpeed periodic endpoints specify the number of additional transaction opportunities per microframe --- components/usb/hcd_dwc.c | 6 +++--- components/usb/include/usb/usb_types_ch9.h | 11 +++++++++-- components/usb/test_apps/hcd/main/test_hcd_bulk.c | 5 +++-- components/usb/usb_helpers.c | 2 +- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/components/usb/hcd_dwc.c b/components/usb/hcd_dwc.c index 41586ea8ee..5065e6a1bc 100644 --- a/components/usb/hcd_dwc.c +++ b/components/usb/hcd_dwc.c @@ -1536,9 +1536,9 @@ static bool pipe_alloc_hcd_support_verification(usb_dwc_hal_context_t *hal, cons } } - if (ep_desc->wMaxPacketSize > limit) { + if (USB_EP_DESC_GET_MPS(ep_desc) > limit) { ESP_LOGE(HCD_DWC_TAG, "EP MPS (%d) exceeds supported limit (%d)", - ep_desc->wMaxPacketSize, + USB_EP_DESC_GET_MPS(ep_desc), limit); return false; } @@ -1571,7 +1571,7 @@ static void pipe_set_ep_char(const hcd_pipe_config_t *pipe_config, usb_transfer_ ep_char->mps = (pipe_config->dev_speed == USB_SPEED_LOW) ? CTRL_EP_MAX_MPS_LS : CTRL_EP_MAX_MPS_HSFS; } else { ep_char->bEndpointAddress = pipe_config->ep_desc->bEndpointAddress; - ep_char->mps = pipe_config->ep_desc->wMaxPacketSize; + ep_char->mps = USB_EP_DESC_GET_MPS(pipe_config->ep_desc); } ep_char->dev_addr = pipe_config->dev_addr; ep_char->ls_via_fs_hub = (port_speed == USB_SPEED_FULL && pipe_config->dev_speed == USB_SPEED_LOW); diff --git a/components/usb/include/usb/usb_types_ch9.h b/components/usb/include/usb/usb_types_ch9.h index 36c4391ccb..8054d91f82 100644 --- a/components/usb/include/usb/usb_types_ch9.h +++ b/components/usb/include/usb/usb_types_ch9.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -435,6 +435,12 @@ ESP_STATIC_ASSERT(sizeof(usb_ep_desc_t) == USB_EP_DESC_SIZE, "Size of usb_ep_des #define USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK 0x0f #define USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK 0x80 +/** + * @brief Bit masks belonging to the wMaxPacketSize field of endpoint descriptor + */ +#define USB_W_MAX_PACKET_SIZE_MPS_MASK 0x07ff +#define USB_W_MAX_PACKET_SIZE_MULT_MASK 0x1800 + /** * @brief Bit masks belonging to the bmAttributes field of an endpoint descriptor */ @@ -459,7 +465,8 @@ ESP_STATIC_ASSERT(sizeof(usb_ep_desc_t) == USB_EP_DESC_SIZE, "Size of usb_ep_des #define USB_EP_DESC_GET_XFERTYPE(desc_ptr) ((usb_transfer_type_t) ((desc_ptr)->bmAttributes & USB_BM_ATTRIBUTES_XFERTYPE_MASK)) #define USB_EP_DESC_GET_EP_NUM(desc_ptr) ((desc_ptr)->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK) #define USB_EP_DESC_GET_EP_DIR(desc_ptr) (((desc_ptr)->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK) ? 1 : 0) -#define USB_EP_DESC_GET_MPS(desc_ptr) ((desc_ptr)->wMaxPacketSize & 0x7FF) +#define USB_EP_DESC_GET_MPS(desc_ptr) ((desc_ptr)->wMaxPacketSize & USB_W_MAX_PACKET_SIZE_MPS_MASK) +#define USB_EP_DESC_GET_MULT(desc_ptr) (((desc_ptr)->wMaxPacketSize & USB_W_MAX_PACKET_SIZE_MULT_MASK) >> 11) // ------------------ String Descriptor -------------------- diff --git a/components/usb/test_apps/hcd/main/test_hcd_bulk.c b/components/usb/test_apps/hcd/main/test_hcd_bulk.c index c425c5b2d3..b22273752a 100644 --- a/components/usb/test_apps/hcd/main/test_hcd_bulk.c +++ b/components/usb/test_apps/hcd/main/test_hcd_bulk.c @@ -68,10 +68,11 @@ TEST_CASE("Test HCD bulk pipe URBs", "[bulk][full_speed]") //Create URBs for CBW, Data, and CSW transport. IN Buffer sizes are rounded up to nearest MPS urb_t *urb_cbw = test_hcd_alloc_urb(0, sizeof(mock_msc_bulk_cbw_t)); urb_t *urb_data = test_hcd_alloc_urb(0, TEST_NUM_SECTORS_PER_XFER * MOCK_MSC_SCSI_SECTOR_SIZE); - urb_t *urb_csw = test_hcd_alloc_urb(0, sizeof(mock_msc_bulk_csw_t) + (mock_msc_scsi_bulk_in_ep_desc.wMaxPacketSize - (sizeof(mock_msc_bulk_csw_t) % mock_msc_scsi_bulk_in_ep_desc.wMaxPacketSize))); + const uint16_t mps = USB_EP_DESC_GET_MPS(&mock_msc_scsi_bulk_in_ep_desc) ; + urb_t *urb_csw = test_hcd_alloc_urb(0, sizeof(mock_msc_bulk_csw_t) + (mps - (sizeof(mock_msc_bulk_csw_t) % mps))); urb_cbw->transfer.num_bytes = sizeof(mock_msc_bulk_cbw_t); urb_data->transfer.num_bytes = TEST_NUM_SECTORS_PER_XFER * MOCK_MSC_SCSI_SECTOR_SIZE; - urb_csw->transfer.num_bytes = sizeof(mock_msc_bulk_csw_t) + (mock_msc_scsi_bulk_in_ep_desc.wMaxPacketSize - (sizeof(mock_msc_bulk_csw_t) % mock_msc_scsi_bulk_in_ep_desc.wMaxPacketSize)); + urb_csw->transfer.num_bytes = sizeof(mock_msc_bulk_csw_t) + (mps - (sizeof(mock_msc_bulk_csw_t) % mps)); for (int block_num = 0; block_num < TEST_NUM_SECTORS_TOTAL; block_num += TEST_NUM_SECTORS_PER_XFER) { //Initialize CBW URB, then send it on the BULK OUT pipe diff --git a/components/usb/usb_helpers.c b/components/usb/usb_helpers.c index 0c06d57f8a..08c50e3b87 100644 --- a/components/usb/usb_helpers.c +++ b/components/usb/usb_helpers.c @@ -198,7 +198,7 @@ static void print_ep_desc(const usb_ep_desc_t *ep_desc) USB_EP_DESC_GET_EP_NUM(ep_desc), USB_EP_DESC_GET_EP_DIR(ep_desc) ? "IN" : "OUT"); printf("\t\tbmAttributes 0x%x\t%s\n", ep_desc->bmAttributes, ep_type_str); - printf("\t\twMaxPacketSize %d\n", ep_desc->wMaxPacketSize); + printf("\t\twMaxPacketSize %d\n", USB_EP_DESC_GET_MPS(ep_desc)); printf("\t\tbInterval %d\n", ep_desc->bInterval); }