psc thread use event instead,add timeout for transfer
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -66,6 +66,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
|
||||
*
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
/* 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;
|
||||
}
|
||||
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;
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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();
|
||||
@@ -116,8 +146,3 @@ void usb_osal_msleep(uint32_t delay)
|
||||
{
|
||||
vTaskDelay(pdMS_TO_TICKS(delay));
|
||||
}
|
||||
|
||||
uint32_t usb_osal_get_tick(void)
|
||||
{
|
||||
return xTaskGetTickCount();
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
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 = usb_osal_sem_take(epinfo->iocsem, timeout);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = epinfo->result;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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? */
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
18
usb_config.h
18
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
|
||||
Reference in New Issue
Block a user