7

我正在为与 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 来终止传输?

(类似于这个问题,但那个问题是关于控制管道的。我问的是散装管道。)

4

2 回答 2

8

规格说明:

情况1

已准确传输预期的数据量

这意味着,如果主机期望 X 数量的字节,而您恰好发送X 数量的字节,则传输将在此处停止。MPS 和 ZLP 不参与其中。


案例2

传输有效载荷大小小于 wMaxPacketSize 的数据包或传输零长度数据包 [ZLP]

这意味着,如果主机期望 X 字节,但您只想发送 Y 字节,其中 Y < X,则只要您执行“短”数据包,即减去 MPS 的数据包,传输就完成了。如果 Y 字节是 MPS 的倍数,那么你将不得不做一个 ZLP。

示例 1(无 ZLP)

MPS = 512,主机需要8192字节。

您只想发送1500个字节。有效载荷将像这样在 3 个数据包中传输:

Packet 0: [512 bytes]  MPS
Packet 1: [512 bytes]  MPS
Packet 2: [476 bytes]  short packet

当主机收到短数据包时,它就知道传输完成了,并且不会继续要求更多的数据包进行传输。

示例 2(使用 ZLP)

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)

当主机收到短数据包时,它就知道传输完成了,并且不会继续要求更多的数据包进行传输。


确定传输大小

您可能想知道如何确定“预期”字节数,因为 BULK 传输没有 CTRL 传输那样的长度。这完全由指定如何在 BULK 管道上进行传输的高级协议确定。主机和设备都遵循此协议,因此它们在任何给定时间要传输多少数据是同步的。

该协议通常由类规范指定,例如大容量存储类协议,或者它可以是您自己设计的一些非常简单的协议。

于 2017-01-26T06:57:19.677 回答
0

传输有效载荷大小小于 wMaxPacketSize 的数据包或传输零长度数据包 [ZLP]

当有效载荷数据的长度恰好是 的整数倍时,必须发送 ZLPwMaxPacketSize

USB 规范定义,如果批量传输的最后一个数据包具有端点最大数据包大小的确切大小,则整个传输 必须以零长度 urb 终止。

如果应用程序在这种情况下未发送此内容,libusb 会超时,并且永远不会发送初始 urb,从而导致应用程序损坏。

所有内核驱动程序都使用 URB_ZERO_PACKET 正确遵守规范。

来源: http: //libusb.org/ticket/6

如果数据长度恰好是wMaxPacketSize 第一个结束条件的整数倍packetSize < wMaxPacketSize不适用,因为在这种情况下packetSize = wMaxPacketSize

所以要表明最后一个数据包已经发送的信息,你需要一个 ZLP,否则对方会期望更多数据

发送 ZLP 时还有其他几种情况,请参阅USB 简而言之网站

于 2017-01-26T11:06:51.357 回答