USB/IP protocol

Architecture

The USB/IP protocol follows a server/client architecture. The server exports the USB devices and the clients import them. The device driver for the exported USB device runs on the client machine.

The client may ask for the list of the exported USB devices. To get the list the client opens a TCP/IP connection to the server, and sends an OP_REQ_DEVLIST packet on top of the TCP/IP connection (so the actual OP_REQ_DEVLIST may be sent in one or more pieces at the low level transport layer). The server sends back the OP_REP_DEVLIST packet which lists the exported USB devices. Finally the TCP/IP connection is closed.

virtual host controller                                 usb host
     "client"                                           "server"
 (imports USB devices)                             (exports USB devices)
         |                                                 |
         |                  OP_REQ_DEVLIST                 |
         | ----------------------------------------------> |
         |                                                 |
         |                  OP_REP_DEVLIST                 |
         | <---------------------------------------------- |
         |                                                 |

Once the client knows the list of exported USB devices it may decide to use one of them. First the client opens a TCP/IP connection to the server and sends an OP_REQ_IMPORT packet. The server replies with OP_REP_IMPORT. If the import was successful the TCP/IP connection remains open and will be used to transfer the URB traffic between the client and the server. The client may send two types of packets: the USBIP_CMD_SUBMIT to submit an URB, and USBIP_CMD_UNLINK to unlink a previously submitted URB. The answers of the server may be USBIP_RET_SUBMIT and USBIP_RET_UNLINK respectively.

virtual host controller                                 usb host
     "client"                                           "server"
 (imports USB devices)                             (exports USB devices)
         |                                                 |
         |                  OP_REQ_IMPORT                  |
         | ----------------------------------------------> |
         |                                                 |
         |                  OP_REP_IMPORT                  |
         | <---------------------------------------------- |
         |                                                 |
         |                                                 |
         |            USBIP_CMD_SUBMIT(seqnum = n)         |
         | ----------------------------------------------> |
         |                                                 |
         |            USBIP_RET_SUBMIT(seqnum = n)         |
         | <---------------------------------------------- |
         |                        .                        |
         |                        :                        |
         |                                                 |
         |            USBIP_CMD_SUBMIT(seqnum = m)         |
         | ----------------------------------------------> |
         |                                                 |
         |            USBIP_CMD_SUBMIT(seqnum = m+1)       |
         | ----------------------------------------------> |
         |                                                 |
         |            USBIP_CMD_SUBMIT(seqnum = m+2)       |
         | ----------------------------------------------> |
         |                                                 |
         |            USBIP_RET_SUBMIT(seqnum = m)         |
         | <---------------------------------------------- |
         |                                                 |
         |            USBIP_CMD_SUBMIT(seqnum = m+3)       |
         | ----------------------------------------------> |
         |                                                 |
         |            USBIP_RET_SUBMIT(seqnum = m+1)       |
         | <---------------------------------------------- |
         |                                                 |
         |            USBIP_CMD_SUBMIT(seqnum = m+4)       |
         | ----------------------------------------------> |
         |                                                 |
         |            USBIP_RET_SUBMIT(seqnum = m+2)       |
         | <---------------------------------------------- |
         |                        .                        |
         |                        :                        |

For UNLINK, note that after a successful USBIP_RET_UNLINK, the unlinked URB submission would not have a corresponding USBIP_RET_SUBMIT (this is explained in function stub_recv_cmd_unlink of drivers/usb/usbip/stub_rx.c).

virtual host controller                                 usb host
     "client"                                           "server"
 (imports USB devices)                             (exports USB devices)
         |                                                 |
         |            USBIP_CMD_SUBMIT(seqnum = p)         |
         | ----------------------------------------------> |
         |                                                 |
         |               USBIP_CMD_UNLINK                  |
         |         (seqnum = p+1, unlink_seqnum = p)       |
         | ----------------------------------------------> |
         |                                                 |
         |               USBIP_RET_UNLINK                  |
         |        (seqnum = p+1, status = -ECONNRESET)     |
         | <---------------------------------------------- |
         |                                                 |
         |         Note: No USBIP_RET_SUBMIT(seqnum = p)   |
         | <--X---X---X---X---X---X---X---X---X---X---X--- |
         |                        .                        |
         |                        :                        |
         |                                                 |
         |            USBIP_CMD_SUBMIT(seqnum = q)         |
         | ----------------------------------------------> |
         |                                                 |
         |            USBIP_RET_SUBMIT(seqnum = q)         |
         | <---------------------------------------------- |
         |                                                 |
         |               USBIP_CMD_UNLINK                  |
         |         (seqnum = q+1, unlink_seqnum = q)       |
         | ----------------------------------------------> |
         |                                                 |
         |               USBIP_RET_UNLINK                  |
         |           (seqnum = q+1, status = 0)            |
         | <---------------------------------------------- |
         |                                                 |

