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