diff --git a/components/hal/include/hal/usb_dwc_hal.h b/components/hal/include/hal/usb_dwc_hal.h index 03ab8736da..7af5bd45fa 100644 --- a/components/hal/include/hal/usb_dwc_hal.h +++ b/components/hal/include/hal/usb_dwc_hal.h @@ -142,7 +142,7 @@ typedef struct { uint32_t val; }; struct { - usb_hal_interval_t interval; /**< The interval of the endpoint */ + unsigned int interval; /**< The interval of the endpoint in frames (FS) or microframes (HS) */ uint32_t phase_offset_frames; /**< Phase offset in number of frames */ } periodic; /**< Characteristic for periodic (interrupt/isochronous) endpoints only */ } usb_dwc_hal_ep_char_t; diff --git a/components/hal/include/hal/usb_dwc_types.h b/components/hal/include/hal/usb_dwc_types.h index 0ffa36aa68..22018953bc 100644 --- a/components/hal/include/hal/usb_dwc_types.h +++ b/components/hal/include/hal/usb_dwc_types.h @@ -51,19 +51,6 @@ typedef enum { USB_HAL_FRAME_LIST_LEN_64 = 64, } usb_hal_frame_list_len_t; -/** - * @brief Support intervals in number of USB frames (i.e., 1ms) - */ -typedef enum { - USB_HAL_INTERVAL_1 = 1, - USB_HAL_INTERVAL_2 = 2, - USB_HAL_INTERVAL_4 = 4, - USB_HAL_INTERVAL_8 = 8, - USB_HAL_INTERVAL_16 = 16, - USB_HAL_INTERVAL_32 = 32, - USB_HAL_INTERVAL_64 = 64, -} usb_hal_interval_t; - #ifdef __cplusplus } #endif diff --git a/components/usb/hcd_dwc.c b/components/usb/hcd_dwc.c index 41586ea8ee..6a8689f724 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,38 +1571,38 @@ 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); // Calculate the pipe's interval in terms of USB frames // @see USB-OTG programming guide chapter 6.5 for more information if (type == USB_TRANSFER_TYPE_INTR || type == USB_TRANSFER_TYPE_ISOCHRONOUS) { - unsigned int interval_frames; - unsigned int xfer_list_len; - if (type == USB_TRANSFER_TYPE_INTR) { - interval_frames = pipe_config->ep_desc->bInterval; - xfer_list_len = XFER_LIST_LEN_INTR; + // Convert bInterval field to real value + // @see USB 2.0 specs, Table 9-13 + unsigned int interval_value; + if (type == USB_TRANSFER_TYPE_INTR && pipe_config->dev_speed != USB_SPEED_HIGH) { + interval_value = pipe_config->ep_desc->bInterval; } else { - interval_frames = (1 << (pipe_config->ep_desc->bInterval - 1)); - xfer_list_len = XFER_LIST_LEN_ISOC; + interval_value = (1 << (pipe_config->ep_desc->bInterval - 1)); } // Round down interval to nearest power of 2 - if (interval_frames >= 32) { - interval_frames = 32; - } else if (interval_frames >= 16) { - interval_frames = 16; - } else if (interval_frames >= 8) { - interval_frames = 8; - } else if (interval_frames >= 4) { - interval_frames = 4; - } else if (interval_frames >= 2) { - interval_frames = 2; - } else if (interval_frames >= 1) { - interval_frames = 1; + if (interval_value >= 32) { + interval_value = 32; + } else if (interval_value >= 16) { + interval_value = 16; + } else if (interval_value >= 8) { + interval_value = 8; + } else if (interval_value >= 4) { + interval_value = 4; + } else if (interval_value >= 2) { + interval_value = 2; + } else if (interval_value >= 1) { + interval_value = 1; } - ep_char->periodic.interval = interval_frames; + ep_char->periodic.interval = interval_value; // We are the Nth pipe to be allocated. Use N as a phase offset + unsigned int xfer_list_len = (type == USB_TRANSFER_TYPE_INTR) ? XFER_LIST_LEN_INTR : XFER_LIST_LEN_ISOC; ep_char->periodic.phase_offset_frames = pipe_idx & (xfer_list_len - 1); } else { ep_char->periodic.interval = 0; 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); }