Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When should a USB device send a ZLP on a bulk pipe?

I'm writing firmware for a USB 2.0 full speed device that communicates with a WinUSB host, with one Bulk Pipe in each direction. When should the device send a zero-length packet (ZLP) to terminate an IN transfer, and how does it know that it should?

Section 5.8.3 of the USB 2.0 spec says:

A bulk transfer is complete when the endpoint does one of the following:

  • Has transferred exactly the amount of data expected
  • Transfers a packet with a payload size less than wMaxPacketSize or transfers a zero-length packet [ZLP]

I interpret this to mean that a ZLP should be sent when the transfer size is an integer multiple of the max packet size, and the "expected" size of the transfer is greater than the actual size (i.e. what is available to be sent). But how does the recipient know what's expected?

For instance, I'm using the WinUSBNet wrapper in C#. When I read from the pipe like this

int bytesRead;
buffer = new byte[128];
try
{
   bytesRead = m_PipeIN.Read(buffer);
   buffer = buffer.Take(bytesRead).ToArray();
}

the library calls WinUsb_ReadPipe() like this:

WinUsb_ReadPipe(InterfaceHandle(ifaceIndex),
   pipeID,
   pBuffer + offset,
   (uint)bytesToRead,
   out bytesRead,
   IntPtr.Zero);

Suppose the device has exactly 128 bytes to send, and max packet size is 64 bytes. How does the device determine what the host is "expecting", thus whether it should send a ZLP to terminate the transfer?

(Similar to this question, but that one is about control pipes. I'm asking about bulk pipes.)

like image 316
cp.engr Avatar asked Jan 25 '17 15:01

cp.engr


1 Answers

Explanation of the spec:

Case 1

Has transferred exactly the amount of data expected

This means that if the host is expecting X amount of bytes, and you send exactly X amount of bytes, the transfer stops right there. MPS and ZLP don't play into it.


Case 2

Transfers a packet with a payload size less than wMaxPacketSize or transfers a zero-length packet [ZLP]

This means that if the host is expecting X bytes but you want to send only Y bytes, where Y < X, the transfer is complete as soon as you do a "short" packet, a packet less the MPS. If Y bytes is a multiple of MPS, then you would have to do a ZLP.

Example 1 (no ZLP)

MPS = 512, the host expects 8192 bytes.

You want to send only 1500 bytes. The payload would go over in 3 packets like this:

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

When the host gets the short packet, it knows the transfer is complete, and won't continue asking for more packets for the transfer.

Example 2 (with ZLP)

MPS = 512, the host expects 8192 bytes.

You want to send only 2048 bytes. The payload would go over in 4 packets like this:

Packet 0: [512 bytes]  MPS
Packet 1: [512 bytes]  MPS
Packet 2: [512 bytes]  MPS
Packet 3: [512 bytes]  MPS

At this point, the host has received 4 MPS-sized packets so it doesn't know the transfer is complete. So it will continue to request packets from the device.

Packet 4: [0 bytes]  short packet (ZLP)

When the host gets the short packet, it knows the transfer is complete, and won't continue asking for more packets for the transfer.


Determining Transfer Size

You may be wondering how to determine the "expected" amount of bytes since BULK transfers do not have a length like CTRL transfers do. This is determined entirely by the higher-level protocol that specifies how to do transfers on the BULK pipes. The host and device both follow this protocol and thus they are in sync about how much data to transfer at any given time.

This protocol is typically specified by a class specification, like the mass-storage class protocol, or it could be some very simple protocol of your own design.

like image 136
robottobor Avatar answered Oct 18 '22 18:10

robottobor