From 4b7e1f699d8ec859df4cd5594ad465fb7e704267 Mon Sep 17 00:00:00 2001 From: CTCaer Date: Sat, 28 Aug 2021 17:09:38 +0300 Subject: [PATCH] ums/xusb: do not allow multiple CBW requests On XUSB do not allow multiple requests for CBW to be done. This avoids an issue with some XHCI controllers and OS combos (e.g. ASMedia and Linux/Mac OS) which confuse that and concatenate an old CBW request with another write request (SCSI Write) and create a babble error (transmit overflow). --- bdk/usb/usb_gadget_ums.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/bdk/usb/usb_gadget_ums.c b/bdk/usb/usb_gadget_ums.c index abc0f06..4be2436 100644 --- a/bdk/usb/usb_gadget_ums.c +++ b/bdk/usb/usb_gadget_ums.c @@ -217,6 +217,7 @@ typedef struct _usbd_gadget_ums_t { u32 tag; u32 residue; u32 usb_amount_left; + bool cbw_req_queued; u32 phase_error; u32 short_packet_received; @@ -1578,6 +1579,8 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums->set_text(ums->label, "#C7EA46 Status:# Medium unmounted"); ums->timeouts++; + if (!bulk_ctxt->bulk_out_status) + ums->timeouts += 3; } if (ums->timeouts > 20) @@ -1588,6 +1591,9 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) return UMS_RES_INVALID_ARG; } + // Clear request flag to allow a new one to be queued. + ums->cbw_req_queued = false; + // Is the CBW valid? bulk_recv_pkt_t *cbw = (bulk_recv_pkt_t *)bulk_ctxt->bulk_out_buf; if (bulk_ctxt->bulk_out_length_actual != USB_BULK_CB_WRAP_LEN || cbw->Signature != USB_BULK_CB_SIG) @@ -1665,7 +1671,19 @@ static int get_next_command(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) bulk_ctxt->bulk_out_length = USB_BULK_CB_WRAP_LEN; // Queue a request to read a Bulk-only CBW. - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_CMD); + if (!ums->cbw_req_queued) + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_CMD); + else + _ums_transfer_finish(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_CMD); + + /* + * On XUSB do not allow multiple requests for CBW to be done. + * This avoids an issue with some XHCI controllers and OS combos (e.g. ASMedia and Linux/Mac OS) + * which confuse that and concatenate an old CBW request with another write request (SCSI Write) + * and create a babble error (transmit overflow). + */ + if (ums->xusb) + ums->cbw_req_queued = true; /* We will drain the buffer in software, which means we * can reuse it for the next filling. No need to advance