From 62d000092661d61a660fa9ea3f52afd6e493db5b Mon Sep 17 00:00:00 2001 From: sakumisu <1203593632@qq.com> Date: Sun, 4 Sep 2022 20:17:32 +0800 Subject: [PATCH] refactor usb host stack: hcd api, hub process and usb no cache ram process --- .gitignore | 1 - cherryusb_config_template.h | 37 +- class/cdc/usbh_cdc_acm.c | 81 +- class/cdc/usbh_cdc_acm.h | 8 +- class/hid/usbh_hid.c | 55 +- class/hid/usbh_hid.h | 5 +- class/hub/usbh_hub.c | 543 +++++--- class/hub/usbh_hub.h | 4 + class/msc/usbh_msc.c | 109 +- class/msc/usbh_msc.h | 9 +- class/mtp/usbh_mtp.c | 18 +- class/mtp/usbh_mtp.h | 6 +- class/printer/usbh_printer.c | 22 +- class/printer/usbh_printer.h | 4 +- class/template/usbh_xxx.c | 14 +- class/template/usbh_xxx.h | 4 +- class/vendor/axusbnet.c | 6 +- class/vendor/axusbnet.h | 6 +- class/vendor/usbh_air724.c | 8 +- class/wireless/usbh_rndis.c | 26 +- class/wireless/usbh_rndis.h | 6 +- common/usb_hc.h | 171 +-- common/usb_list.h | 33 +- core/usbh_core.c | 746 ++++------- core/usbh_core.h | 187 ++- .../ES32F369x/MDK-ARM/example.uvoptx | 8 +- .../ES32F369x/MDK-ARM/example.uvprojx | 10 +- demo/es32/usb_host/ES32F369x/Inc/usb_config.h | 37 +- .../usb_host/ES32F369x/MDK-ARM/example.uvoptx | 169 ++- .../ES32F369x/MDK-ARM/example.uvprojx | 5 - demo/es32/usb_host/ES32F369x/Src/main.c | 3 +- .../stm32f429igt6/Core/Inc/usb_config.h | 97 +- .../usb_host/stm32f429igt6/Core/Src/main.c | 5 +- .../MDK-ARM/stm32f429igt6.uvoptx | 88 +- .../MDK-ARM/stm32f429igt6.uvprojx | 12 +- .../stm32h743xih6/Core/Inc/usb_config.h | 97 +- .../usb_host/stm32h743xih6/Core/Src/main.c | 22 +- .../MDK-ARM/stm32h743xih6.uvoptx | 28 +- .../MDK-ARM/stm32h743xih6.uvprojx | 24 +- .../MDK-ARM/stm32h743xih6/stm32h743xih6.sct | 19 + demo/usb_host.c | 44 +- port/dwc2/usb_dc_dwc2.c | 5 + port/dwc2/usb_hc_dwc2.c | 996 +++++++------- port/ehci/usb_hc_ehci.h | 1116 +++------------- port/musb/usb_dc_musb.c | 5 + port/musb/usb_hc_musb.c | 1181 +++++++---------- 46 files changed, 2605 insertions(+), 3475 deletions(-) create mode 100644 demo/stm32/usb_host/stm32h743xih6/MDK-ARM/stm32h743xih6/stm32h743xih6.sct diff --git a/.gitignore b/.gitignore index 73711751..3338e77d 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,6 @@ *.iex *.lst *.axf -*.sct *.hex *.Bak *.uvguix.* diff --git a/cherryusb_config_template.h b/cherryusb_config_template.h index e01b709d..eab055ba 100644 --- a/cherryusb_config_template.h +++ b/cherryusb_config_template.h @@ -16,17 +16,25 @@ #define CONFIG_USB_PRINTF printf #endif -/* attribute data into no cache ram */ -// #define USB_NOCACHE_RAM_SECTION __attribute__((section(".noncacheable"))) /* Enable print with color */ #define CONFIG_USB_PRINTF_COLOR_ENABLE +/* data align size when use dma */ +#ifndef CONFIG_USB_ALIGN_SIZE +#define CONFIG_USB_ALIGN_SIZE 4 +#endif + +/* attribute data into no cache ram */ +#define USB_NOCACHE_RAM_SECTION __attribute__((section(".noncacheable"))) + /* ================ USB DEVICE Configuration ================*/ /* core */ /* Ep0 max transfer buffer, specially for receiving data from ep0 out */ +#ifndef CONFIG_USBDEV_REQUEST_BUFFER_LEN #define CONFIG_USBDEV_REQUEST_BUFFER_LEN 256 +#endif /* Setup packet log for debug */ // #define CONFIG_USBDEV_SETUP_LOG_PRINT /* Check if the input descriptor is correct */ @@ -79,6 +87,11 @@ #endif /* ================ USB HOST Configuration ================ */ +/* core */ +/* Ep0 max transfer buffer */ +#ifndef CONFIG_USBHOST_REQUEST_BUFFER_LEN +#define CONFIG_USBHOST_REQUEST_BUFFER_LEN 512 +#endif #ifndef CONFIG_USBHOST_RHPORTS #define CONFIG_USBHOST_RHPORTS 1 @@ -88,10 +101,6 @@ #define CONFIG_USBHOST_EHPORTS 4 #endif -#ifndef CONFIG_USBHOST_PIPE_NUM -#define CONFIG_USBHOST_PIPE_NUM 10 -#endif - #ifndef CONFIG_USBHOST_INTF_NUM #define CONFIG_USBHOST_INTF_NUM 6 #endif @@ -101,7 +110,7 @@ #endif #ifndef CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT -#define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 5000 +#define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 500 #endif #ifndef CONFIG_USBHOST_MSC_TIMEOUT @@ -112,22 +121,24 @@ #define CONFIG_USBHOST_PSC_PRIO 4 #endif #ifndef CONFIG_USBHOST_PSC_STACKSIZE -#define CONFIG_USBHOST_PSC_STACKSIZE 4096 +#define CONFIG_USBHOST_PSC_STACKSIZE 2048 #endif #ifndef CONFIG_USBHOST_DEV_NAMELEN #define CONFIG_USBHOST_DEV_NAMELEN 16 #endif -#define CONFIG_USBHOST_ASYNCH //#define CONFIG_USBHOST_GET_STRING_DESC +#ifndef CONFIG_USBHOST_PIPE_NUM +#define CONFIG_USBHOST_PIPE_NUM 10 +#endif + /* ================ EHCI Configuration ================ */ -#define CONFIG_USB_EHCI_HCCR_BASE (0x20072000) -#define CONFIG_USB_EHCI_HCOR_BASE (0x20072000 + 0x10) -#define CONFIG_USB_EHCI_QH_NUM (10) -#define CONFIG_USB_EHCI_QTD_NUM (10) +#define CONFIG_USB_EHCI_HCCR_BASE (0x20072000) +#define CONFIG_USB_EHCI_HCOR_BASE (0x20072000 + 0x10) +#define CONFIG_EHCI_FRAME_LIST_SIZE 1024 // #define CONFIG_USB_EHCI_INFO_ENABLE // #define CONFIG_USB_ECHI_HCOR_RESERVED_DISABLE // #define CONFIG_USB_EHCI_CONFIGFLAG diff --git a/class/cdc/usbh_cdc_acm.c b/class/cdc/usbh_cdc_acm.c index fe20e2ea..0afbcde0 100644 --- a/class/cdc/usbh_cdc_acm.c +++ b/class/cdc/usbh_cdc_acm.c @@ -10,6 +10,8 @@ static uint32_t g_devinuse = 0; +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct cdc_line_coding g_cdc_line_coding; + /**************************************************************************** * Name: usbh_cdc_acm_devno_alloc * @@ -59,8 +61,7 @@ static void usbh_cdc_acm_devno_free(struct usbh_cdc_acm *cdc_acm_class) int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding) { - struct usb_setup_packet *setup = cdc_acm_class->hport->setup; - int ret; + struct usb_setup_packet *setup = &cdc_acm_class->hport->setup; setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; setup->bRequest = CDC_REQUEST_SET_LINE_CODING; @@ -68,17 +69,14 @@ int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_ setup->wIndex = cdc_acm_class->ctrl_intf; setup->wLength = 7; - ret = usbh_control_transfer(cdc_acm_class->hport->ep0, setup, (uint8_t *)line_coding); - if (ret < 0) { - return ret; - } - memcpy(cdc_acm_class->linecoding, line_coding, sizeof(struct cdc_line_coding)); - return 0; + memcpy((uint8_t *)&g_cdc_line_coding, line_coding, sizeof(struct cdc_line_coding)); + + return usbh_control_transfer(cdc_acm_class->hport->ep0, setup, (uint8_t *)&g_cdc_line_coding); } int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding) { - struct usb_setup_packet *setup = cdc_acm_class->hport->setup; + struct usb_setup_packet *setup = &cdc_acm_class->hport->setup; int ret; setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; @@ -87,18 +85,17 @@ int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_ setup->wIndex = cdc_acm_class->ctrl_intf; setup->wLength = 7; - ret = usbh_control_transfer(cdc_acm_class->hport->ep0, setup, (uint8_t *)line_coding); + ret = usbh_control_transfer(cdc_acm_class->hport->ep0, setup, (uint8_t *)&g_cdc_line_coding); if (ret < 0) { return ret; } - memcpy(cdc_acm_class->linecoding, line_coding, sizeof(struct cdc_line_coding)); - return 0; + memcpy(line_coding, (uint8_t *)&g_cdc_line_coding, sizeof(struct cdc_line_coding)); + return ret; } int usbh_cdc_acm_set_line_state(struct usbh_cdc_acm *cdc_acm_class, bool dtr, bool rts) { - struct usb_setup_packet *setup = cdc_acm_class->hport->setup; - int ret; + struct usb_setup_packet *setup = &cdc_acm_class->hport->setup; setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; setup->bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE; @@ -106,15 +103,10 @@ int usbh_cdc_acm_set_line_state(struct usbh_cdc_acm *cdc_acm_class, bool dtr, bo setup->wIndex = cdc_acm_class->ctrl_intf; setup->wLength = 0; - ret = usbh_control_transfer(cdc_acm_class->hport->ep0, setup, NULL); - if (ret < 0) { - return ret; - } - cdc_acm_class->dtr = dtr; cdc_acm_class->rts = rts; - return 0; + return usbh_control_transfer(cdc_acm_class->hport->ep0, setup, NULL); } static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf) @@ -138,17 +130,11 @@ static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf) hport->config.intf[intf].priv = cdc_acm_class; hport->config.intf[intf + 1].priv = NULL; - cdc_acm_class->linecoding = usb_iomalloc(sizeof(struct cdc_line_coding)); - if (cdc_acm_class->linecoding == NULL) { - USB_LOG_ERR("Fail to alloc linecoding\r\n"); - return -ENOMEM; - } - - cdc_acm_class->linecoding->dwDTERate = 115200; - cdc_acm_class->linecoding->bDataBits = 8; - cdc_acm_class->linecoding->bParityType = 0; - cdc_acm_class->linecoding->bCharFormat = 0; - ret = usbh_cdc_acm_set_line_coding(cdc_acm_class, cdc_acm_class->linecoding); + cdc_acm_class->linecoding.dwDTERate = 115200; + cdc_acm_class->linecoding.bDataBits = 8; + cdc_acm_class->linecoding.bParityType = 0; + cdc_acm_class->linecoding.bCharFormat = 0; + ret = usbh_cdc_acm_set_line_coding(cdc_acm_class, &cdc_acm_class->linecoding); if (ret < 0) { USB_LOG_ERR("Fail to set linecoding\r\n"); return ret; @@ -167,7 +153,7 @@ static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf) ep_cfg.ep_mps = ep_desc->wMaxPacketSize; ep_cfg.ep_interval = ep_desc->bInterval; ep_cfg.hport = hport; - usbh_ep_alloc(&cdc_acm_class->intin, &ep_cfg); + usbh_pipe_alloc(&cdc_acm_class->intin, &ep_cfg); #endif for (uint8_t i = 0; i < hport->config.intf[intf + 1].intf_desc.bNumEndpoints; i++) { @@ -175,14 +161,20 @@ static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf) ep_cfg.ep_addr = ep_desc->bEndpointAddress; ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK; - ep_cfg.ep_mps = ep_desc->wMaxPacketSize; + ep_cfg.ep_mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK; ep_cfg.ep_interval = ep_desc->bInterval; ep_cfg.hport = hport; if (ep_desc->bEndpointAddress & 0x80) { - usbh_ep_alloc(&cdc_acm_class->bulkin, &ep_cfg); + usbh_pipe_alloc(&cdc_acm_class->bulkin, &ep_cfg); } else { - usbh_ep_alloc(&cdc_acm_class->bulkout, &ep_cfg); + usbh_pipe_alloc(&cdc_acm_class->bulkout, &ep_cfg); } + + USB_LOG_INFO("Ep=%02x Attr=%02u Mps=%d Interval=%02u\r\n", + ep_desc->bEndpointAddress, + ep_desc->bmAttributes, + ep_desc->wMaxPacketSize, + ep_desc->bInterval); } snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, cdc_acm_class->minor); @@ -199,33 +191,22 @@ static int usbh_cdc_acm_disconnect(struct usbh_hubport *hport, uint8_t intf) struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)hport->config.intf[intf].priv; if (cdc_acm_class) { + usbh_cdc_acm_devno_free(cdc_acm_class); if (cdc_acm_class->bulkin) { - ret = usb_ep_cancel(cdc_acm_class->bulkin); - if (ret < 0) { - } - usbh_ep_free(cdc_acm_class->bulkin); + usbh_pipe_free(cdc_acm_class->bulkin); } if (cdc_acm_class->bulkout) { - ret = usb_ep_cancel(cdc_acm_class->bulkout); - if (ret < 0) { - } - usbh_ep_free(cdc_acm_class->bulkout); + usbh_pipe_free(cdc_acm_class->bulkout); } - if (cdc_acm_class->linecoding) - usb_iofree(cdc_acm_class->linecoding); - + memset(cdc_acm_class, 0, sizeof(struct usbh_cdc_acm)); usb_free(cdc_acm_class); if (hport->config.intf[intf].devname[0] != '\0') USB_LOG_INFO("Unregister CDC ACM Class:%s\r\n", hport->config.intf[intf].devname); - - memset(hport->config.intf[intf].devname, 0, CONFIG_USBHOST_DEV_NAMELEN); - hport->config.intf[intf].priv = NULL; - hport->config.intf[intf + 1].priv = NULL; } return ret; diff --git a/class/cdc/usbh_cdc_acm.h b/class/cdc/usbh_cdc_acm.h index 720ff503..eda1ea93 100644 --- a/class/cdc/usbh_cdc_acm.h +++ b/class/cdc/usbh_cdc_acm.h @@ -11,16 +11,16 @@ struct usbh_cdc_acm { struct usbh_hubport *hport; - struct cdc_line_coding *linecoding; + struct cdc_line_coding linecoding; uint8_t ctrl_intf; /* Control interface number */ uint8_t data_intf; /* Data interface number */ bool dtr; bool rts; uint8_t minor; - usbh_epinfo_t bulkin; /* Bulk IN endpoint */ - usbh_epinfo_t bulkout; /* Bulk OUT endpoint */ + usbh_pipe_t bulkin; /* Bulk IN endpoint */ + usbh_pipe_t bulkout; /* Bulk OUT endpoint */ #ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY - usbh_epinfo_t intin; /* Interrupt IN endpoint (optional) */ + usbh_pipe_t intin; /* Interrupt IN endpoint (optional) */ #endif }; diff --git a/class/hid/usbh_hid.c b/class/hid/usbh_hid.c index f8c55499..9001e751 100644 --- a/class/hid/usbh_hid.c +++ b/class/hid/usbh_hid.c @@ -10,6 +10,8 @@ static uint32_t g_devinuse = 0; +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hid_buf[128]; + /**************************************************************************** * Name: usbh_hid_devno_alloc * @@ -59,7 +61,8 @@ static void usbh_hid_devno_free(struct usbh_hid *hid_class) static int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *buffer) { - struct usb_setup_packet *setup = hid_class->hport->setup; + struct usb_setup_packet *setup = &hid_class->hport->setup; + int ret; setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE; setup->bRequest = USB_REQUEST_GET_DESCRIPTOR; @@ -67,12 +70,17 @@ static int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *b setup->wIndex = hid_class->intf; setup->wLength = 128; - return usbh_control_transfer(hid_class->hport->ep0, setup, buffer); + ret = usbh_control_transfer(hid_class->hport->ep0, setup, g_hid_buf); + if (ret < 0) { + return ret; + } + memcpy(buffer, g_hid_buf, ret - 8); + return ret; } int usbh_hid_set_idle(struct usbh_hid *hid_class, uint8_t report_id, uint8_t duration) { - struct usb_setup_packet *setup = hid_class->hport->setup; + struct usb_setup_packet *setup = &hid_class->hport->setup; setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; setup->bRequest = HID_REQUEST_SET_IDLE; @@ -85,7 +93,8 @@ int usbh_hid_set_idle(struct usbh_hid *hid_class, uint8_t report_id, uint8_t dur int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer) { - struct usb_setup_packet *setup = hid_class->hport->setup; + struct usb_setup_packet *setup = &hid_class->hport->setup; + int ret; setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; setup->bRequest = HID_REQUEST_GET_IDLE; @@ -93,7 +102,12 @@ int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer) setup->wIndex = hid_class->intf; setup->wLength = 1; - return usbh_control_transfer(hid_class->hport->ep0, setup, buffer); + ret = usbh_control_transfer(hid_class->hport->ep0, setup, g_hid_buf); + if (ret < 0) { + return ret; + } + memcpy(buffer, g_hid_buf, 1); + return ret; } int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf) @@ -120,26 +134,29 @@ int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf) return ret; } - uint8_t *report_buffer = usb_iomalloc(128); - ret = usbh_hid_get_report_descriptor(hid_class, report_buffer); + ret = usbh_hid_get_report_descriptor(hid_class, hid_class->report_desc); if (ret < 0) { - usb_iofree(report_buffer); return ret; } - usb_iofree(report_buffer); for (uint8_t i = 0; i < hport->config.intf[intf].intf_desc.bNumEndpoints; i++) { ep_desc = &hport->config.intf[intf].ep[i].ep_desc; ep_cfg.ep_addr = ep_desc->bEndpointAddress; ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK; - ep_cfg.ep_mps = ep_desc->wMaxPacketSize; + ep_cfg.ep_mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK; ep_cfg.ep_interval = ep_desc->bInterval; ep_cfg.hport = hport; if (ep_desc->bEndpointAddress & 0x80) { - usbh_ep_alloc(&hid_class->intin, &ep_cfg); + usbh_pipe_alloc(&hid_class->intin, &ep_cfg); } else { - usbh_ep_alloc(&hid_class->intout, &ep_cfg); + usbh_pipe_alloc(&hid_class->intout, &ep_cfg); } + + USB_LOG_INFO("Ep=%02x Attr=%02u Mps=%d Interval=%02u\r\n", + ep_desc->bEndpointAddress, + ep_desc->bmAttributes, + ep_desc->wMaxPacketSize, + ep_desc->bInterval); } snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, hid_class->minor); @@ -159,26 +176,18 @@ int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf) usbh_hid_devno_free(hid_class); if (hid_class->intin) { - ret = usb_ep_cancel(hid_class->intin); - if (ret < 0) { - } - usbh_ep_free(hid_class->intin); + usbh_pipe_free(hid_class->intin); } if (hid_class->intout) { - ret = usb_ep_cancel(hid_class->intout); - if (ret < 0) { - } - usbh_ep_free(hid_class->intout); + usbh_pipe_free(hid_class->intout); } + memset(hid_class, 0, sizeof(struct usbh_hid)); usb_free(hid_class); if (hport->config.intf[intf].devname[0] != '\0') USB_LOG_INFO("Unregister HID Class:%s\r\n", hport->config.intf[intf].devname); - - memset(hport->config.intf[intf].devname, 0, CONFIG_USBHOST_DEV_NAMELEN); - hport->config.intf[intf].priv = NULL; } return ret; diff --git a/class/hid/usbh_hid.h b/class/hid/usbh_hid.h index 9227c51f..74e8b408 100644 --- a/class/hid/usbh_hid.h +++ b/class/hid/usbh_hid.h @@ -11,10 +11,11 @@ struct usbh_hid { struct usbh_hubport *hport; + uint8_t report_desc[128]; uint8_t intf; /* interface number */ uint8_t minor; - usbh_epinfo_t intin; /* INTR IN endpoint */ - usbh_epinfo_t intout; /* INTR OUT endpoint */ + usbh_pipe_t intin; /* INTR IN endpoint */ + usbh_pipe_t intout; /* INTR OUT endpoint */ }; #ifdef __cplusplus diff --git a/class/hub/usbh_hub.c b/class/hub/usbh_hub.c index 998cbee4..c112e9cf 100644 --- a/class/hub/usbh_hub.c +++ b/class/hub/usbh_hub.c @@ -3,32 +3,32 @@ * * SPDX-License-Identifier: Apache-2.0 */ -#include "usbh_core.h" #include "usbh_hub.h" #define DEV_FORMAT "/dev/hub%d" +#define DEBOUNCE_TIMEOUT 400 +#define DEBOUNCE_TIME_STEP 25 +#define DELAY_TIME_AFTER_RESET 200 + static uint32_t g_devinuse = 0; +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_buf[32]; + +usb_slist_t hub_event_head = USB_SLIST_OBJECT_INIT(hub_event_head); usb_slist_t hub_class_head = USB_SLIST_OBJECT_INIT(hub_class_head); -USB_MEM_ALIGNX uint8_t int_buffer[6][USBH_HUB_INTIN_BUFSIZE]; -extern void usbh_external_hport_connect(struct usbh_hubport *hport); -extern void usbh_external_hport_disconnect(struct usbh_hubport *hport); -extern void usbh_hport_activate(struct usbh_hubport *hport); -extern void usbh_hport_deactivate(struct usbh_hubport *hport); +usb_osal_sem_t hub_event_wait; +usb_osal_thread_t hub_thread; -static void usbh_external_hub_callback(void *arg, int nbytes); +USB_NOCACHE_RAM_SECTION struct usbh_hub roothub; +struct usbh_hubport roothub_parent_port; -static inline void usbh_hub_register(struct usbh_hub *hub_class) -{ - usb_slist_add_tail(&hub_class_head, &hub_class->list); -} +extern int usbh_hport_activate_ep0(struct usbh_hubport *hport); +extern int usbh_hport_deactivate_ep0(struct usbh_hubport *hport); +extern int usbh_enumerate(struct usbh_hubport *hport); -static inline void usbh_hub_unregister(struct usbh_hub *hub_class) -{ - usb_slist_remove(&hub_class_head, &hub_class->list); -} +static const char *speed_table[] = { "error-speed", "low-speed", "full-speed", "high-speed" }; /**************************************************************************** * Name: usbh_hub_devno_alloc @@ -38,7 +38,7 @@ static inline void usbh_hub_unregister(struct usbh_hub *hub_class) * ****************************************************************************/ -static int usbh_hub_devno_alloc(struct usbh_hub *hub_class) +static int usbh_hub_devno_alloc(struct usbh_hub *hub) { size_t flags; int devno; @@ -48,7 +48,7 @@ static int usbh_hub_devno_alloc(struct usbh_hub *hub_class) uint32_t bitno = 1 << devno; if ((g_devinuse & bitno) == 0) { g_devinuse |= bitno; - hub_class->index = devno; + hub->index = devno; usb_osal_leave_critical_section(flags); return 0; } @@ -66,9 +66,9 @@ static int usbh_hub_devno_alloc(struct usbh_hub *hub_class) * ****************************************************************************/ -static void usbh_hub_devno_free(struct usbh_hub *hub_class) +static void usbh_hub_devno_free(struct usbh_hub *hub) { - int devno = hub_class->index; + int devno = hub->index; if (devno >= 2 && devno < 32) { size_t flags = usb_osal_enter_critical_section(); @@ -77,11 +77,12 @@ static void usbh_hub_devno_free(struct usbh_hub *hub_class) } } -static int usbh_hub_get_hub_descriptor(struct usbh_hub *hub_class, uint8_t *buffer) +static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer) { struct usb_setup_packet *setup; + int ret; - setup = hub_class->parent->setup; + setup = &hub->parent->setup; setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE; setup->bRequest = USB_REQUEST_GET_DESCRIPTOR; @@ -89,14 +90,20 @@ static int usbh_hub_get_hub_descriptor(struct usbh_hub *hub_class, uint8_t *buff setup->wIndex = 0; setup->wLength = USB_SIZEOF_HUB_DESC; - return usbh_control_transfer(hub_class->parent->ep0, setup, buffer); + ret = usbh_control_transfer(hub->parent->ep0, setup, g_hub_buf); + if (ret < 0) { + return ret; + } + memcpy(buffer, g_hub_buf, USB_SIZEOF_HUB_DESC); + return ret; } -static int usbh_hub_get_status(struct usbh_hub *hub_class, uint8_t *buffer) +static int _usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer) { struct usb_setup_packet *setup; + int ret; - setup = hub_class->parent->setup; + setup = &hub->parent->setup; setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE; setup->bRequest = HUB_REQUEST_GET_STATUS; @@ -104,14 +111,20 @@ static int usbh_hub_get_status(struct usbh_hub *hub_class, uint8_t *buffer) setup->wIndex = 0; setup->wLength = 2; - return usbh_control_transfer(hub_class->parent->ep0, setup, buffer); + ret = usbh_control_transfer(hub->parent->ep0, setup, g_hub_buf); + if (ret < 0) { + return ret; + } + memcpy(buffer, g_hub_buf, 2); + return ret; } -static int usbh_hub_get_portstatus(struct usbh_hub *hub_class, uint8_t port, struct hub_port_status *port_status) +static int _usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status) { struct usb_setup_packet *setup; + int ret; - setup = hub_class->parent->setup; + setup = &hub->parent->setup; setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER; setup->bRequest = HUB_REQUEST_GET_STATUS; @@ -119,14 +132,19 @@ static int usbh_hub_get_portstatus(struct usbh_hub *hub_class, uint8_t port, str setup->wIndex = port; setup->wLength = 4; - return usbh_control_transfer(hub_class->parent->ep0, setup, (uint8_t *)port_status); + ret = usbh_control_transfer(hub->parent->ep0, setup, g_hub_buf); + if (ret < 0) { + return ret; + } + memcpy(port_status, g_hub_buf, 4); + return ret; } -static int usbh_hub_set_feature(struct usbh_hub *hub_class, uint8_t port, uint8_t feature) +static int _usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature) { struct usb_setup_packet *setup; - setup = hub_class->parent->setup; + setup = &hub->parent->setup; setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER; setup->bRequest = HUB_REQUEST_SET_FEATURE; @@ -134,14 +152,14 @@ static int usbh_hub_set_feature(struct usbh_hub *hub_class, uint8_t port, uint8_ setup->wIndex = port; setup->wLength = 0; - return usbh_control_transfer(hub_class->parent->ep0, setup, NULL); + return usbh_control_transfer(hub->parent->ep0, setup, NULL); } -static int usbh_hub_clear_feature(struct usbh_hub *hub_class, uint8_t port, uint8_t feature) +static int _usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature) { struct usb_setup_packet *setup; - setup = hub_class->parent->setup; + setup = &hub->parent->setup; setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER; setup->bRequest = HUB_REQUEST_CLEAR_FEATURE; @@ -149,7 +167,7 @@ static int usbh_hub_clear_feature(struct usbh_hub *hub_class, uint8_t port, uint setup->wIndex = port; setup->wLength = 0; - return usbh_control_transfer(hub_class->parent->ep0, setup, NULL); + return usbh_control_transfer(hub->parent->ep0, setup, NULL); } static int parse_hub_descriptor(struct usb_hub_descriptor *desc, uint16_t length) @@ -161,97 +179,147 @@ static int parse_hub_descriptor(struct usb_hub_descriptor *desc, uint16_t length USB_LOG_ERR("unexpected descriptor 0x%02x\r\n", desc->bDescriptorType); return -2; } else { - USB_LOG_INFO("Device Descriptor:\r\n"); - USB_LOG_INFO("bLength: 0x%02x \r\n", desc->bLength); - USB_LOG_INFO("bDescriptorType: 0x%02x \r\n", desc->bDescriptorType); - USB_LOG_INFO("bNbrPorts: 0x%02x \r\n", desc->bNbrPorts); - USB_LOG_INFO("wHubCharacteristics: 0x%04x \r\n", desc->wHubCharacteristics); - USB_LOG_INFO("bPwrOn2PwrGood: 0x%02x \r\n", desc->bPwrOn2PwrGood); - USB_LOG_INFO("bHubContrCurrent: 0x%02x \r\n", desc->bHubContrCurrent); - USB_LOG_INFO("DeviceRemovable: 0x%02x \r\n", desc->DeviceRemovable); - USB_LOG_INFO("PortPwrCtrlMask: 0x%02x \r\n", desc->PortPwrCtrlMask); + USB_LOG_RAW("Device Descriptor:\r\n"); + USB_LOG_RAW("bLength: 0x%02x \r\n", desc->bLength); + USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", desc->bDescriptorType); + USB_LOG_RAW("bNbrPorts: 0x%02x \r\n", desc->bNbrPorts); + USB_LOG_RAW("wHubCharacteristics: 0x%04x \r\n", desc->wHubCharacteristics); + USB_LOG_RAW("bPwrOn2PwrGood: 0x%02x \r\n", desc->bPwrOn2PwrGood); + USB_LOG_RAW("bHubContrCurrent: 0x%02x \r\n", desc->bHubContrCurrent); + USB_LOG_RAW("DeviceRemovable: 0x%02x \r\n", desc->DeviceRemovable); + USB_LOG_RAW("PortPwrCtrlMask: 0x%02x \r\n", desc->PortPwrCtrlMask); } return 0; } +static int usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status) +{ + struct usb_setup_packet roothub_setup; + struct usb_setup_packet *setup; + + if (hub->is_roothub) { + setup = &roothub_setup; + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER; + setup->bRequest = HUB_REQUEST_GET_STATUS; + setup->wValue = 0; + setup->wIndex = port; + setup->wLength = 4; + return usbh_roothub_control(&roothub_setup, (uint8_t *)port_status); + } else { + return _usbh_hub_get_portstatus(hub, port, port_status); + } +} + +static int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature) +{ + struct usb_setup_packet roothub_setup; + struct usb_setup_packet *setup; + + if (hub->is_roothub) { + setup = &roothub_setup; + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER; + setup->bRequest = HUB_REQUEST_SET_FEATURE; + setup->wValue = feature; + setup->wIndex = port; + setup->wLength = 0; + return usbh_roothub_control(setup, NULL); + } else { + return _usbh_hub_set_feature(hub, port, feature); + } +} + +static int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature) +{ + struct usb_setup_packet roothub_setup; + struct usb_setup_packet *setup; + + if (hub->is_roothub) { + setup = &roothub_setup; + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER; + setup->bRequest = HUB_REQUEST_CLEAR_FEATURE; + setup->wValue = feature; + setup->wIndex = port; + setup->wLength = 0; + return usbh_roothub_control(setup, NULL); + } else { + return _usbh_hub_clear_feature(hub, port, feature); + } +} + +static void usbh_hub_thread_wakeup(struct usbh_hub *hub) +{ + usb_slist_add_tail(&hub_event_head, &hub->hub_event_list); + usb_osal_sem_give(hub_event_wait); +} + static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf) { struct usbh_endpoint_cfg ep_cfg = { 0 }; struct usb_endpoint_descriptor *ep_desc; + struct hub_port_status port_status; int ret; - struct usbh_hub *hub_class = usb_malloc(sizeof(struct usbh_hub)); - if (hub_class == NULL) { - USB_LOG_ERR("Fail to alloc hub_class\r\n"); + struct usbh_hub *hub = usb_malloc(sizeof(struct usbh_hub)); + if (hub == NULL) { + USB_LOG_ERR("Fail to alloc hub\r\n"); return -ENOMEM; } - memset(hub_class, 0, sizeof(struct usbh_hub)); - usbh_hub_devno_alloc(hub_class); - hub_class->dev_addr = hport->dev_addr; - hub_class->parent = hport; + memset(hub, 0, sizeof(struct usbh_hub)); + usbh_hub_devno_alloc(hub); + hub->hub_addr = hport->dev_addr; + hub->parent = hport; - hub_class->port_status = usb_iomalloc(sizeof(struct hub_port_status)); - if (hub_class->port_status == NULL) { - USB_LOG_ERR("Fail to alloc port_status\r\n"); - return -ENOMEM; - } + hport->config.intf[intf].priv = hub; - hport->config.intf[intf].priv = hub_class; - - uint8_t *hub_desc_buffer = usb_iomalloc(32); - - ret = usbh_hub_get_hub_descriptor(hub_class, hub_desc_buffer); - if (ret != 0) { - usb_iofree(hub_desc_buffer); + ret = _usbh_hub_get_hub_descriptor(hub, (uint8_t *)&hub->hub_desc); + if (ret < 0) { return ret; } - parse_hub_descriptor((struct usb_hub_descriptor *)hub_desc_buffer, USB_SIZEOF_HUB_DESC); - memcpy(&hub_class->hub_desc, hub_desc_buffer, USB_SIZEOF_HUB_DESC); - usb_iofree(hub_desc_buffer); + parse_hub_descriptor(&hub->hub_desc, USB_SIZEOF_HUB_DESC); - hub_class->nports = hub_class->hub_desc.bNbrPorts; - - for (uint8_t port = 1; port <= hub_class->nports; port++) { - hub_class->child[port - 1].port = port; - hub_class->child[port - 1].parent = hub_class; + for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) { + hub->child[port].port = port + 1; + hub->child[port].parent = hub; } - hub_class->int_buffer = int_buffer[hub_class->index - 2]; - usbh_hub_register(hub_class); - ep_desc = &hport->config.intf[intf].ep[0].ep_desc; ep_cfg.ep_addr = ep_desc->bEndpointAddress; ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK; - ep_cfg.ep_mps = ep_desc->wMaxPacketSize; + ep_cfg.ep_mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK; ep_cfg.ep_interval = ep_desc->bInterval; ep_cfg.hport = hport; if (ep_desc->bEndpointAddress & 0x80) { - usbh_ep_alloc(&hub_class->intin, &ep_cfg); + usbh_pipe_alloc(&hub->intin, &ep_cfg); + USB_LOG_INFO("Ep=%02x Attr=%02u Mps=%d Interval=%02u\r\n", + ep_desc->bEndpointAddress, + ep_desc->bmAttributes, + ep_desc->wMaxPacketSize, + ep_desc->bInterval); } else { return -1; } - for (uint8_t port = 1; port <= hub_class->nports; port++) { - ret = usbh_hub_set_feature(hub_class, 1, HUB_PORT_FEATURE_POWER); + for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) { + ret = usbh_hub_set_feature(hub, 1, HUB_PORT_FEATURE_POWER); if (ret < 0) { return ret; } } - for (uint8_t port = 1; port <= hub_class->nports; port++) { - ret = usbh_hub_get_portstatus(hub_class, port, hub_class->port_status); - USB_LOG_INFO("Port:%d, status:0x%02x, change:0x%02x\r\n", port, hub_class->port_status->wPortStatus, hub_class->port_status->wPortChange); + for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) { + ret = usbh_hub_get_portstatus(hub, port + 1, &port_status); + USB_LOG_INFO("port %u, status:0x%02x, change:0x%02x\r\n", port, port_status.wPortStatus, port_status.wPortChange); if (ret < 0) { return ret; } } - snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, hub_class->index); + snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, hub->index); + usbh_hub_register(hub); USB_LOG_INFO("Register HUB Class:%s\r\n", hport->config.intf[intf].devname); - ret = usbh_ep_intr_async_transfer(hub_class->intin, hub_class->int_buffer, USBH_HUB_INTIN_BUFSIZE, usbh_external_hub_callback, hub_class); return 0; } @@ -260,24 +328,18 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf) struct usbh_hubport *child; int ret = 0; - struct usbh_hub *hub_class = (struct usbh_hub *)hport->config.intf[intf].priv; + struct usbh_hub *hub = (struct usbh_hub *)hport->config.intf[intf].priv; - if (hub_class) { - usbh_hub_devno_free(hub_class); + if (hub) { + usbh_hub_devno_free(hub); - if (hub_class->intin) { - ret = usb_ep_cancel(hub_class->intin); - if (ret < 0) { - } - usbh_ep_free(hub_class->intin); + if (hub->intin) { + usbh_pipe_free(hub->intin); } - if (hub_class->port_status) - usb_iofree(hub_class->port_status); - - for (uint8_t port = 1; port <= hub_class->nports; port++) { - child = &hub_class->child[port - 1]; - usbh_hport_deactivate(child); + for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) { + child = &hub->child[port]; + usbh_hport_deactivate_ep0(child); for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) { if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) { ret = CLASS_DISCONNECT(child, i); @@ -288,215 +350,258 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf) child->parent = NULL; } - usbh_hub_unregister(hub_class); - usb_free(hub_class); + usbh_hub_unregister(hub); + memset(hub, 0, sizeof(struct usbh_hub)); + usb_free(hub); if (hport->config.intf[intf].devname[0] != '\0') USB_LOG_INFO("Unregister HUB Class:%s\r\n", hport->config.intf[intf].devname); - - memset(hport->config.intf[intf].devname, 0, CONFIG_USBHOST_DEV_NAMELEN); - hport->config.intf[intf].priv = NULL; } return ret; } -static void usbh_extern_hub_psc_event(void *arg) +static void usbh_roothub_register(void) { - struct usbh_hub *hub_class; - struct usbh_hubport *connport; - uint8_t port_change; - uint16_t status; - uint16_t change; + memset(&roothub, 0, sizeof(struct usbh_hub)); + memset(&roothub_parent_port, 0, sizeof(struct usbh_hubport)); + roothub_parent_port.port = 1; + roothub_parent_port.dev_addr = 1; + roothub.connected = true; + roothub.index = 1; + roothub.is_roothub = true; + roothub.parent = &roothub_parent_port; + roothub.hub_addr = roothub_parent_port.dev_addr; + roothub.hub_desc.bNbrPorts = CONFIG_USBHOST_RHPORTS; + usbh_hub_register(&roothub); +} + +static void usbh_hub_events(struct usbh_hub *hub) +{ + struct usbh_hubport *child; + struct hub_port_status port_status; + uint8_t portchange_index; + uint16_t portstatus; + uint16_t portchange; uint16_t mask; uint16_t feat; + uint8_t speed; int ret; - hub_class = (struct usbh_hub *)arg; - - /* Has the hub been disconnected? */ - if (!hub_class->parent->connected) { + if (!hub->connected) { return; } - port_change = hub_class->int_buffer[0]; - USB_LOG_DBG("port_change:0x%02x\r\n", port_change); + for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) { + portchange_index = hub->int_buffer[0]; - /* Check for status change on any port */ - for (uint8_t port = USBH_HUB_PORT_START_INDEX; port <= hub_class->nports; port++) { - /* Check if port status has changed */ - if ((port_change & (1 << port)) == 0) { + USB_LOG_DBG("Port change:0x%02x\r\n", portchange_index); + + if (!(portchange_index & (1 << (port + 1)))) { continue; } - USB_LOG_DBG("Port %d change\r\n", port); - - /* Port status changed, check what happened */ - port_change &= ~(1 << port); + portchange_index &= ~(1 << (port + 1)); + USB_LOG_DBG("Port %d change\r\n", port + 1); /* Read hub port status */ - ret = usbh_hub_get_portstatus(hub_class, port, hub_class->port_status); + ret = usbh_hub_get_portstatus(hub, port + 1, &port_status); if (ret < 0) { - USB_LOG_ERR("Failed to read port:%d status, errorcode: %d\r\n", port, ret); + USB_LOG_ERR("Failed to read port %u status, errorcode: %d\r\n", port + 1, ret); continue; } - status = hub_class->port_status->wPortStatus; - change = hub_class->port_status->wPortChange; - USB_LOG_DBG("Port:%d, status:0x%02x, change:0x%02x\r\n", port, status, change); + portstatus = port_status.wPortStatus; + portchange = port_status.wPortChange; + + USB_LOG_DBG("port %u, status:0x%02x, change:0x%02x\r\n", port + 1, portstatus, portchange); /* First, clear all change bits */ mask = 1; feat = HUB_PORT_FEATURE_C_CONNECTION; - while (change) { - if (change & mask) { - ret = usbh_hub_clear_feature(hub_class, port, feat); + while (portchange) { + if (portchange & mask) { + ret = usbh_hub_clear_feature(hub, port + 1, feat); if (ret < 0) { - USB_LOG_ERR("Failed to clear port:%d, change mask:%04x, errorcode:%d\r\n", port, mask, ret); + USB_LOG_ERR("Failed to clear port %u, change mask:%04x, errorcode:%d\r\n", port + 1, mask, ret); + continue; } - change &= (~mask); + portchange &= (~mask); } mask <<= 1; feat++; } - change = hub_class->port_status->wPortChange; + portchange = port_status.wPortChange; - /* Handle connect or disconnect, no power management */ - if (change & HUB_PORT_STATUS_C_CONNECTION) { - uint16_t debouncetime = 0; + /* Second, if port changes, debounces first */ + if (portchange & HUB_PORT_STATUS_C_CONNECTION) { + uint16_t connection = 0; uint16_t debouncestable = 0; - uint16_t connection = 0xffff; - - /* Debounce */ - while (debouncetime < 1500) { - ret = usbh_hub_get_portstatus(hub_class, port, hub_class->port_status); + for (uint32_t debouncetime = 0; debouncetime < DEBOUNCE_TIMEOUT; debouncetime += DEBOUNCE_TIME_STEP) { + usb_osal_msleep(DEBOUNCE_TIME_STEP); + /* Read hub port status */ + ret = usbh_hub_get_portstatus(hub, port + 1, &port_status); if (ret < 0) { - USB_LOG_ERR("Failed to read port:%d status, errorcode: %d\r\n", port, ret); - break; + USB_LOG_ERR("Failed to read port %u status, errorcode: %d\r\n", port + 1, ret); + continue; } - status = hub_class->port_status->wPortStatus; - change = hub_class->port_status->wPortChange; - if ((change & HUB_PORT_STATUS_C_CONNECTION) == 0 && - (status & HUB_PORT_STATUS_CONNECTION) == connection) { - debouncestable += 25; - if (debouncestable >= 100) { - USB_LOG_DBG("Port %d debouncestable=%d\r\n", - port, debouncestable); - break; + portstatus = port_status.wPortStatus; + portchange = port_status.wPortChange; + + USB_LOG_DBG("Port %u, status:0x%02x, change:0x%02x\r\n", port + 1, portstatus, portchange); + if ((portstatus & HUB_PORT_STATUS_CONNECTION) == connection) { + if (connection) { + if (++debouncestable == 4) { + break; + } } } else { debouncestable = 0; - connection = status & HUB_PORT_STATUS_CONNECTION; } - if ((change & HUB_PORT_STATUS_C_CONNECTION) != 0) { - ret = usbh_hub_clear_feature(hub_class, port, HUB_PORT_FEATURE_C_CONNECTION); - if (ret < 0) { - USB_LOG_ERR("Failed to clear port:%d, change mask:%04x, errorcode:%d\r\n", port, mask, ret); - } + connection = portstatus & HUB_PORT_STATUS_CONNECTION; + + if (portchange & HUB_PORT_STATUS_C_CONNECTION) { + usbh_hub_clear_feature(hub, port + 1, HUB_PORT_FEATURE_C_CONNECTION); } - debouncetime += 25; - usb_osal_msleep(25); } - if (ret < 0 || debouncetime >= 1500) { - USB_LOG_ERR("ERROR: Failed to debounce port %d: %d\r\n", port, ret); - continue; - } - - if (status & HUB_PORT_STATUS_CONNECTION) { - /* Device connected to a port on the hub */ - USB_LOG_DBG("Connection on port:%d\n", port); - - ret = usbh_hub_set_feature(hub_class, port, HUB_PORT_FEATURE_RESET); + /* Last, check connect status */ + if (portstatus & HUB_PORT_STATUS_CONNECTION) { + ret = usbh_hub_set_feature(hub, port + 1, HUB_PORT_FEATURE_RESET); if (ret < 0) { - USB_LOG_ERR("Failed to reset port:%d,errorcode:%d\r\n", port, ret); + USB_LOG_ERR("Failed to reset port %u,errorcode:%d\r\n", port, ret); continue; } - usb_osal_msleep(100); - - ret = usbh_hub_get_portstatus(hub_class, port, hub_class->port_status); + usb_osal_msleep(DELAY_TIME_AFTER_RESET); + /* Read hub port status */ + ret = usbh_hub_get_portstatus(hub, port + 1, &port_status); if (ret < 0) { - USB_LOG_ERR("Failed to read port:%d status, errorcode: %d\r\n", port, ret); + USB_LOG_ERR("Failed to read port %u status, errorcode: %d\r\n", port + 1, ret); continue; } - status = hub_class->port_status->wPortStatus; - change = hub_class->port_status->wPortChange; - USB_LOG_DBG("Port:%d, status:0x%02x, change:0x%02x after reset\r\n", port, status, change); - - if ((status & HUB_PORT_STATUS_RESET) == 0 && (status & HUB_PORT_STATUS_ENABLE) != 0) { - if (change & HUB_PORT_STATUS_C_RESET) { - ret = usbh_hub_clear_feature(hub_class, port, HUB_PORT_FEATURE_C_RESET); + portstatus = port_status.wPortStatus; + portchange = port_status.wPortChange; + if (!(portstatus & HUB_PORT_STATUS_RESET) && (portstatus & HUB_PORT_STATUS_ENABLE)) { + if (portchange & HUB_PORT_STATUS_C_RESET) { + ret = usbh_hub_clear_feature(hub, port + 1, HUB_PORT_FEATURE_C_RESET); if (ret < 0) { - USB_LOG_ERR("Failed to clear port:%d reset change, errorcode: %d\r\n", port, ret); + USB_LOG_ERR("Failed to clear port %u reset change, errorcode: %d\r\n", port, ret); } } - connport = &hub_class->child[port - 1]; - if (status & HUB_PORT_STATUS_HIGH_SPEED) { - connport->speed = USB_SPEED_HIGH; - } else if (status & HUB_PORT_STATUS_LOW_SPEED) { - connport->speed = USB_SPEED_LOW; + if (portstatus & HUB_PORT_STATUS_HIGH_SPEED) { + speed = USB_SPEED_HIGH; + } else if (portstatus & HUB_PORT_STATUS_LOW_SPEED) { + speed = USB_SPEED_LOW; } else { - connport->speed = USB_SPEED_FULL; + speed = USB_SPEED_FULL; } - /* Device connected from a port on the hub, wakeup psc thread. */ - usbh_external_hport_connect(connport); + child = &hub->child[port]; + memset(child, 0, sizeof(struct usbh_hubport)); + child->parent = hub; + child->connected = true; + child->port = port + 1; + child->speed = speed; + + USB_LOG_INFO("New %s device on Hub %u, Port %u connected\r\n", speed_table[speed], hub->index, port + 1); + + /* Allocate ep info for control endpoint */ + usbh_hport_activate_ep0(child); + if (usbh_enumerate(child) < 0) { + USB_LOG_ERR("Port %u enumerate fail\r\n", port + 1); + } } else { - USB_LOG_ERR("Failed to enable port:%d\r\n", port); + USB_LOG_ERR("Failed to enable port %u\r\n", port + 1); continue; } } else { - /* Device disconnected from a port on the hub, wakeup psc thread. */ - connport = &hub_class->child[port - 1]; - usbh_external_hport_disconnect(connport); + child = &hub->child[port]; + child->connected = false; + usbh_hport_deactivate_ep0(child); + for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) { + if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) { + CLASS_DISCONNECT(child, i); + } + } + + USB_LOG_INFO("Device on on Hub %u, Port %u disconnected\r\n", hub->index, port + 1); + usbh_device_unmount_done_callback(child); + memset(child, 0, sizeof(struct usbh_hubport)); } - } else { - USB_LOG_WRN("status %04x change %04x not handled\r\n", status, change); } } - - /* Check for hub status change */ - - if ((port_change & 1) != 0) { - /* Hub status changed */ - USB_LOG_WRN("Hub status changed, not handled\n"); - } - - if (hub_class->parent->connected) { - ret = usbh_ep_intr_async_transfer(hub_class->intin, hub_class->int_buffer, USBH_HUB_INTIN_BUFSIZE, usbh_external_hub_callback, hub_class); - } } -static void usbh_external_hub_callback(void *arg, int nbytes) +static void usbh_hub_thread(void *argument) { - struct usbh_hub *hub_class = (struct usbh_hub *)arg; - uint32_t delay = 0; - if (nbytes < 0) { - hub_class->int_buffer[0] = 0; - delay = 100; - } - if (hub_class->parent->connected) { - usb_workqueue_submit(&g_lpworkq, &hub_class->work, usbh_extern_hub_psc_event, (void *)hub_class, delay); + size_t flags; + int ret = 0; + + usbh_roothub_register(); + usb_hc_init(); + while (1) { + ret = usb_osal_sem_take(hub_event_wait, 0xffffffff); + if (ret < 0) { + continue; + } + + while (!usb_slist_isempty(&hub_event_head)) { + struct usbh_hub *hub = usb_slist_first_entry(&hub_event_head, struct usbh_hub, hub_event_list); + flags = usb_osal_enter_critical_section(); + usb_slist_remove(&hub_event_head, &hub->hub_event_list); + usb_osal_leave_critical_section(flags); + usbh_hub_events(hub); + } } } -const struct usbh_class_driver hub_class_driver = { +void usbh_roothub_thread_wakeup(uint8_t port) +{ + roothub.int_buffer[0] |= (1 << port); + usbh_hub_thread_wakeup(&roothub); +} + +void usbh_hub_register(struct usbh_hub *hub) +{ + usb_slist_add_tail(&hub_class_head, &hub->list); +} + +void usbh_hub_unregister(struct usbh_hub *hub) +{ + usb_slist_remove(&hub_class_head, &hub->list); +} + +int usbh_hub_initialize(void) +{ + hub_event_wait = usb_osal_sem_create(0); + if (hub_event_wait == NULL) { + return -1; + } + + hub_thread = usb_osal_thread_create("usbh_hub", CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO, usbh_hub_thread, NULL); + if (hub_thread == NULL) { + return -1; + } + return 0; +} + +const struct usbh_class_driver hub_driver = { .driver_name = "hub", .connect = usbh_hub_connect, .disconnect = usbh_hub_disconnect }; -CLASS_INFO_DEFINE const struct usbh_class_info hub_class_info = { +CLASS_INFO_DEFINE const struct usbh_class_info hub_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS, .class = USB_DEVICE_CLASS_HUB, .subclass = 0, .protocol = 0, .vid = 0x00, .pid = 0x00, - .class_driver = &hub_class_driver + .class_driver = &hub_driver }; diff --git a/class/hub/usbh_hub.h b/class/hub/usbh_hub.h index 96763e3b..41807de0 100644 --- a/class/hub/usbh_hub.h +++ b/class/hub/usbh_hub.h @@ -6,6 +6,7 @@ #ifndef USBH_HUB_H #define USBH_HUB_H +#include "usbh_core.h" #include "usb_hub.h" #define USBH_HUB_MAX_PORTS 4 @@ -17,6 +18,9 @@ extern usb_slist_t hub_class_head; #ifdef __cplusplus extern "C" { #endif +void usbh_roothub_thread_wakeup(uint8_t port); +void usbh_hub_register(struct usbh_hub *hub); +void usbh_hub_unregister(struct usbh_hub *hub); int usbh_hub_initialize(void); #ifdef __cplusplus } diff --git a/class/msc/usbh_msc.c b/class/msc/usbh_msc.c index 263ab730..f6fb3942 100644 --- a/class/msc/usbh_msc.c +++ b/class/msc/usbh_msc.c @@ -11,6 +11,8 @@ static uint32_t g_devinuse = 0; +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_msc_buf[32]; + /**************************************************************************** * Name: usbh_msc_devno_alloc * @@ -60,7 +62,7 @@ static void usbh_msc_devno_free(struct usbh_msc *msc_class) static int usbh_msc_get_maxlun(struct usbh_msc *msc_class, uint8_t *buffer) { - struct usb_setup_packet *setup = msc_class->hport->setup; + struct usb_setup_packet *setup = &msc_class->hport->setup; setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; setup->bRequest = MSC_REQUEST_GET_MAX_LUN; @@ -111,7 +113,7 @@ static inline int usbh_msc_scsi_testunitready(struct usbh_msc *msc_class) struct CBW *cbw; /* Construct the CBW */ - cbw = (struct CBW *)msc_class->tx_buffer; + cbw = (struct CBW *)g_msc_buf; memset(cbw, 0, USB_SIZEOF_MSC_CBW); cbw->dSignature = MSC_CBW_Signature; @@ -120,12 +122,12 @@ static inline int usbh_msc_scsi_testunitready(struct usbh_msc *msc_class) usbh_msc_cbw_dump(cbw); /* Send the CBW */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT); + nbytes = usbh_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { /* Receive the CSW */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT); + nbytes = usbh_bulk_transfer(msc_class->bulkin, g_msc_buf, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { - usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer); + usbh_msc_csw_dump((struct CSW *)g_msc_buf); } } return nbytes < 0 ? (int)nbytes : 0; @@ -137,7 +139,7 @@ static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class) struct CBW *cbw; /* Construct the CBW */ - cbw = (struct CBW *)msc_class->tx_buffer; + cbw = (struct CBW *)g_msc_buf; memset(cbw, 0, USB_SIZEOF_MSC_CBW); cbw->dSignature = MSC_CBW_Signature; @@ -149,15 +151,15 @@ static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class) usbh_msc_cbw_dump(cbw); /* Send the CBW */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT); + nbytes = usbh_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { /* Receive the sense data response */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, SCSIRESP_FIXEDSENSEDATA_SIZEOF, CONFIG_USBHOST_MSC_TIMEOUT); + nbytes = usbh_bulk_transfer(msc_class->bulkin, g_msc_buf, SCSIRESP_FIXEDSENSEDATA_SIZEOF, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { /* Receive the CSW */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT); + nbytes = usbh_bulk_transfer(msc_class->bulkin, g_msc_buf, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { - usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer); + usbh_msc_csw_dump((struct CSW *)g_msc_buf); } } } @@ -170,7 +172,7 @@ static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class) struct CBW *cbw; /* Construct the CBW */ - cbw = (struct CBW *)msc_class->tx_buffer; + cbw = (struct CBW *)g_msc_buf; memset(cbw, 0, USB_SIZEOF_MSC_CBW); cbw->dSignature = MSC_CBW_Signature; @@ -182,15 +184,15 @@ static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class) usbh_msc_cbw_dump(cbw); /* Send the CBW */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT); + nbytes = usbh_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { /* Receive the sense data response */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, SCSIRESP_INQUIRY_SIZEOF, CONFIG_USBHOST_MSC_TIMEOUT); + nbytes = usbh_bulk_transfer(msc_class->bulkin, g_msc_buf, SCSIRESP_INQUIRY_SIZEOF, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { /* Receive the CSW */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT); + nbytes = usbh_bulk_transfer(msc_class->bulkin, g_msc_buf, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { - usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer); + usbh_msc_csw_dump((struct CSW *)g_msc_buf); } } } @@ -203,7 +205,7 @@ static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class) struct CBW *cbw; /* Construct the CBW */ - cbw = (struct CBW *)msc_class->tx_buffer; + cbw = (struct CBW *)g_msc_buf; memset(cbw, 0, USB_SIZEOF_MSC_CBW); cbw->dSignature = MSC_CBW_Signature; @@ -214,18 +216,18 @@ static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class) usbh_msc_cbw_dump(cbw); /* Send the CBW */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT); + nbytes = usbh_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { /* Receive the sense data response */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, SCSIRESP_READCAPACITY10_SIZEOF, CONFIG_USBHOST_MSC_TIMEOUT); + nbytes = usbh_bulk_transfer(msc_class->bulkin, g_msc_buf, SCSIRESP_READCAPACITY10_SIZEOF, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { /* Save the capacity information */ - msc_class->blocknum = GET_BE32(&msc_class->tx_buffer[0]) + 1; - msc_class->blocksize = GET_BE32(&msc_class->tx_buffer[4]); + msc_class->blocknum = GET_BE32(&g_msc_buf[0]) + 1; + msc_class->blocksize = GET_BE32(&g_msc_buf[4]); /* Receive the CSW */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT); + nbytes = usbh_bulk_transfer(msc_class->bulkin, g_msc_buf, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { - usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer); + usbh_msc_csw_dump((struct CSW *)g_msc_buf); } } } @@ -238,7 +240,7 @@ int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, con struct CBW *cbw; /* Construct the CBW */ - cbw = (struct CBW *)msc_class->tx_buffer; + cbw = (struct CBW *)g_msc_buf; memset(cbw, 0, USB_SIZEOF_MSC_CBW); cbw->dSignature = MSC_CBW_Signature; @@ -251,15 +253,15 @@ int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, con usbh_msc_cbw_dump(cbw); /* Send the CBW */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT); + nbytes = usbh_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { /* Send the user data */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)buffer, msc_class->blocksize * nsectors, CONFIG_USBHOST_MSC_TIMEOUT); + nbytes = usbh_bulk_transfer(msc_class->bulkout, (uint8_t *)buffer, msc_class->blocksize * nsectors, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { /* Receive the CSW */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT); + nbytes = usbh_bulk_transfer(msc_class->bulkin, g_msc_buf, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { - usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer); + usbh_msc_csw_dump((struct CSW *)g_msc_buf); } } } @@ -272,7 +274,7 @@ int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, cons struct CBW *cbw; /* Construct the CBW */ - cbw = (struct CBW *)msc_class->tx_buffer; + cbw = (struct CBW *)g_msc_buf; memset(cbw, 0, USB_SIZEOF_MSC_CBW); cbw->dSignature = MSC_CBW_Signature; @@ -286,15 +288,15 @@ int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, cons usbh_msc_cbw_dump(cbw); /* Send the CBW */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT); + nbytes = usbh_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { /* Receive the user data */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, (uint8_t *)buffer, msc_class->blocksize * nsectors, CONFIG_USBHOST_MSC_TIMEOUT); + nbytes = usbh_bulk_transfer(msc_class->bulkin, (uint8_t *)buffer, msc_class->blocksize * nsectors, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { /* Receive the CSW */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT); + nbytes = usbh_bulk_transfer(msc_class->bulkin, g_msc_buf, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { - usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer); + usbh_msc_csw_dump((struct CSW *)g_msc_buf); } } } @@ -320,32 +322,32 @@ static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf) hport->config.intf[intf].priv = msc_class; - msc_class->tx_buffer = usb_iomalloc(64); - if (msc_class->tx_buffer == NULL) { - USB_LOG_ERR("Fail to alloc tx_buffer\r\n"); - return -ENOMEM; - } - - ret = usbh_msc_get_maxlun(msc_class, msc_class->tx_buffer); + ret = usbh_msc_get_maxlun(msc_class, g_msc_buf); if (ret < 0) { return ret; } - USB_LOG_INFO("Get max LUN:%u\r\n", msc_class->tx_buffer[0] + 1); + USB_LOG_INFO("Get max LUN:%u\r\n", g_msc_buf[0] + 1); for (uint8_t i = 0; i < hport->config.intf[intf].intf_desc.bNumEndpoints; i++) { ep_desc = &hport->config.intf[intf].ep[i].ep_desc; ep_cfg.ep_addr = ep_desc->bEndpointAddress; ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK; - ep_cfg.ep_mps = ep_desc->wMaxPacketSize; + ep_cfg.ep_mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK; ep_cfg.ep_interval = ep_desc->bInterval; ep_cfg.hport = hport; if (ep_desc->bEndpointAddress & 0x80) { - usbh_ep_alloc(&msc_class->bulkin, &ep_cfg); + usbh_pipe_alloc(&msc_class->bulkin, &ep_cfg); } else { - usbh_ep_alloc(&msc_class->bulkout, &ep_cfg); + usbh_pipe_alloc(&msc_class->bulkout, &ep_cfg); } + + USB_LOG_INFO("Ep=%02x Attr=%02u Mps=%d Interval=%02u\r\n", + ep_desc->bEndpointAddress, + ep_desc->bmAttributes, + ep_desc->wMaxPacketSize, + ep_desc->bInterval); } ret = usbh_msc_scsi_testunitready(msc_class); @@ -364,11 +366,11 @@ static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf) return ret; } - if (msc_class->blocksize) { + if (msc_class->blocksize > 0) { USB_LOG_INFO("Capacity info:\r\n"); USB_LOG_INFO("Block num:%d,block size:%d\r\n", (unsigned int)msc_class->blocknum, (unsigned int)msc_class->blocksize); } else { - USB_LOG_ERR("Fail to read capacity10\r\n"); + USB_LOG_ERR("Invalid block size\r\n"); return -ERANGE; } @@ -389,29 +391,18 @@ static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf) usbh_msc_devno_free(msc_class); if (msc_class->bulkin) { - ret = usb_ep_cancel(msc_class->bulkin); - if (ret < 0) { - } - usbh_ep_free(msc_class->bulkin); + usbh_pipe_free(msc_class->bulkin); } if (msc_class->bulkout) { - ret = usb_ep_cancel(msc_class->bulkout); - if (ret < 0) { - } - usbh_ep_free(msc_class->bulkout); + usbh_pipe_free(msc_class->bulkout); } - if (msc_class->tx_buffer) - usb_iofree(msc_class->tx_buffer); - + memset(msc_class, 0, sizeof(struct usbh_msc)); usb_free(msc_class); if (hport->config.intf[intf].devname[0] != '\0') USB_LOG_INFO("Unregister MSC Class:%s\r\n", hport->config.intf[intf].devname); - - memset(hport->config.intf[intf].devname, 0, CONFIG_USBHOST_DEV_NAMELEN); - hport->config.intf[intf].priv = NULL; } return ret; diff --git a/class/msc/usbh_msc.h b/class/msc/usbh_msc.h index 34b15ccc..cb13a3b2 100644 --- a/class/msc/usbh_msc.h +++ b/class/msc/usbh_msc.h @@ -14,11 +14,10 @@ struct usbh_msc { uint8_t intf; /* Data interface number */ uint8_t sdchar; - usbh_epinfo_t bulkin; /* Bulk IN endpoint */ - usbh_epinfo_t bulkout; /* Bulk OUT endpoint */ - uint8_t *tx_buffer; - uint32_t blocknum; /* Number of blocks on the USB mass storage device */ - uint16_t blocksize; /* Block size of USB mass storage device */ + usbh_pipe_t bulkin; /* Bulk IN endpoint */ + usbh_pipe_t bulkout; /* Bulk OUT endpoint */ + uint32_t blocknum; /* Number of blocks on the USB mass storage device */ + uint16_t blocksize; /* Block size of USB mass storage device */ }; int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors); diff --git a/class/mtp/usbh_mtp.c b/class/mtp/usbh_mtp.c index ca97c8d8..98c02a8b 100644 --- a/class/mtp/usbh_mtp.c +++ b/class/mtp/usbh_mtp.c @@ -37,7 +37,7 @@ static int usbh_mtp_connect(struct usbh_hubport *hport, uint8_t intf) ep_cfg.ep_mps = ep_desc->wMaxPacketSize; ep_cfg.ep_interval = ep_desc->bInterval; ep_cfg.hport = hport; - usbh_ep_alloc(&mtp_class->intin, &ep_cfg); + usbh_pipe_alloc(&mtp_class->intin, &ep_cfg); #endif for (uint8_t i = 0; i < hport->config.intf[intf + 1].intf_desc.bNumEndpoints; i++) { @@ -45,13 +45,13 @@ static int usbh_mtp_connect(struct usbh_hubport *hport, uint8_t intf) ep_cfg.ep_addr = ep_desc->bEndpointAddress; ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK; - ep_cfg.ep_mps = ep_desc->wMaxPacketSize; + ep_cfg.ep_mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;; ep_cfg.ep_interval = ep_desc->bInterval; ep_cfg.hport = hport; if (ep_desc->bEndpointAddress & 0x80) { - usbh_ep_alloc(&mtp_class->bulkin, &ep_cfg); + usbh_pipe_alloc(&mtp_class->bulkin, &ep_cfg); } else { - usbh_ep_alloc(&mtp_class->bulkout, &ep_cfg); + usbh_pipe_alloc(&mtp_class->bulkout, &ep_cfg); } } @@ -70,17 +70,11 @@ static int usbh_mtp_disconnect(struct usbh_hubport *hport, uint8_t intf) if (mtp_class) { if (mtp_class->bulkin) { - ret = usb_ep_cancel(mtp_class->bulkin); - if (ret < 0) { - } - usbh_ep_free(mtp_class->bulkin); + usbh_pipe_free(mtp_class->bulkin); } if (mtp_class->bulkout) { - ret = usb_ep_cancel(mtp_class->bulkout); - if (ret < 0) { - } - usbh_ep_free(mtp_class->bulkout); + usbh_pipe_free(mtp_class->bulkout); } usb_free(mtp_class); diff --git a/class/mtp/usbh_mtp.h b/class/mtp/usbh_mtp.h index 9a383fd4..5fdf28c5 100644 --- a/class/mtp/usbh_mtp.h +++ b/class/mtp/usbh_mtp.h @@ -12,10 +12,10 @@ struct usbh_mtp { struct usbh_hubport *hport; uint8_t intf; /* interface number */ - usbh_epinfo_t bulkin; /* BULK IN endpoint */ - usbh_epinfo_t bulkout; /* BULK OUT endpoint */ + usbh_pipe_t bulkin; /* BULK IN endpoint */ + usbh_pipe_t bulkout; /* BULK OUT endpoint */ #ifdef CONFIG_USBHOST_MTP_NOTIFY - usbh_epinfo_t intin; /* Interrupt IN endpoint (optional) */ + usbh_pipe_t intin; /* Interrupt IN endpoint (optional) */ #endif }; diff --git a/class/printer/usbh_printer.c b/class/printer/usbh_printer.c index bff05ff6..6b55b068 100644 --- a/class/printer/usbh_printer.c +++ b/class/printer/usbh_printer.c @@ -10,7 +10,7 @@ static int usbh_printer_get_device_id(struct usbh_printer *printer_class, uint8_t *buffer) { - struct usb_setup_packet *setup = printer_class->hport->setup; + struct usb_setup_packet *setup = &printer_class->hport->setup; int ret; setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; @@ -24,7 +24,7 @@ static int usbh_printer_get_device_id(struct usbh_printer *printer_class, uint8_ static int usbh_printer_get_port_status(struct usbh_printer *printer_class, uint8_t *buffer) { - struct usb_setup_packet *setup = printer_class->hport->setup; + struct usb_setup_packet *setup = &printer_class->hport->setup; int ret; setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; @@ -38,7 +38,7 @@ static int usbh_printer_get_port_status(struct usbh_printer *printer_class, uint static int usbh_printer_soft_reset(struct usbh_printer *printer_class) { - struct usb_setup_packet *setup = printer_class->hport->setup; + struct usb_setup_packet *setup = &printer_class->hport->setup; int ret; setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; @@ -74,13 +74,13 @@ static int usbh_printer_connect(struct usbh_hubport *hport, uint8_t intf) ep_cfg.ep_addr = ep_desc->bEndpointAddress; ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK; - ep_cfg.ep_mps = ep_desc->wMaxPacketSize; + ep_cfg.ep_mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK; ep_cfg.ep_interval = ep_desc->bInterval; ep_cfg.hport = hport; if (ep_desc->bEndpointAddress & 0x80) { - usbh_ep_alloc(&printer_class->bulkin, &ep_cfg); + usbh_pipe_alloc(&printer_class->bulkin, &ep_cfg); } else { - usbh_ep_alloc(&printer_class->bulkout, &ep_cfg); + usbh_pipe_alloc(&printer_class->bulkout, &ep_cfg); } } @@ -101,17 +101,11 @@ static int usbh_printer_disconnect(struct usbh_hubport *hport, uint8_t intf) if (printer_class) { if (printer_class->bulkin) { - ret = usb_ep_cancel(printer_class->bulkin); - if (ret < 0) { - } - usbh_ep_free(printer_class->bulkin); + usbh_pipe_free(printer_class->bulkin); } if (printer_class->bulkout) { - ret = usb_ep_cancel(printer_class->bulkout); - if (ret < 0) { - } - usbh_ep_free(printer_class->bulkout); + usbh_pipe_free(printer_class->bulkout); } usb_free(printer_class); diff --git a/class/printer/usbh_printer.h b/class/printer/usbh_printer.h index 811de6a5..f9648a3f 100644 --- a/class/printer/usbh_printer.h +++ b/class/printer/usbh_printer.h @@ -12,8 +12,8 @@ struct usbh_printer { struct usbh_hubport *hport; uint8_t intf; /* interface number */ - usbh_epinfo_t bulkin; /* BULK IN endpoint */ - usbh_epinfo_t bulkout; /* BULK OUT endpoint */ + usbh_pipe_t bulkin; /* BULK IN endpoint */ + usbh_pipe_t bulkout; /* BULK OUT endpoint */ }; #ifdef __cplusplus diff --git a/class/template/usbh_xxx.c b/class/template/usbh_xxx.c index d66d3989..4726a117 100644 --- a/class/template/usbh_xxx.c +++ b/class/template/usbh_xxx.c @@ -32,9 +32,9 @@ static int usbh_xxx_connect(struct usbh_hubport *hport, uint8_t intf) ep_cfg.ep_interval = ep_desc->bInterval; ep_cfg.hport = hport; if (ep_desc->bEndpointAddress & 0x80) { - usbh_ep_alloc(&rndis_class->bulkin, &ep_cfg); + usbh_pipe_alloc(&rndis_class->bulkin, &ep_cfg); } else { - usbh_ep_alloc(&rndis_class->bulkout, &ep_cfg); + usbh_pipe_alloc(&rndis_class->bulkout, &ep_cfg); } } @@ -51,17 +51,11 @@ static int usbh_xxx_disconnect(struct usbh_hubport *hport, uint8_t intf) if (xxx_class) { if (xxx_class->bulkin) { - ret = usb_ep_cancel(xxx_class->bulkin); - if (ret < 0) { - } - usbh_ep_free(xxx_class->bulkin); + usbh_pipe_free(xxx_class->bulkin); } if (xxx_class->bulkout) { - ret = usb_ep_cancel(xxx_class->bulkout); - if (ret < 0) { - } - usbh_ep_free(xxx_class->bulkout); + usbh_pipe_free(xxx_class->bulkout); } usb_free(xxx_class); diff --git a/class/template/usbh_xxx.h b/class/template/usbh_xxx.h index 0da86e5b..3bcb6991 100644 --- a/class/template/usbh_xxx.h +++ b/class/template/usbh_xxx.h @@ -7,8 +7,8 @@ struct usbh_xxx { struct usbh_hubport *hport; uint8_t intf; /* interface number */ - usbh_epinfo_t intin; /* INTR IN endpoint */ - usbh_epinfo_t intout; /* INTR OUT endpoint */ + usbh_pipe_t intin; /* INTR IN endpoint */ + usbh_pipe_t intout; /* INTR OUT endpoint */ }; #endif \ No newline at end of file diff --git a/class/vendor/axusbnet.c b/class/vendor/axusbnet.c index 8b1b7115..2faeb6b1 100644 --- a/class/vendor/axusbnet.c +++ b/class/vendor/axusbnet.c @@ -1166,14 +1166,14 @@ static int usbh_axusbnet_connect(struct usbh_hubport *hport, uint8_t intf) if(ep_cfg.ep_type == USB_ENDPOINT_TYPE_BULK) { if (ep_desc->bEndpointAddress & 0x80) { - usbh_ep_alloc(&class->bulkin, &ep_cfg); + usbh_pipe_alloc(&class->bulkin, &ep_cfg); } else { - usbh_ep_alloc(&class->bulkout, &ep_cfg); + usbh_pipe_alloc(&class->bulkout, &ep_cfg); } } else { - usbh_ep_alloc(&class->int_notify, &ep_cfg); + usbh_pipe_alloc(&class->int_notify, &ep_cfg); } } diff --git a/class/vendor/axusbnet.h b/class/vendor/axusbnet.h index b57e5020..75badc45 100644 --- a/class/vendor/axusbnet.h +++ b/class/vendor/axusbnet.h @@ -20,9 +20,9 @@ struct usbh_axusbnet { uint8_t intf; /* interface number */ - usbh_epinfo_t int_notify; /* Notify endpoint */ - usbh_epinfo_t bulkin; /* Bulk IN endpoint */ - usbh_epinfo_t bulkout; /* Bulk OUT endpoint */ + usbh_pipe_t int_notify; /* Notify endpoint */ + usbh_pipe_t bulkin; /* Bulk IN endpoint */ + usbh_pipe_t bulkout; /* Bulk OUT endpoint */ uint32_t bulkin_buf[2048/sizeof(uint32_t)]; }; diff --git a/class/vendor/usbh_air724.c b/class/vendor/usbh_air724.c index 8eebd9a9..a6ee7790 100644 --- a/class/vendor/usbh_air724.c +++ b/class/vendor/usbh_air724.c @@ -12,8 +12,8 @@ static uint32_t g_devinuse = 0; struct usbh_cdc_custom_air724 { struct usbh_hubport *hport; - usbh_epinfo_t bulkin; /* Bulk IN endpoint */ - usbh_epinfo_t bulkout; /* Bulk OUT endpoint */ + usbh_pipe_t bulkin; /* Bulk IN endpoint */ + usbh_pipe_t bulkout; /* Bulk OUT endpoint */ }; int usbh_air724_connect(struct usbh_hubport *hport, uint8_t intf) @@ -48,9 +48,9 @@ int usbh_air724_connect(struct usbh_hubport *hport, uint8_t intf) ep_cfg.ep_interval = ep_desc->bInterval; ep_cfg.hport = hport; if (ep_desc->bEndpointAddress & 0x80) { - usbh_ep_alloc(&cdc_custom_class->bulkin, &ep_cfg); + usbh_pipe_alloc(&cdc_custom_class->bulkin, &ep_cfg); } else { - usbh_ep_alloc(&cdc_custom_class->bulkout, &ep_cfg); + usbh_pipe_alloc(&cdc_custom_class->bulkout, &ep_cfg); } } diff --git a/class/wireless/usbh_rndis.c b/class/wireless/usbh_rndis.c index 43bc8768..cffe15a9 100644 --- a/class/wireless/usbh_rndis.c +++ b/class/wireless/usbh_rndis.c @@ -11,7 +11,7 @@ static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class) { - struct usb_setup_packet *setup = rndis_class->hport->setup; + struct usb_setup_packet *setup = &rndis_class->hport->setup; int ret = 0; rndis_initialize_msg_t cmd; rndis_initialize_cmplt_t resp; @@ -54,7 +54,7 @@ static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class) int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid, uint32_t query_len, uint8_t *info, uint32_t *info_len) { - struct usb_setup_packet *setup = rndis_class->hport->setup; + struct usb_setup_packet *setup = &rndis_class->hport->setup; int ret = 0; rndis_query_msg_t cmd; rndis_query_cmplt_t *resp; @@ -110,7 +110,7 @@ error_out: static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid, uint8_t *info, uint32_t info_len) { - struct usb_setup_packet *setup = rndis_class->hport->setup; + struct usb_setup_packet *setup = &rndis_class->hport->setup; int ret = 0; rndis_set_msg_t *cmd; rndis_set_cmplt_t resp; @@ -164,7 +164,7 @@ error_out: int usbh_rndis_keepalive(struct usbh_rndis *rndis_class) { - struct usb_setup_packet *setup = rndis_class->hport->setup; + struct usb_setup_packet *setup = &rndis_class->hport->setup; int ret = 0; rndis_keepalive_msg_t cmd; rndis_keepalive_cmplt_t resp; @@ -231,10 +231,10 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf) ep_desc = &hport->config.intf[intf].ep[0].ep_desc; ep_cfg.ep_addr = ep_desc->bEndpointAddress; ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK; - ep_cfg.ep_mps = ep_desc->wMaxPacketSize; + ep_cfg.ep_mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;; ep_cfg.ep_interval = ep_desc->bInterval; ep_cfg.hport = hport; - usbh_ep_alloc(&rndis_class->intin, &ep_cfg); + usbh_pipe_alloc(&rndis_class->intin, &ep_cfg); #endif for (uint8_t i = 0; i < hport->config.intf[intf + 1].intf_desc.bNumEndpoints; i++) { @@ -246,9 +246,9 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf) ep_cfg.ep_interval = ep_desc->bInterval; ep_cfg.hport = hport; if (ep_desc->bEndpointAddress & 0x80) { - usbh_ep_alloc(&rndis_class->bulkin, &ep_cfg); + usbh_pipe_alloc(&rndis_class->bulkin, &ep_cfg); } else { - usbh_ep_alloc(&rndis_class->bulkout, &ep_cfg); + usbh_pipe_alloc(&rndis_class->bulkout, &ep_cfg); } } @@ -355,17 +355,11 @@ static int usbh_rndis_disconnect(struct usbh_hubport *hport, uint8_t intf) if (rndis_class) { if (rndis_class->bulkin) { - ret = usb_ep_cancel(rndis_class->bulkin); - if (ret < 0) { - } - usbh_ep_free(rndis_class->bulkin); + usbh_pipe_free(rndis_class->bulkin); } if (rndis_class->bulkout) { - ret = usb_ep_cancel(rndis_class->bulkout); - if (ret < 0) { - } - usbh_ep_free(rndis_class->bulkout); + usbh_pipe_free(rndis_class->bulkout); } usb_free(rndis_class); diff --git a/class/wireless/usbh_rndis.h b/class/wireless/usbh_rndis.h index 9121727b..88562c64 100644 --- a/class/wireless/usbh_rndis.h +++ b/class/wireless/usbh_rndis.h @@ -14,9 +14,9 @@ struct usbh_rndis { uint8_t ctrl_intf; /* Control interface number */ uint8_t data_intf; /* Data interface number */ - usbh_epinfo_t bulkin; /* Bulk IN endpoint */ - usbh_epinfo_t bulkout; /* Bulk OUT endpoint */ - usbh_epinfo_t intin; /* Notify endpoint */ + usbh_pipe_t bulkin; /* Bulk IN endpoint */ + usbh_pipe_t bulkout; /* Bulk OUT endpoint */ + usbh_pipe_t intin; /* Notify endpoint */ uint32_t request_id; uint8_t mac[6]; diff --git a/common/usb_hc.h b/common/usb_hc.h index ac53f6b7..20a32945 100644 --- a/common/usb_hc.h +++ b/common/usb_hc.h @@ -12,8 +12,8 @@ extern "C" { #endif -typedef void (*usbh_asynch_callback_t)(void *arg, int nbytes); -typedef void *usbh_epinfo_t; +typedef void (*usbh_complete_callback_t)(void *arg, int nbytes); +typedef void *usbh_pipe_t; /** * @brief USB Endpoint Configuration. @@ -29,174 +29,87 @@ struct usbh_endpoint_cfg { }; /** - * @brief usb host software init, used for global reset. + * @brief USB Urb Configuration. * - * @return On success will return 0, and others indicate fail. + * Structure containing the USB Urb configuration. */ -int usb_hc_sw_init(void); +struct usbh_urb { + usbh_pipe_t pipe; + struct usb_setup_packet *setup; + uint8_t *transfer_buffer; + uint32_t transfer_buffer_length; + int transfer_flags; + uint32_t actual_length; + uint32_t timeout; + int errorcode; + usbh_complete_callback_t complete; + void *arg; +}; /** * @brief usb host controller hardware init. * * @return On success will return 0, and others indicate fail. */ -int usb_hc_hw_init(void); +int usb_hc_init(void); /** - * @brief get port connect status + * @brief control roothub. * - * @param port + * @param setup setup request buffer. + * @param buf buf for reading response or write data. * @return On success will return 0, and others indicate fail. */ -bool usbh_get_port_connect_status(const uint8_t port); +int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf); /** - * @brief reset roothub port + * @brief reconfig control endpoint pipe. * - * @param port port index - * @return On success will return 0, and others indicate fail. - */ -int usbh_reset_port(const uint8_t port); - -/** - * @brief get roothub port speed - * - * @param port port index - * @return return 1 means USB_SPEED_LOW, 2 means USB_SPEED_FULL and 3 means USB_SPEED_HIGH. - */ -uint8_t usbh_get_port_speed(const uint8_t port); - -/** - * @brief reconfig control endpoint. - * - * @param ep A memory location provided by the caller. + * @param pipe A memory allocated for pipe. * @param dev_addr device address. * @param ep_mps control endpoint max packet size. * @param speed port speed * @return On success will return 0, and others indicate fail. */ -int usbh_ep0_reconfigure(usbh_epinfo_t ep, uint8_t dev_addr, uint8_t ep_mps, uint8_t speed); +int usbh_ep0_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t speed); /** - * @brief Allocate and config endpoint + * @brief Allocate pipe for endpoint * - * @param ep A memory location provided by the caller in which to save the allocated endpoint info. + * @param pipe A memory location provided by the caller in which to save the allocated pipe. * @param ep_cfg Describes the endpoint info to be allocated. * @return On success will return 0, and others indicate fail. */ -int usbh_ep_alloc(usbh_epinfo_t *ep, const struct usbh_endpoint_cfg *ep_cfg); +int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg); /** - * @brief Free a memory in which saves endpoint info. + * @brief Free a pipe in which saves endpoint info. * - * @param ep A memory location provided by the caller in which to free the allocated endpoint info. + * @param pipe A memory location provided by the caller in which to free the allocated endpoint info. * @return On success will return 0, and others indicate fail. */ -int usbh_ep_free(usbh_epinfo_t ep); +int usbh_pipe_free(usbh_pipe_t pipe); /** - * @brief Perform a control transfer. - * This is a blocking method; this method will not return until the transfer has completed. + * @brief Submit a usb transfer request to an endpoint. * - * @param ep The control endpoint to send/receive the control request. - * @param setup Setup packet to be sent. - * @param buffer buffer used for sending the request and for returning any responses. This buffer must be large enough to hold the length value - * in the request description. - * @return On success will return 0, and others indicate fail. + * If timeout is not zero, this function will be in poll transfer mode, + * otherwise will be in async transfer mode. + * + * @param urb Usb request block. + * @return On success will return 0, and others indicate fail. */ -int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint8_t *buffer); +int usbh_submit_urb(struct usbh_urb *urb); /** - * @brief Process a request to handle a transfer descriptor. This method will - * enqueue the transfer request and wait for it to complete. Only one transfer may be queued; - * This is a blocking method; this method will not return until the transfer has completed. + * @brief Cancel a transfer request. * - * @param ep The IN or OUT endpoint descriptor for the device endpoint on which to perform the transfer. - * @param buffer A buffer containing the data to be sent (OUT endpoint) or received (IN endpoint). - * @param buflen The length of the data to be sent or received. - * @param timeout Timeout for transfer, unit is ms. - * @return On success, a non-negative value is returned that indicates the number - * of bytes successfully transferred. On a failure, a negated errno value - * is returned that indicates the nature of the failure: - * - * -EAGAIN - If devices NAKs the transfer (or NYET or other error where - * it may be appropriate to restart the entire transaction). - * -EPERM - If the endpoint stalls - * -EIO - On a TX or data toggle error - * -EPIPE - Overrun errors - * -ETIMEDOUT - Sem wait timeout + * This function will call When calls usbh_submit_urb and return -ETIMEOUT or -ESHUTDOWN. * + * @param urb Usb request block. + * @return On success will return 0, and others indicate fail. */ -int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, uint32_t timeout); - -/** - * @brief Process a request to handle a transfer descriptor. This method will - * enqueue the transfer request and wait for it to complete. Only one transfer may be queued; - * This is a blocking method; this method will not return until the transfer has completed. - * - * @param ep The IN or OUT endpoint descriptor for the device endpoint on which to perform the transfer. - * @param buffer A buffer containing the data to be sent (OUT endpoint) or received (IN endpoint). - * @param buflen The length of the data to be sent or received. - * @param timeout Timeout for transfer, unit is ms. - * @return On success, a non-negative value is returned that indicates the number - * of bytes successfully transferred. On a failure, a negated errno value - * is returned that indicates the nature of the failure: - * - * -EAGAIN - If devices NAKs the transfer (or NYET or other error where - * it may be appropriate to restart the entire transaction). - * -EPERM - If the endpoint stalls - * -EIO - On a TX or data toggle error - * -EPIPE - Overrun errors - * -ETIMEDOUT - Sem wait timeout - * - */ -int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, uint32_t timeout); - -/** - * @brief Process a request to handle a transfer asynchronously. This method - * will enqueue the transfer request and return immediately. Only one transfer may be queued on a given endpoint - * When the transfer completes, the callback will be invoked with the provided argument. - * - * This method is useful for receiving interrupt transfers which may come infrequently. - * - * @param ep The IN or OUT endpoint descriptor for the device endpoint on which to perform the transfer. - * @param buffer A buffer containing the data to be sent (OUT endpoint) or received (IN endpoint). - * @param buflen The length of the data to be sent or received. - * @param callback This function will be called when the transfer completes. - * @param arg The arbitrary parameter that will be passed to the callback function when the transfer completes. - * - * @return On success will return 0, and others indicate fail. - */ -int usbh_ep_bulk_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, usbh_asynch_callback_t callback, void *arg); - -/** - * @brief Process a request to handle a transfer asynchronously. This method - * will enqueue the transfer request and return immediately. Only one transfer may be queued on a given endpoint - * When the transfer completes, the callback will be invoked with the provided argument. - * - * This method is useful for receiving interrupt transfers which may come infrequently. - * - * @param ep The IN or OUT endpoint descriptor for the device endpoint on which to perform the transfer. - * @param buffer A buffer containing the data to be sent (OUT endpoint) or received (IN endpoint). - * @param buflen The length of the data to be sent or received. - * @param callback This function will be called when the transfer completes. - * @param arg The arbitrary parameter that will be passed to the callback function when the transfer completes. - * - * @return On success will return 0, and others indicate fail. - */ -int usbh_ep_intr_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, usbh_asynch_callback_t callback, void *arg); - -/** - * @brief Cancel any pending syncrhonous or asynchronous transfer on an endpoint. - * - * @param ep The IN or OUT endpoint descriptor for the device endpoint on which to cancel. - * @return On success will return 0, and others indicate fail. - */ -int usb_ep_cancel(usbh_epinfo_t ep); - -/* usb hcd irq callback */ - -void usbh_event_notify_handler(uint8_t event, uint8_t rhport); +int usbh_kill_urb(struct usbh_urb *urb); #ifdef __cplusplus } diff --git a/common/usb_list.h b/common/usb_list.h index 228dc6f3..3078a1f2 100644 --- a/common/usb_list.h +++ b/common/usb_list.h @@ -46,12 +46,14 @@ static inline void usb_slist_add_head(usb_slist_t *l, usb_slist_t *n) static inline void usb_slist_add_tail(usb_slist_t *l, usb_slist_t *n) { - while (l->next) { - l = l->next; + usb_slist_t *tmp = l; + + while (tmp->next) { + tmp = tmp->next; } /* append the node to the tail */ - l->next = n; + tmp->next = n; n->next = NULL; } @@ -74,14 +76,15 @@ static inline void usb_slist_insert(usb_slist_t *l, usb_slist_t *next, usb_slist static inline usb_slist_t *usb_slist_remove(usb_slist_t *l, usb_slist_t *n) { + usb_slist_t *tmp = l; /* remove slist head */ - while (l->next && l->next != n) { - l = l->next; + while (tmp->next && tmp->next != n) { + tmp = tmp->next; } /* remove node */ - if (l->next != (usb_slist_t *)0) { - l->next = l->next->next; + if (tmp->next != (usb_slist_t *)0) { + tmp->next = tmp->next->next; } return l; @@ -333,8 +336,8 @@ static inline unsigned int usb_dlist_len(const usb_dlist_t *l) * @brief initialize a dlist object */ #define USB_DLIST_OBJECT_INIT(object) \ - { \ - &(object), &(object) \ + { \ + &(object), &(object) \ } /** * @brief initialize a dlist object @@ -394,11 +397,11 @@ static inline unsigned int usb_dlist_len(const usb_dlist_t *l) * @n: another dlist_t * to use as temporary storage * @head: the head for your list. */ -#define usb_dlist_for_each_safe(pos, n, head) \ +#define usb_dlist_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); \ pos = n, n = pos->next) -#define usb_dlist_for_each_prev_safe(pos, n, head) \ +#define usb_dlist_for_each_prev_safe(pos, n, head) \ for (pos = (head)->prev, n = pos->prev; pos != (head); \ pos = n, n = pos->prev) /** @@ -409,7 +412,7 @@ static inline unsigned int usb_dlist_len(const usb_dlist_t *l) */ #define usb_dlist_for_each_entry(pos, head, member) \ for (pos = usb_dlist_entry((head)->next, typeof(*pos), member); \ - &pos->member != (head); \ + &pos->member != (head); \ pos = usb_dlist_entry(pos->member.next, typeof(*pos), member)) /** @@ -420,7 +423,7 @@ static inline unsigned int usb_dlist_len(const usb_dlist_t *l) */ #define usb_dlist_for_each_entry_reverse(pos, head, member) \ for (pos = usb_dlist_entry((head)->prev, typeof(*pos), member); \ - &pos->member != (head); \ + &pos->member != (head); \ pos = usb_dlist_entry(pos->member.prev, typeof(*pos), member)) /** @@ -433,7 +436,7 @@ static inline unsigned int usb_dlist_len(const usb_dlist_t *l) #define usb_dlist_for_each_entry_safe(pos, n, head, member) \ for (pos = usb_dlist_entry((head)->next, typeof(*pos), member), \ n = usb_dlist_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ + &pos->member != (head); \ pos = n, n = usb_dlist_entry(n->member.next, typeof(*n), member)) /** @@ -446,7 +449,7 @@ static inline unsigned int usb_dlist_len(const usb_dlist_t *l) #define usb_dlist_for_each_entry_safe_reverse(pos, n, head, member) \ for (pos = usb_dlist_entry((head)->prev, typeof(*pos), field), \ n = usb_dlist_entry(pos->member.prev, typeof(*pos), member); \ - &pos->member != (head); \ + &pos->member != (head); \ pos = n, n = usb_dlist_entry(pos->member.prev, typeof(*pos), member)) #ifdef __cplusplus diff --git a/core/usbh_core.c b/core/usbh_core.c index d81e559e..d2b246fb 100644 --- a/core/usbh_core.c +++ b/core/usbh_core.c @@ -4,13 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ #include "usbh_core.h" +#include "usbh_hub.h" struct usbh_class_info *usbh_class_info_table_begin = NULL; struct usbh_class_info *usbh_class_info_table_end = NULL; -static const char *speed_table[] = { "error speed", "low speed", "full speed", "high speed" }; - -static const struct usbh_class_driver *usbh_find_class_driver(uint8_t class, uint8_t subcalss, uint8_t protocol, uint16_t vid, uint16_t pid); +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t ep0_request_buffer[CONFIG_USBHOST_REQUEST_BUFFER_LEN]; /* general descriptor field offsets */ #define DESC_bLength 0 /** Length offset */ @@ -20,7 +19,7 @@ static const struct usbh_class_driver *usbh_find_class_driver(uint8_t class, uin #define USB_DEV_ADDR_MARK_OFFSET 5 #define USB_DEV_ADDR_MARK_MASK 0x1f -struct usbh_devaddr_priv { +struct usbh_devaddr_map { /** * alloctab[0]:addr from 0~31 * alloctab[1]:addr from 32~63 @@ -32,26 +31,11 @@ struct usbh_devaddr_priv { uint32_t alloctab[4]; /* Bit allocation table */ }; -struct usbh_roothubport_priv { - struct usbh_hubport hport; - struct usbh_devaddr_priv devgen; -}; +struct usbh_bus { + struct usbh_devaddr_map devgen; +} g_usbh_bus; -struct usbh_core_priv { - struct usbh_roothubport_priv rhport[CONFIG_USBHOST_RHPORTS]; - volatile struct usbh_hubport *active_hport; /* Used to pass external hub port events */ - usb_osal_event_t pscevent; /* Semaphore to wait for a port event */ -} usbh_core_cfg; - -static inline struct usbh_roothubport_priv *usbh_find_roothub_port(struct usbh_hubport *hport) -{ - while (hport->parent != NULL) { - hport = hport->parent->parent; - } - return (struct usbh_roothubport_priv *)hport; -} - -static int usbh_allocate_devaddr(struct usbh_devaddr_priv *devgen) +static int usbh_allocate_devaddr(struct usbh_devaddr_map *devgen) { uint8_t startaddr = devgen->next; uint8_t devaddr; @@ -61,7 +45,7 @@ static int usbh_allocate_devaddr(struct usbh_devaddr_priv *devgen) for (;;) { devaddr = devgen->next; if (devgen->next >= 0x7f) { - devgen->next = 1; + devgen->next = 2; } else { devgen->next++; } @@ -79,7 +63,7 @@ static int usbh_allocate_devaddr(struct usbh_devaddr_priv *devgen) } } -static int usbh_free_devaddr(struct usbh_devaddr_priv *devgen, uint8_t devaddr) +static int usbh_free_devaddr(struct usbh_devaddr_map *devgen, uint8_t devaddr) { int index; int bitno; @@ -103,58 +87,35 @@ static int usbh_free_devaddr(struct usbh_devaddr_priv *devgen, uint8_t devaddr) return 0; } -static int usbh_devaddr_create(struct usbh_hubport *hport) +static const struct usbh_class_driver *usbh_find_class_driver(uint8_t class, uint8_t subclass, uint8_t protocol, + uint16_t vid, uint16_t pid) { - struct usbh_roothubport_priv *rhport; - rhport = usbh_find_roothub_port(hport); + struct usbh_class_info *index = NULL; - return usbh_allocate_devaddr(&rhport->devgen); -} - -static int usbh_devaddr_destroy(struct usbh_hubport *hport, uint8_t dev_addr) -{ - struct usbh_roothubport_priv *rhport; - rhport = usbh_find_roothub_port(hport); - - return usbh_free_devaddr(&rhport->devgen, dev_addr); -} - -void usbh_hport_activate(struct usbh_hubport *hport) -{ - struct usbh_endpoint_cfg ep0_cfg; - - memset(&ep0_cfg, 0, sizeof(struct usbh_endpoint_cfg)); - - ep0_cfg.ep_addr = 0x00; - ep0_cfg.ep_interval = 0x00; - ep0_cfg.ep_mps = 0x08; - ep0_cfg.ep_type = USB_ENDPOINT_TYPE_CONTROL; - ep0_cfg.hport = hport; - /* Allocate memory for roothub port control endpoint */ - usbh_ep_alloc(&hport->ep0, &ep0_cfg); -} - -void usbh_hport_deactivate(struct usbh_hubport *hport) -{ - size_t flags; - - /* Don't free the control pipe of root hub ports! */ - if (hport->parent != NULL && hport->ep0 != NULL) { - usb_ep_cancel(hport->ep0); - usbh_ep_free(hport->ep0); - hport->ep0 = NULL; + for (index = usbh_class_info_table_begin; index < usbh_class_info_table_end; index++) { + if ((index->match_flags & (USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL)) == + (USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL)) { + if (index->vid == vid && index->pid == pid && + index->class == class && index->subclass == subclass && index->protocol == protocol) { + return index->class_driver; + } + } else if ((index->match_flags & (USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL)) == + (USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL)) { + if (index->class == class && index->subclass == subclass && index->protocol == protocol) { + return index->class_driver; + } + } else if ((index->match_flags & (USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS)) == + (USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS)) { + if (index->vid == vid && index->pid == pid && index->class == class) { + return index->class_driver; + } + } else if (index->match_flags & (USB_CLASS_MATCH_INTF_CLASS)) { + if (index->class == class) { + return index->class_driver; + } + } } - - flags = usb_osal_enter_critical_section(); - /* Free the device address if one has been assigned */ - usbh_devaddr_destroy(hport, hport->dev_addr); - hport->dev_addr = 0; - usb_osal_leave_critical_section(flags); - - if (hport->setup) - usb_iofree(hport->setup); - - hport->setup = NULL; + return NULL; } static int parse_device_descriptor(struct usbh_hubport *hport, struct usb_device_descriptor *desc, uint16_t length) @@ -206,10 +167,15 @@ static int parse_device_descriptor(struct usbh_hubport *hport, struct usb_device static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_configuration_descriptor *desc, uint16_t length) { - uint32_t total_len = 0; - uint8_t ep_num = 0; - uint8_t intf_num = 0; - uint8_t *p = (uint8_t *)desc; + struct usb_interface_descriptor *intf_desc; + struct usb_endpoint_descriptor *ep_desc; + uint8_t cur_alt_setting; + uint8_t cur_iface = 0xff; + uint8_t cur_ep = 0xff; + uint8_t cur_ep_num; + uint32_t desc_len = 0; + uint8_t *p; + if (desc->bLength != USB_SIZEOF_CONFIG_DESC) { USB_LOG_ERR("invalid config bLength 0x%02x\r\n", desc->bLength); return -EINVAL; @@ -241,12 +207,26 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config hport->config.config_desc.bmAttributes = desc->bmAttributes; hport->config.config_desc.bMaxPower = desc->bMaxPower; - if (length > USB_SIZEOF_CONFIG_DESC) { - while (p[DESC_bLength] && (total_len < desc->wTotalLength) && (intf_num < desc->bNumInterfaces)) { - p += p[DESC_bLength]; - total_len += p[DESC_bLength]; - if (p[DESC_bDescriptorType] == USB_DESCRIPTOR_TYPE_INTERFACE) { - struct usb_interface_descriptor *intf_desc = (struct usb_interface_descriptor *)p; + p = (uint8_t *)desc; + p += USB_SIZEOF_CONFIG_DESC; + desc_len = USB_SIZEOF_CONFIG_DESC; + + while (p[DESC_bLength] && (desc_len <= length)) { + switch (p[DESC_bDescriptorType]) { + case USB_DESCRIPTOR_TYPE_INTERFACE: + intf_desc = (struct usb_interface_descriptor *)p; + cur_iface = intf_desc->bInterfaceNumber; + cur_alt_setting = intf_desc->bAlternateSetting; + cur_ep_num = intf_desc->bNumEndpoints; + cur_ep = 0; + if (cur_iface > CONFIG_USBHOST_INTF_NUM) { + return -ENOMEM; + } + if (cur_ep_num > CONFIG_USBHOST_EP_NUM) { + return -ENOMEM; + } + + memset(&hport->config.intf[cur_iface], 0, sizeof(struct usbh_interface)); #if 0 USB_LOG_DBG("Interface Descriptor:\r\n"); USB_LOG_DBG("bLength: 0x%02x \r\n", intf_desc->bLength); @@ -259,77 +239,43 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config USB_LOG_DBG("bInterfaceProtocol: 0x%02x \r\n", intf_desc->bInterfaceProtocol); USB_LOG_DBG("iInterface: 0x%02x \r\n", intf_desc->iInterface); #endif - memset(&hport->config.intf[intf_num], 0, sizeof(struct usbh_interface)); - - hport->config.intf[intf_num].intf_desc.bLength = intf_desc->bLength; - hport->config.intf[intf_num].intf_desc.bDescriptorType = intf_desc->bDescriptorType; - hport->config.intf[intf_num].intf_desc.bInterfaceNumber = intf_desc->bInterfaceNumber; - hport->config.intf[intf_num].intf_desc.bAlternateSetting = intf_desc->bAlternateSetting; - hport->config.intf[intf_num].intf_desc.bNumEndpoints = intf_desc->bNumEndpoints; - hport->config.intf[intf_num].intf_desc.bInterfaceClass = intf_desc->bInterfaceClass; - hport->config.intf[intf_num].intf_desc.bInterfaceSubClass = intf_desc->bInterfaceSubClass; - hport->config.intf[intf_num].intf_desc.bInterfaceProtocol = intf_desc->bInterfaceProtocol; - hport->config.intf[intf_num].intf_desc.iInterface = intf_desc->iInterface; - ep_num = 0; - while (p[DESC_bLength] && (total_len < desc->wTotalLength) && (ep_num < intf_desc->bNumEndpoints)) { - p += p[DESC_bLength]; - total_len += p[DESC_bLength]; - if (p[DESC_bDescriptorType] == USB_DESCRIPTOR_TYPE_ENDPOINT) { - struct usb_endpoint_descriptor *ep_desc = (struct usb_endpoint_descriptor *)p; -#if 0 - USB_LOG_DBG("Endpoint Descriptor:\r\n"); - USB_LOG_DBG("bLength: 0x%02x \r\n", ep_desc->bLength); - USB_LOG_DBG("bDescriptorType: 0x%02x \r\n", ep_desc->bDescriptorType); - USB_LOG_DBG("bEndpointAddress: 0x%02x \r\n", ep_desc->bEndpointAddress); - USB_LOG_DBG("bmAttributes: 0x%02x \r\n", ep_desc->bmAttributes); - USB_LOG_DBG("wMaxPacketSize: 0x%04x \r\n", ep_desc->wMaxPacketSize); - USB_LOG_DBG("bInterval: 0x%02x \r\n", ep_desc->bInterval); -#endif - memset(&hport->config.intf[intf_num].ep[ep_num], 0, sizeof(struct usbh_endpoint)); - - hport->config.intf[intf_num].ep[ep_num].ep_desc.bLength = ep_desc->bLength; - hport->config.intf[intf_num].ep[ep_num].ep_desc.bDescriptorType = ep_desc->bDescriptorType; - hport->config.intf[intf_num].ep[ep_num].ep_desc.bEndpointAddress = ep_desc->bEndpointAddress; - hport->config.intf[intf_num].ep[ep_num].ep_desc.bmAttributes = ep_desc->bmAttributes; - hport->config.intf[intf_num].ep[ep_num].ep_desc.wMaxPacketSize = ep_desc->wMaxPacketSize; - hport->config.intf[intf_num].ep[ep_num].ep_desc.bInterval = ep_desc->bInterval; - ep_num++; - } + memcpy(&hport->config.intf[cur_iface].intf_desc, intf_desc, 9); + if (cur_alt_setting == 1) { + USB_LOG_WRN("Altsetting enable, the previous intf info will be overwrited\r\n"); } - intf_num++; - } + break; + case USB_DESCRIPTOR_TYPE_ENDPOINT: + ep_desc = (struct usb_endpoint_descriptor *)p; + memset(&hport->config.intf[cur_iface].ep[cur_ep], 0, sizeof(struct usbh_endpoint)); + memcpy(&hport->config.intf[cur_iface].ep[cur_ep].ep_desc, ep_desc, 7); + cur_ep++; + break; + + default: + break; } + /* skip to next descriptor */ + p += p[DESC_bLength]; + desc_len += p[DESC_bLength]; } } return 0; } #ifdef CONFIG_USBHOST_GET_STRING_DESC -static int parse_string_descriptor(struct usbh_hubport *hport, struct usb_string_descriptor *desc, uint8_t str_idx) +void usbh_print_string(char *lead, uint8_t *str) { uint8_t string[64 + 1] = { 0 }; - uint8_t *p = (uint8_t *)desc; - if (desc->bDescriptorType != USB_DESCRIPTOR_TYPE_STRING) { - USB_LOG_ERR("unexpected string descriptor 0x%02x\r\n", desc->bDescriptorType); - return -2; - } else { - p += 2; - for (uint32_t i = 0; i < (desc->bLength - 2) / 2; i++) { - string[i] = *p; - p += 2; - } - if (str_idx == USB_STRING_MFC_INDEX) { - USB_LOG_INFO("Manufacturer :%s\r\n", string); - } else if (str_idx == USB_STRING_PRODUCT_INDEX) { - USB_LOG_INFO("Product :%s\r\n", string); + int len, i = 2, j = 0; - } else if (str_idx == USB_STRING_SERIAL_INDEX) { - USB_LOG_INFO("SerialNumber :%s\r\n", string); - } else { - } + len = str[0]; + while (i < len) { + string[j] = str[i]; + i += 2; + j++; } - return 0; + USB_LOG_RAW("%s%s\r\n", lead, string); } #endif @@ -385,33 +331,45 @@ static void usbh_print_hubport_info(struct usbh_hubport *hport) } } -static int usbh_enumerate(struct usbh_hubport *hport) +int usbh_hport_activate_ep0(struct usbh_hubport *hport) +{ + struct usbh_endpoint_cfg ep0_cfg = { 0 }; + + ep0_cfg.ep_addr = 0x00; + ep0_cfg.ep_interval = 0x00; + ep0_cfg.ep_mps = 0x08; + ep0_cfg.ep_type = USB_ENDPOINT_TYPE_CONTROL; + ep0_cfg.hport = hport; + + usbh_pipe_alloc(&hport->ep0, &ep0_cfg); + return 0; +} + +int usbh_hport_deactivate_ep0(struct usbh_hubport *hport) +{ + if (hport->dev_addr > 0) { + usbh_free_devaddr(&g_usbh_bus.devgen, hport->dev_addr); + } + if (hport->ep0) { + usbh_pipe_free(hport->ep0); + } + + hport->ep0 = NULL; + hport->dev_addr = 0; + return 0; +} + +int usbh_enumerate(struct usbh_hubport *hport) { struct usb_interface_descriptor *intf_desc; struct usb_setup_packet *setup; - uint8_t *ep0_buffer; uint8_t descsize; int dev_addr; uint8_t ep_mps; int ret; #define USB_REQUEST_BUFFER_SIZE 256 - /* Allocate buffer for setup and data buffer */ - if (hport->setup == NULL) { - hport->setup = usb_iomalloc(sizeof(struct usb_setup_packet)); - if (hport->setup == NULL) { - USB_LOG_ERR("Fail to alloc setup\r\n"); - return -ENOMEM; - } - } - - setup = hport->setup; - - ep0_buffer = usb_iomalloc(USB_REQUEST_BUFFER_SIZE); - if (ep0_buffer == NULL) { - USB_LOG_ERR("Fail to alloc ep0_buffer\r\n"); - return -ENOMEM; - } + setup = &hport->setup; /* Pick an appropriate packet size for this device * @@ -431,13 +389,13 @@ static int usbh_enumerate(struct usbh_hubport *hport) ep_mps = 64; descsize = USB_SIZEOF_DEVICE_DESC; } else { - /* For low or full, we use 8 bytes, 64 bytes is also ok */ + /* For low or full, we use 8 bytes */ ep_mps = 8; descsize = 8; } /* Configure EP0 with the initial maximum packet size */ - usbh_ep0_reconfigure(hport->ep0, 0, ep_mps, hport->speed); + usbh_ep0_pipe_reconfigure(hport->ep0, 0, ep_mps, hport->speed); /* Read the first 8 bytes of the device descriptor */ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE; @@ -446,26 +404,22 @@ static int usbh_enumerate(struct usbh_hubport *hport) setup->wIndex = 0; setup->wLength = descsize; - ret = usbh_control_transfer(hport->ep0, setup, ep0_buffer); + ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer); if (ret < 0) { USB_LOG_ERR("Failed to get device descriptor,errorcode:%d\r\n", ret); goto errout; } - parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_buffer, descsize); - - if ((hport->parent == NULL) && (hport->speed != USB_SPEED_HIGH)) { - usbh_reset_port(hport->port); - } + parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer, descsize); /* Extract the correct max packetsize from the device descriptor */ - ep_mps = ((struct usb_device_descriptor *)ep0_buffer)->bMaxPacketSize0; + ep_mps = ((struct usb_device_descriptor *)ep0_request_buffer)->bMaxPacketSize0; /* And reconfigure EP0 with the correct maximum packet size */ - usbh_ep0_reconfigure(hport->ep0, 0, ep_mps, hport->speed); + usbh_ep0_pipe_reconfigure(hport->ep0, 0, ep_mps, hport->speed); /* Assign a function address to the device connected to this port */ - dev_addr = usbh_devaddr_create(hport); + dev_addr = usbh_allocate_devaddr(&g_usbh_bus.devgen); if (dev_addr < 0) { USB_LOG_ERR("Failed to allocate devaddr,errorcode:%d\r\n", ret); goto errout; @@ -491,7 +445,7 @@ static int usbh_enumerate(struct usbh_hubport *hport) hport->dev_addr = dev_addr; /* And reconfigure EP0 with the correct address */ - usbh_ep0_reconfigure(hport->ep0, dev_addr, ep_mps, hport->speed); + usbh_ep0_pipe_reconfigure(hport->ep0, dev_addr, ep_mps, hport->speed); /* Read the full device descriptor */ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE; @@ -500,17 +454,17 @@ static int usbh_enumerate(struct usbh_hubport *hport) setup->wIndex = 0; setup->wLength = USB_SIZEOF_DEVICE_DESC; - ret = usbh_control_transfer(hport->ep0, setup, ep0_buffer); + ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer); if (ret < 0) { USB_LOG_ERR("Failed to get full device descriptor,errorcode:%d\r\n", ret); goto errout; } - parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_buffer, USB_SIZEOF_DEVICE_DESC); + parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer, USB_SIZEOF_DEVICE_DESC); USB_LOG_INFO("New device found,idVendor:%04x,idProduct:%04x,bcdDevice:%04x\r\n", - ((struct usb_device_descriptor *)ep0_buffer)->idVendor, - ((struct usb_device_descriptor *)ep0_buffer)->idProduct, - ((struct usb_device_descriptor *)ep0_buffer)->bcdDevice); + ((struct usb_device_descriptor *)ep0_request_buffer)->idVendor, + ((struct usb_device_descriptor *)ep0_request_buffer)->idProduct, + ((struct usb_device_descriptor *)ep0_request_buffer)->bcdDevice); /* Read the first 9 bytes of the config descriptor */ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE; @@ -519,16 +473,16 @@ static int usbh_enumerate(struct usbh_hubport *hport) setup->wIndex = 0; setup->wLength = USB_SIZEOF_CONFIG_DESC; - ret = usbh_control_transfer(hport->ep0, setup, ep0_buffer); + ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer); if (ret < 0) { USB_LOG_ERR("Failed to get config descriptor,errorcode:%d\r\n", ret); goto errout; } - parse_config_descriptor(hport, (struct usb_configuration_descriptor *)ep0_buffer, USB_SIZEOF_CONFIG_DESC); + parse_config_descriptor(hport, (struct usb_configuration_descriptor *)ep0_request_buffer, USB_SIZEOF_CONFIG_DESC); /* Read the full size of the configuration data */ - uint16_t wTotalLength = ((struct usb_configuration_descriptor *)ep0_buffer)->wTotalLength; + uint16_t wTotalLength = ((struct usb_configuration_descriptor *)ep0_request_buffer)->wTotalLength; setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE; setup->bRequest = USB_REQUEST_GET_DESCRIPTOR; @@ -536,14 +490,14 @@ static int usbh_enumerate(struct usbh_hubport *hport) setup->wIndex = 0; setup->wLength = wTotalLength; - ret = usbh_control_transfer(hport->ep0, setup, ep0_buffer); + ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer); if (ret < 0) { USB_LOG_ERR("Failed to get full config descriptor,errorcode:%d\r\n", ret); goto errout; } - parse_config_descriptor(hport, (struct usb_configuration_descriptor *)ep0_buffer, wTotalLength); - USB_LOG_INFO("The device has %d interfaces\r\n", ((struct usb_configuration_descriptor *)ep0_buffer)->bNumInterfaces); + parse_config_descriptor(hport, (struct usb_configuration_descriptor *)ep0_request_buffer, wTotalLength); + USB_LOG_INFO("The device has %d interfaces\r\n", ((struct usb_configuration_descriptor *)ep0_request_buffer)->bNumInterfaces); #ifdef CONFIG_USBHOST_GET_STRING_DESC /* Get Manufacturer string */ @@ -553,13 +507,13 @@ static int usbh_enumerate(struct usbh_hubport *hport) setup->wIndex = 0x0409; setup->wLength = 255; - ret = usbh_control_transfer(hport->ep0, setup, ep0_buffer); + ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer); if (ret < 0) { USB_LOG_ERR("Failed to get Manufacturer string,errorcode:%d\r\n", ret); goto errout; } - parse_string_descriptor(hport, (struct usb_string_descriptor *)ep0_buffer, USB_STRING_MFC_INDEX); + usbh_print_string("Manufacturer: ", ep0_request_buffer); /* Get Product string */ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE; @@ -568,13 +522,13 @@ static int usbh_enumerate(struct usbh_hubport *hport) setup->wIndex = 0x0409; setup->wLength = 255; - ret = usbh_control_transfer(hport->ep0, setup, ep0_buffer); + ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer); if (ret < 0) { USB_LOG_ERR("Failed to get get Product string,errorcode:%d\r\n", ret); goto errout; } - parse_string_descriptor(hport, (struct usb_string_descriptor *)ep0_buffer, USB_STRING_PRODUCT_INDEX); + usbh_print_string("Product: ", ep0_request_buffer); /* Get SerialNumber string */ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE; @@ -583,13 +537,13 @@ static int usbh_enumerate(struct usbh_hubport *hport) setup->wIndex = 0x0409; setup->wLength = 255; - ret = usbh_control_transfer(hport->ep0, setup, ep0_buffer); + ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer); if (ret < 0) { USB_LOG_ERR("Failed to get get SerialNumber string,errorcode:%d\r\n", ret); goto errout; } - parse_string_descriptor(hport, (struct usb_string_descriptor *)ep0_buffer, USB_STRING_SERIAL_INDEX); + usbh_print_string("SerialNumber: ", ep0_request_buffer); #endif /* Select device configuration 1 */ setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE; @@ -631,162 +585,55 @@ static int usbh_enumerate(struct usbh_hubport *hport) usbh_device_mount_done_callback(hport); errout: if (ret < 0) { - usbh_hport_deactivate(hport); - } - - if (ep0_buffer) { - usb_iofree(ep0_buffer); + usbh_hport_deactivate_ep0(hport); } return ret; } -static int usbh_portchange_wait(struct usbh_hubport **hport) +struct usbh_hubport *usbh_find_hubport(uint8_t dev_addr) { - struct usbh_hubport *connport = NULL; - uint32_t recved_event; - size_t flags; - int ret; - - /* Loop until a change in connection state is detected */ - while (1) { - ret = usb_osal_event_recv(usbh_core_cfg.pscevent, USBH_EVENT_CONNECTED | USBH_EVENT_DISCONNECTED, &recved_event); - if (ret < 0) { - continue; - } - - flags = usb_osal_enter_critical_section(); - for (uint8_t port = USBH_HUB_PORT_START_INDEX; port <= CONFIG_USBHOST_RHPORTS; port++) { - /* Check for a change in the connection state on any root hub port */ - connport = &usbh_core_cfg.rhport[port - 1].hport; - if (connport->port_change) { - connport->port_change = false; - /* debounce for port,in order to keep port connect status stability*/ - usb_osal_msleep(100); - if (recved_event & USBH_EVENT_CONNECTED) { - if (usbh_get_port_connect_status(port)) { - if (!connport->connected) { - connport->connected = true; - *hport = connport; - usb_osal_leave_critical_section(flags); - return 0; - } - } - } - if (recved_event & USBH_EVENT_DISCONNECTED) { - if (!usbh_get_port_connect_status(port)) { - if (connport->connected) { - connport->connected = false; - *hport = connport; - usb_osal_leave_critical_section(flags); - return 0; - } - } + struct usbh_hubport *hport; + usb_slist_t *hub_list; + usb_slist_for_each(hub_list, &hub_class_head) + { + struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list); + for (int port = 0; port < hub->hub_desc.bNbrPorts; port++) { + hport = &hub->child[port - 1]; + if (hport->connected) { + if (hport->dev_addr == dev_addr) { + return &hub->child[port - 1]; } } } -#ifdef CONFIG_USBHOST_HUB - /* Is a device connected to an external hub? */ - if (usbh_core_cfg.active_hport) { - connport = (struct usbh_hubport *)usbh_core_cfg.active_hport; - usbh_core_cfg.active_hport = NULL; - *hport = connport; - usb_osal_leave_critical_section(flags); - return 0; - } -#endif - usb_osal_leave_critical_section(flags); } + return NULL; } -static void usbh_portchange_detect_thread(void *argument) +void *usbh_find_class_instance(const char *devname) { - struct usbh_hubport *hport = NULL; + struct usbh_hubport *hport; + usb_slist_t *hub_list; - usb_hc_sw_init(); - - for (uint8_t port = USBH_HUB_PORT_START_INDEX; port <= CONFIG_USBHOST_RHPORTS; port++) { - usbh_core_cfg.rhport[port - 1].hport.port = port; - usbh_core_cfg.rhport[port - 1].devgen.next = 1; - usbh_hport_activate(&usbh_core_cfg.rhport[port - 1].hport); - } - - usb_hc_hw_init(); - - while (1) { - usbh_portchange_wait(&hport); - if (hport->connected) { - /*if roothub port,reset port first*/ - if (ROOTHUB(hport)) { - /* Reset the host port */ - usbh_reset_port(hport->port); - usb_osal_msleep(200); - /* Get the current device speed */ - hport->speed = usbh_get_port_speed(hport->port); - USB_LOG_INFO("Hub %u, Port %u connected, %s\r\n", 1, hport->port, speed_table[hport->speed]); - } else { - USB_LOG_INFO("Hub %u, Port %u connected, %s\r\n", hport->parent->index, hport->port, speed_table[hport->speed]); - } - usbh_enumerate(hport); - } else { - usbh_device_unmount_done_callback(hport); - usbh_hport_deactivate(hport); - for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) { - if (hport->config.intf[i].class_driver && hport->config.intf[i].class_driver->disconnect) { - CLASS_DISCONNECT(hport, i); + usb_slist_for_each(hub_list, &hub_class_head) + { + struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list); + for (int port = 0; port < hub->hub_desc.bNbrPorts; port++) { + hport = &hub->child[port]; + if (hport->connected) { + for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) { + if ((strncmp(hport->config.intf[itf].devname, devname, CONFIG_USBHOST_DEV_NAMELEN) == 0) && hport->config.intf[itf].priv) + return hport->config.intf[itf].priv; } } - - hport->config.config_desc.bNumInterfaces = 0; - - if (ROOTHUB(hport)) { - USB_LOG_INFO("Hub %u,Port:%u disconnected\r\n", 1, hport->port); - } else { - USB_LOG_INFO("Hub %u,Port:%u disconnected\r\n", hport->parent->index, hport->port); - } } } -} - -void usbh_external_hport_connect(struct usbh_hubport *hport) -{ - size_t flags; - - usbh_hport_activate(hport); - - flags = usb_osal_enter_critical_section(); - - hport->connected = true; - usbh_core_cfg.active_hport = hport; - usb_osal_leave_critical_section(flags); - - usb_osal_event_send(usbh_core_cfg.pscevent, USBH_EVENT_CONNECTED); -} - -void usbh_external_hport_disconnect(struct usbh_hubport *hport) -{ - size_t flags; - - flags = usb_osal_enter_critical_section(); - - hport->connected = false; - usbh_core_cfg.active_hport = hport; - - usb_osal_leave_critical_section(flags); - usb_osal_event_send(usbh_core_cfg.pscevent, USBH_EVENT_DISCONNECTED); -} - -void usbh_event_notify_handler(uint8_t event, uint8_t rhport) -{ - usbh_core_cfg.rhport[rhport - 1].hport.port_change = true; - usb_osal_event_send(usbh_core_cfg.pscevent, event); + return NULL; } int usbh_initialize(void) { - usb_osal_thread_t usb_thread; - - memset(&usbh_core_cfg, 0, sizeof(struct usbh_core_priv)); + memset(&g_usbh_bus, 0, sizeof(struct usbh_bus)); #ifdef __ARMCC_VERSION /* ARM C Compiler */ extern const int usbh_class_info$$Base; @@ -800,35 +647,83 @@ int usbh_initialize(void) usbh_class_info_table_end = (struct usbh_class_info *)&__usbh_class_info_end__; #endif - usbh_core_cfg.pscevent = usb_osal_event_create(); - if (usbh_core_cfg.pscevent == NULL) { - return -1; - } - - usb_thread = usb_osal_thread_create("usbh_psc", CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO, usbh_portchange_detect_thread, NULL); - if (usb_thread == NULL) { - return -1; - } + /* devaddr 1 is for roothub */ + g_usbh_bus.devgen.next = 2; + usbh_hub_initialize(); return 0; } +/* usb host transfer wrapper */ + +int usbh_control_transfer(usbh_pipe_t pipe, struct usb_setup_packet *setup, uint8_t *buffer) +{ + struct usbh_urb *urb; + int ret; + + urb = usb_malloc(sizeof(struct usbh_urb)); + memset(urb, 0, sizeof(struct usbh_urb)); + + usbh_control_urb_fill(urb, pipe, setup, buffer, setup->wLength, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT, NULL, NULL); + + ret = usbh_submit_urb(urb); + if (ret == 0) { + ret = urb->actual_length; + } + usb_free(urb); + return ret; +} + +int usbh_bulk_transfer(usbh_pipe_t pipe, uint8_t *buffer, uint32_t buflen, uint32_t timeout) +{ + struct usbh_urb *urb; + int ret; + + urb = usb_malloc(sizeof(struct usbh_urb)); + memset(urb, 0, sizeof(struct usbh_urb)); + + usbh_bulk_urb_fill(urb, pipe, buffer, buflen, timeout, NULL, NULL); + + ret = usbh_submit_urb(urb); + if (ret == 0) { + ret = urb->actual_length; + } + usb_free(urb); + return ret; +} + +int usbh_int_transfer(usbh_pipe_t pipe, uint8_t *buffer, uint32_t buflen, uint32_t timeout) +{ + struct usbh_urb *urb; + int ret; + + urb = usb_malloc(sizeof(struct usbh_urb)); + memset(urb, 0, sizeof(struct usbh_urb)); + + usbh_int_urb_fill(urb, pipe, buffer, buflen, timeout, NULL, NULL); + + ret = usbh_submit_urb(urb); + if (ret == 0) { + ret = urb->actual_length; + } + usb_free(urb); + return ret; +} + int lsusb(int argc, char **argv) { -#ifdef CONFIG_USBHOST_HUB - usb_slist_t *hub_list; -#endif - uint8_t port; + usb_slist_t *i; + struct usbh_hubport *hport; if (argc < 2) { USB_LOG_RAW("Usage: lsusb [options]...\r\n"); USB_LOG_RAW("List USB devices\r\n"); USB_LOG_RAW(" -v, --verbose\r\n"); USB_LOG_RAW(" Increase verbosity (show descriptors)\r\n"); - USB_LOG_RAW(" -s [[bus]:[devnum]]\r\n"); - USB_LOG_RAW(" Show only devices with specified device and/or bus numbers (in decimal)\r\n"); - USB_LOG_RAW(" -d vendor:[product]\r\n"); - USB_LOG_RAW(" Show only devices with the specified vendor and product ID numbers (in hexadecimal)\r\n"); + // USB_LOG_RAW(" -s [[bus]:[devnum]]\r\n"); + // USB_LOG_RAW(" Show only devices with specified device and/or bus numbers (in decimal)\r\n"); + // USB_LOG_RAW(" -d vendor:[product]\r\n"); + // USB_LOG_RAW(" Show only devices with the specified vendor and product ID numbers (in hexadecimal)\r\n"); USB_LOG_RAW(" -t, --tree\r\n"); USB_LOG_RAW(" Dump the physical USB device hierachy as a tree\r\n"); USB_LOG_RAW(" -V, --version\r\n"); @@ -837,167 +732,58 @@ int lsusb(int argc, char **argv) USB_LOG_RAW(" Show usage and help\r\n"); return 0; } - if (argc > 3) { return 0; } if (strcmp(argv[1], "-t") == 0) { - for (port = USBH_HUB_PORT_START_INDEX; port <= CONFIG_USBHOST_RHPORTS; port++) { - if (usbh_core_cfg.rhport[port - 1].hport.connected) { - USB_LOG_RAW("/: Hub %02u,VID:PID 0x%04x:0x%04x\r\n", USBH_ROOT_HUB_INDEX, usbh_core_cfg.rhport[port - 1].hport.device_desc.idVendor, usbh_core_cfg.rhport[port - 1].hport.device_desc.idProduct); - - for (uint8_t i = 0; i < usbh_core_cfg.rhport[port - 1].hport.config.config_desc.bNumInterfaces; i++) { - if (usbh_core_cfg.rhport[port - 1].hport.config.intf[i].class_driver->driver_name) { - USB_LOG_RAW(" |__Port %u,Port addr:0x%02x,If %u,ClassDriver=%s\r\n", usbh_core_cfg.rhport[port - 1].hport.port, usbh_core_cfg.rhport[port - 1].hport.dev_addr, - i, usbh_core_cfg.rhport[port - 1].hport.config.intf[i].class_driver->driver_name); - } - } - } - } -#ifdef CONFIG_USBHOST_HUB - usb_slist_for_each(hub_list, &hub_class_head) + usb_slist_for_each(i, &hub_class_head) { - usbh_hub_t *hub_class = usb_slist_entry(hub_list, struct usbh_hub, list); + struct usbh_hub *hub = usb_slist_entry(i, struct usbh_hub, list); + for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) { + hport = &hub->child[port - 1]; + if (hport->connected) { + USB_LOG_RAW("/: Hub %02u,VID:PID 0x%04x:0x%04x\r\n", + hub->index, + hport->device_desc.idVendor, + hport->device_desc.idProduct); - for (port = USBH_HUB_PORT_START_INDEX; port <= hub_class->nports; port++) { - if (hub_class->child[port - 1].connected) { - USB_LOG_RAW("/: Hub %02u,VID:PID 0x%04x:0x%04x\r\n", hub_class->index, hub_class->child[port - 1].device_desc.idVendor, hub_class->child[port - 1].device_desc.idProduct); - - for (uint8_t i = 0; i < hub_class->child[port - 1].config.config_desc.bNumInterfaces; i++) { - if (hub_class->child[port - 1].config.intf[i].class_driver->driver_name) { - USB_LOG_RAW(" |__Port %u,Port addr:0x%02x,If %u,ClassDriver=%s\r\n", hub_class->child[port - 1].port, hub_class->child[port - 1].dev_addr, - i, hub_class->child[port - 1].config.intf[i].class_driver->driver_name); + for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) { + if (hport->config.intf[i].class_driver->driver_name) { + USB_LOG_RAW(" |__Port %u,Port addr:0x%02x,If %u,ClassDriver=%s\r\n", + hport->port, + hport->dev_addr, + i, + hport->config.intf[i].class_driver->driver_name); } } } } } -#endif - } else if (strcmp(argv[1], "-v") == 0) { - for (port = USBH_HUB_PORT_START_INDEX; port <= CONFIG_USBHOST_RHPORTS; port++) { - if (usbh_core_cfg.rhport[port - 1].hport.connected) { - USB_LOG_RAW("Hub %02u,Port %u,Port addr:0x%02x,VID:PID 0x%04x:0x%04x\r\n", USBH_ROOT_HUB_INDEX, usbh_core_cfg.rhport[port - 1].hport.port, usbh_core_cfg.rhport[port - 1].hport.dev_addr, - usbh_core_cfg.rhport[port - 1].hport.device_desc.idVendor, usbh_core_cfg.rhport[port - 1].hport.device_desc.idProduct); - usbh_print_hubport_info(&usbh_core_cfg.rhport[port - 1].hport); - } - } -#ifdef CONFIG_USBHOST_HUB - usb_slist_for_each(hub_list, &hub_class_head) - { - usbh_hub_t *hub_class = usb_slist_entry(hub_list, struct usbh_hub, list); + } - for (port = USBH_HUB_PORT_START_INDEX; port <= hub_class->nports; port++) { - if (hub_class->child[port - 1].connected) { - USB_LOG_RAW("Hub %02u,Port %u,Port addr:0x%02x,VID:PID 0x%04x:0x%04x\r\n", hub_class->index, hub_class->child[port - 1].port, hub_class->child[port - 1].dev_addr, - hub_class->child[port - 1].device_desc.idVendor, hub_class->child[port - 1].device_desc.idProduct); - usbh_print_hubport_info(&hub_class->child[port - 1]); + if (strcmp(argv[1], "-v") == 0) { + usb_slist_for_each(i, &hub_class_head) + { + struct usbh_hub *hub = usb_slist_entry(i, struct usbh_hub, list); + for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) { + hport = &hub->child[port - 1]; + if (hport->connected) { + USB_LOG_RAW("Hub %02u,Port %u,Port addr:0x%02x,VID:PID 0x%04x:0x%04x\r\n", + hub->index, + hport->port, + hport->dev_addr, + hport->device_desc.idVendor, + hport->device_desc.idProduct); + usbh_print_hubport_info(hport); } } } -#endif } return 0; } -struct usbh_hubport *usbh_find_hubport(uint8_t dev_addr) -{ -#ifdef CONFIG_USBHOST_HUB - usb_slist_t *hub_list; -#endif - uint8_t port; - - for (port = USBH_HUB_PORT_START_INDEX; port <= CONFIG_USBHOST_RHPORTS; port++) { - if (usbh_core_cfg.rhport[port - 1].hport.connected) { - if (usbh_core_cfg.rhport[port - 1].hport.dev_addr == dev_addr) { - return &usbh_core_cfg.rhport[port - 1].hport; - } - } - } -#ifdef CONFIG_USBHOST_HUB - usb_slist_for_each(hub_list, &hub_class_head) - { - usbh_hub_t *hub_class = usb_slist_entry(hub_list, struct usbh_hub, list); - - for (port = USBH_HUB_PORT_START_INDEX; port <= hub_class->nports; port++) { - if (hub_class->child[port - 1].connected) { - if (hub_class->child[port - 1].dev_addr == dev_addr) { - return &hub_class->child[port - 1]; - } - } - } - } -#endif - return NULL; -} - -void *usbh_find_class_instance(const char *devname) -{ -#ifdef CONFIG_USBHOST_HUB - usb_slist_t *hub_list; -#endif - struct usbh_hubport *hport; - uint8_t port; - - for (port = USBH_HUB_PORT_START_INDEX; port <= CONFIG_USBHOST_RHPORTS; port++) { - hport = &usbh_core_cfg.rhport[port - 1].hport; - if (hport->connected) { - for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) { - if (strncmp(hport->config.intf[itf].devname, devname, CONFIG_USBHOST_DEV_NAMELEN) == 0) - return hport->config.intf[itf].priv; - } - } - } -#ifdef CONFIG_USBHOST_HUB - usb_slist_for_each(hub_list, &hub_class_head) - { - usbh_hub_t *hub_class = usb_slist_entry(hub_list, struct usbh_hub, list); - - for (port = USBH_HUB_PORT_START_INDEX; port <= hub_class->nports; port++) { - hport = &hub_class->child[port - 1]; - if (hport->connected) { - for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) { - if (strncmp(hport->config.intf[itf].devname, devname, CONFIG_USBHOST_DEV_NAMELEN) == 0) - return hport->config.intf[itf].priv; - } - } - } - } -#endif - return NULL; -} - -static const struct usbh_class_driver *usbh_find_class_driver(uint8_t class, uint8_t subclass, uint8_t protocol, uint16_t vid, uint16_t pid) -{ - struct usbh_class_info *index = NULL; - - for (index = usbh_class_info_table_begin; index < usbh_class_info_table_end; index++) { - if ((index->match_flags & (USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL)) == - (USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL)) { - if (index->vid == vid && index->pid == pid && - index->class == class && index->subclass == subclass && index->protocol == protocol) { - return index->class_driver; - } - } else if ((index->match_flags & (USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL)) == - (USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL)) { - if (index->class == class && index->subclass == subclass && index->protocol == protocol) { - return index->class_driver; - } - } else if ((index->match_flags & (USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS)) == - (USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS)) { - if (index->vid == vid && index->pid == pid && index->class == class) { - return index->class_driver; - } - } else if (index->match_flags & (USB_CLASS_MATCH_INTF_CLASS)) { - if (index->class == class) { - return index->class_driver; - } - } - } - return NULL; -} - __WEAK void usbh_device_mount_done_callback(struct usbh_hubport *hport) { } diff --git a/core/usbh_core.h b/core/usbh_core.h index 1d13c4ae..7271bda5 100644 --- a/core/usbh_core.h +++ b/core/usbh_core.h @@ -20,22 +20,12 @@ #include "usb_log.h" #include "usb_hc.h" #include "usb_osal.h" -#include "usbh_hub.h" +#include "usb_hub.h" #ifdef __cplusplus extern "C" { #endif -#define USBH_ROOT_HUB_INDEX 1 /* roothub index*/ -#define USBH_EX_HUB_INDEX 2 /* external hub index */ -#define USBH_HUB_PORT_START_INDEX 1 /* first hub port index */ - -#ifdef CONFIG_USBHOST_HUB -#define ROOTHUB(hport) ((hport)->parent == NULL) -#else -#define ROOTHUB(hport) true -#endif - #define USB_CLASS_MATCH_VENDOR 0x0001 #define USB_CLASS_MATCH_PRODUCT 0x0002 #define USB_CLASS_MATCH_INTF_CLASS 0x0004 @@ -46,15 +36,62 @@ extern "C" { #define CLASS_DISCONNECT(hport, i) ((hport)->config.intf[i].class_driver->disconnect(hport, i)) #ifdef __ARMCC_VERSION /* ARM C Compiler */ -#define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1) +#define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1) #elif defined(__GNUC__) -#define CLASS_INFO_DEFINE __attribute__((section(".usbh_class_info"))) __USED __ALIGNED(1) +#define CLASS_INFO_DEFINE __attribute__((section(".usbh_class_info"))) __USED __ALIGNED(1) #endif -enum usbh_event_type { - USBH_EVENT_CONNECTED = (1 << 0), - USBH_EVENT_DISCONNECTED = (1 << 1), -}; +static inline void usbh_control_urb_fill(struct usbh_urb *urb, + usbh_pipe_t pipe, + struct usb_setup_packet *setup, + uint8_t *transfer_buffer, + uint32_t transfer_buffer_length, + uint32_t timeout, + usbh_complete_callback_t complete, + void *arg) +{ + urb->pipe = pipe; + urb->setup = setup; + urb->transfer_buffer = transfer_buffer; + urb->transfer_buffer_length = transfer_buffer_length; + urb->timeout = timeout; + urb->complete = complete; + urb->arg = arg; +} + +static inline void usbh_bulk_urb_fill(struct usbh_urb *urb, + usbh_pipe_t pipe, + uint8_t *transfer_buffer, + uint32_t transfer_buffer_length, + uint32_t timeout, + usbh_complete_callback_t complete, + void *arg) +{ + urb->pipe = pipe; + urb->setup = NULL; + urb->transfer_buffer = transfer_buffer; + urb->transfer_buffer_length = transfer_buffer_length; + urb->timeout = timeout; + urb->complete = complete; + urb->arg = arg; +} + +static inline void usbh_int_urb_fill(struct usbh_urb *urb, + usbh_pipe_t pipe, + uint8_t *transfer_buffer, + uint32_t transfer_buffer_length, + uint32_t timeout, + usbh_complete_callback_t complete, + void *arg) +{ + urb->pipe = pipe; + urb->setup = NULL; + urb->transfer_buffer = transfer_buffer; + urb->transfer_buffer_length = transfer_buffer_length; + urb->timeout = timeout; + urb->complete = complete; + urb->arg = arg; +} struct usbh_class_info { uint8_t match_flags; /* Used for product specific matches; range is inclusive */ @@ -73,59 +110,121 @@ struct usbh_class_driver { int (*disconnect)(struct usbh_hubport *hport, uint8_t intf); }; -typedef struct usbh_endpoint { +struct usbh_endpoint { struct usb_endpoint_descriptor ep_desc; -} usbh_endpoint_t; +}; -typedef struct usbh_interface { +struct usbh_interface { struct usb_interface_descriptor intf_desc; struct usbh_endpoint ep[CONFIG_USBHOST_EP_NUM]; char devname[CONFIG_USBHOST_DEV_NAMELEN]; struct usbh_class_driver *class_driver; void *priv; -} usbh_interface_t; +}; -typedef struct usbh_configuration { +struct usbh_configuration { struct usb_configuration_descriptor config_desc; struct usbh_interface intf[CONFIG_USBHOST_INTF_NUM]; -} usbh_configuration_t; +}; -typedef struct usbh_hubport { - bool connected; /* True: device connected; false: disconnected */ - bool port_change; /* True: port changed; false: port do not change */ - uint8_t port; /* Hub port index */ - uint8_t dev_addr; /* device address */ - uint8_t speed; /* device speed */ - usbh_epinfo_t ep0; /* control ep info */ +struct usbh_hubport { + bool connected; /* True: device connected; false: disconnected */ + uint8_t port; /* Hub port index */ + uint8_t dev_addr; /* device address */ + uint8_t speed; /* device speed */ + usbh_pipe_t ep0; /* control ep pipe info */ struct usb_device_descriptor device_desc; struct usbh_configuration config; + const char *iManufacturer; + const char *iProduct; + const char *iSerialNumber; #if 0 - uint8_t* config_desc; + uint8_t* raw_config_desc; #endif - struct usb_setup_packet *setup; - struct usbh_hub *parent; /*if NULL, is roothub*/ -} usbh_hubport_t; + USB_MEM_ALIGNX struct usb_setup_packet setup; + struct usbh_hub *parent; +}; -typedef struct usbh_hub { +struct usbh_hub { usb_slist_t list; - uint8_t index; /* Hub index */ - uint8_t nports; /* Hub port number */ - uint8_t dev_addr; /* Hub device address */ - usbh_epinfo_t intin; - uint8_t *int_buffer; - struct hub_port_status *port_status; + bool connected; + bool is_roothub; + uint8_t index; + uint8_t hub_addr; + usbh_pipe_t intin; + USB_MEM_ALIGNX uint8_t int_buffer[1]; struct usb_hub_descriptor hub_desc; struct usbh_hubport child[CONFIG_USBHOST_EHPORTS]; - struct usbh_hubport *parent; /* Parent hub port */ -} usbh_hub_t; + struct usbh_hubport *parent; + usb_slist_t hub_event_list; +}; + +/* usb host transfer wrapper */ + +/** + * @brief Submit an bulk transfer to an endpoint. + * This is a blocking method; this method will not return until the transfer has completed. + * Default timeout is 500ms. + * + * @param pipe The control endpoint to send/receive the control request. + * @param setup Setup packet to be sent. + * @param buffer buffer used for sending the request and for returning any responses. + * @return On success will return 0, and others indicate fail. + */ +int usbh_control_transfer(usbh_pipe_t pipe, struct usb_setup_packet *setup, uint8_t *buffer); + +/** + * @brief Submit an bulk transfer to an endpoint. + * This is a blocking method; this method will not return until the transfer has completed. + * + * @param pipe The IN or OUT endpoint pipe info. + * @param buffer A buffer containing the data to be sent (OUT endpoint) or received (IN endpoint). + * @param buflen The length of the data to be sent or received. + * @param timeout Timeout for transfer, unit is ms. + * @return On success, a non-negative value is returned that indicates the number + * of bytes successfully transferred. On a failure, a negated errno value + * is returned that indicates the nature of the failure: + * + * -EAGAIN - If devices NAKs the transfer (or NYET or other error where + * it may be appropriate to restart the entire transaction). + * -EPERM - If the endpoint stalls + * -EIO - On a TX or data toggle error + * -EPIPE - Overrun errors + * -ETIMEDOUT - Sem wait timeout + * + */ +int usbh_bulk_transfer(usbh_pipe_t pipe, uint8_t *buffer, uint32_t buflen, uint32_t timeout); + +/** + * @brief Submit an interrupt transfer to an endpoint. + * This is a blocking method; this method will not return until the transfer has completed. + * + * @param pipe The IN or OUT endpoint pipe info. + * @param buffer A buffer containing the data to be sent (OUT endpoint) or received (IN endpoint). + * @param buflen The length of the data to be sent or received. + * @param timeout Timeout for transfer, unit is ms. + * @return On success, a non-negative value is returned that indicates the number + * of bytes successfully transferred. On a failure, a negated errno value + * is returned that indicates the nature of the failure: + * + * -EAGAIN - If devices NAKs the transfer (or NYET or other error where + * it may be appropriate to restart the entire transaction). + * -EPERM - If the endpoint stalls + * -EIO - On a TX or data toggle error + * -EPIPE - Overrun errors + * -ETIMEDOUT - Sem wait timeout + * + */ +int usbh_int_transfer(usbh_pipe_t pipe, uint8_t *buffer, uint32_t buflen, uint32_t timeout); int usbh_initialize(void); -int lsusb(int argc, char **argv); struct usbh_hubport *usbh_find_hubport(uint8_t dev_addr); void *usbh_find_class_instance(const char *devname); + void usbh_device_mount_done_callback(struct usbh_hubport *hport); void usbh_device_unmount_done_callback(struct usbh_hubport *hport); +int lsusb(int argc, char **argv); #ifdef __cplusplus } #endif diff --git a/demo/es32/usb_device/ES32F369x/MDK-ARM/example.uvoptx b/demo/es32/usb_device/ES32F369x/MDK-ARM/example.uvoptx index c2df1b75..2bdf1dee 100644 --- a/demo/es32/usb_device/ES32F369x/MDK-ARM/example.uvoptx +++ b/demo/es32/usb_device/ES32F369x/MDK-ARM/example.uvoptx @@ -470,8 +470,8 @@ 0 0 0 - ..\..\..\..\..\port\musb\usb_dc_musb.c - usb_dc_musb.c + ..\..\..\..\..\class\hid\usbd_hid.c + usbd_hid.c 0 0 @@ -482,8 +482,8 @@ 0 0 0 - ..\..\..\..\..\class\hid\usbd_hid.c - usbd_hid.c + ..\..\..\..\..\port\musb\usb_dc_musb.c + usb_dc_musb.c 0 0 diff --git a/demo/es32/usb_device/ES32F369x/MDK-ARM/example.uvprojx b/demo/es32/usb_device/ES32F369x/MDK-ARM/example.uvprojx index bd5d475a..fad38480 100644 --- a/demo/es32/usb_device/ES32F369x/MDK-ARM/example.uvprojx +++ b/demo/es32/usb_device/ES32F369x/MDK-ARM/example.uvprojx @@ -479,16 +479,16 @@ 1 ..\..\..\..\..\class\cdc\usbd_cdc.c - - usb_dc_musb.c - 1 - ..\..\..\..\..\port\musb\usb_dc_musb.c - usbd_hid.c 1 ..\..\..\..\..\class\hid\usbd_hid.c + + usb_dc_musb.c + 1 + ..\..\..\..\..\port\musb\usb_dc_musb.c + diff --git a/demo/es32/usb_host/ES32F369x/Inc/usb_config.h b/demo/es32/usb_host/ES32F369x/Inc/usb_config.h index e01b709d..2adf79a5 100644 --- a/demo/es32/usb_host/ES32F369x/Inc/usb_config.h +++ b/demo/es32/usb_host/ES32F369x/Inc/usb_config.h @@ -16,17 +16,25 @@ #define CONFIG_USB_PRINTF printf #endif -/* attribute data into no cache ram */ -// #define USB_NOCACHE_RAM_SECTION __attribute__((section(".noncacheable"))) /* Enable print with color */ #define CONFIG_USB_PRINTF_COLOR_ENABLE +/* data align size when use dma */ +#ifndef CONFIG_USB_ALIGN_SIZE +#define CONFIG_USB_ALIGN_SIZE 4 +#endif + +/* attribute data into no cache ram */ +#define USB_NOCACHE_RAM_SECTION __attribute__((section(".noncacheable"))) + /* ================ USB DEVICE Configuration ================*/ /* core */ /* Ep0 max transfer buffer, specially for receiving data from ep0 out */ +#ifndef CONFIG_USBDEV_REQUEST_BUFFER_LEN #define CONFIG_USBDEV_REQUEST_BUFFER_LEN 256 +#endif /* Setup packet log for debug */ // #define CONFIG_USBDEV_SETUP_LOG_PRINT /* Check if the input descriptor is correct */ @@ -79,6 +87,11 @@ #endif /* ================ USB HOST Configuration ================ */ +/* core */ +/* Ep0 max transfer buffer */ +#ifndef CONFIG_USBHOST_REQUEST_BUFFER_LEN +#define CONFIG_USBHOST_REQUEST_BUFFER_LEN 512 +#endif #ifndef CONFIG_USBHOST_RHPORTS #define CONFIG_USBHOST_RHPORTS 1 @@ -88,10 +101,6 @@ #define CONFIG_USBHOST_EHPORTS 4 #endif -#ifndef CONFIG_USBHOST_PIPE_NUM -#define CONFIG_USBHOST_PIPE_NUM 10 -#endif - #ifndef CONFIG_USBHOST_INTF_NUM #define CONFIG_USBHOST_INTF_NUM 6 #endif @@ -101,7 +110,7 @@ #endif #ifndef CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT -#define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 5000 +#define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 500 #endif #ifndef CONFIG_USBHOST_MSC_TIMEOUT @@ -112,22 +121,24 @@ #define CONFIG_USBHOST_PSC_PRIO 4 #endif #ifndef CONFIG_USBHOST_PSC_STACKSIZE -#define CONFIG_USBHOST_PSC_STACKSIZE 4096 +#define CONFIG_USBHOST_PSC_STACKSIZE 2048 #endif #ifndef CONFIG_USBHOST_DEV_NAMELEN #define CONFIG_USBHOST_DEV_NAMELEN 16 #endif -#define CONFIG_USBHOST_ASYNCH //#define CONFIG_USBHOST_GET_STRING_DESC +#ifndef CONFIG_USBHOST_PIPE_NUM +#define CONFIG_USBHOST_PIPE_NUM 4 +#endif + /* ================ EHCI Configuration ================ */ -#define CONFIG_USB_EHCI_HCCR_BASE (0x20072000) -#define CONFIG_USB_EHCI_HCOR_BASE (0x20072000 + 0x10) -#define CONFIG_USB_EHCI_QH_NUM (10) -#define CONFIG_USB_EHCI_QTD_NUM (10) +#define CONFIG_USB_EHCI_HCCR_BASE (0x20072000) +#define CONFIG_USB_EHCI_HCOR_BASE (0x20072000 + 0x10) +#define CONFIG_EHCI_FRAME_LIST_SIZE 1024 // #define CONFIG_USB_EHCI_INFO_ENABLE // #define CONFIG_USB_ECHI_HCOR_RESERVED_DISABLE // #define CONFIG_USB_EHCI_CONFIGFLAG diff --git a/demo/es32/usb_host/ES32F369x/MDK-ARM/example.uvoptx b/demo/es32/usb_host/ES32F369x/MDK-ARM/example.uvoptx index 078e74ae..dfa8bdc8 100644 --- a/demo/es32/usb_host/ES32F369x/MDK-ARM/example.uvoptx +++ b/demo/es32/usb_host/ES32F369x/MDK-ARM/example.uvoptx @@ -125,7 +125,7 @@ 0 CMSIS_AGDI - -X"essemi CMSIS-DAP" -U0001A000000A -O367 -S0 -C0 -P00000000 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO65554 -TC10000000 -TT10000000 -TP20 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO15 -FD20000000 -FC1000 -FN1 -FF0es32f36xx.FLM -FS00 -FL080000 -FP0($$Device:ES32F3696LT$Flash\es32f36xx.FLM) + -X"essemi CMSIS-DAP" -U0001A000000A -O334 -S0 -C0 -P00000000 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO65554 -TC10000000 -TT10000000 -TP20 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO15 -FD20000000 -FC1000 -FN1 -FF0es32f36xx.FLM -FS00 -FL080000 -FP0($$Device:ES32F3696LT$Flash\es32f36xx.FLM) 0 @@ -163,7 +163,136 @@ -T0 - + + + 0 + 0 + 962 + 1 +
0
+ 0 + 0 + 0 + 0 + 0 + 0 + ..\..\..\..\..\port\musb\usb_hc_musb.c + + +
+ + 1 + 0 + 959 + 1 +
0
+ 0 + 0 + 0 + 0 + 0 + 0 + ..\..\..\..\..\port\musb\usb_hc_musb.c + + +
+ + 2 + 0 + 964 + 1 +
1500
+ 0 + 0 + 0 + 0 + 0 + 1 + ..\..\..\..\..\port\musb\usb_hc_musb.c + + \\out\../../../../../port/musb/usb_hc_musb.c\964 +
+ + 3 + 0 + 964 + 1 +
1516
+ 0 + 0 + 0 + 0 + 0 + 1 + ..\..\..\..\..\port\musb\usb_hc_musb.c + + \\out\../../../../../port/musb/usb_hc_musb.c\964 +
+ + 4 + 0 + 960 + 1 +
1524
+ 0 + 0 + 0 + 0 + 0 + 1 + ..\..\..\..\..\port\musb\usb_hc_musb.c + + \\out\../../../../../port/musb/usb_hc_musb.c\960 +
+ + 5 + 0 + 440 + 1 +
0
+ 0 + 0 + 0 + 0 + 0 + 0 + ..\..\..\..\..\port\musb\usb_hc_musb.c + + +
+ + 6 + 0 + 447 + 1 +
0
+ 0 + 0 + 0 + 0 + 0 + 0 + ..\..\..\..\..\port\musb\usb_hc_musb.c + + +
+ + 7 + 0 + 963 + 1 +
0
+ 0 + 0 + 0 + 0 + 0 + 0 + ..\..\..\..\..\port\musb\usb_hc_musb.c + + +
+
0 @@ -260,7 +389,7 @@ startup - 1 + 0 0 0 0 @@ -280,7 +409,7 @@ ald - 1 + 0 0 0 0 @@ -396,7 +525,7 @@ app - 0 + 1 0 0 0 @@ -535,18 +664,6 @@ 0 0 0 - ..\..\..\..\..\osal\usb_workq.c - usb_workq.c - 0 - 0 - - - 4 - 22 - 1 - 0 - 0 - 0 ..\..\..\..\..\port\musb\usb_hc_musb.c usb_hc_musb.c 0 @@ -556,13 +673,13 @@ FreeRTOS - 1 + 0 0 0 0 5 - 23 + 22 1 0 0 @@ -574,7 +691,7 @@ 5 - 24 + 23 1 0 0 @@ -586,7 +703,7 @@ 5 - 25 + 24 1 0 0 @@ -598,7 +715,7 @@ 5 - 26 + 25 1 0 0 @@ -610,7 +727,7 @@ 5 - 27 + 26 1 0 0 @@ -622,7 +739,7 @@ 5 - 28 + 27 1 0 0 @@ -634,7 +751,7 @@ 5 - 29 + 28 1 0 0 @@ -646,7 +763,7 @@ 5 - 30 + 29 1 0 0 diff --git a/demo/es32/usb_host/ES32F369x/MDK-ARM/example.uvprojx b/demo/es32/usb_host/ES32F369x/MDK-ARM/example.uvprojx index a27aadde..c8165d25 100644 --- a/demo/es32/usb_host/ES32F369x/MDK-ARM/example.uvprojx +++ b/demo/es32/usb_host/ES32F369x/MDK-ARM/example.uvprojx @@ -499,11 +499,6 @@ 1 ..\..\..\..\..\osal\usb_osal_freertos.c - - usb_workq.c - 1 - ..\..\..\..\..\osal\usb_workq.c - usb_hc_musb.c 1 diff --git a/demo/es32/usb_host/ES32F369x/Src/main.c b/demo/es32/usb_host/ES32F369x/Src/main.c index 29461515..009651ae 100644 --- a/demo/es32/usb_host/ES32F369x/Src/main.c +++ b/demo/es32/usb_host/ES32F369x/Src/main.c @@ -140,8 +140,9 @@ int main() uart_pin_init(); printf("\rSystem start...\r\n"); - + extern void usbh_class_test(void); usbh_initialize(); + usbh_class_test(); vTaskStartScheduler(); while (1) { } diff --git a/demo/stm32/usb_host/stm32f429igt6/Core/Inc/usb_config.h b/demo/stm32/usb_host/stm32f429igt6/Core/Inc/usb_config.h index 39c77df6..e33cca9d 100644 --- a/demo/stm32/usb_host/stm32f429igt6/Core/Inc/usb_config.h +++ b/demo/stm32/usb_host/stm32f429igt6/Core/Inc/usb_config.h @@ -1,7 +1,13 @@ -#ifndef _USB_CONFIG_H -#define _USB_CONFIG_H +/* + * Copyright (c) 2022, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef CHERRYUSB_CONFIG_H +#define CHERRYUSB_CONFIG_H + +/* ================ USB common Configuration ================ */ -/* USB common Configuration */ #ifndef CONFIG_USB_DBG_LEVEL #define CONFIG_USB_DBG_LEVEL USB_DBG_INFO #endif @@ -10,26 +16,42 @@ #define CONFIG_USB_PRINTF printf #endif +/* Enable print with color */ #define CONFIG_USB_PRINTF_COLOR_ENABLE -/* USB DEVICE Configuration */ +/* data align size when use dma */ +#ifndef CONFIG_USB_ALIGN_SIZE +#define CONFIG_USB_ALIGN_SIZE 4 +#endif + +/* attribute data into no cache ram */ +#define USB_NOCACHE_RAM_SECTION __attribute__((section(".noncacheable"))) + +/* ================ USB DEVICE Configuration ================*/ + /* core */ + +/* Ep0 max transfer buffer, specially for receiving data from ep0 out */ #ifndef CONFIG_USBDEV_REQUEST_BUFFER_LEN #define CONFIG_USBDEV_REQUEST_BUFFER_LEN 256 #endif - -#ifndef CONFIG_USBDEV_DESC_CHECK -#define CONFIG_USBDEV_DESC_CHECK 0 -#endif - -#ifndef CONFIG_USBDEV_TEST_MODE -#define CONFIG_USBDEV_TEST_MODE 0 -#endif +/* Setup packet log for debug */ +// #define CONFIG_USBDEV_SETUP_LOG_PRINT +/* Check if the input descriptor is correct */ +// #define CONFIG_USBDEV_DESC_CHECK +/* Enable test mode */ +// #define CONFIG_USBDEV_TEST_MODE /* cdc class */ + // #define CONFIG_USBDEV_CDC_ACM_UART /* msc class */ + +#ifndef CONFIG_USBDEV_MSC_BLOCK_SIZE +#define CONFIG_USBDEV_MSC_BLOCK_SIZE 512 +#endif + #ifndef CONFIG_USBDEV_MSC_MANUFACTURER_STRING #define CONFIG_USBDEV_MSC_MANUFACTURER_STRING "" #endif @@ -55,15 +77,22 @@ #endif /* audio class */ + #ifndef CONFIG_USBDEV_AUDIO_VERSION #define CONFIG_USBDEV_AUDIO_VERSION 0x0100 #endif #ifndef CONFIG_USBDEV_AUDIO_MAX_CHANNEL -#define CONFIG_USBDEV_AUDIO_MAX_CHANNEL 2 +#define CONFIG_USBDEV_AUDIO_MAX_CHANNEL 8 +#endif + +/* ================ USB HOST Configuration ================ */ +/* core */ +/* Ep0 max transfer buffer */ +#ifndef CONFIG_USBHOST_REQUEST_BUFFER_LEN +#define CONFIG_USBHOST_REQUEST_BUFFER_LEN 512 #endif -/* USB HOST Configuration */ #ifndef CONFIG_USBHOST_RHPORTS #define CONFIG_USBHOST_RHPORTS 1 #endif @@ -72,10 +101,6 @@ #define CONFIG_USBHOST_EHPORTS 4 #endif -#ifndef CONFIG_USBHOST_PIPE_NUM -#define CONFIG_USBHOST_PIPE_NUM 10 -#endif - #ifndef CONFIG_USBHOST_INTF_NUM #define CONFIG_USBHOST_INTF_NUM 6 #endif @@ -85,48 +110,38 @@ #endif #ifndef CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT -#define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 5000 +#define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 500 #endif #ifndef CONFIG_USBHOST_MSC_TIMEOUT #define CONFIG_USBHOST_MSC_TIMEOUT 5000 #endif -#ifndef CONFIG_USBHOST_HPWORKQ_PRIO -#define CONFIG_USBHOST_HPWORKQ_PRIO 5 -#endif -#ifndef CONFIG_USBHOST_HPWORKQ_STACKSIZE -#define CONFIG_USBHOST_HPWORKQ_STACKSIZE 2048 -#endif - -#ifndef CONFIG_USBHOST_LPWORKQ_PRIO -#define CONFIG_USBHOST_LPWORKQ_PRIO 1 -#endif -#ifndef CONFIG_USBHOST_LPWORKQ_STACKSIZE -#define CONFIG_USBHOST_LPWORKQ_STACKSIZE 2048 -#endif - #ifndef CONFIG_USBHOST_PSC_PRIO #define CONFIG_USBHOST_PSC_PRIO 4 #endif #ifndef CONFIG_USBHOST_PSC_STACKSIZE -#define CONFIG_USBHOST_PSC_STACKSIZE 4096 +#define CONFIG_USBHOST_PSC_STACKSIZE 2048 #endif #ifndef CONFIG_USBHOST_DEV_NAMELEN #define CONFIG_USBHOST_DEV_NAMELEN 16 #endif -#define CONFIG_USBHOST_ASYNCH //#define CONFIG_USBHOST_GET_STRING_DESC -/* EHCI Configuration */ -#define CONFIG_USB_EHCI_HCCR_BASE (0x20072000) -#define CONFIG_USB_EHCI_HCOR_BASE (0x20072000 + 0x10) -#define CONFIG_USB_EHCI_QH_NUM (10) -#define CONFIG_USB_EHCI_QTD_NUM (10) +#ifndef CONFIG_USBHOST_PIPE_NUM +#define CONFIG_USBHOST_PIPE_NUM 12 +#endif + +/* ================ EHCI Configuration ================ */ + +#define CONFIG_USB_EHCI_HCCR_BASE (0x20072000) +#define CONFIG_USB_EHCI_HCOR_BASE (0x20072000 + 0x10) +#define CONFIG_EHCI_FRAME_LIST_SIZE 1024 // #define CONFIG_USB_EHCI_INFO_ENABLE -#define CONFIG_USB_ECHI_HCOR_RESERVED_DISABLE +// #define CONFIG_USB_ECHI_HCOR_RESERVED_DISABLE // #define CONFIG_USB_EHCI_CONFIGFLAG +// #define CONFIG_USB_EHCI_PORT_POWER #endif diff --git a/demo/stm32/usb_host/stm32f429igt6/Core/Src/main.c b/demo/stm32/usb_host/stm32f429igt6/Core/Src/main.c index 9edcc26d..21606e8c 100644 --- a/demo/stm32/usb_host/stm32f429igt6/Core/Src/main.c +++ b/demo/stm32/usb_host/stm32f429igt6/Core/Src/main.c @@ -122,9 +122,10 @@ int main(void) MX_USART1_UART_Init(); //MX_USB_OTG_HS_HCD_Init(); /* USER CODE BEGIN 2 */ - - usbh_initialize(); printf("Start usb host task...\r\n"); + extern void usbh_class_test(void); + usbh_initialize(); + usbh_class_test(); vTaskStartScheduler(); /* USER CODE END 2 */ diff --git a/demo/stm32/usb_host/stm32f429igt6/MDK-ARM/stm32f429igt6.uvoptx b/demo/stm32/usb_host/stm32f429igt6/MDK-ARM/stm32f429igt6.uvoptx index bc0bd9a9..3a19fbd0 100644 --- a/demo/stm32/usb_host/stm32f429igt6/MDK-ARM/stm32f429igt6.uvoptx +++ b/demo/stm32/usb_host/stm32f429igt6/MDK-ARM/stm32f429igt6.uvoptx @@ -159,52 +159,20 @@ 0 347 1 -
134246552
+
0
0 0 0 0 0 - 1 + 0 ..\..\..\..\..\class\msc\usbh_msc.c - \\stm32f429igt6\../../../../../class/msc/usbh_msc.c\347 + 1 0 - 1027 - 1 -
0
- 0 - 0 - 0 - 0 - 0 - 0 - ..\..\..\..\..\port\dwc2\usb_hc_dwc2.c - - -
- - 2 - 0 - 1030 - 1 -
0
- 0 - 0 - 0 - 0 - 0 - 0 - ..\..\..\..\..\port\dwc2\usb_hc_dwc2.c - - -
- - 3 - 0 1309 1
0
@@ -219,7 +187,7 @@
- 4 + 2 0 1314 1 @@ -311,7 +279,7 @@ Application/MDK-ARM - 0 + 1 0 0 0 @@ -399,7 +367,7 @@ Drivers/STM32F4xx_HAL_Driver - 1 + 0 0 0 0 @@ -747,7 +715,7 @@ CherryUSB - 1 + 0 0 0 0 @@ -770,6 +738,18 @@ 0 0 0 + ..\..\..\..\..\class\hub\usbh_hub.c + usbh_hub.c + 0 + 0 +
+ + 6 + 36 + 1 + 0 + 0 + 0 ..\..\..\..\..\class\cdc\usbh_cdc_acm.c usbh_cdc_acm.c 0 @@ -777,7 +757,7 @@ 6 - 36 + 37 1 0 0 @@ -789,7 +769,7 @@ 6 - 37 + 38 1 0 0 @@ -801,7 +781,19 @@ 6 - 38 + 39 + 1 + 0 + 0 + 0 + ..\..\..\..\..\class\wireless\usbh_rndis.c + usbh_rndis.c + 0 + 0 + + + 6 + 40 1 0 0 @@ -813,7 +805,7 @@ 6 - 39 + 41 1 0 0 @@ -833,7 +825,7 @@ 0 7 - 40 + 42 1 0 0 @@ -845,7 +837,7 @@ 7 - 41 + 43 1 0 0 @@ -857,7 +849,7 @@ 7 - 42 + 44 1 0 0 @@ -869,7 +861,7 @@ 7 - 43 + 45 1 0 0 @@ -881,7 +873,7 @@ 7 - 44 + 46 1 0 0 diff --git a/demo/stm32/usb_host/stm32f429igt6/MDK-ARM/stm32f429igt6.uvprojx b/demo/stm32/usb_host/stm32f429igt6/MDK-ARM/stm32f429igt6.uvprojx index fbb4c041..f1212211 100644 --- a/demo/stm32/usb_host/stm32f429igt6/MDK-ARM/stm32f429igt6.uvprojx +++ b/demo/stm32/usb_host/stm32f429igt6/MDK-ARM/stm32f429igt6.uvprojx @@ -340,7 +340,7 @@ USE_HAL_DRIVER,STM32F429xx - ../Core/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F4xx/Include;../Drivers/CMSIS/Include;..\..\..\..\..\common;..\..\..\..\..\core;..\..\..\..\..\class\cdc;..\..\..\..\..\class\hub;..\..\..\..\..\class\hid;..\..\..\..\..\class\msc;..\..\..\..\..\osal;..\..\..\..\..\third_party\FreeRTOS-10.4\include;..\..\..\..\..\third_party\FreeRTOS-10.4\portable\GCC\ARM_CM4F;..\..\..\..\..\third_party\fatfs-0.14\source + ../Core/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F4xx/Include;../Drivers/CMSIS/Include;..\..\..\..\..\common;..\..\..\..\..\core;..\..\..\..\..\class\cdc;..\..\..\..\..\class\hub;..\..\..\..\..\class\hid;..\..\..\..\..\class\msc;..\..\..\..\..\class\wireless;..\..\..\..\..\osal;..\..\..\..\..\third_party\FreeRTOS-10.4\include;..\..\..\..\..\third_party\FreeRTOS-10.4\portable\GCC\ARM_CM4F;..\..\..\..\..\third_party\fatfs-0.14\source @@ -579,6 +579,11 @@ 1 ..\..\..\..\..\core\usbh_core.c + + usbh_hub.c + 1 + ..\..\..\..\..\class\hub\usbh_hub.c + usbh_cdc_acm.c 1 @@ -594,6 +599,11 @@ 1 ..\..\..\..\..\class\hid\usbh_hid.c + + usbh_rndis.c + 1 + ..\..\..\..\..\class\wireless\usbh_rndis.c + usb_osal_freertos.c 1 diff --git a/demo/stm32/usb_host/stm32h743xih6/Core/Inc/usb_config.h b/demo/stm32/usb_host/stm32h743xih6/Core/Inc/usb_config.h index 39c77df6..e33cca9d 100644 --- a/demo/stm32/usb_host/stm32h743xih6/Core/Inc/usb_config.h +++ b/demo/stm32/usb_host/stm32h743xih6/Core/Inc/usb_config.h @@ -1,7 +1,13 @@ -#ifndef _USB_CONFIG_H -#define _USB_CONFIG_H +/* + * Copyright (c) 2022, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef CHERRYUSB_CONFIG_H +#define CHERRYUSB_CONFIG_H + +/* ================ USB common Configuration ================ */ -/* USB common Configuration */ #ifndef CONFIG_USB_DBG_LEVEL #define CONFIG_USB_DBG_LEVEL USB_DBG_INFO #endif @@ -10,26 +16,42 @@ #define CONFIG_USB_PRINTF printf #endif +/* Enable print with color */ #define CONFIG_USB_PRINTF_COLOR_ENABLE -/* USB DEVICE Configuration */ +/* data align size when use dma */ +#ifndef CONFIG_USB_ALIGN_SIZE +#define CONFIG_USB_ALIGN_SIZE 4 +#endif + +/* attribute data into no cache ram */ +#define USB_NOCACHE_RAM_SECTION __attribute__((section(".noncacheable"))) + +/* ================ USB DEVICE Configuration ================*/ + /* core */ + +/* Ep0 max transfer buffer, specially for receiving data from ep0 out */ #ifndef CONFIG_USBDEV_REQUEST_BUFFER_LEN #define CONFIG_USBDEV_REQUEST_BUFFER_LEN 256 #endif - -#ifndef CONFIG_USBDEV_DESC_CHECK -#define CONFIG_USBDEV_DESC_CHECK 0 -#endif - -#ifndef CONFIG_USBDEV_TEST_MODE -#define CONFIG_USBDEV_TEST_MODE 0 -#endif +/* Setup packet log for debug */ +// #define CONFIG_USBDEV_SETUP_LOG_PRINT +/* Check if the input descriptor is correct */ +// #define CONFIG_USBDEV_DESC_CHECK +/* Enable test mode */ +// #define CONFIG_USBDEV_TEST_MODE /* cdc class */ + // #define CONFIG_USBDEV_CDC_ACM_UART /* msc class */ + +#ifndef CONFIG_USBDEV_MSC_BLOCK_SIZE +#define CONFIG_USBDEV_MSC_BLOCK_SIZE 512 +#endif + #ifndef CONFIG_USBDEV_MSC_MANUFACTURER_STRING #define CONFIG_USBDEV_MSC_MANUFACTURER_STRING "" #endif @@ -55,15 +77,22 @@ #endif /* audio class */ + #ifndef CONFIG_USBDEV_AUDIO_VERSION #define CONFIG_USBDEV_AUDIO_VERSION 0x0100 #endif #ifndef CONFIG_USBDEV_AUDIO_MAX_CHANNEL -#define CONFIG_USBDEV_AUDIO_MAX_CHANNEL 2 +#define CONFIG_USBDEV_AUDIO_MAX_CHANNEL 8 +#endif + +/* ================ USB HOST Configuration ================ */ +/* core */ +/* Ep0 max transfer buffer */ +#ifndef CONFIG_USBHOST_REQUEST_BUFFER_LEN +#define CONFIG_USBHOST_REQUEST_BUFFER_LEN 512 #endif -/* USB HOST Configuration */ #ifndef CONFIG_USBHOST_RHPORTS #define CONFIG_USBHOST_RHPORTS 1 #endif @@ -72,10 +101,6 @@ #define CONFIG_USBHOST_EHPORTS 4 #endif -#ifndef CONFIG_USBHOST_PIPE_NUM -#define CONFIG_USBHOST_PIPE_NUM 10 -#endif - #ifndef CONFIG_USBHOST_INTF_NUM #define CONFIG_USBHOST_INTF_NUM 6 #endif @@ -85,48 +110,38 @@ #endif #ifndef CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT -#define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 5000 +#define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 500 #endif #ifndef CONFIG_USBHOST_MSC_TIMEOUT #define CONFIG_USBHOST_MSC_TIMEOUT 5000 #endif -#ifndef CONFIG_USBHOST_HPWORKQ_PRIO -#define CONFIG_USBHOST_HPWORKQ_PRIO 5 -#endif -#ifndef CONFIG_USBHOST_HPWORKQ_STACKSIZE -#define CONFIG_USBHOST_HPWORKQ_STACKSIZE 2048 -#endif - -#ifndef CONFIG_USBHOST_LPWORKQ_PRIO -#define CONFIG_USBHOST_LPWORKQ_PRIO 1 -#endif -#ifndef CONFIG_USBHOST_LPWORKQ_STACKSIZE -#define CONFIG_USBHOST_LPWORKQ_STACKSIZE 2048 -#endif - #ifndef CONFIG_USBHOST_PSC_PRIO #define CONFIG_USBHOST_PSC_PRIO 4 #endif #ifndef CONFIG_USBHOST_PSC_STACKSIZE -#define CONFIG_USBHOST_PSC_STACKSIZE 4096 +#define CONFIG_USBHOST_PSC_STACKSIZE 2048 #endif #ifndef CONFIG_USBHOST_DEV_NAMELEN #define CONFIG_USBHOST_DEV_NAMELEN 16 #endif -#define CONFIG_USBHOST_ASYNCH //#define CONFIG_USBHOST_GET_STRING_DESC -/* EHCI Configuration */ -#define CONFIG_USB_EHCI_HCCR_BASE (0x20072000) -#define CONFIG_USB_EHCI_HCOR_BASE (0x20072000 + 0x10) -#define CONFIG_USB_EHCI_QH_NUM (10) -#define CONFIG_USB_EHCI_QTD_NUM (10) +#ifndef CONFIG_USBHOST_PIPE_NUM +#define CONFIG_USBHOST_PIPE_NUM 12 +#endif + +/* ================ EHCI Configuration ================ */ + +#define CONFIG_USB_EHCI_HCCR_BASE (0x20072000) +#define CONFIG_USB_EHCI_HCOR_BASE (0x20072000 + 0x10) +#define CONFIG_EHCI_FRAME_LIST_SIZE 1024 // #define CONFIG_USB_EHCI_INFO_ENABLE -#define CONFIG_USB_ECHI_HCOR_RESERVED_DISABLE +// #define CONFIG_USB_ECHI_HCOR_RESERVED_DISABLE // #define CONFIG_USB_EHCI_CONFIGFLAG +// #define CONFIG_USB_EHCI_PORT_POWER #endif diff --git a/demo/stm32/usb_host/stm32h743xih6/Core/Src/main.c b/demo/stm32/usb_host/stm32h743xih6/Core/Src/main.c index 3babbd6f..618e502a 100644 --- a/demo/stm32/usb_host/stm32h743xih6/Core/Src/main.c +++ b/demo/stm32/usb_host/stm32h743xih6/Core/Src/main.c @@ -225,15 +225,6 @@ void cpu_mpu_config(uint8_t Region, uint8_t Mode, uint32_t Address, uint32_t Siz } -void usb_dcache_clean(uintptr_t addr, uint32_t len) -{ - SCB_CleanDCache_by_Addr((uint32_t*)addr,len); -} - -void usb_dcache_invalidate(uintptr_t addr, uint32_t len) -{ - SCB_InvalidateDCache_by_Addr((uint32_t*)addr,len); -} /* USER CODE END 0 */ /** @@ -248,10 +239,9 @@ int main(void) /* Enable I-Cache---------------------------------------------------------*/ SCB_EnableICache(); -#ifdef CONFIG_USB_DCACHE_ENABLE /* Enable D-Cache---------------------------------------------------------*/ SCB_EnableDCache(); -#endif + /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ @@ -273,11 +263,13 @@ int main(void) MX_USART1_UART_Init(); //MX_USB_OTG_HS_HCD_Init(); /* USER CODE BEGIN 2 */ -#ifdef CONFIG_USB_DCACHE_ENABLE - cpu_mpu_config(0, MPU_Normal_WB, 0x24000000, MPU_REGION_SIZE_512KB); -#endif - usbh_initialize(); + + cpu_mpu_config(0, MPU_Normal_NonCache, 0x24070000, MPU_REGION_SIZE_64KB); + printf("Start usb host task...\r\n"); + extern void usbh_class_test(void); + usbh_initialize(); + usbh_class_test(); vTaskStartScheduler(); /* USER CODE END 2 */ diff --git a/demo/stm32/usb_host/stm32h743xih6/MDK-ARM/stm32h743xih6.uvoptx b/demo/stm32/usb_host/stm32h743xih6/MDK-ARM/stm32h743xih6.uvoptx index 0db1921f..71451a05 100644 --- a/demo/stm32/usb_host/stm32h743xih6/MDK-ARM/stm32h743xih6.uvoptx +++ b/demo/stm32/usb_host/stm32h743xih6/MDK-ARM/stm32h743xih6.uvoptx @@ -800,8 +800,8 @@ 0 0 0 - ..\..\..\..\..\osal\usb_osal_freertos.c - usb_osal_freertos.c + ..\..\..\..\..\class\hub\usbh_hub.c + usbh_hub.c 0 0 @@ -848,6 +848,30 @@ 0 0 0 + ..\..\..\..\..\class\wireless\usbh_rndis.c + usbh_rndis.c + 0 + 0 + + + 6 + 43 + 1 + 0 + 0 + 0 + ..\..\..\..\..\osal\usb_osal_freertos.c + usb_osal_freertos.c + 0 + 0 + + + 6 + 44 + 1 + 0 + 0 + 0 ..\..\..\..\..\port\dwc2\usb_hc_dwc2.c usb_hc_dwc2.c 0 diff --git a/demo/stm32/usb_host/stm32h743xih6/MDK-ARM/stm32h743xih6.uvprojx b/demo/stm32/usb_host/stm32h743xih6/MDK-ARM/stm32h743xih6.uvprojx index 939819a2..059518c6 100644 --- a/demo/stm32/usb_host/stm32h743xih6/MDK-ARM/stm32h743xih6.uvprojx +++ b/demo/stm32/usb_host/stm32h743xih6/MDK-ARM/stm32h743xih6.uvprojx @@ -211,7 +211,7 @@ 0 0 0 - 0 + 1 1 @@ -338,9 +338,9 @@ 0 - USE_HAL_DRIVER,STM32H743xx,STM32H7,CONFIG_USB_DCACHE_ENABLE,CONFIG_USB_ALIGN_SIZE=32 + USE_HAL_DRIVER,STM32H743xx,STM32H7 - ../Core/Inc;../Drivers/STM32H7xx_HAL_Driver/Inc;../Drivers/STM32H7xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32H7xx/Include;../Drivers/CMSIS/Include;..\..\..\..\..\core;..\..\..\..\..\common;..\..\..\..\..\osal;..\..\..\..\..\class\cdc;..\..\..\..\..\class\hid;..\..\..\..\..\class\msc;..\..\..\..\..\class\hub;..\..\..\..\..\third_party\FreeRTOS-10.4\include;..\..\..\..\..\third_party\FreeRTOS-10.4\portable\GCC\ARM_CM7\r0p1 + ../Core/Inc;../Drivers/STM32H7xx_HAL_Driver/Inc;../Drivers/STM32H7xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32H7xx/Include;../Drivers/CMSIS/Include;..\..\..\..\..\core;..\..\..\..\..\common;..\..\..\..\..\osal;..\..\..\..\..\class\cdc;..\..\..\..\..\class\hid;..\..\..\..\..\class\msc;..\..\..\..\..\class\hub;..\..\..\..\..\class\wireless;..\..\..\..\..\third_party\FreeRTOS-10.4\include;..\..\..\..\..\third_party\FreeRTOS-10.4\portable\GCC\ARM_CM7\r0p1 @@ -362,7 +362,7 @@ - 1 + 0 0 0 0 @@ -371,7 +371,7 @@ - + stm32h743xih6\stm32h743xih6.sct @@ -595,9 +595,9 @@ ..\..\..\..\..\core\usbh_core.c - usb_osal_freertos.c + usbh_hub.c 1 - ..\..\..\..\..\osal\usb_osal_freertos.c + ..\..\..\..\..\class\hub\usbh_hub.c usbh_cdc_acm.c @@ -614,6 +614,16 @@ 1 ..\..\..\..\..\class\msc\usbh_msc.c + + usbh_rndis.c + 1 + ..\..\..\..\..\class\wireless\usbh_rndis.c + + + usb_osal_freertos.c + 1 + ..\..\..\..\..\osal\usb_osal_freertos.c + usb_hc_dwc2.c 1 diff --git a/demo/stm32/usb_host/stm32h743xih6/MDK-ARM/stm32h743xih6/stm32h743xih6.sct b/demo/stm32/usb_host/stm32h743xih6/MDK-ARM/stm32h743xih6/stm32h743xih6.sct new file mode 100644 index 00000000..0d285436 --- /dev/null +++ b/demo/stm32/usb_host/stm32h743xih6/MDK-ARM/stm32h743xih6/stm32h743xih6.sct @@ -0,0 +1,19 @@ +; ************************************************************* +; *** Scatter-Loading Description File generated by uVision *** +; ************************************************************* + +LR_IROM1 0x08000000 0x00200000 { ; load region size_region + ER_IROM1 0x08000000 0x00200000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + .ANY (+XO) + } + RW_IRAM2 0x24000000 0x00070000 { ; RW data + .ANY (+RW +ZI) + } + USB_NOCACHERAM 0x24070000 0x00010000 { ; RW data + *(.noncacheable) + } +} + diff --git a/demo/usb_host.c b/demo/usb_host.c index 999ea5e2..8fec0417 100644 --- a/demo/usb_host.c +++ b/demo/usb_host.c @@ -21,6 +21,8 @@ void usbh_cdc_acm_callback(void *arg, int nbytes) int cdc_acm_test(void) { int ret; + usbh_pipe_t bulkin; + usbh_pipe_t bulkout; struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)usbh_find_class_instance("/dev/ttyACM0"); @@ -29,8 +31,11 @@ int cdc_acm_test(void) return -1; } + bulkin = cdc_acm_class->bulkin; + bulkout = cdc_acm_class->bulkout; + memset(cdc_buffer, 0, 512); - ret = usbh_ep_bulk_transfer(cdc_acm_class->bulkin, cdc_buffer, 512, 3000); + ret = usbh_bulk_transfer(bulkin, cdc_buffer, 20, 3000); if (ret < 0) { USB_LOG_RAW("bulk in error,ret:%d\r\n", ret); } else { @@ -44,7 +49,7 @@ int cdc_acm_test(void) const uint8_t data1[10] = { 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x08, 0x14 }; memcpy(cdc_buffer, data1, 8); - ret = usbh_ep_bulk_transfer(cdc_acm_class->bulkout, cdc_buffer, 8, 3000); + ret = usbh_bulk_transfer(bulkout, cdc_buffer, 8, 3000); if (ret < 0) { USB_LOG_RAW("bulk out error,ret:%d\r\n", ret); } else { @@ -52,9 +57,9 @@ int cdc_acm_test(void) } #if 0 - usbh_ep_bulk_async_transfer(cdc_acm_class->bulkin, cdc_buffer, 512, usbh_cdc_acm_callback, cdc_acm_class); + usbh_bulk_async_transfer(bulkin, cdc_buffer, 512, usbh_cdc_acm_callback, cdc_acm_class); #else - ret = usbh_ep_bulk_transfer(cdc_acm_class->bulkin, cdc_buffer, 512, 3000); + ret = usbh_bulk_transfer(bulkin, cdc_buffer, 512, 3000); if (ret < 0) { USB_LOG_RAW("bulk in error,ret:%d\r\n", ret); } else { @@ -63,9 +68,7 @@ int cdc_acm_test(void) USB_LOG_RAW("0x%02x ", cdc_buffer[i]); } } - USB_LOG_RAW("\r\n"); - return ret; #endif } @@ -166,13 +169,13 @@ int hid_test(void) USB_LOG_RAW("do not find /dev/input0\r\n"); return -1; } -#if 1 - ret = usbh_ep_intr_async_transfer(hid_class->intin, hid_buffer, 128, usbh_hid_callback, hid_class); +#if 0 + ret = usbh_intr_async_transfer(hid_class->intin, hid_buffer, 8, usbh_hid_callback, hid_class); if (ret < 0) { USB_LOG_RAW("intr asnyc in error,ret:%d\r\n", ret); } #else - ret = usbh_ep_intr_transfer(hid_class->intin, hid_buffer, 128, 1000); + ret = usbh_int_transfer(hid_class->intin, hid_buffer, 8, 1000); if (ret < 0) { USB_LOG_RAW("intr in error,ret:%d\r\n", ret); return ret; @@ -184,7 +187,24 @@ int hid_test(void) void usbh_device_mount_done_callback(struct usbh_hubport *hport) { - cdc_acm_test(); - msc_test(); - hid_test(); +} + +void usbh_device_unmount_done_callback(struct usbh_hubport *hport) +{ +} + +static void usbh_class_test_thread(void *argument) +{ + while (1) { + printf("hellworld\r\n"); + usb_osal_msleep(1000); + cdc_acm_test(); + msc_test(); + hid_test(); + } +} + +void usbh_class_test(void) +{ + usb_osal_thread_create("usbh_test", 4096, CONFIG_USBHOST_PSC_PRIO + 1, usbh_class_test_thread, NULL); } \ No newline at end of file diff --git a/port/dwc2/usb_dc_dwc2.c b/port/dwc2/usb_dc_dwc2.c index 26135833..23518285 100644 --- a/port/dwc2/usb_dc_dwc2.c +++ b/port/dwc2/usb_dc_dwc2.c @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2022, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "usbd_core.h" #include "usb_dwc2_reg.h" #include "cmsis_compiler.h" diff --git a/port/dwc2/usb_hc_dwc2.c b/port/dwc2/usb_hc_dwc2.c index 19250969..cc29203f 100644 --- a/port/dwc2/usb_hc_dwc2.c +++ b/port/dwc2/usb_hc_dwc2.c @@ -1,16 +1,12 @@ +/* + * Copyright (c) 2022, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "usbh_core.h" +#include "usbh_hub.h" #include "usb_dwc2_reg.h" -#if defined(STM32F7) || defined(STM32H7) -#ifndef CONFIG_USB_DCACHE_ENABLE -#warning "if you enable dcache,please enable this macro" -#else -#if CONFIG_USB_ALIGN_SIZE != 32 -#error "dwc2 hs with dma and cache, must enable align32" -#endif -#endif -#endif - #ifndef USBH_IRQHandler #define USBH_IRQHandler OTG_HS_IRQHandler #endif @@ -19,8 +15,12 @@ #define USB_BASE (0x40040000UL) #endif -#ifndef CONFIG_USB_DWC2_PIPE_NUM -#define CONFIG_USB_DWC2_PIPE_NUM 12 /* Number of host channels */ +#if CONFIG_USBHOST_PIPE_NUM != 12 +#error dwc2 ip only supports 12 pipe num. +#endif + +#if defined(STM32F7) || defined(STM32H7) +#warning please check your buf addr is not in tcm and use nocache ram. #endif #define USB_OTG_GLB ((USB_OTG_GlobalTypeDef *)(USB_BASE)) @@ -31,35 +31,38 @@ #define USB_OTG_FIFO(i) *(__IO uint32_t *)(USB_BASE + USB_OTG_FIFO_BASE + ((i)*USB_OTG_FIFO_SIZE)) struct dwc2_pipe { + uint8_t dev_addr; uint8_t ep_addr; uint8_t ep_type; - uint16_t ep_mps; + uint8_t ep_interval; uint8_t speed; - uint8_t dev_addr; + uint16_t ep_mps; uint8_t data_pid; uint8_t chidx; - bool inuse; /* True: This channel is "in use" */ - uint8_t ep_interval; /* Interrupt/isochronous EP polling interval */ - uint16_t num_packets; /* for HCTSIZx */ - uint32_t xferlen; /* for HCTSIZx */ - uint8_t *buffer; /* for dcache invalidate */ - volatile int result; /* The result of the transfer */ - volatile uint32_t xfrd; /* Bytes transferred (at end of transfer) */ - volatile bool waiter; /* True: Thread is waiting for a channel event */ - usb_osal_sem_t waitsem; /* Channel wait semaphore */ - usb_osal_mutex_t exclsem; /* Support mutually exclusive access */ -#ifdef CONFIG_USBHOST_ASYNCH - usbh_asynch_callback_t callback; /* Transfer complete callback */ - void *arg; /* Argument that accompanies the callback */ -#endif + volatile uint8_t ep0_state; + uint16_t num_packets; + uint32_t xferlen; + bool inuse; + uint32_t xfrd; + volatile bool waiter; + usb_osal_sem_t waitsem; + struct usbh_hubport *hport; + struct usbh_urb *urb; }; struct dwc2_hcd { - volatile bool connected; - volatile bool port_enable; - struct dwc2_pipe chan[CONFIG_USB_DWC2_PIPE_NUM]; + volatile bool port_csc; + volatile bool port_pec; + volatile bool port_occ; + struct dwc2_pipe pipe_pool[CONFIG_USBHOST_PIPE_NUM]; } g_dwc2_hcd; +#define DWC2_EP0_STATE_SETUP 0 +#define DWC2_EP0_STATE_INDATA 1 +#define DWC2_EP0_STATE_OUTDATA 2 +#define DWC2_EP0_STATE_INSTATUS 3 +#define DWC2_EP0_STATE_OUTSTATUS 4 + static inline int dwc2_reset(void) { uint32_t count = 0U; @@ -356,136 +359,110 @@ static int dwc2_pipe_alloc(void) { int chidx; - for (chidx = 0; chidx < CONFIG_USB_DWC2_PIPE_NUM; chidx++) { - if (!g_dwc2_hcd.chan[chidx].inuse) { - g_dwc2_hcd.chan[chidx].inuse = true; + for (chidx = 0; chidx < CONFIG_USBHOST_PIPE_NUM; chidx++) { + if (!g_dwc2_hcd.pipe_pool[chidx].inuse) { + g_dwc2_hcd.pipe_pool[chidx].inuse = true; return chidx; } } - return -EBUSY; + return -1; } -static void dwc2_pipe_free(struct dwc2_pipe *chan) +static void dwc2_pipe_free(struct dwc2_pipe *pipe) { - chan->inuse = false; + pipe->inuse = false; } -static int dwc2_pipe_waitsetup(struct dwc2_pipe *chan) +static void dwc2_control_pipe_init(struct dwc2_pipe *chan, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen) { - size_t flags; - int ret = -ENODEV; - - flags = usb_osal_enter_critical_section(); - - if (usbh_get_port_connect_status(1)) { - chan->waiter = true; - chan->result = -EBUSY; - chan->xfrd = 0; -#ifdef CONFIG_USBHOST_ASYNCH - chan->callback = NULL; - chan->arg = NULL; -#endif - ret = 0; + if (chan->ep0_state == DWC2_EP0_STATE_SETUP) /* fill setup */ + { + chan->num_packets = dwc2_calculate_packet_num(8, 0x00, chan->ep_mps, &chan->xferlen); + dwc2_pipe_init(chan->chidx, chan->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, chan->ep_mps, chan->speed); + dwc2_pipe_transfer(chan->chidx, 0x00, (uint32_t *)setup, chan->xferlen, chan->num_packets, HC_PID_SETUP); + } else if (chan->ep0_state == DWC2_EP0_STATE_INDATA) /* fill in data */ + { + chan->num_packets = dwc2_calculate_packet_num(setup->wLength, 0x80, chan->ep_mps, &chan->xferlen); + dwc2_pipe_init(chan->chidx, chan->dev_addr, 0x80, USB_ENDPOINT_TYPE_CONTROL, chan->ep_mps, chan->speed); + dwc2_pipe_transfer(chan->chidx, 0x80, (uint32_t *)buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1); + } else if (chan->ep0_state == DWC2_EP0_STATE_OUTDATA) /* fill out data */ + { + chan->num_packets = dwc2_calculate_packet_num(setup->wLength, 0x00, chan->ep_mps, &chan->xferlen); + dwc2_pipe_init(chan->chidx, chan->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, chan->ep_mps, chan->speed); + dwc2_pipe_transfer(chan->chidx, 0x00, (uint32_t *)buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1); + } else if (chan->ep0_state == DWC2_EP0_STATE_INSTATUS) /* fill in status */ + { + chan->num_packets = dwc2_calculate_packet_num(0, 0x80, chan->ep_mps, &chan->xferlen); + dwc2_pipe_init(chan->chidx, chan->dev_addr, 0x80, USB_ENDPOINT_TYPE_CONTROL, chan->ep_mps, chan->speed); + dwc2_pipe_transfer(chan->chidx, 0x80, NULL, chan->xferlen, chan->num_packets, HC_PID_DATA1); + } else if (chan->ep0_state == DWC2_EP0_STATE_OUTSTATUS) /* fill out status */ + { + chan->num_packets = dwc2_calculate_packet_num(0, 0x00, chan->ep_mps, &chan->xferlen); + dwc2_pipe_init(chan->chidx, chan->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, chan->ep_mps, chan->speed); + dwc2_pipe_transfer(chan->chidx, 0x00, NULL, chan->xferlen, chan->num_packets, HC_PID_DATA1); } - usb_osal_leave_critical_section(flags); - return ret; } -#ifdef CONFIG_USBHOST_ASYNCH -static int dwc2_pipe_asynchsetup(struct dwc2_pipe *chan, usbh_asynch_callback_t callback, void *arg) +static void dwc2_other_pipe_init(struct dwc2_pipe *chan, uint8_t *buffer, uint32_t buflen) { - size_t flags; - int ret = -ENODEV; - - flags = usb_osal_enter_critical_section(); - - if (usbh_get_port_connect_status(1)) { - chan->waiter = false; - chan->result = -EBUSY; - chan->xfrd = 0; - chan->callback = callback; - chan->arg = arg; - - ret = 0; - } - - usb_osal_leave_critical_section(flags); - return ret; -} -#endif - -static int dwc2_pipe_wait(struct dwc2_pipe *chan, uint32_t timeout) -{ - int ret; - - /* wait until timeout or sem give */ - if (chan->waiter) { - ret = usb_osal_sem_take(chan->waitsem, timeout); - if (ret < 0) { - return ret; - } - } - - /* Sem give, check if giving from error isr */ - ret = chan->result; - if (ret < 0) { - return ret; - } - return chan->xfrd; + chan->num_packets = dwc2_calculate_packet_num(buflen, chan->ep_addr, chan->ep_mps, &chan->xferlen); + dwc2_pipe_transfer(chan->chidx, chan->ep_addr, (uint32_t *)buffer, chan->xferlen, chan->num_packets, chan->data_pid); } -static void dwc2_pipe_wakeup(struct dwc2_pipe *chan) +static int usbh_reset_port(const uint8_t port) { - usbh_asynch_callback_t callback; - void *arg; - int nbytes; + __IO uint32_t hprt0 = 0U; - if (chan->waiter) { - chan->waiter = false; - usb_osal_sem_give(chan->waitsem); - } -#ifdef CONFIG_USBHOST_ASYNCH - else if (chan->callback) { - callback = chan->callback; - arg = chan->arg; - nbytes = chan->xfrd; - chan->callback = NULL; - chan->arg = NULL; - if (chan->result < 0) { - nbytes = chan->result; - } -#ifdef CONFIG_USB_DCACHE_ENABLE - if (((chan->ep_addr & 0x80) == 0x80) && (nbytes > 0)) { - usb_dcache_invalidate((uint32_t)chan->buffer, nbytes); - } -#endif - callback(arg, nbytes); - } + hprt0 = USB_OTG_HPRT; -#endif + hprt0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET | + USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG); + + USB_OTG_HPRT = (USB_OTG_HPRT_PRST | hprt0); + usb_osal_msleep(100U); /* See Note #1 */ + USB_OTG_HPRT = ((~USB_OTG_HPRT_PRST) & hprt0); + usb_osal_msleep(10U); + + while (!(USB_OTG_HPRT & USB_OTG_HPRT_PENA)) { + } + return 0; +} + +static uint8_t usbh_get_port_speed(const uint8_t port) +{ + __IO uint32_t hprt0 = 0U; + uint8_t speed; + + hprt0 = USB_OTG_HPRT; + + speed = (hprt0 & USB_OTG_HPRT_PSPD) >> 17; + + if (speed == HPRT0_PRTSPD_HIGH_SPEED) { + return USB_SPEED_HIGH; + } else if (speed == HPRT0_PRTSPD_FULL_SPEED) { + return USB_SPEED_FULL; + } else if (speed == HPRT0_PRTSPD_LOW_SPEED) { + return USB_SPEED_LOW; + } else { + return USB_SPEED_UNKNOWN; + } } __WEAK void usb_hc_low_level_init(void) { } -int usb_hc_sw_init(void) -{ - memset(&g_dwc2_hcd, 0, sizeof(struct dwc2_hcd)); - - for (uint8_t chidx = 0; chidx < CONFIG_USB_DWC2_PIPE_NUM; chidx++) { - g_dwc2_hcd.chan[chidx].exclsem = usb_osal_mutex_create(); - g_dwc2_hcd.chan[chidx].waitsem = usb_osal_sem_create(0); - } - - return 0; -} - -int usb_hc_hw_init(void) +int usb_hc_init(void) { int ret; + memset(&g_dwc2_hcd, 0, sizeof(struct dwc2_hcd)); + + for (uint8_t chidx = 0; chidx < CONFIG_USBHOST_PIPE_NUM; chidx++) { + g_dwc2_hcd.pipe_pool[chidx].waitsem = usb_osal_sem_create(0); + } + usb_hc_low_level_init(); USB_OTG_GLB->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT; @@ -498,8 +475,7 @@ int usb_hc_hw_init(void) /* Restart the Phy Clock */ USB_OTG_PCGCCTL = 0U; -#if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) || \ - defined(STM32F7) || defined(STM32H7) +#if defined(STM32F7) || defined(STM32H7) /* Disable HW VBUS sensing */ USB_OTG_GLB->GCCFG &= ~(USB_OTG_GCCFG_VBDEN); /* Disable Battery chargin detector */ @@ -523,7 +499,7 @@ int usb_hc_hw_init(void) ret = dwc2_flush_rxfifo(); /* Clear all pending HC Interrupts */ - for (uint8_t i = 0U; i < CONFIG_USB_DWC2_PIPE_NUM; i++) { + for (uint8_t i = 0U; i < CONFIG_USBHOST_PIPE_NUM; i++) { USB_OTG_HC(i)->HCINT = 0xFFFFFFFFU; USB_OTG_HC(i)->HCINTMSK = 0U; } @@ -550,112 +526,188 @@ int usb_hc_hw_init(void) USB_OTG_GINTSTS_DISCINT | USB_OTG_GINTMSK_PXFRM_IISOOXFRM | USB_OTG_GINTMSK_WUIM); - // USB_OTG_GLB->GINTMSK |=USB_OTG_GINTMSK_SOFM; + USB_OTG_GLB->GINTMSK |= USB_OTG_GINTMSK_SOFM; USB_OTG_GLB->GAHBCFG |= USB_OTG_GAHBCFG_GINT; return 0; } -bool usbh_get_port_connect_status(const uint8_t port) +int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf) { __IO uint32_t hprt0; + uint8_t nports; + uint8_t port; + uint32_t status; - hprt0 = USB_OTG_HPRT; + nports = CONFIG_USBHOST_RHPORTS; + port = setup->wIndex; + if (setup->bmRequestType & USB_REQUEST_RECIPIENT_DEVICE) { + switch (setup->bRequest) { + case HUB_REQUEST_CLEAR_FEATURE: + switch (setup->wValue) { + case HUB_FEATURE_HUB_C_LOCALPOWER: + break; + case HUB_FEATURE_HUB_C_OVERCURRENT: + break; + default: + return -EPIPE; + } + break; + case HUB_REQUEST_SET_FEATURE: + switch (setup->wValue) { + case HUB_FEATURE_HUB_C_LOCALPOWER: + break; + case HUB_FEATURE_HUB_C_OVERCURRENT: + break; + default: + return -EPIPE; + } + break; + case HUB_REQUEST_GET_DESCRIPTOR: + break; + case HUB_REQUEST_GET_STATUS: + memset(buf, 0, 4); + break; + default: + break; + } + } else if (setup->bmRequestType & USB_REQUEST_RECIPIENT_OTHER) { + switch (setup->bRequest) { + case HUB_REQUEST_CLEAR_FEATURE: + if (!port || port > nports) { + return -EPIPE; + } - if ((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS) { - return true; - } else { - return false; + switch (setup->wValue) { + case HUB_PORT_FEATURE_ENABLE: + USB_OTG_HPRT &= ~USB_OTG_HPRT_PENA; + break; + case HUB_PORT_FEATURE_SUSPEND: + case HUB_PORT_FEATURE_C_SUSPEND: + break; + case HUB_PORT_FEATURE_POWER: + break; + case HUB_PORT_FEATURE_C_CONNECTION: + g_dwc2_hcd.port_csc = 0; + break; + case HUB_PORT_FEATURE_C_ENABLE: + g_dwc2_hcd.port_pec = 0; + break; + case HUB_PORT_FEATURE_C_OVER_CURREN: + g_dwc2_hcd.port_occ = 0; + break; + case HUB_PORT_FEATURE_C_RESET: + break; + default: + return -EPIPE; + } + break; + case HUB_REQUEST_SET_FEATURE: + if (!port || port > nports) { + return -EPIPE; + } + + switch (setup->wValue) { + case HUB_PORT_FEATURE_SUSPEND: + break; + case HUB_PORT_FEATURE_POWER: + USB_OTG_HPRT &= ~USB_OTG_HPRT_PPWR; + break; + case HUB_PORT_FEATURE_RESET: + usbh_reset_port(port); + break; + + default: + return -EPIPE; + } + break; + case HUB_REQUEST_GET_STATUS: + if (!port || port > nports) { + return -EPIPE; + } + hprt0 = USB_OTG_HPRT; + + status = 0; + if (g_dwc2_hcd.port_csc) { + status |= (1 << HUB_PORT_FEATURE_C_CONNECTION); + } + if (g_dwc2_hcd.port_pec) { + status |= (1 << HUB_PORT_FEATURE_C_ENABLE); + } + if (g_dwc2_hcd.port_occ) { + status |= (1 << HUB_PORT_FEATURE_C_OVER_CURREN); + } + + if (hprt0 & USB_OTG_HPRT_PCSTS) { + status |= (1 << HUB_PORT_FEATURE_CONNECTION); + } + if (hprt0 & USB_OTG_HPRT_PENA) { + status |= (1 << HUB_PORT_FEATURE_ENABLE); + if (usbh_get_port_speed(port) == USB_SPEED_LOW) { + status |= (1 << HUB_PORT_FEATURE_LOWSPEED); + } else if (usbh_get_port_speed(port) == USB_SPEED_HIGH) { + status |= (1 << HUB_PORT_FEATURE_HIGHSPEED); + } + } + if (hprt0 & USB_OTG_HPRT_POCA) { + status |= (1 << HUB_PORT_FEATURE_OVERCURRENT); + } + if (hprt0 & USB_OTG_HPRT_PRES) { + status |= (1 << HUB_PORT_FEATURE_RESET); + } + if (hprt0 & USB_OTG_HPRT_PPWR) { + status |= (1 << HUB_PORT_FEATURE_POWER); + } + + memcpy(buf, &status, 4); + break; + default: + break; + } } -} - -int usbh_reset_port(const uint8_t port) -{ - __IO uint32_t hprt0 = 0U; - - hprt0 = USB_OTG_HPRT; - - hprt0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET | - USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG); - - USB_OTG_HPRT = (USB_OTG_HPRT_PRST | hprt0); - usb_osal_msleep(100U); /* See Note #1 */ - USB_OTG_HPRT = ((~USB_OTG_HPRT_PRST) & hprt0); - usb_osal_msleep(10U); - - while (!g_dwc2_hcd.port_enable) { - } - return 0; } -uint8_t usbh_get_port_speed(const uint8_t port) -{ - __IO uint32_t hprt0 = 0U; - uint8_t speed; - - hprt0 = USB_OTG_HPRT; - - speed = (hprt0 & USB_OTG_HPRT_PSPD) >> 17; - - if (speed == HPRT0_PRTSPD_HIGH_SPEED) { - return USB_SPEED_HIGH; - } else if (speed == HPRT0_PRTSPD_FULL_SPEED) { - return USB_SPEED_FULL; - } else if (speed == HPRT0_PRTSPD_LOW_SPEED) { - return USB_SPEED_LOW; - } else { - return USB_SPEED_UNKNOWN; - } -} - -int usbh_ep0_reconfigure(usbh_epinfo_t ep, uint8_t dev_addr, uint8_t ep_mps, uint8_t speed) +int usbh_ep0_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t speed) { struct dwc2_pipe *chan; - int ret; - chan = (struct dwc2_pipe *)ep; + chan = (struct dwc2_pipe *)pipe; - ret = usb_osal_mutex_take(chan->exclsem); - if (ret < 0) { - return ret; - } chan->dev_addr = dev_addr; chan->ep_mps = ep_mps; chan->speed = speed; - usb_osal_mutex_give(chan->exclsem); + return 0; } -int usbh_ep_alloc(usbh_epinfo_t *ep, const struct usbh_endpoint_cfg *ep_cfg) +int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg) { struct dwc2_pipe *chan; - struct usbh_hubport *hport; int chidx; - uint8_t speed; usb_osal_sem_t waitsem; - usb_osal_mutex_t exclsem; - - hport = ep_cfg->hport; chidx = dwc2_pipe_alloc(); + if (chidx == -1) { + return -ENOMEM; + } - chan = &g_dwc2_hcd.chan[chidx]; + chan = &g_dwc2_hcd.pipe_pool[chidx]; /* store variables */ waitsem = chan->waitsem; - exclsem = chan->exclsem; memset(chan, 0, sizeof(struct dwc2_pipe)); chan->chidx = chidx; chan->ep_addr = ep_cfg->ep_addr; - chan->ep_mps = ep_cfg->ep_mps; chan->ep_type = ep_cfg->ep_type; + chan->ep_mps = ep_cfg->ep_mps; chan->ep_interval = ep_cfg->ep_interval; - chan->dev_addr = hport->dev_addr; - chan->speed = hport->speed; + chan->speed = ep_cfg->hport->speed; + chan->dev_addr = ep_cfg->hport->dev_addr; + chan->hport = ep_cfg->hport; if (ep_cfg->ep_type == USB_ENDPOINT_TYPE_CONTROL) { chan->data_pid = HC_PID_DATA1; @@ -664,342 +716,163 @@ int usbh_ep_alloc(usbh_epinfo_t *ep, const struct usbh_endpoint_cfg *ep_cfg) chan->data_pid = HC_PID_DATA0; } + if (chan->speed == USB_SPEED_HIGH) { + chan->ep_interval = (1 << (chan->ep_interval - 1)); + } + /* restore variables */ chan->inuse = true; chan->waitsem = waitsem; - chan->exclsem = exclsem; - *ep = (usbh_epinfo_t)chan; + *pipe = (usbh_pipe_t)chan; return 0; } -int usbh_ep_free(usbh_epinfo_t ep) +int usbh_pipe_free(usbh_pipe_t pipe) { struct dwc2_pipe *chan; + struct usbh_urb *urb; - chan = (struct dwc2_pipe *)ep; + chan = (struct dwc2_pipe *)pipe; + + if (!chan) { + return -EINVAL; + } + urb = chan->urb; + if (urb) { + usbh_kill_urb(urb); + } dwc2_pipe_free(chan); return 0; } -int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint8_t *buffer) +int usbh_submit_urb(struct usbh_urb *urb) { struct dwc2_pipe *chan; - int chidx; - int ret; - - chan = (struct dwc2_pipe *)ep; - -#ifdef CONFIG_USB_DCACHE_ENABLE - if ((((uint32_t)setup) & 0x1f) || (buffer && (((uint32_t)buffer) & 0x1f))) { - return -EINVAL; - } -#endif -#if defined(STM32F7) || defined(STM32H7) - if (((((uint32_t)setup) & 0x24000000) != 0x24000000) || - ((buffer && (((uint32_t)buffer) & 0x24000000) != 0x24000000))) { - return -EINVAL; - } -#endif - ret = usb_osal_mutex_take(chan->exclsem); - if (ret < 0) { - return ret; - } - - ret = dwc2_pipe_waitsetup(chan); - if (ret < 0) { - goto error_out; - } - - chidx = chan->chidx; - - chan->waiter = true; - chan->result = -EBUSY; - chan->num_packets = dwc2_calculate_packet_num(8, chan->ep_addr, chan->ep_mps, &chan->xferlen); - usb_dcache_clean((uintptr_t)setup, 8); - dwc2_pipe_init(chidx, chan->dev_addr, 0x00, 0x00, chan->ep_mps, chan->speed); - dwc2_pipe_transfer(chidx, 0x00, (uint32_t *)setup, chan->xferlen, chan->num_packets, HC_PID_SETUP); - ret = dwc2_pipe_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); - if (ret < 0) { - goto error_out; - } - - if (setup->wLength && buffer) { - if (setup->bmRequestType & 0x80) { - chan->waiter = true; - chan->result = -EBUSY; - chan->num_packets = dwc2_calculate_packet_num(setup->wLength, 0x80, chan->ep_mps, &chan->xferlen); - dwc2_pipe_init(chidx, chan->dev_addr, 0x80, 0x00, chan->ep_mps, chan->speed); - dwc2_pipe_transfer(chidx, 0x80, (uint32_t *)buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1); - ret = dwc2_pipe_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); - if (ret < 0) { - goto error_out; - } - usb_dcache_invalidate((uintptr_t)buffer, setup->wLength); - chan->waiter = true; - chan->result = -EBUSY; - chan->num_packets = dwc2_calculate_packet_num(0, 0x00, chan->ep_mps, &chan->xferlen); - dwc2_pipe_init(chidx, chan->dev_addr, 0x00, 0x00, chan->ep_mps, chan->speed); - dwc2_pipe_transfer(chidx, 0x00, NULL, chan->xferlen, chan->num_packets, HC_PID_DATA1); - ret = dwc2_pipe_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); - if (ret < 0) { - goto error_out; - } - } else { - chan->waiter = true; - chan->result = -EBUSY; - chan->num_packets = dwc2_calculate_packet_num(setup->wLength, 0x00, chan->ep_mps, &chan->xferlen); - usb_dcache_clean((uintptr_t)buffer, setup->wLength); - dwc2_pipe_init(chidx, chan->dev_addr, 0x00, 0x00, chan->ep_mps, chan->speed); - dwc2_pipe_transfer(chidx, 0x00, (uint32_t *)buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1); - ret = dwc2_pipe_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); - if (ret < 0) { - goto error_out; - } - chan->waiter = true; - chan->result = -EBUSY; - chan->num_packets = dwc2_calculate_packet_num(0, 0x80, chan->ep_mps, &chan->xferlen); - dwc2_pipe_init(chidx, chan->dev_addr, 0x80, 0x00, chan->ep_mps, chan->speed); - dwc2_pipe_transfer(chidx, 0x80, NULL, chan->xferlen, chan->num_packets, HC_PID_DATA1); - ret = dwc2_pipe_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); - if (ret < 0) { - goto error_out; - } - } - } else { - chan->waiter = true; - chan->result = -EBUSY; - chan->num_packets = dwc2_calculate_packet_num(0, 0x80, chan->ep_mps, &chan->xferlen); - dwc2_pipe_init(chidx, chan->dev_addr, 0x80, 0x00, chan->ep_mps, chan->speed); - dwc2_pipe_transfer(chidx, 0x80, NULL, chan->xferlen, chan->num_packets, HC_PID_DATA1); - ret = dwc2_pipe_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); - if (ret < 0) { - goto error_out; - } - } - usb_osal_mutex_give(chan->exclsem); - return ret; -error_out: - chan->waiter = false; - usb_osal_mutex_give(chan->exclsem); - return ret; -} - -int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, uint32_t timeout) -{ - struct dwc2_pipe *chan; - int chidx; - int ret; - - chan = (struct dwc2_pipe *)ep; -#ifdef CONFIG_USB_DCACHE_ENABLE - if (buffer && (((uint32_t)buffer) & 0x1f)) { - return -EINVAL; - } -#endif -#if defined(STM32F7) || defined(STM32H7) - if ((buffer && (((uint32_t)buffer) & 0x24000000) != 0x24000000)) { - return -EINVAL; - } -#endif - ret = usb_osal_mutex_take(chan->exclsem); - if (ret < 0) { - return ret; - } - - ret = dwc2_pipe_waitsetup(chan); - if (ret < 0) { - goto error_out; - } - - chidx = chan->chidx; - chan->num_packets = dwc2_calculate_packet_num(buflen, chan->ep_addr, chan->ep_mps, &chan->xferlen); -#ifdef CONFIG_USB_DCACHE_ENABLE - if ((chan->ep_addr & 0x80) == 0x00) { - usb_dcache_clean((uintptr_t)buffer, buflen); - } -#endif - dwc2_pipe_transfer(chidx, chan->ep_addr, (uint32_t *)buffer, chan->xferlen, chan->num_packets, chan->data_pid); - ret = dwc2_pipe_wait(chan, timeout); - if (ret < 0) { - goto error_out; - } -#ifdef CONFIG_USB_DCACHE_ENABLE - if ((chan->ep_addr & 0x80) == 0x80) { - usb_dcache_invalidate((uintptr_t)buffer, buflen); - } -#endif - usb_osal_mutex_give(chan->exclsem); - return ret; -error_out: - chan->waiter = false; - usb_osal_mutex_give(chan->exclsem); - return ret; -} - -int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, uint32_t timeout) -{ - struct dwc2_pipe *chan; - int chidx; - int ret; - uint32_t wait_ms_count = 0; - - chan = (struct dwc2_pipe *)ep; -#ifdef CONFIG_USB_DCACHE_ENABLE - if (buffer && (((uint32_t)buffer) & 0x1f)) { - return -EINVAL; - } -#endif -#if defined(STM32F7) || defined(STM32H7) - if ((buffer && (((uint32_t)buffer) & 0x24000000) != 0x24000000)) { - return -EINVAL; - } -#endif - ret = usb_osal_mutex_take(chan->exclsem); - if (ret < 0) { - return ret; - } - - ret = dwc2_pipe_waitsetup(chan); - if (ret < 0) { - goto error_out; - } - - chidx = chan->chidx; - chan->num_packets = dwc2_calculate_packet_num(buflen, chan->ep_addr, chan->ep_mps, &chan->xferlen); -#ifdef CONFIG_USB_DCACHE_ENABLE - if ((chan->ep_addr & 0x80) == 0x00) { - usb_dcache_clean((uintptr_t)buffer, buflen); - } -#endif - while (1) { - wait_ms_count++; - dwc2_pipe_transfer(chidx, chan->ep_addr, (uint32_t *)buffer, chan->xferlen, chan->num_packets, chan->data_pid); - usb_osal_msleep(chan->ep_interval); - if (chan->result != -EBUSY) { - break; - } - if ((wait_ms_count * chan->ep_interval) > timeout) { - ret = -ETIMEDOUT; - goto error_out; - } - } - - ret = dwc2_pipe_wait(chan, 0); - if (ret < 0) { - goto error_out; - } -#ifdef CONFIG_USB_DCACHE_ENABLE - if ((chan->ep_addr & 0x80) == 0x80) { - usb_dcache_invalidate((uintptr_t)buffer, buflen); - } -#endif - usb_osal_mutex_give(chan->exclsem); - return ret; -error_out: - chan->waiter = false; - usb_osal_mutex_give(chan->exclsem); - return ret; -} - -int usbh_ep_bulk_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, usbh_asynch_callback_t callback, void *arg) -{ - struct dwc2_pipe *chan; - int chidx; - int ret; - - chan = (struct dwc2_pipe *)ep; -#ifdef CONFIG_USB_DCACHE_ENABLE - if (buffer && (((uint32_t)buffer) & 0x1f)) { - return -EINVAL; - } -#endif -#if defined(STM32F7) || defined(STM32H7) - if ((buffer && (((uint32_t)buffer) & 0x24000000) != 0x24000000)) { - return -EINVAL; - } -#endif - ret = usb_osal_mutex_take(chan->exclsem); - if (ret < 0) { - return ret; - } - - ret = dwc2_pipe_asynchsetup(chan, callback, arg); - if (ret < 0) { - goto error_out; - } - - chidx = chan->chidx; - chan->num_packets = dwc2_calculate_packet_num(buflen, chan->ep_addr, chan->ep_mps, &chan->xferlen); -#ifdef CONFIG_USB_DCACHE_ENABLE - if ((chan->ep_addr & 0x80) == 0x00) { - usb_dcache_clean((uintptr_t)buffer, buflen); - } -#endif - chan->buffer = buffer; - dwc2_pipe_transfer(chidx, chan->ep_addr, (uint32_t *)buffer, chan->xferlen, chan->num_packets, chan->data_pid); - - return 0; -error_out: - usb_osal_mutex_give(chan->exclsem); - return ret; -} - -int usbh_ep_intr_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, usbh_asynch_callback_t callback, void *arg) -{ - return -1; -} - -int usb_ep_cancel(usbh_epinfo_t ep) -{ - struct dwc2_pipe *chan; - int ret; size_t flags; -#ifdef CONFIG_USBHOST_ASYNCH - usbh_asynch_callback_t callback; - void *arg; -#endif + int ret = 0; - chan = (struct dwc2_pipe *)ep; + chan = urb->pipe; + + if (!urb || !chan) { + return -EINVAL; + } + + /* dma addr must be aligned 4 bytes */ + if ((((uint32_t)urb->setup) & 0x03) || (((uint32_t)urb->transfer_buffer) & 0x03)) { + return -EINVAL; + } flags = usb_osal_enter_critical_section(); -#ifdef CONFIG_USBHOST_ASYNCH - callback = chan->callback; - arg = chan->arg; - chan->callback = NULL; - chan->arg = NULL; + if (!chan->hport->connected) { + return -ENODEV; + } + + if (chan->urb) { + return -EBUSY; + } + + chan->waiter = false; chan->xfrd = 0; -#endif + chan->urb = urb; + urb->errorcode = -EBUSY; + urb->actual_length = 0; + + if (urb->timeout > 0) { + chan->waiter = true; + } usb_osal_leave_critical_section(flags); - /* Check if there is a thread waiting for this transfer to complete? */ - if (chan->waiter) { - chan->waiter = false; - usb_osal_sem_give(chan->waitsem); + switch (chan->ep_type) { + case USB_ENDPOINT_TYPE_CONTROL: + chan->ep0_state = DWC2_EP0_STATE_SETUP; + dwc2_control_pipe_init(chan, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length); + break; + case USB_ENDPOINT_TYPE_BULK: + case USB_ENDPOINT_TYPE_INTERRUPT: + case USB_ENDPOINT_TYPE_ISOCHRONOUS: + dwc2_other_pipe_init(chan, urb->transfer_buffer, urb->transfer_buffer_length); + break; + default: + break; } -#ifdef CONFIG_USBHOST_ASYNCH - /* No.. is an asynchronous callback expected when the transfer completes? */ - else if (callback) { - callback(arg, -ESHUTDOWN); + if (urb->timeout > 0) { + /* wait until timeout or sem give */ + ret = usb_osal_sem_take(chan->waitsem, urb->timeout); + if (ret < 0) { + goto errout_timeout; + } + + ret = urb->errorcode; } -#endif + return ret; +errout_timeout: + chan->waiter = false; + usbh_kill_urb(urb); + return ret; +} + +int usbh_kill_urb(struct usbh_urb *urb) +{ + struct dwc2_pipe *pipe; + size_t flags; + + pipe = urb->pipe; + + if (!urb || !pipe) { + return -EINVAL; + } + + flags = usb_osal_enter_critical_section(); + + dwc2_halt(pipe->chidx); + pipe->urb = NULL; + + usb_osal_leave_critical_section(flags); + return 0; } +static inline void dwc2_pipe_waitup(struct dwc2_pipe *pipe) +{ + struct usbh_urb *urb; + + urb = pipe->urb; + pipe->urb = NULL; + + if (pipe->waiter) { + pipe->waiter = false; + usb_osal_sem_give(pipe->waitsem); + } + + if (urb->complete) { + if (urb->errorcode < 0) { + urb->complete(urb->arg, urb->errorcode); + } else { + urb->complete(urb->arg, urb->actual_length); + } + } +} + static void dwc2_inchan_irq_handler(uint8_t ch_num) { uint32_t chan_intstatus; struct dwc2_pipe *chan; + struct usbh_urb *urb; chan_intstatus = (USB_OTG_HC(ch_num)->HCINT) & (USB_OTG_HC((uint32_t)ch_num)->HCINTMSK); - chan = &g_dwc2_hcd.chan[ch_num]; + chan = &g_dwc2_hcd.pipe_pool[ch_num]; + urb = chan->urb; + //printf("s1:%08x\r\n", chan_intstatus); + for (uint32_t i = 0; i < 0xf; i++) { + } if ((chan_intstatus & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC) { - chan->result = 0; + urb->errorcode = 0; USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); @@ -1007,51 +880,51 @@ static void dwc2_inchan_irq_handler(uint8_t ch_num) CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK); } else if ((chan_intstatus & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR) { USB_UNMASK_HALT_HC_INT(ch_num); - chan->result = -EIO; + urb->errorcode = -EIO; CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR); } else if ((chan_intstatus & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL) { USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); - chan->result = -EPERM; + urb->errorcode = -EPERM; CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL); CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK); } else if ((chan_intstatus & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK) { USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); - chan->result = -EAGAIN; + urb->errorcode = -EAGAIN; CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK); } else if ((chan_intstatus & USB_OTG_HCINT_ACK) == USB_OTG_HCINT_ACK) { CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK); } else if ((chan_intstatus & USB_OTG_HCINT_NYET) == USB_OTG_HCINT_NYET) { USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); - chan->result = -EAGAIN; + urb->errorcode = -EAGAIN; CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET); } else if ((chan_intstatus & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR) { USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); - chan->result = -EIO; + urb->errorcode = -EIO; CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR); } else if ((chan_intstatus & USB_OTG_HCINT_BBERR) == USB_OTG_HCINT_BBERR) { USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); - chan->result = -EIO; + urb->errorcode = -EIO; CLEAR_HC_INT(ch_num, USB_OTG_HCINT_BBERR); } else if ((chan_intstatus & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR) { USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); - chan->result = -EPIPE; + urb->errorcode = -EPIPE; CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR); } else if ((chan_intstatus & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR) { USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); - chan->result = -EIO; + urb->errorcode = -EIO; CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK); CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR); } else if ((chan_intstatus & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH) { USB_MASK_HALT_HC_INT(ch_num); - if (chan->result == 0) { + if (urb->errorcode == 0) { uint32_t count = chan->xferlen - (USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ); /* size that has received */ uint32_t has_sent_packets = chan->num_packets - ((USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_DIEPTSIZ_PKTCNT) >> 19); /*how many packets has sent*/ @@ -1065,16 +938,28 @@ static void dwc2_inchan_irq_handler(uint8_t ch_num) chan->data_pid = HC_PID_DATA0; } } - chan->result = 0; - dwc2_pipe_wakeup(chan); - } else if (chan->result == -EAGAIN) { + + if (chan->ep_type == 0x00) { + if (chan->ep0_state == DWC2_EP0_STATE_INDATA) { + chan->ep0_state = DWC2_EP0_STATE_OUTSTATUS; + dwc2_control_pipe_init(chan, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length); + } else if (chan->ep0_state == DWC2_EP0_STATE_INSTATUS) { + chan->ep0_state = DWC2_EP0_STATE_SETUP; + urb->actual_length = chan->xfrd; + dwc2_pipe_waitup(chan); + } + } else { + urb->actual_length = chan->xfrd; + dwc2_pipe_waitup(chan); + } + } else if (urb->errorcode == -EAGAIN) { /* re-activate the channel */ uint32_t tmpreg = USB_OTG_HC(ch_num)->HCCHAR; tmpreg &= ~USB_OTG_HCCHAR_CHDIS; tmpreg |= USB_OTG_HCCHAR_CHENA; USB_OTG_HC(ch_num)->HCCHAR = tmpreg; } else { - dwc2_pipe_wakeup(chan); + dwc2_pipe_waitup(chan); } CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH); @@ -1085,71 +970,71 @@ static void dwc2_outchan_irq_handler(uint8_t ch_num) { uint32_t chan_intstatus; struct dwc2_pipe *chan; + struct usbh_urb *urb; uint16_t buflen; chan_intstatus = (USB_OTG_HC(ch_num)->HCINT) & (USB_OTG_HC((uint32_t)ch_num)->HCINTMSK); - chan = &g_dwc2_hcd.chan[ch_num]; - + chan = &g_dwc2_hcd.pipe_pool[ch_num]; + urb = chan->urb; + //printf("s2:%08x\r\n", chan_intstatus); if ((chan_intstatus & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC) { CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC); dwc2_halt(ch_num); - chan->result = 0; + urb->errorcode = 0; USB_UNMASK_HALT_HC_INT(ch_num); } else if ((chan_intstatus & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR) { USB_UNMASK_HALT_HC_INT(ch_num); - chan->result = -EIO; + urb->errorcode = -EIO; CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR); } else if ((chan_intstatus & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL) { USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); - chan->result = -EPERM; + urb->errorcode = -EPERM; CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL); } else if ((chan_intstatus & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK) { USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); - chan->result = -EAGAIN; + urb->errorcode = -EAGAIN; CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK); } else if ((chan_intstatus & USB_OTG_HCINT_ACK) == USB_OTG_HCINT_ACK) { CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK); } else if ((chan_intstatus & USB_OTG_HCINT_NYET) == USB_OTG_HCINT_NYET) { USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); - chan->result = -EAGAIN; + urb->errorcode = -EAGAIN; CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET); } else if ((chan_intstatus & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR) { USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); - chan->result = -EIO; + urb->errorcode = -EIO; CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR); } else if ((chan_intstatus & USB_OTG_HCINT_BBERR) == USB_OTG_HCINT_BBERR) { USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); - chan->result = -EIO; + urb->errorcode = -EIO; CLEAR_HC_INT(ch_num, USB_OTG_HCINT_BBERR); } else if ((chan_intstatus & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR) { USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); - chan->result = -EPIPE; + urb->errorcode = -EPIPE; CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR); } else if ((chan_intstatus & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR) { USB_UNMASK_HALT_HC_INT(ch_num); dwc2_halt(ch_num); - chan->result = -EIO; + urb->errorcode = -EIO; CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR); CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK); } else if ((chan_intstatus & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH) { USB_MASK_HALT_HC_INT(ch_num); - if (chan->result == 0) { + if (urb->errorcode == 0) { uint32_t count = (USB_OTG_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ); /* last send size */ - if (count == chan->ep_mps) { chan->xfrd += chan->num_packets * chan->ep_mps; } else { chan->xfrd += (chan->num_packets - 1) * chan->ep_mps + count; } - if ((chan->num_packets % 2) == 1) /* Flip in odd numbers */ { if (chan->data_pid == HC_PID_DATA0) { @@ -1158,16 +1043,38 @@ static void dwc2_outchan_irq_handler(uint8_t ch_num) chan->data_pid = HC_PID_DATA0; } } - chan->result = 0; - dwc2_pipe_wakeup(chan); - } else if (chan->result == -EAGAIN) { + if (chan->ep_type == 0x00) { + if (chan->ep0_state == DWC2_EP0_STATE_SETUP) { + if (urb->setup->wLength) { + if (urb->setup->bmRequestType & 0x80) { + chan->ep0_state = DWC2_EP0_STATE_INDATA; + } else { + chan->ep0_state = DWC2_EP0_STATE_OUTDATA; + } + } else { + chan->ep0_state = DWC2_EP0_STATE_INSTATUS; + } + dwc2_control_pipe_init(chan, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length); + } else if (chan->ep0_state == DWC2_EP0_STATE_OUTDATA) { + chan->ep0_state = DWC2_EP0_STATE_INSTATUS; + dwc2_control_pipe_init(chan, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length); + } else if (chan->ep0_state == DWC2_EP0_STATE_OUTSTATUS) { + chan->ep0_state = DWC2_EP0_STATE_SETUP; + urb->actual_length = chan->xfrd; + dwc2_pipe_waitup(chan); + } + } else { + urb->actual_length = chan->xfrd; + dwc2_pipe_waitup(chan); + } + } else if (urb->errorcode == -EAGAIN) { /* re-activate the channel */ uint32_t tmpreg = USB_OTG_HC(ch_num)->HCCHAR; tmpreg &= ~USB_OTG_HCCHAR_CHDIS; tmpreg |= USB_OTG_HCCHAR_CHENA; USB_OTG_HC(ch_num)->HCCHAR = tmpreg; } else { - dwc2_pipe_wakeup(chan); + dwc2_pipe_waitup(chan); } CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH); @@ -1188,14 +1095,16 @@ static void dwc2_port_irq_handler(void) /* Check whether Port Connect detected */ if ((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET) { if ((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS) { - usbh_event_notify_handler(USBH_EVENT_CONNECTED, 1); + usbh_roothub_thread_wakeup(1); } hprt0_dup |= USB_OTG_HPRT_PCDET; + g_dwc2_hcd.port_csc = 1; } /* Check whether Port Enable Changed */ if ((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG) { hprt0_dup |= USB_OTG_HPRT_PENCHNG; + g_dwc2_hcd.port_pec = 1; if ((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA) { #if defined(CONFIG_USB_DWC2_ULPI_PHY) @@ -1218,17 +1127,14 @@ static void dwc2_port_irq_handler(void) } } #endif - for (uint32_t i = 0; i < 1000; i++) { - } - g_dwc2_hcd.port_enable = true; } else { - g_dwc2_hcd.port_enable = false; } } /* Check for an overcurrent */ if ((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG) { hprt0_dup |= USB_OTG_HPRT_POCCHNG; + g_dwc2_hcd.port_occ = 1; } /* Clear Port Interrupts */ USB_OTG_HPRT = hprt0_dup; @@ -1248,21 +1154,23 @@ void USBH_IRQHandler(void) dwc2_port_irq_handler(); } if (gint_status & USB_OTG_GINTSTS_DISCINT) { - for (int chidx = 0; chidx < CONFIG_USB_DWC2_PIPE_NUM; chidx++) { - struct dwc2_pipe *chan; - chan = &g_dwc2_hcd.chan[chidx]; + g_dwc2_hcd.port_csc = 1; + for (uint8_t index = 0; index < CONFIG_USBHOST_PIPE_NUM; index++) { + struct dwc2_pipe *chan = &g_dwc2_hcd.pipe_pool[index]; + struct usbh_urb *urb = chan->urb; if (chan->waiter) { chan->waiter = false; - chan->result = -ENXIO; + urb->errorcode = -ESHUTDOWN; usb_osal_sem_give(chan->waitsem); } } - usbh_event_notify_handler(USBH_EVENT_DISCONNECTED, 1); + usbh_roothub_thread_wakeup(1); + USB_OTG_GLB->GINTSTS = USB_OTG_GINTSTS_DISCINT; } if (gint_status & USB_OTG_GINTSTS_HCINT) { chan_int = (USB_OTG_HOST->HAINT & USB_OTG_HOST->HAINTMSK) & 0xFFFFU; - for (uint8_t i = 0U; i < CONFIG_USB_DWC2_PIPE_NUM; i++) { + for (uint8_t i = 0U; i < CONFIG_USBHOST_PIPE_NUM; i++) { if ((chan_int & (1UL << (i & 0xFU))) != 0U) { if ((USB_OTG_HC(i)->HCCHAR & USB_OTG_HCCHAR_EPDIR) == USB_OTG_HCCHAR_EPDIR) { dwc2_inchan_irq_handler(i); @@ -1274,6 +1182,16 @@ void USBH_IRQHandler(void) USB_OTG_GLB->GINTSTS = USB_OTG_GINTSTS_HCINT; } if (gint_status & USB_OTG_GINTSTS_SOF) { + for (uint8_t index = 0; index < CONFIG_USBHOST_PIPE_NUM; index++) { + struct dwc2_pipe *chan = &g_dwc2_hcd.pipe_pool[index]; + struct usbh_urb *urb = chan->urb; + if (chan->urb && + !(dwc2_get_current_frame() % chan->ep_interval) && + ((chan->ep_type == USB_ENDPOINT_TYPE_INTERRUPT) || + (chan->ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS))) { + dwc2_other_pipe_init(chan, urb->transfer_buffer, urb->transfer_buffer_length); + } + } USB_OTG_GLB->GINTSTS = USB_OTG_GINTSTS_SOF; } } diff --git a/port/ehci/usb_hc_ehci.h b/port/ehci/usb_hc_ehci.h index 005cd8a7..5568ef17 100644 --- a/port/ehci/usb_hc_ehci.h +++ b/port/ehci/usb_hc_ehci.h @@ -1,847 +1,244 @@ /* - * Apache NuttX - * Copyright 2020 The Apache Software Foundation + * Copyright (c) 2022, sakumisu * * SPDX-License-Identifier: Apache-2.0 */ -#ifndef __INCLUDE_NUTTX_USB_EHCI_H -#define __INCLUDE_NUTTX_USB_EHCI_H +#ifndef USB_HC_EHCI_H +#define USB_HC_EHCI_H -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/* General definitions ******************************************************/ - -/* Endpoint speed values as used in endpoint characteristics field. - * NOTE: These values are *NOT* the same as the SPEED definitions in usb.h. - */ - -#define EHCI_FULL_SPEED (0) /* Full-Speed (12Mbs) */ -#define EHCI_LOW_SPEED (1) /* Low-Speed (1.5Mbs) */ -#define EHCI_HIGH_SPEED (2) /* High-Speed (480 Mb/s) */ - -#define EHCI_DIR_IN (1) /* Direction IN: Peripheral to host */ -#define EHCI_DIR_OUT (0) /* Direction OUT: Host to peripheral */ - -/* PCI Configuration Space Register Offsets *********************************/ - -/* Paragraph 2.1 */ - -/* 0x0009-0x000b: Class Code */ - -#define EHCI_PCI_CLASSC_OFFSET 0x0009 - -/* 0x0010-0x0013: Base Address to Memory-mapped Host Controller Register - * Space - */ - -#define EHCI_PCIUSBBASE_OFFSET 0x0010 - -/* 0x0060: Serial Bus Release Number */ - -#define EHCI_PCI_SBRN_OFFSET 0x0060 - -/* 0x0061: Frame Length Adjustment Register */ - -#define EHCI_PCI_FLADJ_OFFSET 0x0061 - -/* 0x0062-0x0063: Port wake capabilities register (OPTIONAL) */ - -#define EHCI_PCI_PORTWAKECAP_OFFSET 0x0062 - -/* EECP+0x0000: USB Legacy Support EHCI Extended Capability Register */ - -#define EHCI_PCI_USBLEGSUP_OFFSET 0x0000 - -/* EECP+0x0000: USB Legacy Support Control and Status Register */ - -#define EHCI_PCI_USBLEGCTLSTS_OFFSET 0x0004 - -/* Host Controller Capability Register Offsets ******************************/ - -/* Paragraph 2.2 */ - -#define EHCI_CAPLENGTH_OFFSET 0x0000 /* Core Capability Register Length */ - /* 0x0001 Reserved */ -#define EHCI_HCIVERSION_OFFSET 0x0002 /* Core Interface Version Number */ -#define EHCI_HCSPARAMS_OFFSET 0x0004 /* Core Structural Parameters */ -#define EHCI_HCCPARAMS_OFFSET 0x0008 /* Core Capability Parameters */ -#define EHCI_HCSP_PORTROUTE_OFFSET 0x000c /* Core Companion Port Route Description */ - -/* Host Controller Operational Register Offsets *****************************/ - -/* Paragraph 2.3 */ - -#define EHCI_USBCMD_OFFSET 0x0000 /* USB Command */ -#define EHCI_USBSTS_OFFSET 0x0004 /* USB Status */ -#define EHCI_USBINTR_OFFSET 0x0008 /* USB Interrupt Enable */ -#define EHCI_FRINDEX_OFFSET 0x000c /* USB Frame Index */ -#define EHCI_CTRLDSSEGMENT_OFFSET 0x0010 /* 4G Segment Selector */ -#define EHCI_PERIODICLISTBASE_OFFSET 0x0014 /* Frame List Base Address */ -#define EHCI_ASYNCLISTADDR_OFFSET 0x0018 /* Next Asynchronous List Address */ - /* 0x001c-0x003f: Reserved */ -#define EHCI_CONFIGFLAG_OFFSET 0x0040 /* Configured Flag Register */ - -/* Port Status/Control, Port 1-n */ - -#define EHCI_PORTSC_OFFSET(n) (0x0044 + ((n-1) << 2)) -#define EHCI_PORTSC1_OFFSET 0x0044 /* Port Status/Control, Port 1 */ -#define EHCI_PORTSC2_OFFSET 0x0048 /* Port Status/Control, Port 2 */ -#define EHCI_PORTSC3_OFFSET 0x004c /* Port Status/Control, Port 3 */ -#define EHCI_PORTSC4_OFFSET 0x0050 /* Port Status/Control, Port 4 */ -#define EHCI_PORTSC5_OFFSET 0x0054 /* Port Status/Control, Port 5 */ -#define EHCI_PORTSC6_OFFSET 0x0058 /* Port Status/Control, Port 6 */ -#define EHCI_PORTSC7_OFFSET 0x005c /* Port Status/Control, Port 7 */ -#define EHCI_PORTSC8_OFFSET 0x0060 /* Port Status/Control, Port 8 */ -#define EHCI_PORTSC9_OFFSET 0x0064 /* Port Status/Control, Port 9 */ -#define EHCI_PORTSC10_OFFSET 0x0068 /* Port Status/Control, Port 10 */ -#define EHCI_PORTSC11_OFFSET 0x006c /* Port Status/Control, Port 11 */ -#define EHCI_PORTSC12_OFFSET 0x0070 /* Port Status/Control, Port 12 */ -#define EHCI_PORTSC13_OFFSET 0x0074 /* Port Status/Control, Port 13 */ -#define EHCI_PORTSC14_OFFSET 0x0078 /* Port Status/Control, Port 14 */ -#define EHCI_PORTSC15_OFFSET 0x007c /* Port Status/Control, Port 15 */ - -/* Debug Register Offsets ***************************************************/ - -/* Paragraph C.3 */ - -#define EHCI_DEBUG_PCS_OFFSET 0x0000 /* Debug Port Control/Status Register */ -#define EHCI_DEBUG_USBPIDS_OFFSET 0x0004 /* Debug USB PIDs Register */ -#define EHCI_DEBUG_DATA0_OFFSET 0x0008 /* Debug Data Buffer 0 Register [31:0] */ -#define EHCI_DEBUG_DATA1_OFFSET 0x000c /* Debug Data Buffer 1 Register [63:32] */ -#define EHCI_DEBUG_DEVADDR_OFFSET 0x0010 /* Debug Device Address Register */ - -/* PCI Configuration Space Register Bit Definitions *************************/ - -/* 0x0009-0x000b: Class Code. Paragraph 2.1.2 */ - -#define EHCI_PCI_PI_SHIFT (0) /* Bits 0-7: Programming Interface */ -#define EHCI_PCI_PI_MASK (0xff << EHCI_PCI_PI_SHIFT) -# define EHCI_PCI_PI (0x20 << EHCI_PCI_PI_SHIFT) -#define EHCI_PCI_SCC_SHIFT (8) /* Bits 8-15: Sub-Class Code */ -#define EHCI_PCI_SCC_MASK (0xff << EHCI_PCI_SCC_SHIFT) -# define EHCI_PCI_SCC (0x03 << EHCI_PCI_SCC_SHIFT) -#define EHCI_PCI_BASEC_SHIFT (16) /* Base Class Code */ -#define EHCI_PCI_BASEC_MASK (0xff << EHCI_PCI_BASEC_SHIFT) -# define EHCI_PCI_BASEC (0x0c << EHCI_PCI_BASEC_SHIFT) -#define EHCI_PCI_CLASSC 0x000c0320 /* Default value (little endian) */ - -/* 0x0010-0x0013: Base Address to Memory-mapped Host Controller Register - * Space. Paragraph 2.1.3 - */ - - /* Bit 0: Reserved */ - -#define EHCI_PCIUSBBASE_TYPE_SHIFT (0) /* Bits 1-2: Type */ -#define EHCI_PCIUSBBASE_TYPE_MASK (3 << EHCI_PCIUSBBASE_TYPE_SHIFT) -# define EHCI_PCIUSBBASE_TYPE_32BIT (3 << EHCI_PCIUSBBASE_TYPE_SHIFT) /* 32-bit addressing */ -# define EHCI_PCIUSBBASE_TYPE_64BIT (3 << EHCI_PCIUSBBASE_TYPE_SHIFT) /* 64-bit addressing */ - - /* Bits 3-7: Reserved */ -#define EHCI_PCIUSBBASE_BASE_SHIFT (8) /* Bits 8-31: Base address */ -#define EHCI_PCIUSBBASE_BASE_MASK (0xffffff00) - -/* 0x0060: Serial Bus Release Number. Paragraph 2.1.4 */ - -#define EHCI_PCI_SBRN_MASK 0xff /* Bits 0-7: Serial Bus Release Number */ - -/* 0x0061: Frame Length Adjustment Register. Paragraph 2.1.5 */ - -#define EHCI_PCI_FLADJ_SHIFT (0) /* Bit 0-5: Frame Length Timing Value */ -#define EHCI_PCI_FLADJ_MASK (0x3f >> EHCI_PCI_FLADJ_SHIFT) - /* Bits 6-7: Reserved */ - -/* 0x0062-0x0063: Port wake capabilities register (OPTIONAL). - * Paragraph 2.1.6 - */ - -#define EHCI_PCI_PORTWAKECAP_MASK (0xffff) - -/* EECP+0x0000: USB Legacy Support EHCI Extended Capability Register. - * Paragraph 2.1.7 - */ - -#define EHCI_PCI_USBLEGSUP_CAPID_SHIFT (0) /* Bits 0-7 Capability ID */ -#define EHCI_PCI_USBLEGSUP_CAPID_MASK (0xff << EHCI_PCI_USBLEGSUP_CAPID_SHIFT) -#define EHCI_PCI_USBLEGSUP_NEECP_SHIFT (8) /* Bits 8-15: Next EHCI Extended Capability Pointer */ -#define EHCI_PCI_USBLEGSUP_NEECP_MASK (0xff << EHCI_PCI_USBLEGSUP_NEECP_SHIFT) -#define EHCI_PCI_USBLEGSUP_BOWN (1 << 16) /* Bit 16: HC BIOS Owned Semaphore */ - /* Bits 17-23: Reserved */ -#define EHCI_PCI_USBLEGSUP_OSOWN (1 << 24) /* Bit 24: HC OS Owned Semaphore */ - /* Bits 25-31: Reserved */ - -/* EECP+0x0000: USB Legacy Support Control and Status Register. - * Paragraph 2.1.8 - */ - -#define EHCI_PCI_USBLEGCTLSTS_USBCMPEN (1 << 0) /* Bit 0: USB SMI Enable */ -#define EHCI_PCI_USBLEGCTLSTS_USBERREN (1 << 1) /* Bit 1: SMI on USB Error Enable */ -#define EHCI_PCI_USBLEGCTLSTS_PCHEN (1 << 2) /* Bit 2: SMI on Port Change Enable */ -#define EHCI_PCI_USBLEGCTLSTS_FLREN (1 << 3) /* Bit 3: SMI on Frame List Rollover Enable */ -#define EHCI_PCI_USBLEGCTLSTS_HSEEN (1 << 4) /* Bit 4: SMI on Host System Error Enable */ -#define EHCI_PCI_USBLEGCTLSTS_AAEN (1 << 5) /* Bit 5: SMI on Async Advance Enable */ - /* Bits 6-12: Reserved */ -#define EHCI_PCI_USBLEGCTLSTS_OOEN (1 << 13) /* Bit 13: SMI on OS Ownership Enable */ -#define EHCI_PCI_USBLEGCTLSTS_PCEN (1 << 14) /* Bit 14: SMI on PCI Command Enable */ -#define EHCI_PCI_USBLEGCTLSTS_BAREN (1 << 15) /* Bit 15: SMI on BAR Enable */ -#define EHCI_PCI_USBLEGCTLSTS_USBCMP (1 << 16) /* Bit 16: SMI on USB Complete */ -#define EHCI_PCI_USBLEGCTLSTS_USBERR (1 << 17) /* Bit 17: SMI on USB Error */ -#define EHCI_PCI_USBLEGCTLSTS_PCH (1 << 18) /* Bit 18: SMI on Port Change Detect */ -#define EHCI_PCI_USBLEGCTLSTS_FLR (1 << 19) /* Bit 19: SMI on Frame List Rollover */ -#define EHCI_PCI_USBLEGCTLSTS_HSE (1 << 20) /* Bit 20: SMI on Host System Error */ -#define EHCI_PCI_USBLEGCTLSTS_AA (1 << 21) /* Bit 21: SMI on Async Advance */ - /* Bits 22-28: Reserved */ -#define EHCI_PCI_USBLEGCTLSTS_OO (1 << 29) /* Bit 29: SMI on OS Ownership Change */ -#define EHCI_PCI_USBLEGCTLSTS_PC (1 << 30) /* Bit 30: SMI on PCI Command */ -#define EHCI_PCI_USBLEGCTLSTS_BAR (1 << 31) /* Bit 31: SMI on BAR */ +#define EHCI_FULL_SPEED (0) /* Full-Speed (12Mbs) */ +#define EHCI_LOW_SPEED (1) /* Low-Speed (1.5Mbs) */ +#define EHCI_HIGH_SPEED (2) /* High-Speed (480 Mb/s) */ /* Host Controller Capability Register Bit Definitions **********************/ -/* Paragraph 2.2 */ +/* Structural Parameters. Paragraph 2.2.3 */ -/* Core Capability Register Length. Paragraph 2.2.1. 8-bit length. */ +#define EHCI_HCSPARAMS_NPORTS_SHIFT (0) /* Bit 0-3: Number of physical downstream ports */ +#define EHCI_HCSPARAMS_NPORTS_MASK (15 << EHCI_HCSPARAMS_NPORTS_SHIFT) +#define EHCI_HCSPARAMS_PPC (1 << 4) /* Bit 4: Port Power Control */ +#define EHCI_HCSPARAMS_PRR (1 << 7) /* Bit 7: Port Routing Rules */ +#define EHCI_HCSPARAMS_NPCC_SHIFT (8) /* Bit 8-11: Number of Ports per Companion Controller */ +#define EHCI_HCSPARAMS_NPCC_MASK (15 << EHCI_HCSPARAMS_NPCC_SHIFT) +#define EHCI_HCSPARAMS_NCC_SHIFT (12) /* Bit 12-15: Number of Companion Controllers */ +#define EHCI_HCSPARAMS_NCC_MASK (15 << EHCI_HCSPARAMS_NCC_SHIFT) +#define EHCI_HCSPARAMS_PIND (1 << 16) /* Bit 16: Port Indicators */ +#define EHCI_HCSPARAMS_DBGPORT_SHIFT (20) /* Bit 20-23: Debug Port Number */ +#define EHCI_HCSPARAMS_DBGPORT_MASK (15 << EHCI_HCSPARAMS_DBGPORT_SHIFT) -/* Core Interface Version Number. Paragraph 2.2.2. Two byte BCD encoding */ +/* Capability Parameters. Paragraph 2.2.4 */ -/* Core Structural Parameters. Paragraph 2.2.3 */ - -#define EHCI_HCSPARAMS_NPORTS_SHIFT (0) /* Bit 0-3: Number of physical downstream ports */ -#define EHCI_HCSPARAMS_NPORTS_MASK (15 << EHCI_HCSPARAMS_NPORTS_SHIFT) -#define EHCI_HCSPARAMS_PPC (1 << 4) /* Bit 4: Port Power Control */ - /* Bits 5-6: Reserved */ -#define EHCI_HCSPARAMS_PRR (1 << 7) /* Bit 7: Port Routing Rules */ -#define EHCI_HCSPARAMS_NPCC_SHIFT (8) /* Bit 8-11: Number of Ports per Companion Controller */ -#define EHCI_HCSPARAMS_NPCC_MASK (15 << EHCI_HCSPARAMS_NPCC_SHIFT) -#define EHCI_HCSPARAMS_NCC_SHIFT (12) /* Bit 12-15: Number of Companion Controllers */ -#define EHCI_HCSPARAMS_NCC_MASK (15 << EHCI_HCSPARAMS_NCC_SHIFT) -#define EHCI_HCSPARAMS_PIND (1 << 16) /* Bit 16: Port Indicators */ - /* Bits 17-19: Reserved */ -#define EHCI_HCSPARAMS_DBGPORT_SHIFT (20) /* Bit 20-23: Debug Port Number */ -#define EHCI_HCSPARAMS_DBGPORT_MASK (15 << EHCI_HCSPARAMS_DBGPORT_SHIFT) - /* Bits 24-31: Reserved */ - -/* Core Capability Parameters. Paragraph 2.2.4 */ - -#define EHCI_HCCPARAMS_64BIT (1 << 0) /* Bit 0: 64-bit Addressing Capability */ -#define EHCI_HCCPARAMS_PFLF (1 << 1) /* Bit 1: Programmable Frame List Flag */ -#define EHCI_HCCPARAMS_ASPC (1 << 2) /* Bit 2: Asynchronous Schedule Park Capability */ - /* Bit 3: Reserved */ -#define EHCI_HCCPARAMS_IST_SHIFT (4) /* Bits 4-7: Isochronous Scheduling Threshold */ -#define EHCI_HCCPARAMS_IST_MASK (15 << EHCI_HCCPARAMS_IST_SHIFT) -#define EHCI_HCCPARAMS_EECP_SHIFT (8) /* Bits 8-15: EHCI Extended Capabilities Pointer */ -#define EHCI_HCCPARAMS_EECP_MASK (0xff << EHCI_HCCPARAMS_EECP_SHIFT) - /* Bits 16-31: Reserved */ - -/* Core Companion Port Route Description. - * Paragraph 2.2.5. 15 x 4-bit array (60 bits) - */ +#define EHCI_HCCPARAMS_64BIT (1 << 0) /* Bit 0: 64-bit Addressing Capability */ +#define EHCI_HCCPARAMS_PFLF (1 << 1) /* Bit 1: Programmable Frame List Flag */ +#define EHCI_HCCPARAMS_ASPC (1 << 2) /* Bit 2: Asynchronous Schedule Park Capability */ +#define EHCI_HCCPARAMS_IST_SHIFT (4) /* Bits 4-7: Isochronous Scheduling Threshold */ +#define EHCI_HCCPARAMS_IST_MASK (15 << EHCI_HCCPARAMS_IST_SHIFT) +#define EHCI_HCCPARAMS_EECP_SHIFT (8) /* Bits 8-15: EHCI Extended Capabilities Pointer */ +#define EHCI_HCCPARAMS_EECP_MASK (0xff << EHCI_HCCPARAMS_EECP_SHIFT) /* Host Controller Operational Register Bit Definitions *********************/ -/* Paragraph 2.3 */ - /* USB Command. Paragraph 2.3.1 */ -#define EHCI_USBCMD_RUN (1 << 0) /* Bit 0: Run/Stop */ -#define EHCI_USBCMD_HCRESET (1 << 1) /* Bit 1: Host Controller Reset */ -#define EHCI_USBCMD_FLSIZE_SHIFT (2) /* Bits 2-3: Frame List Size */ -#define EHCI_USBCMD_FLSIZE_MASK (3 << EHCI_USBCMD_FLSIZE_SHIFT) -# define EHCI_USBCMD_FLSIZE_1024 (0 << EHCI_USBCMD_FLSIZE_SHIFT) /* 1024 elements (4096 bytes) */ -# define EHCI_USBCMD_FLSIZE_512 (1 << EHCI_USBCMD_FLSIZE_SHIFT) /* 512 elements (2048 bytes) */ -# define EHCI_USBCMD_FLSIZE_256 (2 << EHCI_USBCMD_FLSIZE_SHIFT) /* 256 elements (1024 bytes) */ - -#define EHCI_USBCMD_PSEN (1 << 4) /* Bit 4: Periodic Schedule Enable */ -#define EHCI_USBCMD_ASEN (1 << 5) /* Bit 5: Asynchronous Schedule Enable */ -#define EHCI_USBCMD_IAADB (1 << 6) /* Bit 6: Interrupt on Async Advance Doorbell */ -#define EHCI_USBCMD_LRESET (1 << 7) /* Bit 7: Light Host Controller Reset */ -#define EHCI_USBCMD_PARKCNT_SHIFT (8) /* Bits 8-9: Asynchronous Schedule Park Mode Count */ -#define EHCI_USBCMD_PARKCNT_MASK (3 << EHCI_USBCMD_PARKCNT_SHIFT) - /* Bit 10: Reserved */ -#define EHCI_USBCMD_PARK (1 << 11) /* Bit 11: Asynchronous Schedule Park Mode Enable */ - /* Bits 12-15: Reserved */ -#define EHCI_USBCMD_ITHRE_SHIFT (16) /* Bits 16-23: Interrupt Threshold Control */ -#define EHCI_USBCMD_ITHRE_MASK (0xff << EHCI_USBCMD_ITHRE_SHIFT) -# define EHCI_USBCMD_ITHRE_1MF (0x01 << EHCI_USBCMD_ITHRE_SHIFT) /* 1 micro-frame */ -# define EHCI_USBCMD_ITHRE_2MF (0x02 << EHCI_USBCMD_ITHRE_SHIFT) /* 2 micro-frames */ -# define EHCI_USBCMD_ITHRE_4MF (0x04 << EHCI_USBCMD_ITHRE_SHIFT) /* 4 micro-frames */ -# define EHCI_USBCMD_ITHRE_8MF (0x08 << EHCI_USBCMD_ITHRE_SHIFT) /* 8 micro-frames (default, 1 ms) */ -# define EHCI_USBCMD_ITHRE_16MF (0x10 << EHCI_USBCMD_ITHRE_SHIFT) /* 16 micro-frames (2 ms) */ -# define EHCI_USBCMD_ITHRE_32MF (0x20 << EHCI_USBCMD_ITHRE_SHIFT) /* 32 micro-frames (4 ms) */ -# define EHCI_USBCMD_ITHRE_64MF (0x40 << EHCI_USBCMD_ITHRE_SHIFT) /* 64 micro-frames (8 ms) */ - - /* Bits 24-31: Reserved */ +#define EHCI_USBCMD_RUN (1 << 0) /* Bit 0: Run/Stop */ +#define EHCI_USBCMD_HCRESET (1 << 1) /* Bit 1: Host Controller Reset */ +#define EHCI_USBCMD_FLSIZE_SHIFT (2) /* Bits 2-3: Frame List Size */ +#define EHCI_USBCMD_FLSIZE_MASK (3 << EHCI_USBCMD_FLSIZE_SHIFT) +#define EHCI_USBCMD_FLSIZE_1024 (0 << EHCI_USBCMD_FLSIZE_SHIFT) /* 1024 elements (4096 bytes) */ +#define EHCI_USBCMD_FLSIZE_512 (1 << EHCI_USBCMD_FLSIZE_SHIFT) /* 512 elements (2048 bytes) */ +#define EHCI_USBCMD_FLSIZE_256 (2 << EHCI_USBCMD_FLSIZE_SHIFT) /* 256 elements (1024 bytes) */ +#define EHCI_USBCMD_PSEN (1 << 4) /* Bit 4: Periodic Schedule Enable */ +#define EHCI_USBCMD_ASEN (1 << 5) /* Bit 5: Asynchronous Schedule Enable */ +#define EHCI_USBCMD_IAAD (1 << 6) /* Bit 6: Interrupt on Async Advance Doorbell */ +#define EHCI_USBCMD_LRESET (1 << 7) /* Bit 7: Light Host Controller Reset */ +#define EHCI_USBCMD_ASYNC_PARKCNT_SHIFT (8) /* Bits 8-9: Asynchronous Schedule Park Mode Count */ +#define EHCI_USBCMD_ASYNC_PARKCNT_MASK (3 << EHCI_USBCMD_PARKCNT_SHIFT) +#define EHCI_USBCMD_ASYNC_PARK (1 << 11) /* Bit 11: Asynchronous Schedule Park Mode Enable */ +#define EHCI_USBCMD_ITHRE_SHIFT (16) /* Bits 16-23: Interrupt Threshold Control */ +#define EHCI_USBCMD_ITHRE_MASK (0xff << EHCI_USBCMD_ITHRE_SHIFT) +#define EHCI_USBCMD_ITHRE_1MF (0x01 << EHCI_USBCMD_ITHRE_SHIFT) /* 1 micro-frame */ +#define EHCI_USBCMD_ITHRE_2MF (0x02 << EHCI_USBCMD_ITHRE_SHIFT) /* 2 micro-frames */ +#define EHCI_USBCMD_ITHRE_4MF (0x04 << EHCI_USBCMD_ITHRE_SHIFT) /* 4 micro-frames */ +#define EHCI_USBCMD_ITHRE_8MF (0x08 << EHCI_USBCMD_ITHRE_SHIFT) /* 8 micro-frames (default, 1 ms) */ +#define EHCI_USBCMD_ITHRE_16MF (0x10 << EHCI_USBCMD_ITHRE_SHIFT) /* 16 micro-frames (2 ms) */ +#define EHCI_USBCMD_ITHRE_32MF (0x20 << EHCI_USBCMD_ITHRE_SHIFT) /* 32 micro-frames (4 ms) */ +#define EHCI_USBCMD_ITHRE_64MF (0x40 << EHCI_USBCMD_ITHRE_SHIFT) /* 64 micro-frames (8 ms) */ /* USB Status. Paragraph 2.3.2 */ +#define EHCI_USBSTS_INT (1 << 0) /* Bit 0: USB Interrupt */ +#define EHCI_USBSTS_ERR (1 << 1) /* Bit 1: USB Error Interrupt */ +#define EHCI_USBSTS_PCD (1 << 2) /* Bit 2: Port Change Detect */ +#define EHCI_USBSTS_FLR (1 << 3) /* Bit 3: Frame List Rollover */ +#define EHCI_USBSTS_FATAL (1 << 4) /* Bit 4: Host System Error */ +#define EHCI_USBSTS_IAA (1 << 5) /* Bit 5: Interrupt on Async Advance */ +#define EHCI_USBSTS_HALTED (1 << 12) /* Bit 12: HC Halted */ +#define EHCI_USBSTS_RECLAM (1 << 13) /* Bit 13: Reclamation */ +#define EHCI_USBSTS_PSS (1 << 14) /* Bit 14: Periodic Schedule Status */ +#define EHCI_USBSTS_ASS (1 << 15) /* Bit 15: Asynchronous Schedule Status */ + /* Bits 16-31: Reserved */ + /* USB Interrupt Enable. Paragraph 2.3.3 */ -#define EHCI_INT_USBINT (1 << 0) /* Bit 0: USB Interrupt */ -#define EHCI_INT_USBERRINT (1 << 1) /* Bit 1: USB Error Interrupt */ -#define EHCI_INT_PORTSC (1 << 2) /* Bit 2: Port Change Detect */ -#define EHCI_INT_FLROLL (1 << 3) /* Bit 3: Frame List Rollover */ -#define EHCI_INT_SYSERROR (1 << 4) /* Bit 4: Host System Error */ -#define EHCI_INT_AAINT (1 << 5) /* Bit 5: Interrupt on Async Advance */ -#define EHCI_INT_ALLINTS (0x3f) /* Bits 0-5: All interrupts */ - /* Bits 6-11: Reserved */ -#define EHCI_USBSTS_HALTED (1 << 12) /* Bit 12: HC Halted */ -#define EHCI_USBSTS_RECLAM (1 << 13) /* Bit 13: Reclamation */ -#define EHCI_USBSTS_PSS (1 << 14) /* Bit 14: Periodic Schedule Status */ -#define EHCI_USBSTS_ASS (1 << 15) /* Bit 15: Asynchronous Schedule Status */ - /* Bits 16-31: Reserved */ +#define EHCI_USBIE_INT (1 << 0) /* Bit 0: USB Interrupt */ +#define EHCI_USBIE_ERR (1 << 1) /* Bit 1: USB Error Interrupt */ +#define EHCI_USBIE_PCD (1 << 2) /* Bit 2: Port Change Detect */ +#define EHCI_USBIE_FLROLL (1 << 3) /* Bit 3: Frame List Rollover */ +#define EHCI_USBIE_FATAL (1 << 4) /* Bit 4: Host System Error */ +#define EHCI_USBIE_IAA (1 << 5) /* Bit 5: Interrupt on Async Advance */ +#define EHCI_USBIE_ALLINTS (0x3f) /* Bits 0-5: All interrupts */ /* USB Frame Index. Paragraph 2.3.4 */ -#define EHCI_FRINDEX_MASK (0x1fff) /* Bits 0-13: Frame index */ - /* Bits 14-31: Reserved */ +#define EHCI_FRINDEX_MASK (0x1fff) /* Bits 0-13: Frame index */ /* 4G Segment Selector. * Paragraph 2.3.5, Bits[64:32] of data structure addresses */ /* Frame List Base Address. Paragraph 2.3.6 */ - - /* Bits 0-11: Reserved */ -#define EHCI_PERIODICLISTBASE_MASK (0xfffff000) /* Bits 12-31: Base Address (Low) */ +#define EHCI_PERIODICLISTBASE_MASK (0xfffff000) /* Bits 12-31: Base Address (Low) */ /* Next Asynchronous List Address. Paragraph 2.3.7 */ - /* Bits 0-4: Reserved */ -#define EHCI_ASYNCLISTADDR_MASK (0xffffffe0) /* Bits 5-31: Link Pointer Low (LPL) */ +#define EHCI_ASYNCLISTADDR_MASK (0xffffffe0) /* Bits 5-31: Link Pointer Low (LPL) */ /* Configured Flag Register. Paragraph 2.3.8 */ -#define EHCI_CONFIGFLAG (1 << 0) /* Bit 0: Configure Flag */ - /* Bits 1-31: Reserved */ +#define EHCI_CONFIGFLAG (1 << 0) /* Bit 0: Configure Flag */ /* Port Status/Control, Port 1-n. Paragraph 2.3.9 */ -#define EHCI_PORTSC_CCS (1 << 0) /* Bit 0: Current Connect Status */ -#define EHCI_PORTSC_CSC (1 << 1) /* Bit 1: Connect Status Change */ -#define EHCI_PORTSC_PE (1 << 2) /* Bit 2: Port Enable */ -#define EHCI_PORTSC_PEC (1 << 3) /* Bit 3: Port Enable/Disable Change */ -#define EHCI_PORTSC_OCA (1 << 4) /* Bit 4: Over-current Active */ -#define EHCI_PORTSC_OCC (1 << 5) /* Bit 5: Over-current Change */ -#define EHCI_PORTSC_RESUME (1 << 6) /* Bit 6: Force Port Resume */ -#define EHCI_PORTSC_SUSPEND (1 << 7) /* Bit 7: Suspend */ -#define EHCI_PORTSC_RESET (1 << 8) /* Bit 8: Port Reset */ - /* Bit 9: Reserved */ -#define EHCI_PORTSC_LSTATUS_SHIFT (10) /* Bits 10-11: Line Status */ -#define EHCI_PORTSC_LSTATUS_MASK (3 << EHCI_PORTSC_LSTATUS_SHIFT) -# define EHCI_PORTSC_LSTATUS_SE0 (0 << EHCI_PORTSC_LSTATUS_SHIFT) /* SE0 Not Low-speed device, perform EHCI reset */ -# define EHCI_PORTSC_LSTATUS_KSTATE (1 << EHCI_PORTSC_LSTATUS_SHIFT) /* K-state Low-speed device, release ownership of port */ -# define EHCI_PORTSC_LSTATUS_JSTATE (2 << EHCI_PORTSC_LSTATUS_SHIFT) /* J-state Not Low-speed device, perform EHCI reset */ +#define EHCI_PORTSC_CCS (1 << 0) /* Bit 0: Current Connect Status */ +#define EHCI_PORTSC_CSC (1 << 1) /* Bit 1: Connect Status Change */ +#define EHCI_PORTSC_PE (1 << 2) /* Bit 2: Port Enable */ +#define EHCI_PORTSC_PEC (1 << 3) /* Bit 3: Port Enable/Disable Change */ +#define EHCI_PORTSC_OCA (1 << 4) /* Bit 4: Over-current Active */ +#define EHCI_PORTSC_OCC (1 << 5) /* Bit 5: Over-current Change */ +#define EHCI_PORTSC_RESUME (1 << 6) /* Bit 6: Force Port Resume */ +#define EHCI_PORTSC_SUSPEND (1 << 7) /* Bit 7: Suspend */ +#define EHCI_PORTSC_RESET (1 << 8) /* Bit 8: Port Reset */ +#define EHCI_PORTSC_LSTATUS_SHIFT (10) /* Bits 10-11: Line Status */ +#define EHCI_PORTSC_LSTATUS_MASK (3 << EHCI_PORTSC_LSTATUS_SHIFT) +#define EHCI_PORTSC_LSTATUS_SE0 (0 << EHCI_PORTSC_LSTATUS_SHIFT) /* SE0 Not Low-speed device, perform EHCI reset */ +#define EHCI_PORTSC_LSTATUS_KSTATE (1 << EHCI_PORTSC_LSTATUS_SHIFT) /* K-state Low-speed device, release ownership of port */ +#define EHCI_PORTSC_LSTATUS_JSTATE (2 << EHCI_PORTSC_LSTATUS_SHIFT) /* J-state Not Low-speed device, perform EHCI reset */ +#define EHCI_PORTSC_PP (1 << 12) /* Bit 12: Port Power */ +#define EHCI_PORTSC_OWNER (1 << 13) /* Bit 13: Port Owner */ +#define EHCI_PORTSC_PIC_SHIFT (14) /* Bits 14-15: Port Indicator Control */ +#define EHCI_PORTSC_PIC_MASK (3 << EHCI_PORTSC_PIC_SHIFT) +#define EHCI_PORTSC_PIC_OFF (0 << EHCI_PORTSC_PIC_SHIFT) /* Port indicators are off */ +#define EHCI_PORTSC_PIC_AMBER (1 << EHCI_PORTSC_PIC_SHIFT) /* Amber */ +#define EHCI_PORTSC_PIC_GREEN (2 << EHCI_PORTSC_PIC_SHIFT) /* Green */ +#define EHCI_PORTSC_PTC_SHIFT (16) /* Bits 16-19: Port Test Control */ +#define EHCI_PORTSC_PTC_MASK (15 << EHCI_PORTSC_PTC_SHIFT) +#define EHCI_PORTSC_PTC_DISABLED (0 << EHCI_PORTSC_PTC_SHIFT) /* Test mode not enabled */ +#define EHCI_PORTSC_PTC_JSTATE (1 << EHCI_PORTSC_PTC_SHIFT) /* Test J_STATE */ +#define EHCI_PORTSC_PTC_KSTATE (2 << EHCI_PORTSC_PTC_SHIFT) /* Test K_STATE */ +#define EHCI_PORTSC_PTC_SE0NAK (3 << EHCI_PORTSC_PTC_SHIFT) /* Test SE0_NAK */ +#define EHCI_PORTSC_PTC_PACKET (4 << EHCI_PORTSC_PTC_SHIFT) /* Test Packet */ +#define EHCI_PORTSC_PTC_ENABLE (5 << EHCI_PORTSC_PTC_SHIFT) /* Test FORCE_ENABLE */ +#define EHCI_PORTSC_WKCCNTE (1 << 20) /* Bit 20: Wake on Connect Enable */ +#define EHCI_PORTSC_WKDSCNNTE (1 << 21) /* Bit 21: Wake on Disconnect Enable */ +#define EHCI_PORTSC_WKOCE (1 << 22) /* Bit 22: Wake on Over-current Enable */ + /* Bits 23-31: Reserved */ -#define EHCI_PORTSC_PP (1 << 12) /* Bit 12: Port Power */ -#define EHCI_PORTSC_OWNER (1 << 13) /* Bit 13: Port Owner */ -#define EHCI_PORTSC_PIC_SHIFT (14) /* Bits 14-15: Port Indicator Control */ -#define EHCI_PORTSC_PIC_MASK (3 << EHCI_PORTSC_PIC_SHIFT) -# define EHCI_PORTSC_PIC_OFF (0 << EHCI_PORTSC_PIC_SHIFT) /* Port indicators are off */ -# define EHCI_PORTSC_PIC_AMBER (1 << EHCI_PORTSC_PIC_SHIFT) /* Amber */ -# define EHCI_PORTSC_PIC_GREEN (2 << EHCI_PORTSC_PIC_SHIFT) /* Green */ +#define EHCI_PORTSC_ALLINTS (EHCI_PORTSC_CSC | EHCI_PORTSC_PEC | \ + EHCI_PORTSC_OCC | EHCI_PORTSC_RESUME) -#define EHCI_PORTSC_PTC_SHIFT (16) /* Bits 16-19: Port Test Control */ -#define EHCI_PORTSC_PTC_MASK (15 << EHCI_PORTSC_PTC_SHIFT) -# define EHCI_PORTSC_PTC_DISABLED (0 << EHCI_PORTSC_PTC_SHIFT) /* Test mode not enabled */ -# define EHCI_PORTSC_PTC_JSTATE (1 << EHCI_PORTSC_PTC_SHIFT) /* Test J_STATE */ -# define EHCI_PORTSC_PTC_KSTATE (2 << EHCI_PORTSC_PTC_SHIFT) /* Test K_STATE */ -# define EHCI_PORTSC_PTC_SE0NAK (3 << EHCI_PORTSC_PTC_SHIFT) /* Test SE0_NAK */ -# define EHCI_PORTSC_PTC_PACKET (4 << EHCI_PORTSC_PTC_SHIFT) /* Test Packet */ -# define EHCI_PORTSC_PTC_ENABLE (5 << EHCI_PORTSC_PTC_SHIFT) /* Test FORCE_ENABLE */ +/* Queue Head. Paragraph 3.6 */ -#define EHCI_PORTSC_WKCCNTE (1 << 20) /* Bit 20: Wake on Connect Enable */ -#define EHCI_PORTSC_WKDSCNNTE (1 << 21) /* Bit 21: Wake on Disconnect Enable */ -#define EHCI_PORTSC_WKOCE (1 << 22) /* Bit 22: Wake on Over-current Enable */ - /* Bits 23-31: Reserved */ +/* Queue Head Horizontal Link Pointer: Queue Head DWord 0. Table 3-19 */ -#define EHCI_PORTSC_ALLINTS (EHCI_PORTSC_CSC | EHCI_PORTSC_PEC | \ - EHCI_PORTSC_OCC | EHCI_PORTSC_RESUME) +#define QH_HLP_END 0x1 -/* Debug Register Bit Definitions *******************************************/ +#define QH_HLP_ITD(x) (((uint32_t)(x) & ~0x1F) | 0x0) /* Isochronous Transfer Descriptor */ +#define QH_HLP_QH(x) (((uint32_t)(x) & ~0x1F) | 0x2) /* Queue Head */ +#define QH_HLP_SITD(x) (((uint32_t)(x) & ~0x1F) | 0x4) /* Split Transaction Isochronous Transfer Descriptor */ +#define QH_HLP_FSTN(x) (((uint32_t)(x) & ~0x1F) | 0x6) /* Frame Span Traversal Node */ -/* Debug Port Control/Status Register. Paragraph C.3.1 */ +/* Endpoint Characteristics: Queue Head DWord 1. Table 3-19 */ -#define EHCI_DEBUG_PCS_LENGTH_SHIFT (0) /* Bits 0-3: Data Length */ -#define EHCI_DEBUG_PCS_LENGTH_MASK (15 << EHCI_DEBUG_PCS_LENGTH_SHIFT) -#define EHCI_DEBUG_PCS_WRITE (1 << 4) /* Bit 6: Write/Read# */ -#define EHCI_DEBUG_PCS_GO (1 << 5) /* Bit 5: Go */ -#define EHCI_DEBUG_PCS_ERROR (1 << 6) /* Bit 6: Error/Good# */ -#define EHCI_DEBUG_PCS_EXCEPTION_SHIFT (17) /* Bits 7-9: Exception */ -#define EHCI_DEBUG_PCS_EXCEPTION_MASK (7 << EHCI_DEBUG_PCS_EXCEPTION_SHIFT) -#define EHCI_DEBUG_PCS_INUSE (1 << 10) /* Bit 10: In Use */ - /* Bits 11-15: Reserved */ -#define EHCI_DEBUG_PCS_DONE (1 << 16) /* Bit 16: Done */ - /* Bits 17-27: Reserved */ -#define EHCI_DEBUG_PCS_ENABLED (1 << 28) /* Bit 28: Enabled */ - /* Bit 29: Reserved */ -#define EHCI_DEBUG_PCS_OWNER (1 << 30) /* Bit 30: Owner */ - /* Bit 31: Reserved */ +#define QH_EPCHAR_DEVADDR_SHIFT (0) /* Bitx 0-6: Device Address */ +#define QH_EPCHAR_DEVADDR_MASK (0x7f << QH_EPCHAR_DEVADDR_SHIFT) +#define QH_EPCHAR_I (1 << 7) /* Bit 7: Inactivate on Next Transaction */ +#define QH_EPCHAR_ENDPT_SHIFT (8) /* Bitx 8-11: Endpoint Number */ +#define QH_EPCHAR_ENDPT_MASK (15 << QH_EPCHAR_ENDPT_SHIFT) +#define QH_EPCHAR_EPS_SHIFT (12) /* Bitx 12-13: Endpoint Speed */ +#define QH_EPCHAR_EPS_MASK (3 << QH_EPCHAR_EPS_SHIFT) +#define QH_EPCHAR_EPS_FULL (0 << QH_EPCHAR_EPS_SHIFT) /* Full-Speed (12Mbs) */ +#define QH_EPCHAR_EPS_LOW (1 << QH_EPCHAR_EPS_SHIFT) /* Low-Speed (1.5Mbs) */ +#define QH_EPCHAR_EPS_HIGH (2 << QH_EPCHAR_EPS_SHIFT) /* High-Speed (480 Mb/s) */ +#define QH_EPCHAR_DTC (1 << 14) /* Bit 14: Data Toggle Control */ +#define QH_EPCHAR_H (1 << 15) /* Bit 15: Head of Reclamation List Flag */ +#define QH_EPCHAR_MAXPKT_SHIFT (16) /* Bitx 16-26: Maximum Packet Length */ +#define QH_EPCHAR_MAXPKT_MASK (0x7ff << QH_EPCHAR_MAXPKT_SHIFT) +#define QH_EPCHAR_C (1 << 27) /* Bit 27: Control Endpoint Flag */ +#define QH_EPCHAR_RL_SHIFT (28) /* Bitx 28-31: Nak Count Reload */ +#define QH_EPCHAR_RL_MASK (15 << QH_EPCHAR_RL_SHIFT) -/* Debug USB PIDs Register. Paragraph C.3.2 */ +/* Endpoint Capabilities: Queue Head DWord 2. Table 3-20 */ -#define EHCI_DEBUG_USBPIDS_TKPID_SHIFT (0) /* Bits 0-7: Token PID */ -#define EHCI_DEBUG_USBPIDS_TKPID_MASK (0xff << EHCI_DEBUG_USBPIDS_TKPID_SHIFT) -#define EHCI_DEBUG_USBPIDS_SPID_SHIFT (8) /* Bits 8-15: Sent PID */ -#define EHCI_DEBUG_USBPIDS_SPID_MASK (0xff << EHCI_DEBUG_USBPIDS_SPID_SHIFT) -#define EHCI_DEBUG_USBPIDS_RPID_SHIFT (16) /* Bits 16-23: Received PID */ -#define EHCI_DEBUG_USBPIDS_RPID_MASK (0xff << EHCI_DEBUG_USBPIDS_RPID_SHIFT) - /* Bits 24-31: Reserved */ - -/* Debug Data Buffer 0/1 Register [64:0]. - * Paragreph C.3.3. 64 bits of data. - */ - -/* Debug Device Address Register. Paragraph C.3.4 */ - -#define EHCI_DEBUG_DEVADDR_ENDPT_SHIFT (0) /* Bit 0-3: USB Endpoint */ -#define EHCI_DEBUG_DEVADDR_ENDPT_MASK (15 << EHCI_DEBUG_DEVADDR_ENDPT_SHIFT) - /* Bits 4-7: Reserved */ -#define EHCI_DEBUG_DEVADDR_ADDR_SHIFT (8) /* Bits 8-14: USB Address */ -#define EHCI_DEBUG_DEVADDR_ADDR_MASK (0x7f << EHCI_DEBUG_DEVADDR_ADDR_SHIFT) - /* Bits 15-31: Reserved */ - -/* Data Structures **********************************************************/ - -/* Paragraph 3 */ - -/* Periodic Frame List. Paragraph 3.1 */ - -#define PFL_T (1 << 0) /* Bit 0: Terminate, Link pointer invalid */ -#define PFL_TYP_SHIFT (1) /* Bits 1-2: Type */ -#define PFL_TYP_MASK (3 << PFL_TYP_SHIFT) -# define PFL_TYP_ITD (0 << PFL_TYP_SHIFT) /* Isochronous Transfer Descriptor */ -# define PFL_TYP_QH (1 << PFL_TYP_SHIFT) /* Queue Head */ -# define PFL_TYP_SITD (2 << PFL_TYP_SHIFT) /* Split Transaction Isochronous Transfer Descriptor */ -# define PFL_TYP_FSTN (3 << PFL_TYP_SHIFT) /* Frame Span Traversal Node */ - - /* Bits 3-4: zero */ -#define PFL_MASK (0xffffffe0) /* Bits 5-31: Frame List Link Pointer */ - -/* Aysnchronous List Queue Head Pointer. - * Paragraph 3.2. Circular list of queue heads - */ - -/* Isochronous (High-Speed) Transfer Descriptor (iTD). Paragraph 3.3 */ - -/* iTD Next Link Pointer. Paragraph 3.3.1 */ - -#define ITD_NLP_T (1 << 0) /* Bit 0: Terminate, Link pointer invalid */ -#define ITD_NLP_TYP_SHIFT (1) /* Bits 1-2: Type */ -#define ITD_NLP_TYP_MASK (3 << ITD_NLP_TYP_SHIFT) -# define ITD_NLP_TYP_ITD (0 << ITD_NLP_TYP_SHIFT) /* Isochronous Transfer Descriptor */ -# define ITD_NLP_TYP_QH (1 << ITD_NLP_TYP_SHIFT) /* Queue Head */ -# define ITD_NLP_TYP_SITD (2 << ITD_NLP_TYP_SHIFT) /* Split Transaction Isochronous Transfer Descriptor */ -# define ITD_NLP_TYP_FSTN (3 << ITD_NLP_TYP_SHIFT) /* Frame Span Traversal Node */ - - /* Bits 3-4: zero */ -#define ITD_NLP_MASK (0xffffffe0) /* Bits 5-31: Frame List Link Pointer */ - -/* iTD Transaction Status and Control List. Paragraph 3.3.2 */ - -#define ITD_TRAN_XOFFS_SHIFT (0) /* Bits 0-11: Transaction X offset */ -#define ITD_TRAN_XOFFS_MASK (0xfff << ITD_TRAN_XOFFS_SHIFT) -#define ITD_TRAN_PG_SHIFT (12) /* Bits 12-14: Page select */ -#define ITD_TRAN_PG_MASK (7 << ITD_TRAN_PG_SHIFT) -#define ITD_TRAN_IOC (1 << 15) /* Bit 15: Interrupt On Comp */ -#define ITD_TRAN_LENGTH_SHIFT (16) /* Bits 16-27: Transaction length */ -#define ITD_TRAN_LENGTH_MASK (0xfff << ITD_TRAN_LENGTH_SHIFT) -#define ITD_TRAN_STATUS_SHIFT (28) /* Bits 28-31: Transaction status */ -#define ITD_TRAN_STATUS_MASK (15 << ITD_TRAN_STATUS_SHIFT) -# define ITD_TRAN_STATUS_XACTERR (1 << 28) /* Bit 28: Transaction error */ -# define ITD_TRAN_STATUS_BABBLE (1 << 29) /* Bit 29: Babble Detected */ -# define ITD_TRAN_STATUS_DBERROR (1 << 30) /* Bit 30: Data Buffer Error */ -# define ITD_TRAN_STATUS_ACTIVE (1 << 31) /* Bit 28: Transaction error */ - -/* iTD Buffer Page Pointer List. Paragraph 3.3.4 */ - -/* iTD Buffer Pointer Page 0. Table 3-4 */ - -#define ITD_BUFPTR0_DEVADDR_SHIFT (0) /* Bits 0-6: Device Address */ -#define ITD_BUFPTR0_DEVADDR_MASK (0x7f << ITD_BUFPTR0_DEVADDR_SHIFT) - /* Bit 7: Reserved */ -#define ITD_BUFPTR0_ENDPT_SHIFT (8) /* Bits 8-11: Endpoint Number */ -#define ITD_BUFPTR0_ENDPT_MASK (15 << ITD_BUFPTR0_ENDPT_SHIFT) - -/* iTD Buffer Pointer Page 1. Table 3-5 */ - -#define ITD_BUFPTR1_MAXPKT_SHIFT (0) /* Bits 0-10: Maximum Packet Size */ -#define ITD_BUFPTR1_MAXPKT_MASK (0x7ff << ITD_BUFPTR1_MAXPKT_SHIFT) -#define ITD_BUFPTR1_DIRIN (1 << 11) /* Bit 11: Direction 1=IN */ -#define ITD_BUFPTR1_DIROUT (0) /* Bit 11: Direction 0=OUT */ - -/* iTD Buffer Pointer Page 2. Table 3-6 */ - -#define ITD_BUFPTR2_MULTI_SHIFT (0) /* Bits 0-1: Multi */ -#define ITD_BUFPTR2_MULTI_MASK (3 << ITD_BUFPTR2_MULTI_SHIFT) -# define ITD_BUFPTR2_MULTI_1 (1 << ITD_BUFPTR2_MULTI_SHIFT) /* One transaction per micro-frame */ -# define ITD_BUFPTR2_MULTI_2 (2 << ITD_BUFPTR2_MULTI_SHIFT) /* Two transactions per micro-frame */ -# define ITD_BUFPTR2_MULTI_3 (3 << ITD_BUFPTR2_MULTI_SHIFT) /* Three transactions per micro-frame */ - - /* Bits 2-11: Reserved */ - -/* iTD Buffer Pointer Page 3-6. Table 3-7 */ - - /* Bits 0-11: Reserved */ - -/* iTD Buffer Pointer All Pages */ - -#define ITD_BUFPTR_MASK (0xfffff000) /* Bits 12-31: Buffer Pointer */ - -/* Split Transaction Isochronous Transfer Descriptor (siTD). - * Paragraph 3.4 - */ - -/* siTD Next Link Pointer. Paragraph 3.4.1 */ - -#define SITD_NLP_T (1 << 0) /* Bit 0: Terminate, Link pointer invalid */ -#define SITD_NLP_TYP_SHIFT (1) /* Bits 1-2: Type */ -#define SITD_NLP_TYP_MASK (3 << SITD_NLP_TYP_SHIFT) -# define SITD_NLP_TYP_ITD (0 << SITD_NLP_TYP_SHIFT) /* Isochronous Transfer Descriptor */ -# define SITD_NLP_TYP_QH (1 << SITD_NLP_TYP_SHIFT) /* Queue Head */ -# define SITD_NLP_TYP_SITD (2 << SITD_NLP_TYP_SHIFT) /* Split Transaction Isochronous Transfer Descriptor */ -# define SITD_NLP_TYP_FSTN (3 << SITD_NLP_TYP_SHIFT) /* Frame Span Traversal Node */ - - /* Bits 3-4: zero */ -#define SITD_NLP_MASK (0xffffffe0) /* Bits 5-31: Frame List Link Pointer */ - -/* siTD Endpoint Capabilities/Characteristics. - * Paragraph 3.4.2 - */ - -/* Endpoint and Transaction Translator Characteristics. Table 3-9 */ - -#define SITD_EPCHAR_DEVADDR_SHIFT (0) /* Bitx 0-6: Device Address */ -#define SITD_EPCHAR_DEVADDR_MASK (0x7f << SITD_EPCHAR_DEVADDR_SHIFT) - /* Bits 7: Reserved */ -#define SITD_EPCHAR_ENDPT_SHIFT (8) /* Bitx 8-11: Endpoint Number */ -#define SITD_EPCHAR_ENDPT_MASK (15 << SITD_EPCHAR_ENDPT_SHIFT) - /* Bits 12-15: Reserved */ -#define SITD_EPCHAR_HUBADDR_SHIFT (16) /* Bitx 16-22: Hub Address */ -#define SITD_EPCHAR_HUBADDR_MASK (0x7f << SITD_EPCHAR_HUBADDR_SHIFT) - /* Bit 23: Reserved */ -#define SITD_EPCHAR_DIRIN (1 << 31) /* Bit 31: Direction 1=IN */ -#define SITD_EPCHAR_DIROUT (0) /* Bit 31: Direction 0=OUT */ - -/* Micro-frame Schedule Control. Table 3-10 */ - -#define SITD_FMSCHED_SSMASK_SHIFT (0) /* Bitx 0-7: Split Start Mask (�Frame S-mask) */ -#define SITD_FMSCHED_SSMASK_MASK (0xff << SITD_FMSCHED_SSMASK_SHIFT) -# define SITD_FMSCHED_SSMASK(n) ((n) << SITD_FMSCHED_SSMASK_SHIFT) -#define SITD_FMSCHED_SCMASK_SHIFT (8) /* Bitx 8-15: Split Completion Mask (�Frame C-Mask) */ -#define SITD_FMSCHED_SCMASK_MASK (0xff << SITD_FMSCHED_SCMASK_SHIFT) -# define SITD_FMSCHED_SCMASK(n) ((n) << SITD_FMSCHED_SCMASK_SHIFT) - /* Bits 16-31: Reserved */ - -/* siTD Transfer State. Paragraph 3.4.3 */ - -#define SITD_XFRSTATE_STATUS_SHIFT (0) /* Bits 0-7: Status */ -#define SITD_XFRSTATE_STATUS_MASK (0xff << SITD_XFRSTATE_STATUS_SHIFT) -#define SITD_XFRSTATE_CPROGMASK_SHIFT (8) /* Bits 8-15: �Frame Complete-split Progress Mask */ -#define SITD_XFRSTATE_CPROGMASK_MASK (0xff << SITD_XFRSTATE_CPROGMASK_SHIFT) -#define SITD_XFRSTATE_NBYTES_SHIFT (16) /* Bits 16-25: Total Bytes To Transfer */ -#define SITD_XFRSTATE_NBYTES_MASK (0x3ff << SITD_XFRSTATE_NBYTES_SHIFT) - /* Bits 26-29: Reserved */ -#define SITD_XFRSTATE_P (1 << 30) /* Bit 30: Page Select */ -#define SITD_XFRSTATE_IOC (1 << 31) /* Bit 31: Interrupt On Complete */ - -/* siTD Buffer Pointer List. - * Paragraph 3.4.4 - */ - -/* Page 0 */ - -#define SITD_BUFPTR0_OFFSET_SHIFT (0) /* Bits 0-11: Current Offset */ -#define SITD_BUFPTR0_OFFSET_MASK (0xff << SITD_BUFPTR0_OFFSET_SHIFT) - -/* Page 1 */ - -#define SITD_BUFPTR1_TCOUNT_SHIFT (0) /* Bits 0-2: Transaction count */ -#define SITD_BUFPTR1_TCOUNT_MASK (7 << SITD_BUFPTR1_TCOUNT_SHIFT) -#define SITD_BUFPTR1_TP_SHIFT (33) /* Bits 3-4: Transaction position */ -#define SITD_BUFPTR1_TP_MASK (3 << SITD_BUFPTR1_TP_SHIFT) -# define SITD_BUFPTR1_TP_ENTIRE (0 << SITD_BUFPTR1_TP_SHIFT) /* Entire full-speed transaction data payload. */ -# define SITD_BUFPTR1_TP_BEGIN (1 << SITD_BUFPTR1_TP_SHIFT) /* This is the first data payload */ -# define SITD_BUFPTR1_TP_MID (2 << SITD_BUFPTR1_TP_SHIFT) /* This the middle payload */ -# define SITD_BUFPTR1_TP_END (3 << SITD_BUFPTR1_TP_SHIFT) /* This is the last payload */ - - /* Bits 5-11: Reserved */ - -/* All pages */ - -#define SITD_BUFPTR_MASK (0xfffff000) /* Bits 12-31: Buffer Pointer List */ - -/* Queue Element Transfer Descriptor (qTD). - * Paragraph 3.5 - */ - -/* Next qTD Pointer. - * Paragraph 3.5.1 - */ - -#define QTD_NQP_T (1 << 0) /* Bit 0: Terminate */ - /* Bits 1-4: Reserved */ -#define QTD_NQP_NTEP_SHIFT (5) /* Bits 5-31: Next Transfer Element Pointer */ -#define QTD_NQP_NTEP_MASK (0xffffffe0) - -/* Alternate Next qTD Pointer. - * Paragraph 3.5.2 - */ - -#define QTD_AQP_T (1 << 0) /* Bit 0: Terminate */ - /* Bits 1-4: Reserved */ -#define QTD_AQP_NTEP_SHIFT (5) /* Bits 5-31: Next Transfer Element Pointer */ -#define QTD_AQP_NTEP_MASK (0xffffffe0) +#define QH_EPCAPS_SSMASK_SHIFT (0) /* Bitx 0-7: Interrupt Schedule Mask (Frame S-mask) */ +#define QH_EPCAPS_SSMASK_MASK (0xff << QH_EPCAPS_SSMASK_SHIFT) +#define QH_EPCAPS_SSMASK(n) ((n) << QH_EPCAPS_SSMASK_SHIFT) +#define QH_EPCAPS_SCMASK_SHIFT (8) /* Bitx 8-15: Split Completion Mask (Frame C-Mask) */ +#define QH_EPCAPS_SCMASK_MASK (0xff << QH_EPCAPS_SCMASK_SHIFT) +#define QH_EPCAPS_SCMASK(n) ((n) << QH_EPCAPS_SCMASK_SHIFT) +#define QH_EPCAPS_HUBADDR_SHIFT (16) /* Bitx 16-22: Hub Address */ +#define QH_EPCAPS_HUBADDR_MASK (0x7f << QH_EPCAPS_HUBADDR_SHIFT) +#define QH_EPCAPS_HUBADDR(n) ((n) << QH_EPCAPS_HUBADDR_SHIFT) +#define QH_EPCAPS_PORT_SHIFT (23) /* Bit 23-29: Port Number */ +#define QH_EPCAPS_PORT_MASK (0x7f << QH_EPCAPS_PORT_SHIFT) +#define QH_EPCAPS_PORT(n) ((n) << QH_EPCAPS_PORT_SHIFT) +#define QH_EPCAPS_MULT_SHIFT (30) /* Bit 30-31: High-Bandwidth Pipe Multiplier */ +#define QH_EPCAPS_MULT_MASK (3 << QH_EPCAPS_MULT_SHIFT) +#define QH_EPCAPS_MULT(n) ((n) << QH_EPCAPS_MULT_SHIFT) /* qTD Token. * Paragraph 3.5.3 */ +#define QTD_LIST_END 1 -#define QTD_TOKEN_STATUS_SHIFT (0) /* Bits 0-7: Status */ -#define QTD_TOKEN_STATUS_MASK (0xff << QTD_TOKEN_STATUS_SHIFT) -# define QTD_TOKEN_P (1 << 0) /* Bit 0 Ping State */ -# define QTD_TOKEN_ERR (1 << 0) /* Bit 0 Error */ -# define QTD_TOKEN_SPLITXSTATE (1 << 1) /* Bit 1 Split Transaction State */ -# define QTD_TOKEN_MMF (1 << 2) /* Bit 2 Missed Micro-Frame */ -# define QTD_TOKEN_XACTERR (1 << 3) /* Bit 3 Transaction Error */ -# define QTD_TOKEN_BABBLE (1 << 4) /* Bit 4 Babble Detected */ -# define QTD_TOKEN_DBERR (1 << 5) /* Bit 5 Data Buffer Error */ -# define QTD_TOKEN_HALTED (1 << 6) /* Bit 6 Halted */ -# define QTD_TOKEN_ACTIVE (1 << 7) /* Bit 7 Active */ -# define QTD_TOKEN_ERRORS (0x78 << QTD_TOKEN_STATUS_SHIFT) -#define QTD_TOKEN_PID_SHIFT (8) /* Bits 8-9: PID Code */ -#define QTD_TOKEN_PID_MASK (3 << QTD_TOKEN_PID_SHIFT) -# define QTD_TOKEN_PID_OUT (0 << QTD_TOKEN_PID_SHIFT) /* OUT Token generates token (E1H) */ -# define QTD_TOKEN_PID_IN (1 << QTD_TOKEN_PID_SHIFT) /* IN Token generates token (69H) */ -# define QTD_TOKEN_PID_SETUP (2 << QTD_TOKEN_PID_SHIFT) /* SETUP Token generates token (2DH) */ - -#define QTD_TOKEN_CERR_SHIFT (10) /* Bits 10-11: Error Counter */ -#define QTD_TOKEN_CERR_MASK (3 << QTD_TOKEN_CERR_SHIFT) -#define QTD_TOKEN_CPAGE_SHIFT (12) /* Bits 12-14: Current Page */ -#define QTD_TOKEN_CPAGE_MASK (7 << QTD_TOKEN_CPAGE_SHIFT) -#define QTD_TOKEN_IOC (1 << 15) /* Bit 15: Interrupt On Complete */ -#define QTD_TOKEN_NBYTES_SHIFT (16) /* Bits 16-30: Total Bytes to Transfer */ -#define QTD_TOKEN_NBYTES_MASK (0x7fff << QTD_TOKEN_NBYTES_SHIFT) -#define QTD_TOKEN_TOGGLE_SHIFT (31) /* Bit 31: Data Toggle */ -#define QTD_TOKEN_TOGGLE (1 << 31) /* Bit 31: Data Toggle */ - -/* qTD Buffer Page Pointer List. - * Paragraph 3.5.4 - */ - -/* Page 0 */ - -#define QTD_BUFPTR0_OFFFSET_SHIFT (0) /* Bits 0-11: Current Offset */ -#define QTD_BUFPTR0_OFFFSET_MASK (0xfff << QTD_BUFPTR0_OFFFSET_SHIFT) - -/* Other pages */ - - /* Bits 0-11: Reserved */ - -/* All pages */ - -#define QTD_BUFPTR_SHIFT (12) /* Bits 12-31: Buffer Pointer List */ -#define QTD_BUFPTR_MASK (0xfffff000) - -/* Queue Head. Paragraph 3.6 */ - -/* Queue Head Horizontal Link Pointer. - * Paragraph 3.6.1 - */ - -#define QH_HLP_T (1 << 0) /* Bit 0: Terminate, QH HL pointer invalid */ -#define QH_HLP_TYP_SHIFT (1) /* Bits 1-2: Type */ -#define QH_HLP_TYP_MASK (3 << QH_HLP_TYP_SHIFT) -# define QH_HLP_TYP_ITD (0 << QH_HLP_TYP_SHIFT) /* Isochronous Transfer Descriptor */ -# define QH_HLP_TYP_QH (1 << QH_HLP_TYP_SHIFT) /* Queue Head */ -# define QH_HLP_TYP_SITD (2 << QH_HLP_TYP_SHIFT) /* Split Transaction Isochronous Transfer Descriptor */ -# define QH_HLP_TYP_FSTN (3 << QH_HLP_TYP_SHIFT) /* Frame Span Traversal Node */ - - /* Bits 3-4: Reserved */ -#define QH_HLP_MASK (0xffffffe0) /* Bits 5-31: Queue Head Horizontal Link Pointer */ - -/* Endpoint Capabilities/Characteristics. Paragraph 3.6.2 */ - -/* Endpoint Characteristics: Queue Head DWord. Table 3-19 */ - -#define QH_EPCHAR_DEVADDR_SHIFT (0) /* Bitx 0-6: Device Address */ -#define QH_EPCHAR_DEVADDR_MASK (0x7f << QH_EPCHAR_DEVADDR_SHIFT) -#define QH_EPCHAR_I (1 << 7) /* Bit 7: Inactivate on Next Transaction */ -#define QH_EPCHAR_ENDPT_SHIFT (8) /* Bitx 8-11: Endpoint Number */ -#define QH_EPCHAR_ENDPT_MASK (15 << QH_EPCHAR_ENDPT_SHIFT) -#define QH_EPCHAR_EPS_SHIFT (12) /* Bitx 12-13: Endpoint Speed */ -#define QH_EPCHAR_EPS_MASK (3 << QH_EPCHAR_EPS_SHIFT) -# define QH_EPCHAR_EPS_FULL (0 << QH_EPCHAR_EPS_SHIFT) /* Full-Speed (12Mbs) */ -# define QH_EPCHAR_EPS_LOW (1 << QH_EPCHAR_EPS_SHIFT) /* Low-Speed (1.5Mbs) */ -# define QH_EPCHAR_EPS_HIGH (2 << QH_EPCHAR_EPS_SHIFT) /* High-Speed (480 Mb/s) */ - -#define QH_EPCHAR_DTC (1 << 14) /* Bit 14: Data Toggle Control */ -#define QH_EPCHAR_H (1 << 15) /* Bit 15: Head of Reclamation List Flag */ -#define QH_EPCHAR_MAXPKT_SHIFT (16) /* Bitx 16-26: Maximum Packet Length */ -#define QH_EPCHAR_MAXPKT_MASK (0x7ff << QH_EPCHAR_MAXPKT_SHIFT) -#define QH_EPCHAR_C (1 << 27) /* Bit 27: Control Endpoint Flag */ -#define QH_EPCHAR_RL_SHIFT (28) /* Bitx 28-31: Nak Count Reload */ -#define QH_EPCHAR_RL_MASK (15 << QH_EPCHAR_RL_SHIFT) - -/* Endpoint Capabilities: Queue Head DWord 2. Table 3-20 */ - -#define QH_EPCAPS_SSMASK_SHIFT (0) /* Bitx 0-7: Interrupt Schedule Mask (�Frame S-mask) */ -#define QH_EPCAPS_SSMASK_MASK (0xff << QH_EPCAPS_SSMASK_SHIFT) -# define QH_EPCAPS_SSMASK(n) ((n) << QH_EPCAPS_SSMASK_SHIFT) -#define QH_EPCAPS_SCMASK_SHIFT (8) /* Bitx 8-15: Split Completion Mask (�Frame C-Mask) */ -#define QH_EPCAPS_SCMASK_MASK (0xff << QH_EPCAPS_SCMASK_SHIFT) -# define QH_EPCAPS_SCMASK(n) ((n) << QH_EPCAPS_SCMASK_SHIFT) -#define QH_EPCAPS_HUBADDR_SHIFT (16) /* Bitx 16-22: Hub Address */ -#define QH_EPCAPS_HUBADDR_MASK (0x7f << QH_EPCAPS_HUBADDR_SHIFT) -# define QH_EPCAPS_HUBADDR(n) ((n) << QH_EPCAPS_HUBADDR_SHIFT) -#define QH_EPCAPS_PORT_SHIFT (23) /* Bit 23-29: Port Number */ -#define QH_EPCAPS_PORT_MASK (0x7f << QH_EPCAPS_PORT_SHIFT) -# define QH_EPCAPS_PORT(n) ((n) << QH_EPCAPS_PORT_SHIFT) -#define QH_EPCAPS_MULT_SHIFT (30) /* Bit 30-31: High-Bandwidth Pipe Multiplier */ -#define QH_EPCAPS_MULT_MASK (3 << QH_EPCAPS_MULT_SHIFT) -# define QH_EPCAPS_MULT(n) ((n) << QH_EPCAPS_MULT_SHIFT) - -/* Current qTD Link Pointer. Table 3-21 */ - -#define QH_CQP_NTEP_SHIFT (5) /* Bits 5-31: Next Transfer Element Pointer */ -#define QH_CQP_NTEP_MASK (0xffffffe0) - -/* Transfer Overlay. Paragraph 3.6.3 - * - * NOTES: - * 1. Same as the field of the same name in struct ehci_qtd_s - * 2. Similar to the field of the same name in struct ehci_qtd_s, but with - * some additional bitfields. - */ - -/* Next qTD Pointer (NOTE 1) */ - -#define QH_NQP_T (1 << 0) /* Bit 0: Terminate */ - /* Bits 1-4: Reserved */ -#define QH_NQP_NTEP_SHIFT (5) /* Bits 5-31: Next Transfer Element Pointer */ -#define QH_NQP_NTEP_MASK (0xffffffe0) - -/* Alternate Next qTD Pointer. Table 3.7 (NOTE 2) */ - -#define QH_AQP_T (1 << 0) /* Bit 0: Terminate */ -#define QH_AQP_NAKCNT (1) /* Bits 1-4: Nak Counter */ -#define QH_AQP_NTEP_SHIFT (5) /* Bits 5-31: Next Transfer Element Pointer */ -#define QH_AQP_NTEP_MASK (0xffffffe0) - -/* qTD Token (NOTE 1) */ - -#define QH_TOKEN_STATUS_SHIFT (0) /* Bits 0-7: Status */ -#define QH_TOKEN_STATUS_MASK (0xff << QH_TOKEN_STATUS_SHIFT) -# define QH_TOKEN_P (1 << 0) /* Bit 0 Ping State */ -# define QH_TOKEN_ERR (1 << 0) /* Bit 0 Error */ -# define QH_TOKEN_SPLITXSTATE (1 << 1) /* Bit 1 Split Transaction State */ -# define QH_TOKEN_MMF (1 << 2) /* Bit 2 Missed Micro-Frame */ -# define QH_TOKEN_XACTERR (1 << 3) /* Bit 3 Transaction Error */ -# define QH_TOKEN_BABBLE (1 << 4) /* Bit 4 Babble Detected */ -# define QH_TOKEN_DBERR (1 << 5) /* Bit 5 Data Buffer Error */ -# define QH_TOKEN_HALTED (1 << 6) /* Bit 6 Halted */ -# define QH_TOKEN_ACTIVE (1 << 7) /* Bit 7 Active */ -# define QH_TOKEN_ERRORS (0x78 << QH_TOKEN_STATUS_SHIFT) -#define QH_TOKEN_PID_SHIFT (8) /* Bits 8-9: PID Code */ -#define QH_TOKEN_PID_MASK (3 << QH_TOKEN_PID_SHIFT) -# define QH_TOKEN_PID_OUT (0 << QH_TOKEN_PID_SHIFT) /* OUT Token generates token (E1H) */ -# define QH_TOKEN_PID_IN (1 << QH_TOKEN_PID_SHIFT) /* IN Token generates token (69H) */ -# define QH_TOKEN_PID_SETUP (2 << QH_TOKEN_PID_SHIFT) /* SETUP Token generates token (2DH) */ - -#define QH_TOKEN_CERR_SHIFT (10) /* Bits 10-11: Error Counter */ -#define QH_TOKEN_CERR_MASK (3 << QH_TOKEN_CERR_SHIFT) -#define QH_TOKEN_CPAGE_SHIFT (12) /* Bits 12-14: Current Page */ -#define QH_TOKEN_CPAGE_MASK (7 << QH_TOKEN_CPAGE_SHIFT) -#define QH_TOKEN_IOC (1 << 15) /* Bit 15: Interrupt On Complete */ -#define QH_TOKEN_NBYTES_SHIFT (16) /* Bits 16-30: Total Bytes to Transfer */ -#define QH_TOKEN_NBYTES_MASK (0x7fff << QH_TOKEN_NBYTES_SHIFT) -#define QH_TOKEN_TOGGLE_SHIFT (31) /* Bit 31: Data Toggle */ -#define QH_TOKEN_TOGGLE (1 << 31) /* Bit 31: Data Toggle */ - -/* Buffer Page Pointer List (NOTE 2) */ - -/* Page 0 */ - -#define QH_BUFPTR0_OFFFSET_SHIFT (0) /* Bits 0-11: Current Offset */ -#define QH_BUFPTR0_OFFFSET_MASK (0xfff << QH_BUFPTR0_OFFFSET_SHIFT) - -/* Page 1. Table 3.22 */ - -#define QH_BUFPTR1_CPROGMASK_SHIFT (0) /* Bits 0-7: Split-transaction Complete-split Progress */ -#define QH_BUFPTR1_CPROGMASK_MASK (0xff << QH_BUFPTR1_CPROGMASK_SHIFT) - /* Bits 8-11: Reserved */ - -/* Page 2. Table 3.22 */ - -#define QH_BUFPTR2_FRAMETAG_SHIFT (0) /* Bits 0-4: Split-transaction Frame Tag */ -#define QH_BUFPTR2_FRAMETAG_MASK (31 << QH_BUFPTR2_FRAMETAG_SHIFT) -#define QH_BUFPTR2_SBYTES_SHIFT (5) /* Bits 5-11: S-bytes */ -#define QH_BUFPTR2_SBYTES_MASK (0x7f << QH_BUFPTR2_SBYTES_SHIFT) - -/* Other pages */ - - /* Bits 0-11: Reserved */ - -/* All pages */ - -#define QH_BUFPTR_SHIFT (12) /* Bits 12-31: Buffer Pointer List */ -#define QH_BUFPTR_MASK (0xfffff000) - -/* Periodic Frame Span Traversal Node (STN). Paragrap 3.7 */ - -/* FSTN Normal Path Pointer. Paragraph 3.7.1 */ - -#define FSTN_NPP_T (1 << 0) /* Bit 0: Terminate. 1=Link Pointer not valid */ -#define FSTN_NPP_TYP_SHIFT (1) /* Bits 1-2: Type */ -#define FSTN_NPP_TYP_MASK (3 << FSTN_NPP_TYP_SHIFT) -# define FSTN_NPP_TYP_ITD (0 << FSTN_NPP_TYP_SHIFT) /* Isochronous Transfer Descriptor */ -# define FSTN_NPP_TYP_QH (1 << FSTN_NPP_TYP_SHIFT) /* Queue Head */ -# define FSTN_NPP_TYP_SITD (2 << FSTN_NPP_TYP_SHIFT) /* Split Transaction Isochronous Transfer Descriptor */ -# define FSTN_NPP_TYP_FSTN (3 << FSTN_NPP_TYP_SHIFT) /* Frame Span Traversal Node */ - - /* Bits 3-4: Reserved */ -#define FSTN_NPP_NPLP_SHIFT (5) /* Bits 5-31: Normal Path Link Pointer */ -#define FSTN_NPP_NPLP_MASK (0xffffffe0) - -/* FSTN Back Path Link Pointer. Paragraph 3.7.2 */ - -#define FSTN_BPP_T (1 << 0) /* Bit 0: Terminate. 1=Link Pointer not valid */ -#define FSTN_BPP_TYP_SHIFT (1) /* Bits 1-2: Type */ -#define FSTN_BPP_TYP_MASK (3 << FSTN_BPP_TYP_SHIFT) -# define FSTN_BPP_TYP_QH (1 << FSTN_BPP_TYP_SHIFT) /* Queue Head */ - - /* Bits 3-4: Reserved */ -#define FSTN_BPP_BPLP_SHIFT (5) /* Bits 5-31: Back Path Link Pointer */ -#define FSTN_BPP_BPLP_MASK (0xffffffe0) - -/**************************************************************************** - * Public Types - ****************************************************************************/ +#define QTD_TOKEN_STATUS_SHIFT (0) /* Bits 0-7: Status */ +#define QTD_TOKEN_STATUS_MASK (0xff << QTD_TOKEN_STATUS_SHIFT) +#define QTD_TOKEN_STATUS_PINGSTATE (1 << 0) /* Bit 0 Ping State */ +#define QTD_TOKEN_STATUS_ERR (1 << 0) /* Bit 0 Error */ +#define QTD_TOKEN_STATUS_SPLITXSTATE (1 << 1) /* Bit 1 Split Transaction State */ +#define QTD_TOKEN_STATUS_MMF (1 << 2) /* Bit 2 Missed Micro-Frame */ +#define QTD_TOKEN_STATUS_XACTERR (1 << 3) /* Bit 3 Transaction Error */ +#define QTD_TOKEN_STATUS_BABBLE (1 << 4) /* Bit 4 Babble Detected */ +#define QTD_TOKEN_STATUS_DBERR (1 << 5) /* Bit 5 Data Buffer Error */ +#define QTD_TOKEN_STATUS_HALTED (1 << 6) /* Bit 6 Halted */ +#define QTD_TOKEN_STATUS_ACTIVE (1 << 7) /* Bit 7 Active */ +#define QTD_TOKEN_STATUS_ERRORS (0x78 << QTD_TOKEN_STATUS_SHIFT) +#define QTD_TOKEN_PID_SHIFT (8) /* Bits 8-9: PID Code */ +#define QTD_TOKEN_PID_MASK (3 << QTD_TOKEN_PID_SHIFT) +#define QTD_TOKEN_PID_OUT (0 << QTD_TOKEN_PID_SHIFT) /* OUT Token generates token (E1H) */ +#define QTD_TOKEN_PID_IN (1 << QTD_TOKEN_PID_SHIFT) /* IN Token generates token (69H) */ +#define QTD_TOKEN_PID_SETUP (2 << QTD_TOKEN_PID_SHIFT) /* SETUP Token generates token (2DH) */ +#define QTD_TOKEN_CERR_SHIFT (10) /* Bits 10-11: Error Counter */ +#define QTD_TOKEN_CERR_MASK (3 << QTD_TOKEN_CERR_SHIFT) +#define QTD_TOKEN_CPAGE_SHIFT (12) /* Bits 12-14: Current Page */ +#define QTD_TOKEN_CPAGE_MASK (7 << QTD_TOKEN_CPAGE_SHIFT) +#define QTD_TOKEN_IOC (1 << 15) /* Bit 15: Interrupt On Complete */ +#define QTD_TOKEN_NBYTES_SHIFT (16) /* Bits 16-30: Total Bytes to Transfer */ +#define QTD_TOKEN_NBYTES_MASK (0x7fff << QTD_TOKEN_NBYTES_SHIFT) +#define QTD_TOKEN_TOGGLE (1 << 31) /* Bit 31: Data Toggle */ /* Registers ****************************************************************/ -/* Since the operational registers are not known a compile time, representing - * register blocks with structures is more convenient than using individual - * register offsets. - */ - /* Host Controller Capability Registers. * This register block must be positioned at a well known address. */ -struct ehci_hccr_s -{ - uint8_t caplength; /* 0x00: Capability Register Length */ - uint8_t reserved; - uint16_t hciversion; /* 0x02: Interface Version Number */ - uint32_t hcsparams; /* 0x04: Structural Parameters */ - uint32_t hccparams; /* 0x08: Capability Parameters */ - uint8_t hcspportrt[8]; /* 0x0c: Companion Port Route Description */ +struct ehci_hccr { + uint8_t caplength; /* 0x00: Capability Register Length */ + uint8_t reserved; /* 0x01: reserved */ + uint16_t hciversion; /* 0x02: Interface Version Number */ + uint32_t hcsparams; /* 0x04: Structural Parameters */ + uint32_t hccparams; /* 0x08: Capability Parameters */ + uint8_t hcspportroute[8]; /* 0x0c: Companion Port Route Description */ }; /* Host Controller Operational Registers. @@ -849,20 +246,19 @@ struct ehci_hccr_s * beginning of the Host Controller Capability Registers. */ -struct ehci_hcor_s -{ - uint32_t usbcmd; /* 0x00: USB Command */ - uint32_t usbsts; /* 0x04: USB Status */ - uint32_t usbintr; /* 0x08: USB Interrupt Enable */ - uint32_t frindex; /* 0x0c: USB Frame Index */ - uint32_t ctrldssegment; /* 0x10: 4G Segment Selector */ - uint32_t periodiclistbase; /* 0x14: Frame List Base Address */ - uint32_t asynclistaddr; /* 0x18: Next Asynchronous List Address */ +struct ehci_hcor { + uint32_t usbcmd; /* 0x00: USB Command */ + uint32_t usbsts; /* 0x04: USB Status */ + uint32_t usbintr; /* 0x08: USB Interrupt Enable */ + uint32_t frindex; /* 0x0c: USB Frame Index */ + uint32_t ctrldssegment; /* 0x10: 4G Segment Selector */ + uint32_t periodiclistbase; /* 0x14: Frame List Base Address */ + uint32_t asynclistaddr; /* 0x18: Next Asynchronous List Address */ #ifndef CONFIG_USB_ECHI_HCOR_RESERVED_DISABLE - uint32_t reserved[9]; + uint32_t reserved[9]; #endif - uint32_t configflag; /* 0x40: Configured Flag Register */ - uint32_t portsc[15]; /* 0x44: Port Status/Control */ + uint32_t configflag; /* 0x40: Configured Flag Register */ + uint32_t portsc[15]; /* 0x44: Port Status/Control */ }; /* USB2 Debug Port Register Interface. @@ -871,124 +267,36 @@ struct ehci_hcor_s * location of these registers. */ -struct ehci_debug_s -{ - uint32_t psc; /* 0x00: Debug Port Control/Status Register */ - uint32_t pids; /* 0x04: Debug USB PIDs Register */ - uint32_t data[2]; /* 0x08: Debug Data buffer Registers */ - uint32_t addr; /* 0x10: Device Address Register */ +struct ehci_debug { + uint32_t psc; /* 0x00: Debug Port Control/Status Register */ + uint32_t pids; /* 0x04: Debug USB PIDs Register */ + uint32_t data[2]; /* 0x08: Debug Data buffer Registers */ + uint32_t addr; /* 0x10: Device Address Register */ }; /* Data Structures **********************************************************/ -/* Paragraph 3 */ - -/* Periodic Frame List. - * Paragraph 3.1. An array of pointers. - */ - -/* Aysnchronous List Queue Head Pointer. - * Paragraph 3.2. Circular list of queue heads - */ - -/* Isochronous (High-Speed) Transfer Descriptor (iTD). - * Paragraph 3.3. Must be aligned to 32-byte boundaries. - */ - -struct ehci_itd_s -{ - uint32_t nlp; /* 0x00-0x03: Next link pointer */ - uint32_t trans[8]; /* 0x04-0x23: Transaction Status and Control List */ - uint32_t bpl[7]; /* 0x24-0x3c: Buffer Page Pointer List */ -}; - -#define SIZEOF_EHCI_ITD_S (64) /* 16*sizeof(uint32_t) */ - -/* Split Transaction Isochronous Transfer Descriptor (siTD). Paragraph 3.4 */ - -struct ehci_sitd_s -{ - uint32_t nlp; /* 0x00-0x03: Next link pointer */ - uint32_t epchar; /* 0x04-0x07: Endpoint and Transaction Translator Characteristics */ - uint32_t fmsched; /* 0x08-0x0b: Micro-frame Schedule Control */ - uint32_t xfrstate; /* 0x0c-0x0f: Transfer Status and Control */ - uint32_t bpl[2]; /* 0x10-0x17: Buffer Pointer List */ - uint32_t blp; /* 0x18-0x1b: Back link pointer */ -}; - -#define SIZEOF_EHCI_SITD_S (28) /* 7*sizeof(uint32_t) */ - /* Queue Element Transfer Descriptor (qTD). Paragraph 3.5 */ -/* 32-bit version. See EHCI Appendix B for the 64-bit version. */ - -struct ehci_qtd_s -{ - uint32_t nqp; /* 0x00-0x03: Next qTD Pointer */ - uint32_t alt; /* 0x04-0x07: Alternate Next qTD Pointer */ - uint32_t token; /* 0x08-0x0b: qTD Token */ - uint32_t bpl[5]; /* 0x0c-0x1c: Buffer Page Pointer List */ +struct ehci_qtd { + uint32_t next_qtd; /* 0x00-0x03: Next qTD Pointer */ + uint32_t alt_next_qtd; /* 0x04-0x07: Alternate Next qTD Pointer */ + uint32_t token; /* 0x08-0x0b: qTD Token */ + uint32_t bpl[5]; /* 0x0c-0x1c: Buffer Page Pointer List */ }; -#define SIZEOF_EHCI_QTD_S (32) /* 8*sizeof(uint32_t) */ +#define SIZEOF_EHCI_QTD (32) /* 8*sizeof(uint32_t) */ -/* Queue Head. Paragraph 3.6 - * - * NOTE: - * 1. Same as the field of the same name in struct ehci_qtd_s - * 2. Similar to the field of the same name in struct ehci_qtd_s, - * but with some additional bitfields. - */ +/* Queue Head. Paragraph 3.6 */ -struct ehci_overlay_s -{ - uint32_t nqp; /* 0x00-0x03: Next qTD Pointer (NOTE 1) */ - uint32_t alt; /* 0x04-0x07: Alternate Next qTD Pointer (NOTE 2) */ - uint32_t token; /* 0x08-0x0b: qTD Token (NOTE 1) */ - uint32_t bpl[5]; /* 0x0c-0x1c: Buffer Page Pointer List (NOTE 2) */ +struct ehci_qh { + uint32_t hlp; /* 0x00-0x03: Queue Head Horizontal Link Pointer */ + uint32_t epchar; /* 0x04-0x07: Endpoint Characteristics */ + uint32_t epcap; /* 0x08-0x0b: Endpoint Capabilities */ + uint32_t curr_qtd; /* 0x0c-0x0f: Current qTD Pointer */ + struct ehci_qtd overlay; /* 0x10-0x2c: Transfer overlay */ }; -#define SIZEOF_EHCI_OVERLAY (32) /* 8*sizeof(uint32_t) */ +#define SIZEOF_EHCI_QH (48) /* 4*sizeof(uint32_t) + 32 */ -struct ehci_qh_s -{ - uint32_t hlp; /* 0x00-0x03: Queue Head Horizontal Link Pointer */ - uint32_t epchar; /* 0x04-0x07: Endpoint Characteristics */ - uint32_t epcaps; /* 0x08-0x0b: Endpoint Capabilities */ - uint32_t cqp; /* 0x0c-0x0f: Current qTD Pointer */ - struct ehci_overlay_s overlay; /* 0x10-0x2c: Transfer overlay */ -}; - -#define SIZEOF_EHCI_QH (48) /* 4*sizeof(uint32_t) + SIZEOF_EHCI_OVERLAY */ - -/* Periodic Frame Span Traversal Node (STN). Paragrap 3.7 */ - -struct ehci_fstn_s -{ - uint32_t npp; /* 0x00-0x03: Normal Path Pointer */ - uint32_t bpp; /* 0x04-0x07: Back Path Link Pointer */ -}; - -#define SIZEOF_EHCI_FSTN_S (8) /* 2*sizeof(uint32_t) */ - -/**************************************************************************** - * Public Data - ****************************************************************************/ - -#ifdef __cplusplus -#define EXTERN extern "C" -extern "C" -{ -#else -#define EXTERN extern -#endif - -/**************************************************************************** - * Public Function Prototypes - ****************************************************************************/ - -#undef EXTERN -#ifdef __cplusplus -} -#endif -#endif /* __INCLUDE_NUTTX_USB_EHCI_H */ +#endif /* USB_HC_EHCI_H */ diff --git a/port/musb/usb_dc_musb.c b/port/musb/usb_dc_musb.c index 2f0642c3..64f0aff5 100644 --- a/port/musb/usb_dc_musb.c +++ b/port/musb/usb_dc_musb.c @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2022, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "usbd_core.h" #include "usb_musb_reg.h" diff --git a/port/musb/usb_hc_musb.c b/port/musb/usb_hc_musb.c index 99cf5cf7..9c4d0d3f 100644 --- a/port/musb/usb_hc_musb.c +++ b/port/musb/usb_hc_musb.c @@ -1,4 +1,10 @@ +/* + * Copyright (c) 2022, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "usbh_core.h" +#include "usbh_hub.h" #include "usb_musb_reg.h" #define HWREG(x) \ @@ -8,6 +14,9 @@ #define HWREGB(x) \ (*((volatile uint8_t *)(x))) +#if CONFIG_USBHOST_PIPE_NUM != 4 +#error musb host ip only supports 4 pipe num +#endif #ifdef CONFIG_USB_MUSB_SUNXI #ifndef USB_BASE @@ -144,32 +153,28 @@ typedef enum { } ep0_state_t; struct musb_pipe { - uint8_t ep_idx; - bool enable; /* True: start transfer */ - bool in; /* True: IN endpoint */ - uint16_t mps; - uint8_t interval; /* Polling interval */ + uint8_t dev_addr; + uint8_t ep_addr; + uint8_t ep_type; + uint8_t ep_interval; uint8_t speed; - uint8_t *buffer; - volatile uint32_t buflen; - volatile uint16_t xfrd; /* Bytes transferred (at end of transfer) */ - volatile int result; /* The result of the transfer */ - volatile bool waiter; /* True: Thread is waiting for a channel event */ - usb_osal_sem_t waitsem; /* Channel wait semaphore */ -#ifdef CONFIG_USBHOST_ASYNCH - usbh_asynch_callback_t callback; /* Transfer complete callback */ - void *arg; /* Argument that accompanies the callback */ -#endif + uint16_t ep_mps; + bool inuse; + uint32_t xfrd; + volatile bool waiter; + usb_osal_sem_t waitsem; struct usbh_hubport *hport; + struct usbh_urb *urb; }; struct musb_hcd { - struct musb_pipe chan[CONIFG_USB_MUSB_PIPE_NUM][2]; /* Support Bidirectional ep */ - usb_osal_mutex_t exclsem[CONIFG_USB_MUSB_PIPE_NUM]; /* Support mutually exclusive access */ + volatile bool port_csc; + volatile bool port_pec; + volatile bool port_pe; + struct musb_pipe pipe_pool[CONFIG_USBHOST_PIPE_NUM][2]; /* Support Bidirectional ep */ } g_musb_hcd; static volatile uint8_t usb_ep0_state = USB_EP0_STATE_SETUP; -volatile uint8_t ep0_outlen = 0; /* get current active ep */ static uint8_t musb_get_active_ep(void) @@ -262,122 +267,136 @@ static void musb_read_packet(uint8_t ep_idx, uint8_t *buffer, uint16_t len) } } -static int musb_pipe_waitsetup(struct musb_pipe *chan) +void musb_control_pipe_init(struct musb_pipe *pipe, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen) { - size_t flags; - int ret = -ENODEV; + uint8_t old_ep_index; - flags = usb_osal_enter_critical_section(); + old_ep_index = musb_get_active_ep(); + musb_set_active_ep(0); - if (usbh_get_port_connect_status(0)) { - chan->waiter = true; - chan->enable = true; - chan->result = -EBUSY; - chan->xfrd = 0; -#ifdef CONFIG_USBHOST_ASYNCH - chan->callback = NULL; - chan->arg = NULL; -#endif - ret = 0; - } - usb_osal_leave_critical_section(flags); - return ret; + HWREGB(USB_TXADDR_BASE(0)) = pipe->dev_addr; + HWREGB(USB_BASE + MUSB_IND_TXTYPE_OFFSET) = pipe->speed; + HWREGB(USB_TXHUBADDR_BASE(0)) = 0; + HWREGB(USB_TXHUBPORT_BASE(0)) = 0; + + musb_write_packet(0, (uint8_t *)setup, 8); + HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_CSRL0_TXRDY | USB_CSRL0_SETUP; + musb_set_active_ep(old_ep_index); } -#ifdef CONFIG_USBHOST_ASYNCH -static int musb_pipe_asynchsetup(struct musb_pipe *chan, usbh_asynch_callback_t callback, void *arg) +void musb_bulk_pipe_init(struct musb_pipe *pipe, uint8_t *buffer, uint32_t buflen) { - size_t flags; - int ret = -ENODEV; + uint8_t ep_idx; + uint8_t old_ep_index; - flags = usb_osal_enter_critical_section(); + ep_idx = pipe->ep_addr & 0x7f; + old_ep_index = musb_get_active_ep(); + musb_set_active_ep(ep_idx); - if (usbh_get_port_connect_status(0)) { - chan->waiter = false; - chan->enable = true; - chan->result = -EBUSY; - chan->xfrd = 0; - chan->callback = callback; - chan->arg = arg; - ret = 0; - } + if (pipe->ep_addr & 0x80) { + HWREGB(USB_RXADDR_BASE(ep_idx)) = pipe->dev_addr; + HWREGB(USB_BASE + MUSB_IND_RXTYPE_OFFSET) = ep_idx | pipe->speed | USB_TXTYPE1_PROTO_BULK; + HWREGB(USB_BASE + MUSB_IND_RXINTERVAL_OFFSET) = 0; + HWREGB(USB_RXHUBADDR_BASE(ep_idx)) = 0; + HWREGB(USB_RXHUBPORT_BASE(ep_idx)) = 0; + HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) &= ~USB_TXCSRH1_MODE; + HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) = USB_RXCSRL1_REQPKT; + } else { + HWREGB(USB_TXADDR_BASE(ep_idx)) = pipe->dev_addr; + HWREGB(USB_BASE + MUSB_IND_TXTYPE_OFFSET) = ep_idx | pipe->speed | USB_TXTYPE1_PROTO_BULK; + HWREGB(USB_BASE + MUSB_IND_TXINTERVAL_OFFSET) = 0; + HWREGB(USB_TXHUBADDR_BASE(ep_idx)) = 0; + HWREGB(USB_TXHUBPORT_BASE(ep_idx)) = 0; - usb_osal_leave_critical_section(flags); - return ret; -} -#endif - -static int musb_pipe_wait(struct musb_pipe *chan, uint32_t timeout) -{ - int ret; - - /* wait until timeout or sem give */ - if (chan->waiter) { - ret = usb_osal_sem_take(chan->waitsem, timeout); - if (ret < 0) { - return ret; - } - } - - /* Sem give, check if giving from error isr */ - ret = chan->result; - - if (ret < 0) { - return ret; - } - - return chan->xfrd; -} - -static void musb_pipe_wakeup(struct musb_pipe *chan) -{ - usbh_asynch_callback_t callback; - void *arg; - int nbytes; - - chan->enable = false; - if (chan->waiter) { - chan->waiter = false; - usb_osal_sem_give(chan->waitsem); - } -#ifdef CONFIG_USBHOST_ASYNCH - else if (chan->callback) { - callback = chan->callback; - arg = chan->arg; - nbytes = chan->xfrd; - chan->callback = NULL; - chan->arg = NULL; - if (chan->result < 0) { - nbytes = chan->result; + if (buflen > pipe->ep_mps) { + buflen = pipe->ep_mps; } - callback(arg, nbytes); + musb_write_packet(ep_idx, buffer, buflen); + HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) &= ~USB_TXCSRH1_MODE; + HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) |= USB_TXCSRH1_MODE; + HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_TXCSRL1_TXRDY; } -#endif + musb_set_active_ep(old_ep_index); +} + +void musb_intr_pipe_init(struct musb_pipe *pipe, uint8_t *buffer, uint32_t buflen) +{ + uint8_t ep_idx; + uint8_t old_ep_index; + + ep_idx = pipe->ep_addr & 0x7f; + old_ep_index = musb_get_active_ep(); + musb_set_active_ep(ep_idx); + + if (pipe->ep_addr & 0x80) { + HWREGB(USB_RXADDR_BASE(ep_idx)) = pipe->dev_addr; + HWREGB(USB_BASE + MUSB_IND_RXTYPE_OFFSET) = ep_idx | pipe->speed | USB_TXTYPE1_PROTO_INT; + HWREGB(USB_BASE + MUSB_IND_RXINTERVAL_OFFSET) = pipe->ep_interval; + HWREGB(USB_RXHUBADDR_BASE(ep_idx)) = 0; + HWREGB(USB_RXHUBPORT_BASE(ep_idx)) = 0; + HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) &= ~USB_TXCSRH1_MODE; + HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) = USB_RXCSRL1_REQPKT; + } else { + HWREGB(USB_TXADDR_BASE(ep_idx)) = pipe->dev_addr; + HWREGB(USB_BASE + MUSB_IND_TXTYPE_OFFSET) = ep_idx | pipe->speed | USB_TXTYPE1_PROTO_INT; + HWREGB(USB_BASE + MUSB_IND_TXINTERVAL_OFFSET) = pipe->ep_interval; + HWREGB(USB_TXHUBADDR_BASE(ep_idx)) = 0; + HWREGB(USB_TXHUBPORT_BASE(ep_idx)) = 0; + + if (buflen > pipe->ep_mps) { + buflen = pipe->ep_mps; + } + + musb_write_packet(ep_idx, buffer, buflen); + HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) &= ~USB_TXCSRH1_MODE; + HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) |= USB_TXCSRH1_MODE; + HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_TXCSRL1_TXRDY; + } + musb_set_active_ep(old_ep_index); +} + +static int usbh_reset_port(const uint8_t port) +{ + g_musb_hcd.port_pe = 0; + HWREGB(USB_BASE + MUSB_POWER_OFFSET) |= USB_POWER_RESET; + usb_osal_msleep(20); + HWREGB(USB_BASE + MUSB_POWER_OFFSET) &= ~(USB_POWER_RESET); + usb_osal_msleep(20); + g_musb_hcd.port_pe = 1; + return 0; +} + +static uint8_t usbh_get_port_speed(const uint8_t port) +{ + uint8_t speed; + + if (HWREGB(USB_BASE + MUSB_POWER_OFFSET) & USB_POWER_HSMODE) + speed = USB_SPEED_HIGH; + else if (HWREGB(USB_BASE + MUSB_DEVCTL_OFFSET) & USB_DEVCTL_FSDEV) + speed = USB_SPEED_FULL; + else if (HWREGB(USB_BASE + MUSB_DEVCTL_OFFSET) & USB_DEVCTL_LSDEV) + speed = USB_SPEED_LOW; + + return speed; } __WEAK void usb_hc_low_level_init(void) { } -int usb_hc_sw_init(void) -{ - memset(&g_musb_hcd, 0, sizeof(struct musb_hcd)); - - for (uint8_t i = 0; i < CONIFG_USB_MUSB_PIPE_NUM; i++) { - g_musb_hcd.exclsem[i] = usb_osal_mutex_create(); - g_musb_hcd.chan[i][0].waitsem = usb_osal_sem_create(0); - g_musb_hcd.chan[i][1].waitsem = usb_osal_sem_create(0); - } - - return 0; -} - -int usb_hc_hw_init(void) +int usb_hc_init(void) { uint8_t regval; uint32_t fifo_offset = 0; + memset(&g_musb_hcd, 0, sizeof(struct musb_hcd)); + + for (uint8_t i = 0; i < CONFIG_USBHOST_PIPE_NUM; i++) { + g_musb_hcd.pipe_pool[i][0].waitsem = usb_osal_sem_create(0); + g_musb_hcd.pipe_pool[i][1].waitsem = usb_osal_sem_create(0); + } + usb_hc_low_level_init(); musb_set_active_ep(0); @@ -417,634 +436,411 @@ int usb_hc_hw_init(void) return 0; } -bool usbh_get_port_connect_status(const uint8_t port) +int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf) { - if (HWREGB(USB_BASE + MUSB_DEVCTL_OFFSET) & USB_DEVCTL_FSDEV) - return true; - if (HWREGB(USB_BASE + MUSB_DEVCTL_OFFSET) & USB_DEVCTL_LSDEV) - return true; + __IO uint32_t hprt0; + uint8_t nports; + uint8_t port; + uint32_t status; - return false; -} + nports = CONFIG_USBHOST_RHPORTS; + port = setup->wIndex; + if (setup->bmRequestType & USB_REQUEST_RECIPIENT_DEVICE) { + switch (setup->bRequest) { + case HUB_REQUEST_CLEAR_FEATURE: + switch (setup->wValue) { + case HUB_FEATURE_HUB_C_LOCALPOWER: + break; + case HUB_FEATURE_HUB_C_OVERCURRENT: + break; + default: + return -EPIPE; + } + break; + case HUB_REQUEST_SET_FEATURE: + switch (setup->wValue) { + case HUB_FEATURE_HUB_C_LOCALPOWER: + break; + case HUB_FEATURE_HUB_C_OVERCURRENT: + break; + default: + return -EPIPE; + } + break; + case HUB_REQUEST_GET_DESCRIPTOR: + break; + case HUB_REQUEST_GET_STATUS: + memset(buf, 0, 4); + break; + default: + break; + } + } else if (setup->bmRequestType & USB_REQUEST_RECIPIENT_OTHER) { + switch (setup->bRequest) { + case HUB_REQUEST_CLEAR_FEATURE: + if (!port || port > nports) { + return -EPIPE; + } -int usbh_reset_port(const uint8_t port) -{ - HWREGB(USB_BASE + MUSB_POWER_OFFSET) |= USB_POWER_RESET; - usb_osal_msleep(20); - HWREGB(USB_BASE + MUSB_POWER_OFFSET) &= ~(USB_POWER_RESET); - usb_osal_msleep(20); + switch (setup->wValue) { + case HUB_PORT_FEATURE_ENABLE: + break; + case HUB_PORT_FEATURE_SUSPEND: + case HUB_PORT_FEATURE_C_SUSPEND: + break; + case HUB_PORT_FEATURE_POWER: + break; + case HUB_PORT_FEATURE_C_CONNECTION: + g_musb_hcd.port_csc = 0; + break; + case HUB_PORT_FEATURE_C_ENABLE: + g_musb_hcd.port_pec = 0; + break; + case HUB_PORT_FEATURE_C_OVER_CURREN: + break; + case HUB_PORT_FEATURE_C_RESET: + break; + default: + return -EPIPE; + } + break; + case HUB_REQUEST_SET_FEATURE: + if (!port || port > nports) { + return -EPIPE; + } + + switch (setup->wValue) { + case HUB_PORT_FEATURE_SUSPEND: + break; + case HUB_PORT_FEATURE_POWER: + break; + case HUB_PORT_FEATURE_RESET: + usbh_reset_port(port); + break; + + default: + return -EPIPE; + } + break; + case HUB_REQUEST_GET_STATUS: + if (!port || port > nports) { + return -EPIPE; + } + + status = 0; + if (g_musb_hcd.port_csc) { + status |= (1 << HUB_PORT_FEATURE_C_CONNECTION); + } + if (g_musb_hcd.port_pec) { + status |= (1 << HUB_PORT_FEATURE_C_ENABLE); + } + + if (g_musb_hcd.port_pe) { + status |= (1 << HUB_PORT_FEATURE_CONNECTION); + status |= (1 << HUB_PORT_FEATURE_ENABLE); + if (usbh_get_port_speed(port) == USB_SPEED_LOW) { + status |= (1 << HUB_PORT_FEATURE_LOWSPEED); + } else if (usbh_get_port_speed(port) == USB_SPEED_HIGH) { + status |= (1 << HUB_PORT_FEATURE_HIGHSPEED); + } + } + + memcpy(buf, &status, 4); + break; + default: + break; + } + } return 0; } -uint8_t usbh_get_port_speed(const uint8_t port) +int usbh_ep0_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t speed) { - uint8_t speed; + struct musb_pipe *ppipe = (struct musb_pipe *)pipe; - if (HWREGB(USB_BASE + MUSB_POWER_OFFSET) & USB_POWER_HSMODE) - speed = USB_SPEED_HIGH; - else if (HWREGB(USB_BASE + MUSB_DEVCTL_OFFSET) & USB_DEVCTL_FSDEV) - speed = USB_SPEED_FULL; - else if (HWREGB(USB_BASE + MUSB_DEVCTL_OFFSET) & USB_DEVCTL_LSDEV) - speed = USB_SPEED_LOW; - - return speed; -} - -int usbh_ep0_reconfigure(usbh_epinfo_t ep, uint8_t dev_addr, uint8_t ep_mps, uint8_t speed) -{ - int ret; - struct musb_pipe *chan = (struct musb_pipe *)ep; - - ret = usb_osal_mutex_take(g_musb_hcd.exclsem[0]); - if (ret < 0) { - return ret; - } - - chan->mps = ep_mps; - chan->hport->dev_addr = dev_addr; + ppipe->dev_addr = dev_addr; + ppipe->ep_mps = ep_mps; if (speed == USB_SPEED_HIGH) { - chan->speed = USB_TYPE0_SPEED_HIGH; + ppipe->speed = USB_TYPE0_SPEED_HIGH; } else if (speed == USB_SPEED_FULL) { - chan->speed = USB_TYPE0_SPEED_FULL; + ppipe->speed = USB_TYPE0_SPEED_FULL; } else if (speed == USB_SPEED_LOW) { - chan->speed = USB_TYPE0_SPEED_LOW; + ppipe->speed = USB_TYPE0_SPEED_LOW; } - usb_osal_mutex_give(g_musb_hcd.exclsem[0]); - return ret; + return 0; } -int usbh_ep_alloc(usbh_epinfo_t *ep, const struct usbh_endpoint_cfg *ep_cfg) +int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg) { - struct usbh_hubport *hport; - struct musb_pipe *chan; - uint8_t ep_idx = 0; + struct musb_pipe *ppipe; uint8_t old_ep_index; - - hport = ep_cfg->hport; + uint8_t ep_idx; + usb_osal_sem_t waitsem; ep_idx = ep_cfg->ep_addr & 0x7f; if (ep_idx > CONIFG_USB_MUSB_PIPE_NUM) { - return -1; + return -ENOMEM; } old_ep_index = musb_get_active_ep(); musb_set_active_ep(ep_idx); if (ep_cfg->ep_addr & 0x80) { - chan = &g_musb_hcd.chan[ep_idx][1]; - chan->in = true; + ppipe = &g_musb_hcd.pipe_pool[ep_idx][1]; } else { - chan = &g_musb_hcd.chan[ep_idx][0]; - chan->in = false; + ppipe = &g_musb_hcd.pipe_pool[ep_idx][0]; } - chan->enable = false; - chan->ep_idx = ep_idx; + /* store variables */ + waitsem = ppipe->waitsem; + + memset(ppipe, 0, sizeof(struct musb_pipe)); + + ppipe->ep_addr = ep_cfg->ep_addr; + ppipe->ep_type = ep_cfg->ep_type; + ppipe->ep_mps = ep_cfg->ep_mps; + ppipe->ep_interval = ep_cfg->ep_interval; + ppipe->speed = ep_cfg->hport->speed; + ppipe->dev_addr = ep_cfg->hport->dev_addr; + ppipe->hport = ep_cfg->hport; if (ep_cfg->ep_type == USB_ENDPOINT_TYPE_CONTROL) { - chan->interval = 0; - chan->mps = ep_cfg->ep_mps; - chan->hport = hport; - - *ep = (usbh_epinfo_t)chan; } else { - chan->interval = ep_cfg->ep_interval; - chan->mps = ep_cfg->ep_mps; - - if (hport->speed == USB_SPEED_HIGH) { - chan->speed = USB_TXTYPE1_SPEED_HIGH; - } else if (hport->speed == USB_SPEED_FULL) { - chan->speed = USB_TXTYPE1_SPEED_FULL; - } else if (hport->speed == USB_SPEED_LOW) { - chan->speed = USB_TXTYPE1_SPEED_LOW; + if (ppipe->speed == USB_SPEED_HIGH) { + ppipe->speed = USB_TXTYPE1_SPEED_HIGH; + } else if (ppipe->speed == USB_SPEED_FULL) { + ppipe->speed = USB_TXTYPE1_SPEED_FULL; + } else if (ppipe->speed == USB_SPEED_LOW) { + ppipe->speed = USB_TXTYPE1_SPEED_LOW; } - chan->hport = hport; - - if (chan->in) { + if (ppipe->ep_addr & 0x80) { HWREGH(USB_BASE + MUSB_RXIE_OFFSET) |= (1 << ep_idx); } else { HWREGH(USB_BASE + MUSB_TXIE_OFFSET) |= (1 << ep_idx); } - - *ep = (usbh_epinfo_t)chan; } + /* restore variable */ + ppipe->inuse = true; + ppipe->waitsem = waitsem; musb_set_active_ep(old_ep_index); + *pipe = (usbh_pipe_t)ppipe; return 0; } -int usbh_ep_free(usbh_epinfo_t ep) +int usbh_pipe_free(usbh_pipe_t pipe) { - //struct musb_pipe *chan = (struct musb_pipe *)ep; return 0; } -int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint8_t *buffer) -{ - int ret; - uint32_t old_ep_index; - struct musb_pipe *chan = (struct musb_pipe *)ep; - - ret = usb_osal_mutex_take(g_musb_hcd.exclsem[0]); - if (ret < 0) { - return ret; - } - - ret = musb_pipe_waitsetup(chan); - if (ret < 0) { - goto errout_with_mutex; - } - - old_ep_index = musb_get_active_ep(); - musb_set_active_ep(0); - - HWREGB(USB_TXADDR_BASE(0)) = chan->hport->dev_addr; - HWREGB(USB_BASE + MUSB_IND_TXTYPE_OFFSET) = chan->speed; - if (chan->hport->parent == NULL) { - HWREGB(USB_TXHUBADDR_BASE(0)) = 0; - HWREGB(USB_TXHUBPORT_BASE(0)) = 0; - } else { - HWREGB(USB_TXHUBADDR_BASE(0)) = chan->hport->parent->dev_addr; - HWREGB(USB_TXHUBPORT_BASE(0)) = chan->hport->parent->index - 1; - } - - musb_write_packet(0, (uint8_t *)setup, 8); - ep0_outlen = 8; - if (setup->wLength && buffer) { - if (setup->bmRequestType & 0x80) { - usb_ep0_state = USB_EP0_STATE_IN_DATA; - } else { - usb_ep0_state = USB_EP0_STATE_OUT_DATA; - } - chan->buffer = buffer; - chan->buflen = setup->wLength; - } else { - usb_ep0_state = USB_EP0_STATE_IN_STATUS; - } - - HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_CSRL0_TXRDY | USB_CSRL0_SETUP; - musb_set_active_ep(old_ep_index); - - ret = musb_pipe_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); - if (ret < 0) { - goto errout_with_mutex; - } - - usb_osal_mutex_give(g_musb_hcd.exclsem[0]); - return ret; -errout_with_mutex: - chan->waiter = false; - chan->enable = false; - usb_osal_mutex_give(g_musb_hcd.exclsem[0]); - return ret; -} - -int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, uint32_t timeout) -{ - int ret; - uint32_t old_ep_index; - struct musb_pipe *chan = (struct musb_pipe *)ep; - - ret = usb_osal_mutex_take(g_musb_hcd.exclsem[chan->ep_idx]); - if (ret < 0) { - return ret; - } - - ret = musb_pipe_waitsetup(chan); - if (ret < 0) { - goto errout_with_mutex; - } - - old_ep_index = musb_get_active_ep(); - musb_set_active_ep(chan->ep_idx); - - if (chan->in) { - HWREGB(USB_RXADDR_BASE(chan->ep_idx)) = chan->hport->dev_addr; - HWREGB(USB_BASE + MUSB_IND_RXTYPE_OFFSET) = chan->ep_idx | chan->speed | USB_TXTYPE1_PROTO_BULK; - HWREGB(USB_BASE + MUSB_IND_RXINTERVAL_OFFSET) = chan->interval; - if (chan->hport->parent == NULL) { - HWREGB(USB_RXHUBADDR_BASE(chan->ep_idx)) = 0; - HWREGB(USB_RXHUBPORT_BASE(chan->ep_idx)) = 0; - } else { - HWREGB(USB_RXHUBADDR_BASE(chan->ep_idx)) = chan->hport->parent->dev_addr; - HWREGB(USB_RXHUBPORT_BASE(chan->ep_idx)) = chan->hport->parent->index - 1; - } - - chan->buffer = buffer; - chan->buflen = buflen; - HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) &= ~USB_TXCSRH1_MODE; - HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) = USB_RXCSRL1_REQPKT; - } else { - HWREGB(USB_TXADDR_BASE(chan->ep_idx)) = chan->hport->dev_addr; - HWREGB(USB_BASE + MUSB_IND_TXTYPE_OFFSET) = chan->ep_idx | chan->speed | USB_TXTYPE1_PROTO_BULK; - HWREGB(USB_BASE + MUSB_IND_TXINTERVAL_OFFSET) = chan->interval; - if (chan->hport->parent == NULL) { - HWREGB(USB_TXHUBADDR_BASE(chan->ep_idx)) = 0; - HWREGB(USB_TXHUBPORT_BASE(chan->ep_idx)) = 0; - } else { - HWREGB(USB_TXHUBADDR_BASE(chan->ep_idx)) = chan->hport->parent->dev_addr; - HWREGB(USB_TXHUBPORT_BASE(chan->ep_idx)) = chan->hport->parent->index - 1; - } - - chan->buffer = buffer; - chan->buflen = buflen; - if (buflen > chan->mps) { - buflen = chan->mps; - } - - musb_write_packet(chan->ep_idx, chan->buffer, buflen); - HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) &= ~USB_TXCSRH1_MODE; - HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) |= USB_TXCSRH1_MODE; - HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_TXCSRL1_TXRDY; - } - musb_set_active_ep(old_ep_index); - - ret = musb_pipe_wait(chan, timeout); - if (ret < 0) { - goto errout_with_mutex; - } - - usb_osal_mutex_give(g_musb_hcd.exclsem[chan->ep_idx]); - return ret; -errout_with_mutex: - chan->waiter = false; - chan->enable = false; - usb_osal_mutex_give(g_musb_hcd.exclsem[chan->ep_idx]); - return ret; -} - -int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, uint32_t timeout) -{ - int ret; - uint32_t old_ep_index; - struct musb_pipe *chan = (struct musb_pipe *)ep; - - ret = usb_osal_mutex_take(g_musb_hcd.exclsem[chan->ep_idx]); - if (ret < 0) { - return ret; - } - - ret = musb_pipe_waitsetup(chan); - if (ret < 0) { - goto errout_with_mutex; - } - - old_ep_index = musb_get_active_ep(); - musb_set_active_ep(chan->ep_idx); - - if (chan->in) { - HWREGB(USB_RXADDR_BASE(chan->ep_idx)) = chan->hport->dev_addr; - HWREGB(USB_BASE + MUSB_IND_RXTYPE_OFFSET) = chan->ep_idx | chan->speed | USB_TXTYPE1_PROTO_INT; - HWREGB(USB_BASE + MUSB_IND_RXINTERVAL_OFFSET) = chan->interval; - if (chan->hport->parent == NULL) { - HWREGB(USB_RXHUBADDR_BASE(chan->ep_idx)) = 0; - HWREGB(USB_RXHUBPORT_BASE(chan->ep_idx)) = 0; - } else { - HWREGB(USB_RXHUBADDR_BASE(chan->ep_idx)) = chan->hport->parent->dev_addr; - HWREGB(USB_RXHUBPORT_BASE(chan->ep_idx)) = chan->hport->parent->index - 1; - } - - chan->buffer = buffer; - chan->buflen = buflen; - HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) &= ~USB_TXCSRH1_MODE; - HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) = USB_RXCSRL1_REQPKT; - } else { - HWREGB(USB_TXADDR_BASE(chan->ep_idx)) = chan->hport->dev_addr; - HWREGB(USB_BASE + MUSB_IND_TXTYPE_OFFSET) = chan->ep_idx | chan->speed | USB_TXTYPE1_PROTO_INT; - HWREGB(USB_BASE + MUSB_IND_TXINTERVAL_OFFSET) = chan->interval; - if (chan->hport->parent == NULL) { - HWREGB(USB_TXHUBADDR_BASE(chan->ep_idx)) = 0; - HWREGB(USB_TXHUBPORT_BASE(chan->ep_idx)) = 0; - } else { - HWREGB(USB_TXHUBADDR_BASE(chan->ep_idx)) = chan->hport->parent->dev_addr; - HWREGB(USB_TXHUBPORT_BASE(chan->ep_idx)) = chan->hport->parent->index - 1; - } - - chan->buffer = buffer; - chan->buflen = buflen; - if (buflen > chan->mps) { - buflen = chan->mps; - } - - musb_write_packet(chan->ep_idx, chan->buffer, buflen); - HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) &= ~USB_TXCSRH1_MODE; - HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) |= USB_TXCSRH1_MODE; - HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_TXCSRL1_TXRDY; - } - musb_set_active_ep(old_ep_index); - - ret = musb_pipe_wait(chan, timeout); - if (ret < 0) { - goto errout_with_mutex; - } - - usb_osal_mutex_give(g_musb_hcd.exclsem[chan->ep_idx]); - return ret; -errout_with_mutex: - chan->waiter = false; - chan->enable = false; - usb_osal_mutex_give(g_musb_hcd.exclsem[chan->ep_idx]); - return ret; -} - -int usbh_ep_bulk_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, usbh_asynch_callback_t callback, void *arg) -{ - int ret; - uint32_t old_ep_index; - struct musb_pipe *chan = (struct musb_pipe *)ep; - - if (chan->enable) { - return -EINVAL; - } - - ret = usb_osal_mutex_take(g_musb_hcd.exclsem[chan->ep_idx]); - if (ret < 0) { - return ret; - } - - ret = musb_pipe_asynchsetup(chan, callback, arg); - if (ret < 0) { - goto errout_with_mutex; - } - - old_ep_index = musb_get_active_ep(); - musb_set_active_ep(chan->ep_idx); - - if (chan->in) { - HWREGB(USB_RXADDR_BASE(chan->ep_idx)) = chan->hport->dev_addr; - HWREGB(USB_BASE + MUSB_IND_RXTYPE_OFFSET) = chan->ep_idx | chan->speed | USB_TXTYPE1_PROTO_BULK; - HWREGB(USB_BASE + MUSB_IND_RXINTERVAL_OFFSET) = chan->interval; - if (chan->hport->parent == NULL) { - HWREGB(USB_RXHUBADDR_BASE(chan->ep_idx)) = 0; - HWREGB(USB_RXHUBPORT_BASE(chan->ep_idx)) = 0; - } else { - HWREGB(USB_RXHUBADDR_BASE(chan->ep_idx)) = chan->hport->parent->dev_addr; - HWREGB(USB_RXHUBPORT_BASE(chan->ep_idx)) = chan->hport->parent->index - 1; - } - - chan->buffer = buffer; - chan->buflen = buflen; - HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) &= ~USB_TXCSRH1_MODE; - HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) = USB_RXCSRL1_REQPKT; - } else { - HWREGB(USB_TXADDR_BASE(chan->ep_idx)) = chan->hport->dev_addr; - HWREGB(USB_BASE + MUSB_IND_TXTYPE_OFFSET) = chan->ep_idx | chan->speed | USB_TXTYPE1_PROTO_BULK; - HWREGB(USB_BASE + MUSB_IND_TXINTERVAL_OFFSET) = chan->interval; - if (chan->hport->parent == NULL) { - HWREGB(USB_TXHUBADDR_BASE(chan->ep_idx)) = 0; - HWREGB(USB_TXHUBPORT_BASE(chan->ep_idx)) = 0; - } else { - HWREGB(USB_TXHUBADDR_BASE(chan->ep_idx)) = chan->hport->parent->dev_addr; - HWREGB(USB_TXHUBPORT_BASE(chan->ep_idx)) = chan->hport->parent->index - 1; - } - - chan->buffer = buffer; - chan->buflen = buflen; - if (buflen > chan->mps) { - buflen = chan->mps; - } - - musb_write_packet(chan->ep_idx, chan->buffer, buflen); - HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) &= ~USB_TXCSRH1_MODE; - HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) |= USB_TXCSRH1_MODE; - HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_TXCSRL1_TXRDY; - } - musb_set_active_ep(old_ep_index); - - usb_osal_mutex_give(g_musb_hcd.exclsem[chan->ep_idx]); - return ret; -errout_with_mutex: - chan->enable = false; - usb_osal_mutex_give(g_musb_hcd.exclsem[chan->ep_idx]); - return ret; -} - -int usbh_ep_intr_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, usbh_asynch_callback_t callback, void *arg) -{ - int ret; - uint32_t old_ep_index; - struct musb_pipe *chan = (struct musb_pipe *)ep; - - if (chan->enable) { - return -EINVAL; - } - - ret = usb_osal_mutex_take(g_musb_hcd.exclsem[chan->ep_idx]); - if (ret < 0) { - return ret; - } - - ret = musb_pipe_asynchsetup(chan, callback, arg); - if (ret < 0) { - goto errout_with_mutex; - } - - old_ep_index = musb_get_active_ep(); - musb_set_active_ep(chan->ep_idx); - - if (chan->in) { - HWREGB(USB_RXADDR_BASE(chan->ep_idx)) = chan->hport->dev_addr; - HWREGB(USB_BASE + MUSB_IND_RXTYPE_OFFSET) = chan->ep_idx | chan->speed | USB_TXTYPE1_PROTO_INT; - HWREGB(USB_BASE + MUSB_IND_RXINTERVAL_OFFSET) = chan->interval; - if (chan->hport->parent == NULL) { - HWREGB(USB_RXHUBADDR_BASE(chan->ep_idx)) = 0; - HWREGB(USB_RXHUBPORT_BASE(chan->ep_idx)) = 0; - } else { - HWREGB(USB_RXHUBADDR_BASE(chan->ep_idx)) = chan->hport->parent->dev_addr; - HWREGB(USB_RXHUBPORT_BASE(chan->ep_idx)) = chan->hport->parent->index - 1; - } - - chan->buffer = buffer; - chan->buflen = buflen; - HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) &= ~USB_TXCSRH1_MODE; - HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) = USB_RXCSRL1_REQPKT; - } else { - HWREGB(USB_TXADDR_BASE(chan->ep_idx)) = chan->hport->dev_addr; - HWREGB(USB_BASE + MUSB_IND_TXTYPE_OFFSET) = chan->ep_idx | chan->speed | USB_TXTYPE1_PROTO_INT; - HWREGB(USB_BASE + MUSB_IND_TXINTERVAL_OFFSET) = chan->interval; - if (chan->hport->parent == NULL) { - HWREGB(USB_TXHUBADDR_BASE(chan->ep_idx)) = 0; - HWREGB(USB_TXHUBPORT_BASE(chan->ep_idx)) = 0; - } else { - HWREGB(USB_TXHUBADDR_BASE(chan->ep_idx)) = chan->hport->parent->dev_addr; - HWREGB(USB_TXHUBPORT_BASE(chan->ep_idx)) = chan->hport->parent->index - 1; - } - - chan->buffer = buffer; - chan->buflen = buflen; - if (buflen > chan->mps) { - buflen = chan->mps; - } - - musb_write_packet(chan->ep_idx, chan->buffer, buflen); - HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) &= ~USB_TXCSRH1_MODE; - HWREGB(USB_BASE + MUSB_IND_TXCSRH_OFFSET) |= USB_TXCSRH1_MODE; - HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_TXCSRL1_TXRDY; - } - musb_set_active_ep(old_ep_index); - - usb_osal_mutex_give(g_musb_hcd.exclsem[chan->ep_idx]); - return ret; -errout_with_mutex: - chan->enable = false; - usb_osal_mutex_give(g_musb_hcd.exclsem[chan->ep_idx]); - return ret; -} - -int usb_ep_cancel(usbh_epinfo_t ep) +int usbh_submit_urb(struct usbh_urb *urb) { + struct musb_pipe *pipe; size_t flags; - struct musb_pipe *chan = (struct musb_pipe *)ep; -#ifdef CONFIG_USBHOST_ASYNCH - usbh_asynch_callback_t callback; - void *arg; -#endif + int ret = 0; + + pipe = urb->pipe; + + if (!urb || !pipe) { + return -EINVAL; + } flags = usb_osal_enter_critical_section(); - chan->result = -ESHUTDOWN; -#ifdef CONFIG_USBHOST_ASYNCH - /* Extract the callback information */ - callback = chan->callback; - arg = chan->arg; - chan->callback = NULL; - chan->arg = NULL; - chan->xfrd = 0; -#endif + if (!pipe->hport->connected) { + return -ENODEV; + } - chan->enable = false; + if (pipe->urb) { + return -EBUSY; + } + + pipe->waiter = false; + pipe->xfrd = 0; + pipe->urb = urb; + urb->errorcode = -EBUSY; + urb->actual_length = 0; + + if (urb->timeout > 0) { + pipe->waiter = true; + } usb_osal_leave_critical_section(flags); - /* Check if there is a thread waiting for this transfer to complete? */ - if (chan->waiter) { - chan->waiter = false; - usb_osal_sem_give(chan->waitsem); + switch (pipe->ep_type) { + case USB_ENDPOINT_TYPE_CONTROL: + usb_ep0_state = USB_EP0_STATE_SETUP; + musb_control_pipe_init(pipe, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length); + break; + case USB_ENDPOINT_TYPE_BULK: + musb_bulk_pipe_init(pipe, urb->transfer_buffer, urb->transfer_buffer_length); + break; + case USB_ENDPOINT_TYPE_INTERRUPT: + musb_intr_pipe_init(pipe, urb->transfer_buffer, urb->transfer_buffer_length); + break; + case USB_ENDPOINT_TYPE_ISOCHRONOUS: + break; + default: + break; } -#ifdef CONFIG_USBHOST_ASYNCH - /* No.. is an asynchronous callback expected when the transfer completes? */ - else if (callback) { - callback(arg, -ESHUTDOWN); + if (urb->timeout > 0) { + /* wait until timeout or sem give */ + ret = usb_osal_sem_take(pipe->waitsem, urb->timeout); + if (ret < 0) { + goto errout_timeout; + } + + ret = urb->errorcode; } -#endif + return ret; +errout_timeout: + pipe->waiter = false; + usbh_kill_urb(urb); + return ret; + return -1; +} + +int usbh_kill_urb(struct usbh_urb *urb) +{ return 0; } +static inline void musb_pipe_waitup(struct musb_pipe *pipe) +{ + struct usbh_urb *urb; + + urb = pipe->urb; + pipe->urb = NULL; + + if (pipe->waiter) { + pipe->waiter = false; + usb_osal_sem_give(pipe->waitsem); + } + + if (urb->complete) { + if (urb->errorcode < 0) { + urb->complete(urb->arg, urb->errorcode); + } else { + urb->complete(urb->arg, urb->actual_length); + } + } +} + void handle_ep0(void) { uint8_t ep0_status; - struct musb_pipe *chan; - int result = 0; + struct musb_pipe *pipe; + struct usbh_urb *urb; + uint32_t size; - chan = (struct musb_pipe *)&g_musb_hcd.chan[0][0]; + pipe = (struct musb_pipe *)&g_musb_hcd.pipe_pool[0][0]; + urb = pipe->urb; musb_set_active_ep(0); ep0_status = HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET); - if (ep0_status & USB_CSRL0_STALLED) { HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_CSRL0_STALLED; usb_ep0_state = USB_EP0_STATE_SETUP; - result = -EPERM; - goto chan_wait; + urb->errorcode = -EPERM; + musb_pipe_waitup(pipe); + return; } - if (ep0_status & USB_CSRL0_ERROR) { HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_CSRL0_ERROR; musb_fifo_flush(0); usb_ep0_state = USB_EP0_STATE_SETUP; - result = -EIO; - goto chan_wait; + urb->errorcode = -EIO; + musb_pipe_waitup(pipe); + return; } - if (ep0_status & USB_CSRL0_STALL) { HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_CSRL0_STALL; usb_ep0_state = USB_EP0_STATE_SETUP; - result = -EPERM; - goto chan_wait; + urb->errorcode = -EPERM; + musb_pipe_waitup(pipe); + return; } switch (usb_ep0_state) { case USB_EP0_STATE_SETUP: + urb->actual_length += 8; + if (urb->transfer_buffer_length) { + if (urb->setup->bmRequestType & 0x80) { + usb_ep0_state = USB_EP0_STATE_IN_DATA; + HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_CSRL0_REQPKT; + } else { + usb_ep0_state = USB_EP0_STATE_OUT_DATA; + size = urb->transfer_buffer_length; + if (size > pipe->ep_mps) { + size = pipe->ep_mps; + } + + musb_write_packet(0, urb->transfer_buffer, size); + HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_CSRL0_TXRDY; + + urb->transfer_buffer += size; + urb->transfer_buffer_length -= size; + urb->actual_length += size; + } + } else { + usb_ep0_state = USB_EP0_STATE_IN_STATUS; + HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = (USB_CSRL0_REQPKT | USB_CSRL0_STATUS); + } break; case USB_EP0_STATE_IN_DATA: - HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_RXCSRL1_REQPKT; - usb_ep0_state = USB_EP0_STATE_IN_DATA_C; - chan->xfrd += 8; - break; - case USB_EP0_STATE_IN_DATA_C: if (ep0_status & USB_CSRL0_RXRDY) { - uint32_t size = chan->buflen; - if (size > chan->mps) { - size = chan->mps; + size = urb->transfer_buffer_length; + if (size > pipe->ep_mps) { + size = pipe->ep_mps; } size = MIN(size, HWREGH(USB_BASE + MUSB_IND_RXCOUNT_OFFSET)); - - musb_read_packet(0, chan->buffer, size); - + musb_read_packet(0, urb->transfer_buffer, size); HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_CSRL0_RXRDY; + urb->transfer_buffer += size; + urb->transfer_buffer_length -= size; + urb->actual_length += size; - chan->buffer += size; - chan->buflen -= size; - chan->xfrd += size; - if ((size < chan->mps) || (chan->buflen == 0)) { + if ((size < pipe->ep_mps) || (urb->transfer_buffer_length == 0)) { usb_ep0_state = USB_EP0_STATE_OUT_STATUS; HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = (USB_CSRL0_TXRDY | USB_CSRL0_STATUS); } else { - HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_RXCSRL1_REQPKT; + HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_CSRL0_REQPKT; } } break; - case USB_EP0_STATE_OUT_STATUS: - usb_ep0_state = USB_EP0_STATE_SETUP; - result = 0; - goto chan_wait; - case USB_EP0_STATE_IN_STATUS_C: - if (ep0_status & (USB_CSRL0_RXRDY | USB_CSRL0_STATUS)) { - HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~(USB_CSRL0_RXRDY | USB_CSRL0_STATUS); - } + case USB_EP0_STATE_OUT_DATA: + if (urb->transfer_buffer_length > 0) { + size = urb->transfer_buffer_length; + if (size > pipe->ep_mps) { + size = pipe->ep_mps; + } - usb_ep0_state = USB_EP0_STATE_SETUP; - result = 0; - goto chan_wait; + musb_write_packet(0, urb->transfer_buffer, size); + HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_CSRL0_TXRDY; - break; - case USB_EP0_STATE_IN_STATUS: - HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = (USB_CSRL0_REQPKT | USB_CSRL0_STATUS); - usb_ep0_state = USB_EP0_STATE_IN_STATUS_C; - chan->xfrd += 8; - break; - - case USB_EP0_STATE_OUT_DATA: { - uint32_t size = chan->buflen; - if (size > chan->mps) { - size = chan->mps; - } - - chan->xfrd += ep0_outlen; - - musb_write_packet(0, chan->buffer, size); - - chan->buffer += size; - chan->buflen -= size; - ep0_outlen = size; - if (size == chan->mps) { + urb->transfer_buffer += size; + urb->transfer_buffer_length -= size; + urb->actual_length += size; } else { usb_ep0_state = USB_EP0_STATE_IN_STATUS; + HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = (USB_CSRL0_REQPKT | USB_CSRL0_STATUS); } - HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_CSRL0_TXRDY; - } - - break; - } - return; -chan_wait: - if (chan->enable) { - chan->result = result; - musb_pipe_wakeup(chan); + break; + case USB_EP0_STATE_OUT_STATUS: + urb->errorcode = 0; + musb_pipe_waitup(pipe); + break; + case USB_EP0_STATE_IN_STATUS: + if (ep0_status & (USB_CSRL0_RXRDY | USB_CSRL0_STATUS)) { + HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~(USB_CSRL0_RXRDY | USB_CSRL0_STATUS); + urb->errorcode = 0; + musb_pipe_waitup(pipe); + } + break; } } @@ -1055,10 +851,10 @@ void USBH_IRQHandler(void) uint32_t rxis; uint8_t ep_csrl_status; // uint8_t ep_csrh_status; - struct musb_pipe *chan; + struct musb_pipe *pipe; + struct usbh_urb *urb; uint8_t ep_idx; uint8_t old_ep_idx; - int result = 0; is = HWREGB(USB_BASE + MUSB_IS_OFFSET); txis = HWREGH(USB_BASE + MUSB_TXIS_OFFSET); @@ -1069,26 +865,28 @@ void USBH_IRQHandler(void) old_ep_idx = musb_get_active_ep(); if (is & USB_IS_CONN) { - if (usbh_get_port_connect_status(0)) { - usbh_event_notify_handler(USBH_EVENT_CONNECTED, 1); - } + g_musb_hcd.port_csc = 1; + g_musb_hcd.port_pec = 1; + g_musb_hcd.port_pe = 1; + usbh_roothub_thread_wakeup(1); } if (is & USB_IS_DISCON) { - if (usbh_get_port_connect_status(0) == false) { - for (ep_idx = 0; ep_idx < CONIFG_USB_MUSB_PIPE_NUM; ep_idx++) { - for (uint8_t j = 0; j < 2; j++) { - chan = &g_musb_hcd.chan[ep_idx][j]; - - if (chan->waiter) { - chan->result = -ENXIO; - musb_pipe_wakeup(chan); - } + g_musb_hcd.port_csc = 1; + g_musb_hcd.port_pec = 1; + g_musb_hcd.port_pe = 0; + for (uint8_t index = 0; index < CONFIG_USBHOST_PIPE_NUM; index++) { + for (uint8_t j = 0; j < 2; j++) { + struct musb_pipe *pipe = &g_musb_hcd.pipe_pool[index][j]; + struct usbh_urb *urb = pipe->urb; + if (pipe->waiter) { + pipe->waiter = false; + urb->errorcode = -ESHUTDOWN; + usb_osal_sem_give(pipe->waitsem); } } - - usbh_event_notify_handler(USBH_EVENT_DISCONNECTED, 1); } + usbh_roothub_thread_wakeup(1); } if (is & USB_IS_SOF) { @@ -1121,40 +919,40 @@ void USBH_IRQHandler(void) if (txis & (1 << ep_idx)) { HWREGH(USB_BASE + MUSB_TXIS_OFFSET) = (1 << ep_idx); - chan = &g_musb_hcd.chan[ep_idx][0]; - + pipe = &g_musb_hcd.pipe_pool[ep_idx][0]; + urb = pipe->urb; musb_set_active_ep(ep_idx); ep_csrl_status = HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET); if (ep_csrl_status & USB_TXCSRL1_ERROR) { HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_TXCSRL1_ERROR; - result = -EIO; - goto chan_wait; + urb->errorcode = -EIO; + goto pipe_wait; } else if (ep_csrl_status & USB_TXCSRL1_NAKTO) { HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_TXCSRL1_NAKTO; - result = -EBUSY; - goto chan_wait; + urb->errorcode = -EBUSY; + goto pipe_wait; } else if (ep_csrl_status & USB_TXCSRL1_STALL) { HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) &= ~USB_TXCSRL1_STALL; - result = -EPERM; - goto chan_wait; + urb->errorcode = -EPERM; + goto pipe_wait; } else { - uint32_t size = chan->buflen; + uint32_t size = urb->transfer_buffer_length; - if (size > chan->mps) { - size = chan->mps; + if (size > pipe->ep_mps) { + size = pipe->ep_mps; } - chan->buffer += size; - chan->buflen -= size; - chan->xfrd += size; + urb->transfer_buffer += size; + urb->transfer_buffer_length -= size; + urb->actual_length += size; - if (chan->buflen == 0) { - result = 0; - goto chan_wait; + if (urb->transfer_buffer_length == 0) { + urb->errorcode = 0; + goto pipe_wait; } else { - musb_write_packet(ep_idx, chan->buffer, size); + musb_write_packet(ep_idx, urb->transfer_buffer, size); HWREGB(USB_BASE + MUSB_IND_TXCSRL_OFFSET) = USB_TXCSRL1_TXRDY; } } @@ -1166,8 +964,8 @@ void USBH_IRQHandler(void) if (rxis & (1 << ep_idx)) { HWREGH(USB_BASE + MUSB_RXIS_OFFSET) = (1 << ep_idx); // clear isr flag - chan = &g_musb_hcd.chan[ep_idx][1]; - + pipe = &g_musb_hcd.pipe_pool[ep_idx][1]; + urb = pipe->urb; musb_set_active_ep(ep_idx); ep_csrl_status = HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET); @@ -1175,46 +973,43 @@ void USBH_IRQHandler(void) if (ep_csrl_status & USB_RXCSRL1_ERROR) { HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) &= ~USB_RXCSRL1_ERROR; - result = -EIO; - goto chan_wait; + urb->errorcode = -EIO; + goto pipe_wait; } else if (ep_csrl_status & USB_RXCSRL1_NAKTO) { HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) &= ~USB_RXCSRL1_NAKTO; - result = -EBUSY; - goto chan_wait; + urb->errorcode = -EBUSY; + goto pipe_wait; } else if (ep_csrl_status & USB_RXCSRL1_STALL) { HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) &= ~USB_RXCSRL1_STALL; - result = -EPERM; - goto chan_wait; + urb->errorcode = -EPERM; + goto pipe_wait; } else if (ep_csrl_status & USB_RXCSRL1_RXRDY) { - uint32_t size = chan->buflen; - if (size > chan->mps) { - size = chan->mps; + uint32_t size = urb->transfer_buffer_length; + if (size > pipe->ep_mps) { + size = pipe->ep_mps; } size = MIN(size, HWREGH(USB_BASE + MUSB_IND_RXCOUNT_OFFSET)); - musb_read_packet(ep_idx, chan->buffer, size); + musb_read_packet(ep_idx, urb->transfer_buffer, size); HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) &= ~USB_RXCSRL1_RXRDY; - chan->buffer += size; - chan->buflen -= size; - chan->xfrd += size; - if ((size < chan->mps) || (chan->buflen == 0)) { - result = 0; - goto chan_wait; + urb->transfer_buffer += size; + urb->transfer_buffer_length -= size; + urb->actual_length += size; + + if ((size < pipe->ep_mps) || (urb->transfer_buffer_length == 0)) { + urb->errorcode = 0; + goto pipe_wait; } else { HWREGB(USB_BASE + MUSB_IND_RXCSRL_OFFSET) = USB_RXCSRL1_REQPKT; } } } } - musb_set_active_ep(old_ep_idx); return; -chan_wait: +pipe_wait: musb_set_active_ep(old_ep_idx); - if (chan->enable) { - chan->result = result; - musb_pipe_wakeup(chan); - } + musb_pipe_waitup(pipe); } \ No newline at end of file