Can you assume predictable ordering of responses when enqueuing multiple USB Mass Storage read commands?
Short answer:
No, you cannot safely assume that the responses will be returned in the same order you enqueued them โ unless you implement strict synchronization and tracking mechanisms.
Even though the USB Mass Storage Class (MSC) Bulk-Only Transport (BOT) protocol is logically sequential (CBW โ Data โ CSW), the XHCI controller and host stack introduce a layer of abstraction and parallelism:
XHCI TRBs (Transfer Request Blocks) are processed asynchronously.
The controller may reorder or pipeline requests for performance.
The Bulk-In endpoint is shared for both data and CSW, and the host must parse and interpret the incoming data stream correctly.
The key is the dCBWTag
field in the CBW and the matching dCSWTag
in the CSW. This is your only reliable way to correlate a CSW with its corresponding CBW.
However, this doesn't help you before the CSW โ i.e., when you're reading the actual data payload. So you must:
Track the order of CBWs you enqueue.
Associate each CBW with a known memory buffer for its expected data size.
Ensure that the Bulk-In TRBs are aligned with the expected data sizes and order.
To manage multiple enqueued requests safely:
Maintain a queue of pending commands, each with:
CBW tag
Expected data size
Target memory address
Enqueue Bulk-In TRBs in the same order as CBWs, matching the expected data sizes.
On interrupt, parse the data and CSW, and match using the tag.
Validate that the data received matches the expected size before processing the CSW.
If any command stalls, the entire sequence may be disrupted.
If data sizes are misaligned, you may read part of one response into the wrong buffer.
CSWs are only 13 bytes, but they must be read after the data phase โ so you must know when the data ends.
CBW TagLBASizeData AddressCSW Address0x0104 KiB0x100000x10000x0284 KiB0x200000x11000x032024 KiB0x300000x1200
If you enqueue TRBs in this exact order and sizes match, yes, the data will likely end up in the correct buffers โ but only if nothing goes wrong.
To maximize throughput without risking data misalignment, consider:
Using UASP (USB Attached SCSI Protocol) instead of BOT โ it supports command queuing natively.
Implementing a state machine to track each command's lifecycle.
Using interrupts or polling to confirm each transfer before proceeding.