The fields are in network (big endian) byte order meaning that the most significant byte (MSB) is stored at the lowest address.

Protocol Version

The documented USBIP version is v1.1.1. The binary representation of this version in message headers is 0x0111.

This is defined in tools/usb/usbip/configure.ac

Message Format

OP_REQ_DEVLIST:

Retrieve the list of exported USB devices.

Offset

Length

Value

Description

0

2

USBIP version

2

2

0x8005

Command code: Retrieve the list of exported USB devices.

4

4

0x00000000

Status: unused, shall be set to 0

OP_REP_DEVLIST:

Reply with the list of exported USB devices.

Offset

Length

Value

Description

0

2

USBIP version

2

2

0x0005

Reply code: The list of exported USB devices.

4

4

0x00000000

Status: 0 for OK

8

4

n

Number of exported devices: 0 means no exported devices.

0x0C

From now on the exported n devices are described, if any. If no devices are exported the message ends with the previous “number of exported devices” field.

256

path: Path of the device on the host exporting the USB device, string closed with zero byte, e.g. “/sys/devices/pci0000:00/0000:00:1d.1/usb3/3-2” The unused bytes shall be filled with zero bytes.

0x10C

32

busid: Bus ID of the exported device, string closed with zero byte, e.g. “3-2”. The unused bytes shall be filled with zero bytes.

0x12C

4

busnum

0x130

4

devnum

0x134

4

speed

0x138

2

idVendor

0x13A

2

idProduct

0x13C

2

bcdDevice

0x13E

1

bDeviceClass

0x13F

1

bDeviceSubClass

0x140

1

bDeviceProtocol

0x141

1

bConfigurationValue

0x142

1

bNumConfigurations

0x143

1

bNumInterfaces

0x144

m_0

From now on each interface is described, all together bNumInterfaces times, with the following 4 fields:

1

bInterfaceClass

0x145

1

bInterfaceSubClass

0x146

1

bInterfaceProtocol

0x147

1

padding byte for alignment, shall be set to zero

0xC + i*0x138 + m_(i-1)*4

The second exported USB device starts at i=1 with the path field.

OP_REQ_IMPORT:

Request to import (attach) a remote USB device.

Offset

Length

Value

Description

0

2

USBIP version

2

2

0x8003

Command code: import a remote USB device.

4

4

0x00000000

Status: unused, shall be set to 0

8

32

busid: the busid of the exported device on the remote host. The possible values are taken from the message field OP_REP_DEVLIST.busid. A string closed with zero, the unused bytes shall be filled with zeros.

OP_REP_IMPORT:

Reply to import (attach) a remote USB device.

Offset

Length

Value

Description

0

2

USBIP version

2

2

0x0003

Reply code: Reply to import.

4

4

0x00000000

Status:

  • 0 for OK

  • 1 for error

8

From now on comes the details of the imported device, if the previous status field was OK (0), otherwise the reply ends with the status field.

256

path: Path of the device on the host exporting the USB device, string closed with zero byte, e.g. “/sys/devices/pci0000:00/0000:00:1d.1/usb3/3-2” The unused bytes shall be filled with zero bytes.

0x108

32

busid: Bus ID of the exported device, string closed with zero byte, e.g. “3-2”. The unused bytes shall be filled with zero bytes.

0x128

4

busnum

0x12C

4

devnum

0x130

4

speed

0x134

2

idVendor

0x136

2

idProduct

0x138

2

bcdDevice

0x139

1

bDeviceClass

0x13A

1

bDeviceSubClass

0x13B

1

bDeviceProtocol

0x13C

1

bConfigurationValue

0x13D

1

bNumConfigurations

0x13E

1

bNumInterfaces

