When do USB Hosts require a zero-length IN packet

2019-01-14 09:24发布

问题:

I am writing code for a USB device. Suppose the USB host starts a control read transfer to read some data from the device, and the amount of data requested (wLength in the Setup Packet) is a multiple of the Endpoint 0 max packet size. Then after the host has received all the data (in the form of several IN transactions with maximum-sized data packets), will it initiate another IN transaction to see if there is more data even though there can't be more?

Here's an example sequence of events that I am wondering about:

  1. USB enumeration process: max packet size on endpoint 0 is reported to be 64.
  2. SETUP-DATA-ACK transaction starts a control read transfer, wLength = 128.
  3. IN-DATA-ACK transaction delivers first 64 bytes of data to host.
  4. IN-DATA-ACK transaction delivers last 64 bytes of data to host.
  5. IN-DATA-ACK with zero-length DATA packet? Does this transaction ever happen?
  6. OUT-DATA-ACK transaction completes Status Phase of the transfer; transfer is over.

I tested this on my computer (Windows Vista, if it matters) and the answer was no: the host was smart enough to know that no more data can be received from the device, even though all the packets sent by the device were full (maximum size allowed on Endpoint 0). I'm wondering if there are any hosts that are not smart enough, and will try to perform another IN transaction and expect to receive a zero-length data packet.

I think I read the relevant parts of the USB 2.0 and USB 3.0 specifications from usb.org but I did not find this issue addressed. I would appreciate it if someone can point me to the right section in either of those documents.

I know that a zero-length packet can be necessary if the device chooses to send less data than the host requested in wLength.

I know that I could make my code flexible enough to handle either case, but I'm hoping I don't have to.

Thanks to anyone who can answer this question!

回答1:

Read carefully USB specification:

The Data stage of a control transfer from an endpoint to the host is complete when the endpoint does one of the following:

  • Has transferred exactly the amount of data specified during the Setup stage
  • Transfers a packet with a payload size less than wMaxPacketSize or transfers a zero-length packet

So, in your case, when wLength == transfer size, answer is NO, you don't need ZLP.

In case wLength > transfer size, and (transfer size % ep0 size) == 0 answer is YES, you need ZLP.



回答2:

In general, USB uses a less-than-max-length packet to demarcate an end-of-transfer. So in the case of a transfer which is an integer multiple of max-packet-length, a ZLP is used for demarcation.

You see this in bulk pipes a lot. For example, if you have a 4096 byte transfer, that will be broken down into an integer number of max-length packets plus one zero-length-packet. If the SW driver has a big enough receive buffer set up, higher-level SW receives the entire transfer at once, when the ZLP occurs.

Control transfers are a special case because they have the wLength field, so ZLP isn't strictly necessary.

But I'd strongly suggest SW be flexible to both, as you may see variations with different USB host silicon or low-level HCD drivers.



回答3:

I would like to expand on MBR's answer. The USB specification 2.0, in section 5.5.3, says:

The Data stage of a control transfer from an endpoint to the host is complete when the endpoint does one of the following:

  • Has transferred exactly the amount of data specified during the Setup stage
  • Transfers a packet with a payload size less than wMaxPacketSize or transfers a zero-length packet

When a Data stage is complete, the Host Controller advances to the Status stage instead of continuing on with another data transaction. If the Host Controller does not advance to the Status stage when the Data stage is complete, the endpoint halts the pipe as was outlined in Section 5.3.2. If a larger-than-expected data payload is received from the endpoint, the IRP for the control transfer will be aborted/retired.

I added emphasis to one of the sentences in that quote because it seems to specifically say what the device should do: it should "halt" the pipe if the host tries to continue the data phase after it was done, and it is done if all the requested data has been transmitted (i.e. the number of bytes transferred is greater than or equal to wLength). I think halting refers to sending a STALL packet.

In other words, the device does not need a zero-length packet in this situation and in fact the USB specification says it should not provide one.



回答4:

You don't have to. (*)

The whole point of wLength is to tell the host the maximum number of bytes it should attempt to read (but it might read less !)

(*) I have seen devices that crash when IN/OUT requests were made at incorrect time during control transfers (when debugging our host solution). So any host doing what you are worried about, would of killed those devices and is hopefully not in the market.