summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjzlv <[email protected]>2022-03-23 14:47:18 +0800
committerjzlv <[email protected]>2022-03-23 14:47:18 +0800
commitc44a26d69f686f2aba3212aed9dbcb7682918bdb (patch)
tree37fcc9fc3e96edecdcffb46be03374590fb756e5
parentbe3e9d542555319d79d11f1d6ac9938d75d2bd9f (diff)
psc thread use event instead,add timeout for transfer
-rw-r--r--class/msc/usbh_msc.c37
-rw-r--r--common/usb_hc.h15
-rw-r--r--core/usbh_core.c101
-rw-r--r--core/usbh_core.h7
-rw-r--r--demo/usb_host.c12
-rw-r--r--osal/usb_osal.h13
-rw-r--r--osal/usb_osal_freertos.c41
-rw-r--r--osal/usb_osal_rtthread.c36
-rw-r--r--osal/usb_workq.c26
-rw-r--r--osal/usb_workq.h22
-rw-r--r--port/ehci/usb_ehci.c234
-rw-r--r--usb_config.h18
12 files changed, 326 insertions, 236 deletions
diff --git a/class/msc/usbh_msc.c b/class/msc/usbh_msc.c
index 47685888..f78b4662 100644
--- a/class/msc/usbh_msc.c
+++ b/class/msc/usbh_msc.c
@@ -32,7 +32,7 @@ static uint32_t g_devinuse = 0;
* Name: usbh_msc_devno_alloc
*
* Description:
- * Allocate a unique /dev/ttyACM[n] minor number in the range 0-31.
+ * Allocate a unique /dev/sd[n] minor number in the range 0-31.
*
****************************************************************************/
@@ -144,10 +144,10 @@ 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);
+ nbytes = usbh_ep_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);
+ nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes >= 0) {
usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer);
}
@@ -173,13 +173,13 @@ 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);
+ nbytes = usbh_ep_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);
+ nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, 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);
+ nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes >= 0) {
usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer);
}
@@ -206,13 +206,13 @@ 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);
+ nbytes = usbh_ep_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);
+ nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, 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);
+ nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes >= 0) {
usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer);
}
@@ -238,16 +238,16 @@ 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);
+ nbytes = usbh_ep_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);
+ nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, 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]);
/* Receive the CSW */
- nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW);
+ nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes >= 0) {
usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer);
}
@@ -275,13 +275,13 @@ 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);
+ nbytes = usbh_ep_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);
+ nbytes = usbh_ep_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);
+ nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes >= 0) {
usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer);
}
@@ -310,13 +310,13 @@ 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);
+ nbytes = usbh_ep_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);
+ nbytes = usbh_ep_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);
+ nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes >= 0) {
usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer);
}
@@ -338,7 +338,6 @@ int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
}
memset(msc_class, 0, sizeof(struct usbh_msc));
- msc_class->hport = hport;
usbh_msc_devno_alloc(msc_class);
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
diff --git a/common/usb_hc.h b/common/usb_hc.h
index 7a12a98b..fbf8eef8 100644
--- a/common/usb_hc.h
+++ b/common/usb_hc.h
@@ -67,6 +67,15 @@ struct usbh_endpoint_cfg {
int usb_hc_init(void);
/**
+ * @brief get port connect status
+ *
+ * @param port
+ * @return true
+ * @return false
+ */
+bool usbh_get_port_connect_status(const uint8_t port);
+
+/**
* @brief reset roothub port
*
* @param port port index
@@ -130,6 +139,7 @@ int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint
* @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:
@@ -141,7 +151,7 @@ int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint
* EPIPE - Overrun errors
*
*/
-int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen);
+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
@@ -151,6 +161,7 @@ int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen);
* @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:
@@ -162,7 +173,7 @@ int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen);
* EPIPE - Overrun errors
*
*/
-int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen);
+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
diff --git a/core/usbh_core.c b/core/usbh_core.c
index d07c64ca..74454b42 100644
--- a/core/usbh_core.c
+++ b/core/usbh_core.c
@@ -57,8 +57,7 @@ struct usbh_roothubport_priv {
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 */
- volatile bool pscwait; /* TRUE: Thread is waiting for port status change event */
- usb_osal_sem_t pscsem; /* Semaphore to wait for a port event */
+ 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)
@@ -671,23 +670,46 @@ errout:
static int usbh_portchange_wait(struct usbh_hubport **hport)
{
struct usbh_hubport *connport = NULL;
+ uint32_t recved_event;
uint32_t flags;
int ret;
/* Loop until a change in connection state is detected */
while (1) {
- /* Check for a change in the connection state on any root hub port */
+ 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;
- *hport = connport;
- usb_osal_leave_critical_section(flags);
- return 0;
+ /* debounce for port,in order to keep port connect status stability*/
+ usb_osal_msleep(25);
+ 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;
+ }
+ }
+ } else 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;
+ }
+ }
+ }
}
}
+#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;
@@ -696,13 +718,8 @@ static int usbh_portchange_wait(struct usbh_hubport **hport)
usb_osal_leave_critical_section(flags);
return 0;
}
- /* No changes on any port. Wait for a connection/disconnection event and check again */
- usbh_core_cfg.pscwait = true;
+#endif
usb_osal_leave_critical_section(flags);
- ret = usb_osal_sem_take(usbh_core_cfg.pscsem);
- if (ret < 0) {
- return ret;
- }
}
}
@@ -762,15 +779,9 @@ void usbh_external_hport_connect(struct usbh_hubport *hport)
hport->connected = true;
usbh_core_cfg.active_hport = hport;
-
- if (usbh_core_cfg.pscwait) {
- usbh_core_cfg.pscwait = false;
- usb_osal_leave_critical_section(flags);
- usb_osal_sem_give(usbh_core_cfg.pscsem);
- return;
- }
-
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)
@@ -778,45 +789,18 @@ void usbh_external_hport_disconnect(struct usbh_hubport *hport)
uint32_t flags;
flags = usb_osal_enter_critical_section();
+
hport->connected = false;
usbh_core_cfg.active_hport = hport;
- if (usbh_core_cfg.pscwait) {
- usbh_core_cfg.pscwait = false;
- usb_osal_leave_critical_section(flags);
- usb_osal_sem_give(usbh_core_cfg.pscsem);
- return;
- }
-
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)
{
- switch (event) {
- case USBH_EVENT_ATTACHED:
- if (!usbh_core_cfg.rhport[rhport - 1].hport.connected) {
- usbh_core_cfg.rhport[rhport - 1].hport.connected = true;
- usbh_core_cfg.rhport[rhport - 1].hport.port_change = true;
- if (usbh_core_cfg.pscwait) {
- usbh_core_cfg.pscwait = false;
- usb_osal_sem_give(usbh_core_cfg.pscsem);
- }
- }
- break;
- case USBH_EVENT_REMOVED:
- if (usbh_core_cfg.rhport[rhport - 1].hport.connected) {
- usbh_core_cfg.rhport[rhport - 1].hport.connected = false;
- usbh_core_cfg.rhport[rhport - 1].hport.port_change = true;
- if (usbh_core_cfg.pscwait) {
- usbh_core_cfg.pscwait = false;
- usb_osal_sem_give(usbh_core_cfg.pscsem);
- }
- }
- break;
- default:
- break;
- }
+ usbh_core_cfg.rhport[rhport - 1].hport.port_change = true;
+ usb_osal_event_send(usbh_core_cfg.pscevent, event);
}
int usbh_initialize(void)
@@ -824,11 +808,11 @@ int usbh_initialize(void)
usb_osal_thread_t usb_thread;
memset(&usbh_core_cfg, 0, sizeof(struct usbh_core_priv));
-
+#ifdef CONFIG_USBHOST_HUB
usbh_workq_initialize();
-
- usbh_core_cfg.pscsem = usb_osal_sem_create(0);
- if (usbh_core_cfg.pscsem == NULL) {
+#endif
+ usbh_core_cfg.pscevent = usb_osal_event_create();
+ if (usbh_core_cfg.pscevent == NULL) {
return -1;
}
@@ -880,6 +864,7 @@ int lsusb(int argc, char **argv)
}
}
}
+#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);
@@ -897,6 +882,7 @@ int lsusb(int argc, char **argv)
}
}
}
+#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) {
@@ -905,7 +891,7 @@ int lsusb(int argc, char **argv)
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);
@@ -918,6 +904,7 @@ int lsusb(int argc, char **argv)
}
}
}
+#endif
}
return 0;
diff --git a/core/usbh_core.h b/core/usbh_core.h
index fb001771..dd46b17d 100644
--- a/core/usbh_core.h
+++ b/core/usbh_core.h
@@ -27,8 +27,10 @@
#include "usb_def.h"
#include "usb_hc.h"
#include "usb_osal.h"
+#ifdef CONFIG_USBHOST_HUB
#include "usb_workq.h"
#include "usbh_hub.h"
+#endif
#include "usb_config.h"
#ifdef __cplusplus
@@ -49,11 +51,12 @@ extern "C" {
#define CLASS_DISCONNECT(hport, i) ((hport)->config.intf[i].class_driver->disconnect(hport, i))
enum usbh_event_type {
- USBH_EVENT_ATTACHED,
- USBH_EVENT_REMOVED,
+ USBH_EVENT_CONNECTED = (1 << 0),
+ USBH_EVENT_DISCONNECTED = (1 << 1),
};
struct usbh_class_info {
+ uint8_t match_flags;
uint8_t class; /* Base device class code */
uint8_t subclass; /* Sub-class, depends on base class. Eg. */
uint8_t protocol; /* Protocol, depends on base class. Eg. */
diff --git a/demo/usb_host.c b/demo/usb_host.c
index 26e38037..90210f47 100644
--- a/demo/usb_host.c
+++ b/demo/usb_host.c
@@ -30,7 +30,7 @@ int cdc_acm_test(void)
}
memset(cdc_buffer, 0, 512);
- ret = usbh_ep_bulk_transfer(cdc_acm_class->bulkin, cdc_buffer, 512);
+ ret = usbh_ep_bulk_transfer(cdc_acm_class->bulkin, cdc_buffer, 512, 3000);
if (ret < 0) {
printf("bulk in error\r\n");
return ret;
@@ -43,7 +43,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);
+ ret = usbh_ep_bulk_transfer(cdc_acm_class->bulkout, cdc_buffer, 8, 3000);
if (ret < 0) {
printf("bulk out error\r\n");
return ret;
@@ -53,7 +53,7 @@ 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);
#else
- ret = usbh_ep_bulk_transfer(cdc_acm_class->bulkin, cdc_buffer, 512);
+ ret = usbh_ep_bulk_transfer(cdc_acm_class->bulkin, cdc_buffer, 512, 3000);
if (ret < 0) {
printf("bulk in error\r\n");
return ret;
@@ -68,7 +68,6 @@ int cdc_acm_test(void)
#endif
}
-
#include "ff.h"
int msc_test(void)
@@ -130,14 +129,13 @@ int msc_test(void)
/*unmount*/
f_mount(NULL, "2:", 1);
} else {
- printf("open error:%d\r\n",res_sd);
+ printf("open error:%d\r\n", res_sd);
}
usb_iofree(ReadBuffer);
#endif
return ret;
}
-
uint8_t hid_buffer[128];
void usbh_hid_callback(void *arg, int nbytes)
@@ -167,7 +165,7 @@ int hid_test(void)
return ret;
}
#else
- ret = usbh_ep_intr_transfer(hid_class->intin, hid_buffer, 128);
+ ret = usbh_ep_intr_transfer(hid_class->intin, hid_buffer, 128, 1000);
if (ret < 0) {
return ret;
}
diff --git a/osal/usb_osal.h b/osal/usb_osal.h
index 04703c80..92957c33 100644
--- a/osal/usb_osal.h
+++ b/osal/usb_osal.h
@@ -25,11 +25,10 @@
#include <stdint.h>
-#define USB_OSAL_MS2TICK(ms)
-
typedef void *usb_osal_thread_t;
typedef void *usb_osal_sem_t;
typedef void *usb_osal_mutex_t;
+typedef void *usb_osal_event_t;
typedef void (*usb_thread_entry_t)(void *argument);
usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args);
@@ -39,7 +38,7 @@ void usb_osal_thread_resume(usb_osal_thread_t thread);
usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count);
void usb_osal_sem_delete(usb_osal_sem_t sem);
-int usb_osal_sem_take(usb_osal_sem_t sem);
+int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout);
int usb_osal_sem_give(usb_osal_sem_t sem);
usb_osal_mutex_t usb_osal_mutex_create(void);
@@ -47,11 +46,15 @@ void usb_osal_mutex_delete(usb_osal_mutex_t mutex);
int usb_osal_mutex_take(usb_osal_mutex_t mutex);
int usb_osal_mutex_give(usb_osal_mutex_t mutex);
+usb_osal_event_t usb_osal_event_create(void);
+void usb_osal_event_delete(usb_osal_event_t event);
+int usb_osal_event_recv(usb_osal_event_t event, uint32_t set, uint32_t *recved);
+int usb_osal_event_send(usb_osal_event_t event, uint32_t set);
+
uint32_t usb_osal_enter_critical_section(void);
void usb_osal_leave_critical_section(uint32_t flag);
void usb_osal_msleep(uint32_t delay);
-uint32_t usb_osal_get_tick(void);
+#endif
-#endif \ No newline at end of file
diff --git a/osal/usb_osal_freertos.c b/osal/usb_osal_freertos.c
index 6a551393..98b9ac1e 100644
--- a/osal/usb_osal_freertos.c
+++ b/osal/usb_osal_freertos.c
@@ -23,6 +23,8 @@
#include "usb_osal.h"
#include <FreeRTOS.h>
#include "semphr.h"
+#include "timers.h"
+#include "event_groups.h"
usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args)
{
@@ -52,9 +54,9 @@ void usb_osal_sem_delete(usb_osal_sem_t sem)
vSemaphoreDelete((SemaphoreHandle_t)sem);
}
-int usb_osal_sem_take(usb_osal_sem_t sem)
+int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout)
{
- return (xSemaphoreTake((SemaphoreHandle_t)sem, portMAX_DELAY) == pdPASS) ? 0 : -1;
+ return (xSemaphoreTake((SemaphoreHandle_t)sem, pdMS_TO_TICKS(timeout)) == pdPASS) ? 0 : -1;
}
int usb_osal_sem_give(usb_osal_sem_t sem)
@@ -101,6 +103,34 @@ int usb_osal_mutex_give(usb_osal_mutex_t mutex)
return (xSemaphoreGive((SemaphoreHandle_t)mutex) == pdPASS) ? 0 : -1;
}
+usb_osal_event_t usb_osal_event_create(void)
+{
+ return (usb_osal_event_t)xEventGroupCreate();
+}
+
+void usb_osal_event_delete(usb_osal_event_t event)
+{
+ vEventGroupDelete((EventGroupHandle_t)event);
+}
+
+int usb_osal_event_recv(usb_osal_event_t event, uint32_t set, uint32_t *recved)
+{
+ *recved = xEventGroupWaitBits((EventGroupHandle_t)event, set, pdTRUE, pdFALSE, portMAX_DELAY);
+ return 0;
+}
+
+int usb_osal_event_send(usb_osal_event_t event, uint32_t set)
+{
+ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+ int ret;
+
+ ret = xEventGroupSetBitsFromISR((EventGroupHandle_t)event, set, &xHigherPriorityTaskWoken);
+ if (ret == pdPASS) {
+ portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+ }
+ return (ret == pdPASS) ? 0 : -1;
+}
+
uint32_t usb_osal_enter_critical_section(void)
{
taskENTER_CRITICAL();
@@ -115,9 +145,4 @@ void usb_osal_leave_critical_section(uint32_t flag)
void usb_osal_msleep(uint32_t delay)
{
vTaskDelay(pdMS_TO_TICKS(delay));
-}
-
-uint32_t usb_osal_get_tick(void)
-{
- return xTaskGetTickCount();
-}
+} \ No newline at end of file
diff --git a/osal/usb_osal_rtthread.c b/osal/usb_osal_rtthread.c
index f9e911b2..bb3adefa 100644
--- a/osal/usb_osal_rtthread.c
+++ b/osal/usb_osal_rtthread.c
@@ -51,9 +51,9 @@ void usb_osal_sem_delete(usb_osal_sem_t sem)
rt_sem_delete((rt_sem_t)sem);
}
-int usb_osal_sem_take(usb_osal_sem_t sem)
+int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout)
{
- return (int)rt_sem_take((rt_sem_t)sem, RT_WAITING_FOREVER);
+ return (int)rt_sem_take((rt_sem_t)sem, rt_tick_from_millisecond(timeout));
}
int usb_osal_sem_give(usb_osal_sem_t sem)
@@ -66,6 +66,11 @@ usb_osal_mutex_t usb_osal_mutex_create(void)
return (usb_osal_mutex_t)rt_mutex_create("usbh_mutex", RT_IPC_FLAG_FIFO);
}
+void usb_osal_mutex_delete(usb_osal_mutex_t mutex)
+{
+ rt_mutex_delete((rt_mutex_t)mutex);
+}
+
int usb_osal_mutex_take(usb_osal_mutex_t mutex)
{
return (int)rt_mutex_take((rt_mutex_t)mutex, RT_WAITING_FOREVER);
@@ -76,18 +81,37 @@ int usb_osal_mutex_give(usb_osal_mutex_t mutex)
return (int)rt_mutex_release((rt_mutex_t)mutex);
}
+usb_osal_event_t usb_osal_event_create(void)
+{
+ return (usb_osal_event_t)rt_event_create("psc_event", RT_IPC_FLAG_FIFO);
+}
+
+void usb_osal_event_delete(usb_osal_event_t event)
+{
+ rt_event_delete((rt_event_t)event);
+}
+
+int usb_osal_event_recv(usb_osal_event_t event, uint32_t set, uint32_t *recved)
+{
+ rt_event_recv((rt_event_t)event, set, RT_EVENT_FLAG_OR, RT_WAITING_FOREVER, recved);
+}
+
+int usb_osal_event_send(usb_osal_event_t event, uint32_t set)
+{
+ rt_event_send((rt_event_t)event, set);
+}
+
uint32_t usb_osal_enter_critical_section(void)
{
- rt_enter_critical();
- return 1;
+ return rt_hw_interrupt_disable();
}
void usb_osal_leave_critical_section(uint32_t flag)
{
- rt_exit_critical();
+ rt_hw_interrupt_enable(flag);
}
void usb_osal_msleep(uint32_t delay)
{
- rt_thread_mdelay(delay);
+ rt_thread_mdelay(rt_tick_from_millisecond(delay));
} \ No newline at end of file
diff --git a/osal/usb_workq.c b/osal/usb_workq.c
index ab4279bd..f8c1feb2 100644
--- a/osal/usb_workq.c
+++ b/osal/usb_workq.c
@@ -1,3 +1,25 @@
+/**
+ * @file usb_workq.c
+ * @brief
+ *
+ * Copyright (c) 2022 sakumisu
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ */
#include "usb_list.h"
#include "usb_osal.h"
#include "usb_workq.h"
@@ -29,7 +51,7 @@ static void usbh_hpwork_thread(void *argument)
int ret;
struct usb_workqueue *queue = (struct usb_workqueue *)argument;
while (1) {
- ret = usb_osal_sem_take(queue->sem);
+ ret = usb_osal_sem_take(queue->sem, 0xffffffff);
if (ret < 0) {
continue;
}
@@ -52,7 +74,7 @@ static void usbh_lpwork_thread(void *argument)
int ret;
struct usb_workqueue *queue = (struct usb_workqueue *)argument;
while (1) {
- ret = usb_osal_sem_take(queue->sem);
+ ret = usb_osal_sem_take(queue->sem, 0xffffffff);
if (ret < 0) {
continue;
}
diff --git a/osal/usb_workq.h b/osal/usb_workq.h
index 4e20d93f..6d54b167 100644
--- a/osal/usb_workq.h
+++ b/osal/usb_workq.h
@@ -1,3 +1,25 @@
+/**
+ * @file usb_workq.h
+ * @brief
+ *
+ * Copyright (c) 2022 sakumisu
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ */
#ifndef _USB_WORKQUEUE_H
#define _USB_WORKQUEUE_H
diff --git a/port/ehci/usb_ehci.c b/port/ehci/usb_ehci.c
index 0da339ae..cbd61e12 100644
--- a/port/ehci/usb_ehci.c
+++ b/port/ehci/usb_ehci.c
@@ -127,28 +127,22 @@ struct usb_ehci_epinfo_s {
uint16_t speed : 2; /* See USB_*_SPEED definitions in ehci.h */
int result; /* The result of the transfer */
uint32_t xfrd; /* On completion, will hold the number of bytes transferred */
-
- usb_osal_sem_t iocsem; /* Semaphore used to wait for transfer completion */
+ bool inuse;
+ usb_osal_sem_t iocsem; /* Semaphore used to wait for transfer completion */
+ 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
struct usbh_hubport *hport;
- usb_slist_t list;
};
/* This structure retains the overall state of the USB host controller */
struct usb_ehci_s {
- volatile bool connected; /* Connected to device */
- usb_osal_mutex_t exclsem; /* Support mutually exclusive access */
- struct usb_work work;
-
struct usb_ehci_list_s *qhfree; /* List of free Queue Head (QH) structures */
struct usb_ehci_list_s *qtdfree; /* List of free Queue Element Transfer Descriptor (qTD) */
-
- struct usb_ehci_epinfo_s ep0[CONFIG_USBHOST_RHPORTS]; /* EP0 endpoint info */
- usb_slist_t epinfo_list;
+ struct usb_ehci_epinfo_s chan[CONFIG_USBHOST_PIPE_NUM];
};
/****************************************************************************
@@ -303,6 +297,32 @@ static inline uint32_t usb_ehci_getreg(volatile uint32_t *regaddr)
return *regaddr;
}
+static int usb_ehci_chan_alloc(struct usb_ehci_s *priv)
+{
+ int chidx;
+
+ /* Search the table of channels */
+
+ for (chidx = 0; chidx < CONFIG_USBHOST_PIPE_NUM; chidx++) {
+ /* Is this channel available? */
+ if (!priv->chan[chidx].inuse) {
+ /* Yes... make it "in use" and return the index */
+
+ priv->chan[chidx].inuse = true;
+ return chidx;
+ }
+ }
+
+ /* All of the channels are "in-use" */
+
+ return -EBUSY;
+}
+
+static void usb_ehci_chan_free(struct usb_ehci_epinfo_s *chan)
+{
+ /* Mark the channel available */
+ chan->inuse = false;
+}
/****************************************************************************
* Name: usb_ehci_qh_alloc
*
@@ -1287,7 +1307,7 @@ static int usb_ehci_ioc_setup(struct usb_ehci_epinfo_s *epinfo)
/* Is the device still connected? */
flags = usb_osal_enter_critical_section();
- if (g_ehci.connected) {
+ if (epinfo->hport->connected) {
/* Then set iocwait to indicate that we expect to be informed when
* either (1) the device is disconnected, or (2) the transfer
* completed.
@@ -1341,7 +1361,7 @@ static int usb_ehci_ioc_async_setup(struct usb_ehci_epinfo_s *epinfo, usbh_async
/* Is the device still connected? */
flags = usb_osal_enter_critical_section();
- if (g_ehci.connected) {
+ if (epinfo->hport->connected) {
/* Then set iocwait to indicate that we expect to be informed when
* either (1) the device is disconnected, or (2) the transfer
* completed.
@@ -1437,34 +1457,21 @@ static void usb_ehci_asynch_completion(struct usb_ehci_epinfo_s *epinfo)
*
****************************************************************************/
-static int usb_ehci_transfer_wait(struct usb_ehci_epinfo_s *epinfo)
+static int usb_ehci_transfer_wait(struct usb_ehci_epinfo_s *epinfo, uint32_t timeout)
{
int ret = 0;
- int ret2;
-
- /* Release the EHCI semaphore while we wait. Other threads need the
- * opportunity to access the EHCI resources while we wait. */
-
- usb_osal_mutex_give(g_ehci.exclsem);
/* Wait for the IOC completion event */
if (epinfo->iocwait) {
- ret = usb_osal_sem_take(epinfo->iocsem);
- if (ret == 0) {
- ret = epinfo->result;
+ ret = usb_osal_sem_take(epinfo->iocsem, timeout);
+ if (ret < 0) {
+ return ret;
}
}
- /* Re-acquire the EHCI semaphore. The caller expects to be holding this upon return.*/
- ret2 = usb_osal_mutex_take(g_ehci.exclsem);
- if (ret2 < 0) {
- ret = ret2;
- }
-
- /* Did epinfo->result or usb_osal_mutex_take() report an error? */
+ ret = epinfo->result;
if (ret < 0) {
- epinfo->iocwait = false;
return ret;
}
@@ -1831,30 +1838,18 @@ static inline void usb_ehci_portsc_bottomhalf(void)
/* Handle port connection status change (CSC) events */
if ((portsc & EHCI_PORTSC_CSC) != 0) {
- /* Debounce */
- usb_osal_msleep(25);
- /* Check current connect status*/
- portsc = usb_ehci_getreg(&HCOR->portsc[rhpndx]);
if ((portsc & EHCI_PORTSC_CCS) == EHCI_PORTSC_CCS) {
/* Connected ... Did we just become connected? */
- if (!g_ehci.connected) {
- g_ehci.connected = 1;
- usbh_event_notify_handler(USBH_EVENT_ATTACHED, 1);
- }
+ usbh_event_notify_handler(USBH_EVENT_CONNECTED, 1);
} else {
- if (g_ehci.connected) {
- g_ehci.connected = 0;
- usb_slist_t *i;
- usb_slist_for_each(i, &g_ehci.epinfo_list)
- {
- struct usb_ehci_epinfo_s *epinfo = usb_slist_entry(i, struct usb_ehci_epinfo_s, list);
- if (epinfo->iocwait) {
- epinfo->iocwait = false;
- usb_osal_sem_give(epinfo->iocsem);
- }
+ for (uint8_t chidx = 0; chidx < CONFIG_USBHOST_PIPE_NUM; chidx++) {
+ struct usb_ehci_epinfo_s *epinfo = &g_ehci.chan[chidx];
+ if (epinfo->iocwait) {
+ epinfo->iocwait = false;
+ usb_osal_sem_give(epinfo->iocsem);
}
- usbh_event_notify_handler(USBH_EVENT_REMOVED, 1);
}
+ usbh_event_notify_handler(USBH_EVENT_DISCONNECTED, 1);
}
}
@@ -2035,12 +2030,9 @@ int usb_hc_init(void)
uintptr_t physaddr1;
uintptr_t physaddr2;
- g_ehci.connected = 0;
g_ehci.qhfree = NULL;
g_ehci.qtdfree = NULL;
- usb_slist_init(&g_ehci.epinfo_list);
-
/* Initialize the list of free Queue Head (QH) structures */
for (uint8_t i = 0; i < CONFIG_USB_EHCI_QH_NUM; i++) {
@@ -2106,8 +2098,6 @@ int usb_hc_init(void)
usb_ehci_dcache_clean((uintptr_t)&g_intrhead.hw, sizeof(struct usb_ehci_qh_s));
usb_ehci_dcache_clean((uintptr_t)g_framelist, FRAME_LIST_SIZE * sizeof(uint32_t));
- g_ehci.exclsem = usb_osal_mutex_create();
-
usb_hc_low_level_init();
/* Host Controller Initialization. Paragraph 4.1 */
@@ -2194,6 +2184,17 @@ int usb_hc_init(void)
return ret;
}
+bool usbh_get_port_connect_status(const uint8_t port)
+{
+ uint32_t portsc;
+ portsc = usb_ehci_getreg(&HCOR->portsc[port - 1]);
+ if ((portsc & EHCI_PORTSC_CCS) == EHCI_PORTSC_CCS) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
int usbh_reset_port(const uint8_t port)
{
uint32_t timeout = 0;
@@ -2249,7 +2250,7 @@ int usbh_ep0_reconfigure(usbh_epinfo_t ep, uint8_t dev_addr, uint8_t ep_mps, uin
DEBUGASSERT(epinfo != NULL && ep_mps < 2048);
- ret = usb_osal_mutex_take(g_ehci.exclsem);
+ ret = usb_osal_mutex_take(epinfo->exclsem);
if (ret < 0) {
return ret;
}
@@ -2258,7 +2259,7 @@ int usbh_ep0_reconfigure(usbh_epinfo_t ep, uint8_t dev_addr, uint8_t ep_mps, uin
epinfo->speed = speed;
epinfo->maxpacket = ep_mps;
- usb_osal_mutex_give(g_ehci.exclsem);
+ usb_osal_mutex_give(epinfo->exclsem);
return ret;
}
@@ -2267,24 +2268,18 @@ int usbh_ep_alloc(usbh_epinfo_t *ep, const struct usbh_endpoint_cfg *ep_cfg)
{
struct usb_ehci_epinfo_s *epinfo;
struct usbh_hubport *hport;
+ int chidx;
DEBUGASSERT(ep_cfg != NULL && ep_cfg->hport != NULL);
hport = ep_cfg->hport;
- /* new roothub ep info */
- if (((ep_cfg->ep_type & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_CONTROL) && (hport->parent == NULL)) {
- memset(&g_ehci.ep0, 0, sizeof(struct usb_ehci_epinfo_s));
- epinfo = &g_ehci.ep0[hport->port - 1];
- } else {
- /* new exteranl hub ep info */
- epinfo = usb_malloc(sizeof(struct usb_ehci_epinfo_s));
- memset(epinfo, 0, sizeof(struct usb_ehci_epinfo_s));
- if (epinfo == NULL) {
- return -1;
- }
- }
+ chidx = usb_ehci_chan_alloc(&g_ehci);
+
+ epinfo = &g_ehci.chan[chidx];
+ memset(epinfo, 0, sizeof(struct usb_ehci_epinfo_s));
+ epinfo->inuse = true;
epinfo->epno = ep_cfg->ep_addr & 0x7f;
epinfo->dirin = (ep_cfg->ep_addr & 0x80) ? 1 : 0;
epinfo->devaddr = hport->dev_addr;
@@ -2297,9 +2292,9 @@ int usbh_ep_alloc(usbh_epinfo_t *ep, const struct usbh_endpoint_cfg *ep_cfg)
epinfo->hport = hport;
epinfo->iocsem = usb_osal_sem_create(0);
- usb_slist_add_tail(&g_ehci.epinfo_list, &epinfo->list);
+ epinfo->exclsem = usb_osal_mutex_create();
- *ep = epinfo;
+ *ep = (usbh_epinfo_t)epinfo;
return 0;
}
@@ -2309,8 +2304,8 @@ int usbh_ep_free(usbh_epinfo_t ep)
struct usb_ehci_epinfo_s *epinfo = (struct usb_ehci_epinfo_s *)ep;
usb_osal_sem_delete(epinfo->iocsem);
- usb_slist_remove(&g_ehci.epinfo_list, &epinfo->list);
- usb_free(epinfo);
+ usb_osal_mutex_delete(epinfo->exclsem);
+ usb_ehci_chan_free(epinfo);
return 0;
}
@@ -2330,7 +2325,7 @@ int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint
DEBUGASSERT(setup || buffer);
- ret = usb_osal_mutex_take(g_ehci.exclsem);
+ ret = usb_osal_mutex_take(epinfo->exclsem);
if (ret < 0) {
return ret;
}
@@ -2347,18 +2342,22 @@ int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint
}
/* And wait for the transfer to complete */
- nbytes = usb_ehci_transfer_wait(epinfo);
- usb_osal_mutex_give(g_ehci.exclsem);
- return nbytes >= 0 ? 0 : (int)nbytes;
+ nbytes = usb_ehci_transfer_wait(epinfo, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT);
+ if (nbytes < 0) {
+ goto errout_with_iocwait;
+ }
+
+ usb_osal_mutex_give(epinfo->exclsem);
+ return nbytes;
errout_with_iocwait:
epinfo->iocwait = false;
errout_with_sem:
- usb_osal_mutex_give(g_ehci.exclsem);
+ usb_osal_mutex_give(epinfo->exclsem);
return ret;
}
-int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen)
+int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
int nbytes;
int ret;
@@ -2367,7 +2366,7 @@ int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen)
DEBUGASSERT(epinfo && buffer && buflen > 0);
- ret = usb_osal_mutex_take(g_ehci.exclsem);
+ ret = usb_osal_mutex_take(epinfo->exclsem);
if (ret < 0) {
return ret;
}
@@ -2383,18 +2382,21 @@ int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen)
}
/* And wait for the transfer to complete */
- nbytes = usb_ehci_transfer_wait(epinfo);
- usb_osal_mutex_give(g_ehci.exclsem);
+ nbytes = usb_ehci_transfer_wait(epinfo, timeout);
+ if (nbytes < 0) {
+ goto errout_with_iocwait;
+ }
+ usb_osal_mutex_give(epinfo->exclsem);
return nbytes;
errout_with_iocwait:
epinfo->iocwait = false;
errout_with_sem:
- usb_osal_mutex_give(g_ehci.exclsem);
+ usb_osal_mutex_give(epinfo->exclsem);
return ret;
}
-int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen)
+int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
int nbytes;
int ret;
@@ -2403,14 +2405,13 @@ int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen)
DEBUGASSERT(epinfo && buffer && buflen > 0);
- ret = usb_osal_mutex_take(g_ehci.exclsem);
+ ret = usb_osal_mutex_take(epinfo->exclsem);
if (ret < 0) {
return ret;
}
ret = usb_ehci_ioc_setup(epinfo);
-
- if (ret != 0) {
+ if (ret < 0) {
goto errout_with_sem;
}
@@ -2420,14 +2421,17 @@ int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen)
}
/* And wait for the transfer to complete */
- nbytes = usb_ehci_transfer_wait(epinfo);
- usb_osal_mutex_give(g_ehci.exclsem);
+ nbytes = usb_ehci_transfer_wait(epinfo, timeout);
+ if (nbytes < 0) {
+ goto errout_with_iocwait;
+ }
+ usb_osal_mutex_give(epinfo->exclsem);
return nbytes;
errout_with_iocwait:
epinfo->iocwait = false;
errout_with_sem:
- usb_osal_mutex_give(g_ehci.exclsem);
+ usb_osal_mutex_give(epinfo->exclsem);
return ret;
}
#ifdef CONFIG_USBHOST_ASYNCH
@@ -2439,7 +2443,7 @@ int usbh_ep_bulk_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t bufl
DEBUGASSERT(epinfo && buffer && buflen > 0);
- ret = usb_osal_mutex_take(g_ehci.exclsem);
+ ret = usb_osal_mutex_take(epinfo->exclsem);
if (ret < 0) {
return ret;
}
@@ -2457,14 +2461,14 @@ int usbh_ep_bulk_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t bufl
}
/* The transfer is in progress */
- usb_osal_mutex_give(g_ehci.exclsem);
+ usb_osal_mutex_give(epinfo->exclsem);
return 0;
errout_with_callback:
epinfo->callback = NULL;
epinfo->arg = NULL;
errout_with_sem:
- usb_osal_mutex_give(&g_ehci.exclsem);
+ usb_osal_mutex_give(epinfo->exclsem);
return ret;
}
@@ -2476,7 +2480,7 @@ int usbh_ep_intr_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t bufl
DEBUGASSERT(epinfo && buffer && buflen > 0);
- ret = usb_osal_mutex_take(g_ehci.exclsem);
+ ret = usb_osal_mutex_take(epinfo->exclsem);
if (ret < 0) {
return ret;
}
@@ -2494,14 +2498,14 @@ int usbh_ep_intr_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t bufl
}
/* The transfer is in progress */
- usb_osal_mutex_give(g_ehci.exclsem);
+ usb_osal_mutex_give(epinfo->exclsem);
return 0;
errout_with_callback:
epinfo->callback = NULL;
epinfo->arg = NULL;
errout_with_sem:
- usb_osal_mutex_give(g_ehci.exclsem);
+ usb_osal_mutex_give(epinfo->exclsem);
return ret;
}
#endif
@@ -2548,7 +2552,7 @@ int usb_ep_cancel(usbh_epinfo_t ep)
* interrupt level.
*/
- ret = usb_osal_sem_take(g_ehci.exclsem);
+ ret = usb_osal_mutex_take(epinfo->exclsem);
if (ret < 0) {
return ret;
}
@@ -2688,21 +2692,14 @@ exit_terminate:
#endif
errout_with_sem:
- usb_osal_mutex_give(g_ehci.exclsem);
+ usb_osal_mutex_give(epinfo->exclsem);
return ret;
}
static void usb_ehci_bottomhalf(void *arg)
{
uint32_t pending = (uint32_t)arg;
- /* We need to have exclusive access to the EHCI data structures. Waiting
- * here is not a good thing to do on the worker thread, but there is no
- * real option (other than to reschedule and delay).
- */
- usb_osal_mutex_take(g_ehci.exclsem);
-
- /* Handle all unmasked interrupt sources */
/* USB Interrupt (USBINT)
*
* "The Host Controller sets this bit to 1 on the completion of a USB
@@ -2785,14 +2782,6 @@ static void usb_ehci_bottomhalf(void *arg)
if ((pending & EHCI_INT_AAINT) != 0) {
}
- /* Re-enable relevant EHCI interrupts. Interrupts should still be enabled
- * at the level of the interrupt controller.
- */
-
- usb_ehci_putreg(EHCI_HANDLED_INTS, &HCOR->usbintr);
-
- /* We are done with the EHCI structures */
- usb_osal_mutex_give(g_ehci.exclsem);
}
void usb_ehci_interrupt(void)
@@ -2810,23 +2799,18 @@ void usb_ehci_interrupt(void)
pending = usbsts & regval;
if (pending != 0) {
- /* Schedule interrupt handling work for the high priority worker
- * thread so that we are not pressed for time and so that we can
- * interrupt with other USB threads gracefully.
- *
- * The worker should be available now because we implement a handshake
- * by controlling the EHCI interrupts.
- */
-
- usb_workqueue_submit(&g_hpworkq, &g_ehci.work, usb_ehci_bottomhalf, (void *)pending, 0);
- /* Disable further EHCI interrupts so that we do not overrun the work
- * queue.
- */
+ /* Disable further EHCI interrupts so that we do not overrun the work queue.*/
usb_ehci_putreg(0, &HCOR->usbintr);
-
/* Clear all pending status bits by writing the value of the pending
* interrupt bits back to the status register.
*/
usb_ehci_putreg(usbsts & EHCI_INT_ALLINTS, &HCOR->usbsts);
+
+ usb_ehci_bottomhalf((void *)pending);
+
+ /* Re-enable relevant EHCI interrupts. Interrupts should still be enabled
+ * at the level of the interrupt controller.
+ */
+ usb_ehci_putreg(EHCI_HANDLED_INTS, &HCOR->usbintr);
}
} \ No newline at end of file
diff --git a/usb_config.h b/usb_config.h
index 6a1fc714..86c786cc 100644
--- a/usb_config.h
+++ b/usb_config.h
@@ -12,12 +12,24 @@
#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
#ifndef CONFIG_USBHOST_EP_NUM
-#define CONFIG_USBHOST_EP_NUM 2
+#define CONFIG_USBHOST_EP_NUM 4
+#endif
+
+#ifndef CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT
+#define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 5000
+#endif
+
+#ifndef CONFIG_USBHOST_MSC_TIMEOUT
+#define CONFIG_USBHOST_MSC_TIMEOUT 5000
#endif
#ifndef CONFIG_USBHOST_HPWORKQ_PRIO
@@ -38,7 +50,7 @@
#define CONFIG_USBHOST_PSC_PRIO 4
#endif
#ifndef CONFIG_USBHOST_PSC_STACKSIZE
-#define CONFIG_USBHOST_PSC_STACKSIZE 2048
+#define CONFIG_USBHOST_PSC_STACKSIZE 4096
#endif
#ifndef CONFIG_USBHOST_DEV_NAMELEN
@@ -54,7 +66,7 @@
#define CONFIG_USB_EHCI_QH_NUM (10)
#define CONFIG_USB_EHCI_QTD_NUM (10)
// #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
#endif \ No newline at end of file