summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsakumisu <[email protected]>2023-11-03 22:18:58 +0800
committersakumisu <[email protected]>2023-11-03 22:18:58 +0800
commit0738c09a4d2b66974d15b9ef802f945f11473650 (patch)
tree40f49ba7d56c3f0f8d85ebefed8d0d4800ea0b7a
parentcf4dfde49d171a44c31c53ff7cf57a8d3d16465c (diff)
check qtd active status to fix nbytes = 0 in nak or ping status
-rw-r--r--class/hub/usbh_hub.c3
-rw-r--r--port/ehci/usb_hc_ehci.c75
2 files changed, 44 insertions, 34 deletions
diff --git a/class/hub/usbh_hub.c b/class/hub/usbh_hub.c
index 25038234..8c084893 100644
--- a/class/hub/usbh_hub.c
+++ b/class/hub/usbh_hub.c
@@ -299,8 +299,7 @@ static void hub_int_complete_callback(void *arg, int nbytes)
{
struct usbh_hub *hub = (struct usbh_hub *)arg;
- // >=0 can pass device enumeration on EXT hub.
- if (nbytes >= 0)
+ if (nbytes > 0)
{
usbh_hub_thread_wakeup(hub);
}
diff --git a/port/ehci/usb_hc_ehci.c b/port/ehci/usb_hc_ehci.c
index 145320f9..cdabdf01 100644
--- a/port/ehci/usb_hc_ehci.c
+++ b/port/ehci/usb_hc_ehci.c
@@ -656,17 +656,15 @@ void ehci_pipe_waitup(struct ehci_pipe *pipe)
}
}
-static void ehci_qh_scan_qtds(struct ehci_qh_hw *qh)
+static void ehci_qh_scan_qtds(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh)
{
struct ehci_qtd_hw *qtd;
+ ehci_qh_remove(qhead, qh);
+
qtd = EHCI_ADDR2QTD(qh->first_qtd);
while (qtd) {
- // if (qtd->hw.token & QTD_TOKEN_STATUS_ACTIVE) {
- // continue;
- // }
-
qtd->urb->actual_length += (qtd->total_len - ((qtd->hw.token & QTD_TOKEN_NBYTES_MASK) >> QTD_TOKEN_NBYTES_SHIFT));
ehci_qtd_free(qtd);
@@ -679,43 +677,56 @@ static void ehci_check_qh(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh)
{
struct usbh_urb *urb;
struct ehci_pipe *pipe;
+ struct ehci_qtd_hw *qtd;
uint32_t token;
token = qh->hw.overlay.token;
if (token & QTD_TOKEN_STATUS_ACTIVE) {
- } else {
- urb = qh->urb;
- pipe = urb->pipe;
+ return;
+ }
- ehci_qh_scan_qtds(qh);
- if (qh->first_qtd & QTD_LIST_END) {
- /* remove qh from list */
- ehci_qh_remove(qhead, qh);
+ qtd = EHCI_ADDR2QTD(qh->first_qtd);
- if ((token & QTD_TOKEN_STATUS_ERRORS) == 0) {
- if (token & QTD_TOKEN_TOGGLE) {
- pipe->toggle = true;
- } else {
- pipe->toggle = false;
- }
- urb->errorcode = 0;
- } else {
- if (token & QTD_TOKEN_STATUS_BABBLE) {
- urb->errorcode = -EPERM;
- pipe->toggle = 0;
- } else if (token & QTD_TOKEN_STATUS_HALTED) {
- urb->errorcode = -EPERM;
- pipe->toggle = 0;
- } else if (token & (QTD_TOKEN_STATUS_DBERR | QTD_TOKEN_STATUS_XACTERR)) {
- urb->errorcode = -EIO;
- }
- }
+ while (qtd) {
+ if (qtd->hw.token & QTD_TOKEN_STATUS_ACTIVE) {
+ return;
+ }
+ qtd = EHCI_ADDR2QTD(qtd->hw.next_qtd);
+ }
- qh->remove_in_iaad = 1;
+ urb = qh->urb;
+ pipe = urb->pipe;
- EHCI_HCOR->usbcmd |= EHCI_USBCMD_IAAD;
+ ehci_qh_scan_qtds(qhead, qh);
+
+ if ((token & QTD_TOKEN_STATUS_ERRORS) == 0) {
+ if (token & QTD_TOKEN_TOGGLE) {
+ pipe->toggle = true;
+ } else {
+ pipe->toggle = false;
}
+ urb->errorcode = 0;
+ } else {
+ if (token & QTD_TOKEN_STATUS_BABBLE) {
+ urb->errorcode = -EPERM;
+ pipe->toggle = 0;
+ } else if (token & QTD_TOKEN_STATUS_HALTED) {
+ urb->errorcode = -EPERM;
+ pipe->toggle = 0;
+ } else if (token & (QTD_TOKEN_STATUS_DBERR | QTD_TOKEN_STATUS_XACTERR)) {
+ urb->errorcode = -EIO;
+ }
+ }
+
+ if (pipe->ep_type == USB_ENDPOINT_TYPE_INTERRUPT) {
+ qh->remove_in_iaad = 0;
+ ehci_qh_free(qh);
+ ehci_pipe_waitup(pipe);
+ } else {
+ qh->remove_in_iaad = 1;
+
+ EHCI_HCOR->usbcmd |= EHCI_USBCMD_IAAD;
}
}