USB bulk data transfers is how most data transfer occurs between a USB host such as a PC and a peripheral. This post shows, with help from a Total Phase Beagle USB 480, how the data transfer looks like. Here’s data captured using Data Center software and a Total Phase Beagle USB 480. According to the USB specification, all bits in a byte are written to the bus in little-endian fashion, and multi-byte values are also written in little-endian order. While the latter is still valid with the Beagle USB 480, single byte values are represented in their normal big-endian order.
Each USB bulk data transfer is broken into smaller data transfers. Each of the smaller data transfers is initiated by a token packet, followed by a data packet, and an ACK packet.
Incoming transfers begin with a token packet, that has a PID (packet identifier) of IN (0x69) in the first byte. Actually, the PID is contained in the last 4 bits (0x9), the first 4 bits are a one’s complement of that value (0x6). The second and third bytes form a single word in little endian byte order, containing a 5-bit CRC, followed by a 4-bit endpoint ID, followed by a 7-bit device ID. Thus ASCII hex sequence 81 58 in the figure above, should be interpreted as 0x5881, which results in a CRC of 0x0B, an endpoint ID of 0x1, and a device ID of 0x01.
The token packet is followed by a data packet. The PID of the data packet may be DATA0 (0xC3) or DATA1 (0x4B) for full-speed, and also DATA2 (0x87) for high-speed bulk transfers. The data packet has a maximum payload size determined by the USB specification, and is described by wMaxPacketSize attribute in the endpoint descriptor. It may be 8, 16, 32, or 64 bytes for full-speed bulk endpoints (USB 1.1), and also 512 bytes for high-speed (USB 2.0) bulk endpoints. It is 64 bytes in the capture shown above. The payload is followed by a 2-byte CRC.
The ACK handshake packet indicates the end of data transfer. A bulk data transfer is composed of several such data transfers in sequence. The end of a bulk data transfer is signalled by a data packet that has less than wMaxPacketSize bytes. If the last, or only data packet, carries wMaxPacketSize, a data transfer containing data packet with payload size of 0 bytes is required.
Outgoing transfers are quite similar, except that the token packet uses a PID of OUT (0xE1, or 0x1 to be more accurate). Outgoing bulk data transfers can appear jumbled up with incoming bulk data transfers. Applications that leverage Beagle API need to take this into consideration, when parsing data captured on the bus.