我正在为与WinUSB主机通信的USB 2.0全速设备编写固件,每个方向都有一个Bulk Pipe。什么时候设备应该发送一个零长度数据包(ZLP)来终止IN传输,它怎么知道它应该?
USB 2.0 spec的第5.8.3节说:
当端点执行以下操作之一时,批量传输完成:
- 已准确转移了预期的数据量
- 传输有效负载大小小于wMaxPacketSize的数据包或传输零长度数据包[ZLP]
我将此解释为当传输大小是最大数据包大小的整数倍时,应该发送ZLP,和"期望&# 34;传输大小大于实际大小(即可以发送的大小)。但收件人如何知道预期的内容?
例如,我在C#中使用WinUSBNet包装器。当我从这个管道读取时
int bytesRead;
buffer = new byte[128];
try
{
bytesRead = m_PipeIN.Read(buffer);
buffer = buffer.Take(bytesRead).ToArray();
}
图书馆像这样调用WinUsb_ReadPipe():
WinUsb_ReadPipe(InterfaceHandle(ifaceIndex),
pipeID,
pBuffer + offset,
(uint)bytesToRead,
out bytesRead,
IntPtr.Zero);
假设设备正好要发送128个字节,最大数据包大小为64个字节。设备如何确定主机是什么"期待",从而是否应该发送ZLP来终止传输?
(类似于this question,但那个是关于控制管道。我问的是散装管道。)
答案 0 :(得分:4)
规范说明:
<案例1已准确转移了预期的数据量
这意味着如果主机期望X字节数,并且您发送完全 X字节量,则传输将在那里停止。 MPS和ZLP不参与其中。
<案例2传输有效负载大小小于wMaxPacketSize的数据包或传输零长度数据包[ZLP]
这意味着如果主机期望X字节但是你想只发送Y字节,那么Y <1。 X,一旦你做了&#34;短&#34;转移就完成了。数据包,一个数据包少于MPS。如果Y字节是MPS的倍数,那么你必须做一个ZLP。
MPS = 512,主机需要 8192 字节。
您只想发送 1500 字节。有效载荷将在3个包中重复:
Packet 0: [512 bytes] MPS
Packet 1: [512 bytes] MPS
Packet 2: [476 bytes] short packet
当主机获得短数据包时,它知道传输已完成,并且不再继续要求传输更多数据包。
MPS = 512,主机需要 8192 字节。
您只想发送 2048 字节。有效载荷将在4个包中过去,如下所示:
Packet 0: [512 bytes] MPS
Packet 1: [512 bytes] MPS
Packet 2: [512 bytes] MPS
Packet 3: [512 bytes] MPS
此时,主机已收到4个MPS大小的数据包,因此它不知道传输已完成。因此它将继续请求来自设备的数据包。
Packet 4: [0 bytes] short packet (ZLP)
当主机获得短数据包时,它知道传输已完成,并且不再继续要求传输更多数据包。
您可能想知道如何确定&#34;预期&#34;自BULK传输以来没有像CTRL传输那样的长度的字节数。这完全由更高级别的协议决定,该协议指定如何在BULK管道上进行传输。主机和设备都遵循此协议,因此它们在任何给定时间同步传输多少数据。
此协议通常由类规范指定,如大容量存储类协议,或者它可能是您自己设计的一些非常简单的协议。
答案 1 :(得分:0)
传输有效负载大小小于wMaxPacketSize的数据包或传输零长度数据包[ZLP]
当有效载荷数据的长度恰好是wMaxPacketSize
的整数倍时,必须发送ZLP
USB规范定义了批量传输的最后一个数据包 端点最大包大小的确切大小,整个传输 必须以零长度urb结束。
如果应用程序在这种情况下没有发送此消息,则libusb会超时 从不发送初始urb导致应用程序损坏。
所有内核驱动程序都使用URB_ZERO_PACKET来符合规范 正确。
如果数据长度恰好是wMaxPacketSize
的整数倍
第一个结束条件packetSize
&lt; wMaxPacketSize
不适用,因为在这种情况下packetSize
= wMaxPacketSize
。< / p>
所以要指出最后一个数据包已经发送的信息你需要一个ZLP,否则另一方会期望更多的数据
发送ZLP时还有其他几种情况,请参见USB in a nutshell website