8

我正在为 USB 设备编写代码。假设 USB 主机启动控制读取传输以从设备读取一些数据,并且请求的数据量(设置数据包中的 wLength)是端点 0 最大数据包大小的倍数。那么在主机收到所有数据后(以数个最大数据包的 IN 事务的形式),它是否会发起另一个 IN 事务以查看是否还有更多数据,即使不能更多?

这是我想知道的事件序列示例:

  1. USB 枚举过程:端点 0 上的最大数据包大小报告为 64。
  2. SETUP-DATA-ACK 事务启动控制读取传输,wLength = 128。
  3. IN-DATA-ACK 事务将前 64 个字节的数据传送到主机。
  4. IN-DATA-ACK 事务将最后 64 个字节的数据传送到主机。
  5. 带有零长度数据包的 IN-DATA-ACK?这种交易是否发生过?
  6. OUT-DATA-ACK 事务完成传输的状态阶段;转移结束。

我在我的计算机上测试了这个(Windows Vista,如果重要的话),答案是否定的:主机足够聪明,知道无法从设备接收更多数据,即使设备发送的所有数据包都已满(端点 0 上允许的最大大小)。我想知道是否有任何主机不够聪明,并且会尝试执行另一个 IN 事务并期望收到一个零长度的数据包。

我想我从 usb.org 阅读了 USB 2.0 和 USB 3.0 规范的相关部分,但我没有发现这个问题得到解决。如果有人能指出我在这些文件中的正确部分,我将不胜感激。

我知道如果设备选择发送的数据少于 wLength 中请求的主机,则可能需要一个零长度的数据包。

我知道我可以使我的代码足够灵活以处理任何一种情况,但我希望我不必这样做。

感谢任何可以回答这个问题的人!

4

4 回答 4

11

仔细阅读 USB 规范:

当端点执行以下操作之一时,从端点到主机的控制传输的数据阶段完成:

  • 已准确传输设置阶段指定的数据量
  • 传输有效载荷大小小于 wMaxPacketSize 的数据包或传输零长度数据包

因此,在您的情况下,当 wLength == 传输大小时,答案是否定的,您不需要 ZLP。

如果 wLength > 传输大小,并且 (传输大小 % ep0 大小) == 0 答案是肯定的,则需要 ZLP。

于 2012-04-20T05:51:14.940 回答
5

通常,USB 使用小于最大长度的数据包来划分传输结束。因此,在传输是 max-packet-length 的整数倍的情况下,ZLP 用于划界。

您在散装管道中经常看到这种情况。例如,如果您有一个 4096 字节的传输,它将被分解为一个整数个最大长度的数据包加上一个零长度的数据包。如果 SW 驱动程序设置了足够大的接收缓冲区,则更高级别的 SW 会在 ZLP 发生时立即接收整个传输。

控制传输是一种特殊情况,因为它们具有 wLength 字段,因此 ZLP 不是绝对必要的。

但我强烈建议 SW 对两者都灵活,因为您可能会看到不同 USB 主机芯片或低级 HCD 驱动程序的变化。

于 2011-01-15T23:27:07.140 回答
4

我想扩展 MBR 的答案。USB 规范 2.0在第 5.5.3 节中说:

当端点执行以下操作之一时,从端点到主机的控制传输的数据阶段完成:

  • 已准确传输设置阶段指定的数据量
  • 传输有效载荷大小小于 wMaxPacketSize 的数据包或传输零长度数据包

当数据阶段完成时,主机控制器进入状态阶段,而不是继续进行另一个数据事务。 如果在数据阶段完成时主机控制器没有进入状态阶段,端点将停止管道,如第 5.3.2 节所述。如果从端点接收到大于预期的数据负载,则用于控制传输的 IRP 将被中止/退出。

我强调了那句话中的一个句子,因为它似乎明确说明了设备应该做什么:如果主机在完成后尝试继续数据阶段,它应该“停止”管道,并且如果所有请求的数据已传输(即传输的字节数大于或等于wLength)。我认为停止是指发送一个 STALL 数据包。

换句话说,在这种情况下,设备不需要零长度数据包,实际上 USB 规范说它不应该提供零长度数据包。

于 2014-01-02T21:31:19.760 回答
1

你不必。(*)

wLength 的全部意义在于告诉主机它应该尝试读取的最大字节数(但它可能会读取更少!)

(*) 我看到在控制传输期间(在调试我们的主机解决方案时)在不正确的时间发出 IN/OUT 请求时设备崩溃。因此,任何做您担心的事情的主机都会杀死这些设备,并且希望不会出现在市场上。

于 2010-09-21T12:57:29.807 回答