首页 文章

什么时候USB主机在控制读传输结束时需要零长度的IN数据包?

提问于
浏览
7

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

以下是我想知道的一系列事件示例:

  • USB枚举过程: endpoints 0上的最大数据包大小报告为64 .

  • SETUP-DATA-ACK事务启动控制读传输,wLength = 128 .

  • IN-DATA-ACK事务将前64个字节的数据传送给主机 .

  • IN-DATA-ACK事务向主机提供最后64字节的数据 .

  • 带有零长度DATA包的IN-DATA-ACK?这次交易是否会发生?

  • OUT-DATA-ACK事务完成传输的状态阶段;转移结束了 .

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

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

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

我知道我可以使我的代码足够灵活,以处理任何一种情况,但我希望我没有必要 .

感谢能够回答这个问题的任何人!

4 回答

  • 1

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

    你在散装管道中看到了很多 . 例如,如果您有4096字节的传输,则会将其分解为整数个最大长度数据包加上一个零长度数据包 . 如果SW驱动器具有足够大的接收缓冲区设置,则当ZLP发生时,更高级别的SW立即接收整个传输 .

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

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

  • 9

    仔细阅读USB规范:

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

    • 已准确传输了在安装阶段指定的数据量

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

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

    如果wLength>传输大小,(传输大小%ep0大小)== 0回答为是,则需要ZLP .

  • 3

    我想扩展MBR的答案 . USB specification 2.0,在5.5.3节中说:

    当 endpoints 执行以下操作之一时,从 endpoints 到主机的控制传输的数据阶段已完成:已准确传输在安装阶段指定的数据量传输有效负载大小小于wMaxPacketSizeor的数据包传输零-length数据包完成数据阶段后,主机控制器将进入状态阶段,而不是继续进行另一个数据事务处理 . 如果主机控制器在数据阶段完成时没有进入状态阶段,则 endpoints 将停止管道,如第5.3.2节中所述 . 如果从 endpoints 接收到大于预期的数据有效载荷,则控制传输的IRP将被中止/退出 .

    我强调了引用中的一个句子,因为它似乎具体说明了设备应该做什么:如果主机在完成后尝试继续数据阶段,它应该"halt"管道如果所有请求都完成了数据已传输(即传输的字节数大于或等于 wLength ) . 我认为暂停是指发送STALL数据包 .

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

  • 5

    你不必 . (*)

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

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

相关问题