代码之家  ›  专栏  ›  技术社区  ›  David Grayson

USB主机何时要求在控制读取传输结束时数据包长度为零?

  •  7
  • David Grayson  · 技术社区  · 14 年前

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

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

    1. SETUP-DATA-ACK事务启动控制读取传输,wLength=128。
    2. IN-DATA-ACK事务将前64个字节的数据传送到主机。
    3. IN-DATA-ACK事务将最后64字节的数据传送到主机。
    4. 具有零长度数据包的IN-DATA-ACK?这个交易曾经发生过吗?

    我在我的电脑上测试了这个(如果有必要的话,可以用WindowsVista),答案是 足够聪明,将尝试执行另一个IN事务,并期望收到一个零长度的数据包。

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

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

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

    感谢所有能回答这个问题的人!

    4 回复  |  直到 14 年前
        1
  •  11
  •   Étienne Hampden123    10 年前

    仔细阅读USB规范:

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

    • 已准确传输设置阶段指定的数据量

    所以,在您的例子中,当wLength==传输大小时,答案是否定的,您不需要ZLP。

        2
  •  5
  •   Nils Dmitriy Kuznetsov    11 年前

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

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

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

        3
  •  4
  •   David Grayson    6 年前

    USB specification 2.0 ,在第5.5.3节中说:

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

    • 传输有效负载大小小于wMaxPacketSize的数据包或传输长度为零的数据包

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

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

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

        4
  •  1
  •   Boris    14 年前

    你不必这么做。(*)