USB 主机何时需要在控制读传输结束时使用零长度 IN 数据包?
我正在为 USB 设备编写代码。假设 USB 主机启动控制读取传输以从设备读取一些数据,并且请求的数据量(设置数据包中的 wLength)是端点 0 最大数据包大小的倍数。那么主机接收到所有数据(以多个最大数据包的 IN 事务的形式)后,是否会发起另一个 IN 事务来查看是否还有更多数据,即使不能有更多数据?
以下是我想知道的事件序列示例:
- USB 枚举过程:端点 0 上的最大数据包大小据报告为 64。SETUP
- -DATA-ACK 事务启动控制读传输,wLength = 128。IN
- -DATA-ACK 事务将前 64 字节数据传送到主机。
- IN-DATA-ACK 事务将最后 64 字节数据传送到主机。
- IN-DATA-ACK 带有零长度数据包?这笔交易曾经发生过吗?
- OUT-DATA-ACK 事务完成传输的状态阶段;转移结束。
我在我的计算机(Windows Vista,如果重要的话)上测试了这一点,答案是否:主机足够聪明,知道无法从设备接收更多数据,即使所有数据包设备发送的数据已满(端点 0 允许的最大大小)。我想知道是否有任何主机不够足够智能,并且会尝试执行另一个 IN 事务并期望收到零长度数据包。
我想我从 usb.org 阅读了 USB 2.0 和 USB 3.0 规范的相关部分,但我没有发现这个问题得到解决。如果有人能指出我在这些文档中的正确部分,我将不胜感激。
我知道如果设备选择发送的数据少于主机在 wLength 中请求的数据,则可能需要零长度数据包。
我知道我可以使我的代码足够灵活来处理这两种情况,但我希望我不必这样做。
感谢任何能回答这个问题的人!
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:
- USB enumeration process: max packet size on endpoint 0 is reported to be 64.
- SETUP-DATA-ACK transaction starts a control read transfer, wLength = 128.
- IN-DATA-ACK transaction delivers first 64 bytes of data to host.
- IN-DATA-ACK transaction delivers last 64 bytes of data to host.
- IN-DATA-ACK with zero-length DATA packet? Does this transaction ever happen?
- 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!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
仔细阅读 USB 规范:
当端点执行以下操作之一时,从端点到主机的控制传输的数据阶段已完成
以下内容:
因此,在您的情况下,当 wLength == 传输大小时,答案是否定的,您不需要ZLP。
如果wLength>传输大小,并且 (传输大小 % ep0 size) == 0 答案是 YES,您需要 ZLP。
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:
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.
一般来说,USB 使用小于最大长度的数据包来划分传输结束。因此,如果传输是最大数据包长度的整数倍,则使用 ZLP 进行划分。
您在散装管道中经常看到这种情况。例如,如果您有 4096 字节的传输,它将被分解为整数个最大长度数据包加上一个零长度数据包。如果软件驱动程序设置了足够大的接收缓冲区,则当 ZLP 发生时,更高级别的软件会立即接收整个传输。
控制传输是一种特殊情况,因为它们具有 wLength 字段,因此 ZLP 并不是严格必要的。
但我强烈建议软件对两者都灵活,因为您可能会看到不同 USB 主机芯片或低级 HCD 驱动程序的变化。
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.
我想扩展 MBR 的答案。 USB 规范 2.0 在第 5.5.3 节中表示:
我强调了该引用中的其中一个句子,因为它似乎具体说明了设备应该做什么:如果主机在完成后尝试继续数据阶段,则它应该“停止”管道,并且如果全部完成,则完成请求的数据已传输(即传输的字节数大于或等于
wLength
)。我认为停止是指发送一个 STALL 数据包。换句话说,在这种情况下,设备不需要零长度数据包,事实上 USB 规范规定它不应该提供零长度数据包。
I would like to expand on MBR's answer. The USB specification 2.0, in section 5.5.3, says:
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.
你不必这样做。 (*)
wLength 的全部意义在于告诉主机它应该尝试读取的最大字节数(但它可能读取更少!)
(*) 我见过在不正确的时间发出 IN/OUT 请求时设备崩溃的情况在控制传输期间(调试我们的主机解决方案时)。因此,任何主机做你担心的事情,都会杀死这些设备,并且希望不会出现在市场上。
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.