diff --git a/src/add-ons/kernel/busses/usb/ehci.cpp b/src/add-ons/kernel/busses/usb/ehci.cpp index 5aa27232c8..70ea5b15d1 100644 --- a/src/add-ons/kernel/busses/usb/ehci.cpp +++ b/src/add-ons/kernel/busses/usb/ehci.cpp @@ -1500,9 +1500,24 @@ EHCI::FinishTransfers() callbackStatus = B_DEV_CRC_ERROR; reasons++; } + if ((transfer->queue_head->endpoint_chars + & EHCI_QH_CHARS_EPS_HIGH) == 0) { + // For full-/lowspeed endpoints the unused ping + // state bit is used as another error bit, it is + // unspecific however. + if ((status & EHCI_QTD_STATUS_LS_ERR) != 0) { + callbackStatus = B_DEV_STALLED; + reasons++; + } + } if (reasons > 1) callbackStatus = B_DEV_MULTIPLE_ERRORS; + else if (reasons == 0) { + TRACE_ERROR("error counter counted down to zero " + "but none of the error bits are set\n"); + callbackStatus = B_DEV_STALLED; + } } else if (status & EHCI_QTD_STATUS_BABBLE) { // there is a babble condition callbackStatus = transfer->incoming ? B_DEV_FIFO_OVERRUN : B_DEV_FIFO_UNDERRUN; diff --git a/src/add-ons/kernel/busses/usb/ehci_hardware.h b/src/add-ons/kernel/busses/usb/ehci_hardware.h index 5344332bf4..876414d184 100644 --- a/src/add-ons/kernel/busses/usb/ehci_hardware.h +++ b/src/add-ons/kernel/busses/usb/ehci_hardware.h @@ -237,6 +237,7 @@ typedef struct ehci_qtd { #define EHCI_QTD_STATUS_MISSED (1 << 2) // Missed Micro-Frame #define EHCI_QTD_STATUS_SPLIT (1 << 1) // Split Transaction State #define EHCI_QTD_STATUS_PING (1 << 0) // Ping State +#define EHCI_QTD_STATUS_LS_ERR (1 << 0) // Full-/Lowspeed Error #define EHCI_QTD_PAGE_MASK 0xfffff000