The following four commands have a common basic header called ‘usbip_header_basic’, and their headers, called ‘usbip_header’ (before transfer_buffer payload), have the same length, therefore paddings are needed.

usbip_header_basic:

Offset

Length

Description

0

4

command

4

4

seqnum: sequential number that identifies requests and corresponding responses; incremented per connection

8

4

devid: specifies a remote USB device uniquely instead of busnum and devnum; for client (request), this value is ((busnum << 16) | devnum); for server (response), this shall be set to 0

0xC

4

direction:

  • 0: USBIP_DIR_OUT

  • 1: USBIP_DIR_IN

only used by client, for server this shall be 0

0x10

4

ep: endpoint number only used by client, for server this shall be 0; for UNLINK, this shall be 0

USBIP_CMD_SUBMIT:

Submit an URB

Offset

Length

Description

0

20

usbip_header_basic, ‘command’ shall be 0x00000001

0x14

4

transfer_flags: possible values depend on the USBIP_URB transfer_flags. Refer to include/uapi/linux/usbip.h and USB Request Block (URB). Refer to usbip_pack_cmd_submit() and tweak_transfer_flags() in drivers/usb/usbip/ usbip_common.c.

0x18

4

transfer_buffer_length: use URB transfer_buffer_length

0x1C

4

start_frame: use URB start_frame; initial frame for ISO transfer; shall be set to 0 if not ISO transfer

0x20

4

number_of_packets: number of ISO packets; shall be set to 0xffffffff if not ISO transfer

0x24

4

interval: maximum time for the request on the server-side host controller

0x28

8

setup: data bytes for USB setup, filled with zeros if not used.

0x30

n

transfer_buffer. If direction is USBIP_DIR_OUT then n equals transfer_buffer_length; otherwise n equals 0. For ISO transfers the padding between each ISO packets is not transmitted.

0x30+n

m

iso_packet_descriptor

USBIP_RET_SUBMIT:

Reply for submitting an URB

Offset

Length

Description

0

20

usbip_header_basic, ‘command’ shall be 0x00000003

0x14

4

status: zero for successful URB transaction, otherwise some kind of error happened.

0x18

4

actual_length: number of URB data bytes; use URB actual_length

0x1C

4

start_frame: use URB start_frame; initial frame for ISO transfer; shall be set to 0 if not ISO transfer

0x20

4

number_of_packets: number of ISO packets; shall be set to 0xffffffff if not ISO transfer

0x24

4

error_count

0x28

8

padding, shall be set to 0

0x30

n

transfer_buffer. If direction is USBIP_DIR_IN then n equals actual_length; otherwise n equals 0. For ISO transfers the padding between each ISO packets is not transmitted.

0x30+n

m

iso_packet_descriptor

USBIP_CMD_UNLINK:

Unlink an URB

Offset

Length

Description

0

20

usbip_header_basic, ‘command’ shall be 0x00000002

0x14

4

unlink_seqnum, of the SUBMIT request to unlink

0x18

24

padding, shall be set to 0

USBIP_RET_UNLINK:

Reply for URB unlink

Offset

Length

Description

0

20

usbip_header_basic, ‘command’ shall be 0x00000004

0x14

4

status: This is similar to the status of USBIP_RET_SUBMIT (share the same memory offset). When UNLINK is successful, status is -ECONNRESET; when USBIP_CMD_UNLINK is after USBIP_RET_SUBMIT status is 0

0x18

24

padding, shall be set to 0

EXAMPLE

The following data is captured from wire with Human Interface Devices (HID) payload

CmdIntrIN:  00000001 00000d05 0001000f 00000001 00000001 00000200 00000040 ffffffff 00000000 00000004 00000000 00000000
CmdIntrOUT: 00000001 00000d06 0001000f 00000000 00000001 00000000 00000040 ffffffff 00000000 00000004 00000000 00000000
            ffffffff860008a784ce5ae212376300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
RetIntrOut: 00000003 00000d06 00000000 00000000 00000000 00000000 00000040 ffffffff 00000000 00000000 00000000 00000000
RetIntrIn:  00000003 00000d05 00000000 00000000 00000000 00000000 00000040 ffffffff 00000000 00000000 00000000 00000000
            ffffffff860011a784ce5ae2123763612891b1020100000400000000000000000000000000000000000000000000000000000000000000000000000000000000