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

USB主机何时要求在控制读取传输结束时数据包长度为零?,usb,protocols,packets,Usb,Protocols,Packets,我正在为USB设备编写代码。假设USB主机启动控制读取传输以从设备读取一些数据,并且请求的数据量(设置数据包中的wLength)是端点0最大数据包大小的倍数。然后,在主机接收到所有数据(以具有最大大小数据包的多个in事务的形式)后,它是否会启动另一个in事务以查看是否有更多的数据,即使不能有更多的数据 下面是我想知道的事件序列示例: USB枚举进程:端点0上的最大数据包大小报告为64 SETUP-DATA-ACK事务启动控制读取传输,wLength=128 IN-DATA-ACK事务将前64个字

我正在为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上允许的最大大小)。我想知道是否有主机不够智能,并且将尝试在事务中执行另一个,并期望接收零长度的数据包

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

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

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

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

    你不必这么做。(*)

    wLength的整个要点是告诉主机它应该尝试读取的最大字节数(但它可能读取的更少!)


    (*)我见过在控制传输期间(调试主机解决方案时)在不正确的时间发出输入/输出请求时设备崩溃。因此,任何做你担心的事情的主机,都可能会杀死那些设备,希望不会出现在市场上

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

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

    控制传输是一种特殊情况,因为它们有wLength字段,所以ZLP不是严格必需的


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

    仔细阅读USB规范:

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

    • 已准确传输设置阶段指定的数据量
    • 传输有效负载大小小于wMaxPacketSize的数据包或传输长度为零的数据包
    所以,在您的例子中,当wLength==传输大小时,答案是否定的,您不需要ZLP


    如果wLength>transfer size,and(transfer size%ep0 size)==0,答案是肯定的,您需要ZLP。

    我想详述MBR的答案。第5.5.3节中的说明如下:

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

    • 已准确传输设置阶段指定的数据量
    • 传输有效负载大小小于wMaxPacketSize的数据包或传输长度为零的数据包
    当数据阶段完成时,主机控制器前进到 状态阶段,而不是继续进行另一个数据事务。 如果主机控制器在 数据阶段完成,端点停止管道,如中所述 第5.3.2节。如果从接收到大于预期的数据有效负载 端点,控制传输的IRP将是 中止/退休

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


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

    USB有一些臭名昭著的糟糕实现。有助于提高它的健壮性:在你接受的内容上要自由,在你做的事情上要保守。因此,确保你的设备在这种情况下不会损坏。没有合规主机会关心您在第三次请求时返回一个空数据包。在第一种情况下发送ZLP不必要时是否不符合规范?“ZLP不是严格必要的”-不,在“控制读取”请求的数据阶段可能是必要的,因为设备发送的数据可能少于
    wLength
    (例如,对于设备描述符,请求64个字节,但仅传输18个字节)“所有请求的数据”应更正为“