check qtd active status to fix nbytes = 0 in nak or ping status

This commit is contained in:
sakumisu
2023-11-03 22:18:58 +08:00
parent cf4dfde49d
commit 0738c09a4d
2 changed files with 46 additions and 36 deletions

View File

@@ -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);
}

View File

@@ -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;
}
}
qh->remove_in_iaad = 1;
EHCI_HCOR->usbcmd |= EHCI_USBCMD_IAAD;
while (qtd) {
if (qtd->hw.token & QTD_TOKEN_STATUS_ACTIVE) {
return;
}
qtd = EHCI_ADDR2QTD(qtd->hw.next_qtd);
}
urb = qh->urb;
pipe = urb->pipe;
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;
}
}