我正在为与WinUSB主机通信的USB 2.0全速设备编写固件,每个方向都有一个Bulk Pipe。设备何时应该发送零长度数据包(ZLP)来终止IN传输,它如何知道应该这样做?
USB 2.0规范的第5.8.3节说:
当端点执行以下操作之一时,批量传输完成:
已准确传输了预期的数据量
传输有效载荷大小小于wMaxPacketSize的数据包或传输零长度数据包[ZLP]
我的解释是,当传输大小是最大数据包大小的整数倍,并且传输的“预期”大小大于实际大小(即可以发送的大小)时,应该发送ZLP 。但是接收者如何知道期望的呢?
例如,我在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来终止传输?
(类似于这个问题,但是那是关于控制管道的。我要问的是散装管道。)
规格说明:
已准确传输了预期的数据量
这意味着,如果主机期望X个字节的数量,而您恰好发送了 X个字节的数量,则传输就在那里停止。MPS和ZLP不起作用。
传输有效载荷大小小于wMaxPacketSize的数据包或传输零长度数据包[ZLP]
这意味着,如果主机期望X个字节,但您只想发送Y个字节(Y MPS = 512,主机期望8192字节。 您只想发送1500个字节。有效负载将以3个数据包的形式经过: 当主机收到短数据包时,它知道传输已完成,并且不会继续请求更多数据包进行传输。 MPS = 512,主机期望8192字节。 您只想发送2048个字节。有效载荷将像这样在4个数据包中传递: 此时,主机已收到4个MPS大小的数据包,因此它不知道传输已完成。因此它将继续从设备请求数据包。 当主机收到短数据包时,它知道传输已完成,并且不会继续请求更多数据包进行传输。 您可能想知道如何确定“预期的”字节数,因为BULK传输没有CTRL传输那样长。这完全由更高级别的协议决定,该协议指定如何在BULK管道上进行传输。主机和设备都遵循此协议,因此它们在任何给定时间都可以同步传输多少数据。 该协议通常由类规范(例如,大容量存储类协议)指定,或者可以是您自己设计的一些非常简单的协议。示例1(无ZLP)
Packet 0: [512 bytes] MPS
Packet 1: [512 bytes] MPS
Packet 2: [476 bytes] short packet
示例2(使用ZLP)
Packet 0: [512 bytes] MPS
Packet 1: [512 bytes] MPS
Packet 2: [512 bytes] MPS
Packet 3: [512 bytes] MPS
Packet 4: [0 bytes] short packet (ZLP)
确定传输大小