요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
===============
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 + | | | The second exported USB device starts at i=1 |
| i*0x138 + | | | with the path field. |
| m_(i-1)*4 | | | |
+-----------+--------+------------+---------------------------------------------------+
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 |
+-----------+--------+------------+---------------------------------------------------+
| 0x13A | 1 | | bDeviceClass |
+-----------+--------+------------+---------------------------------------------------+
| 0x13B | 1 | | bDeviceSubClass |
+-----------+--------+------------+---------------------------------------------------+
| 0x13C | 1 | | bDeviceProtocol |
+-----------+--------+------------+---------------------------------------------------+
| 0x13D | 1 | | bConfigurationValue |
+-----------+--------+------------+---------------------------------------------------+
| 0x13E | 1 | | bNumConfigurations |
+-----------+--------+------------+---------------------------------------------------+
| 0x13F | 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 |
| | | Documentation/driver-api/usb/URB.rst. |
| | | 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
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
Architecture: exported device 목록
1-31USB/IP protocol은 server/client architecture를 따릅니다. server는 USB device를 export하고 client는 이를 import합니다. export된 USB device의 device driver는 client machine에서 실행됩니다.
client는 export된 USB device 목록을 요청할 수 있습니다. 목록을 얻으려면 server에 TCP/IP connection을 열고 그 위로 `OP_REQ_DEVLIST` packet을 보냅니다. 낮은 수준의 transport layer에서는 실제 packet이 하나 이상의 조각으로 전송될 수 있습니다.
server는 export된 USB device를 나열하는 `OP_REP_DEVLIST` packet을 돌려보내고, 이 교환이 끝나면 TCP/IP connection을 닫습니다.
원문의 client/server ASCII sequence를 같은 message 순서로 구조화했습니다.
===============
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 |
| <---------------------------------------------- |
| |
Architecture: import와 URB traffic
32-87export 목록을 확인한 client는 그중 하나를 사용할 수 있습니다. 먼저 server에 TCP/IP connection을 열고 `OP_REQ_IMPORT` packet을 보내며 server는 `OP_REP_IMPORT`로 응답합니다.
import에 성공하면 TCP/IP connection을 계속 열어 두고 client와 server 사이의 URB traffic 전송에 사용합니다.
client가 보내는 packet은 URB를 제출하는 `USBIP_CMD_SUBMIT`과 이미 제출한 URB를 unlink하는 `USBIP_CMD_UNLINK` 두 종류입니다. server는 각각 `USBIP_RET_SUBMIT`과 `USBIP_RET_UNLINK`로 응답할 수 있습니다.
각 SUBMIT request와 reply는 같은 `seqnum`으로 대응합니다. 여러 request를 연속해서 전송할 수 있으므로 `m`, `m+1`, `m+2` request를 보낸 뒤 reply를 받는 동안 `m+3`, `m+4`를 추가로 보낼 수 있습니다.
원문의 import와 pipelined SUBMIT sequence를 구조화했습니다.
client command와 server response의 대응입니다.
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) |
| <---------------------------------------------- |
| . |
| : |
UNLINK 동작과 byte order
88-131UNLINK가 성공해 `USBIP_RET_UNLINK`를 받으면 unlink된 URB submission에는 대응하는 `USBIP_RET_SUBMIT`이 오지 않습니다. 이 동작은 `drivers/usb/usbip/stub_rx.c`의 `stub_recv_cmd_unlink` 함수에 설명되어 있습니다.
예에서 client는 `USBIP_CMD_SUBMIT(seqnum=p)` 뒤 `USBIP_CMD_UNLINK(seqnum=p+1, unlink_seqnum=p)`를 보냅니다. server가 `USBIP_RET_UNLINK(seqnum=p+1, status=-ECONNRESET)`을 반환하면 `USBIP_RET_SUBMIT(seqnum=p)`는 보내지 않습니다.
이미 `USBIP_CMD_SUBMIT(seqnum=q)`에 대해 `USBIP_RET_SUBMIT(seqnum=q)`가 반환된 다음 `USBIP_CMD_UNLINK(seqnum=q+1, unlink_seqnum=q)`가 도착하면 server는 `USBIP_RET_UNLINK(seqnum=q+1, status=0)`을 반환합니다.
모든 field는 network byte order, 즉 big endian입니다. 따라서 most significant byte(MSB)가 가장 낮은 address에 저장됩니다.
SUBMIT 완료 전에 unlink한 경우 RET_SUBMIT이 생략됩니다.
SUBMIT reply가 이미 반환된 경우 UNLINK status는 0입니다.
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
132-139문서화된 USBIP version은 `v1.1.1`이며 message header의 binary representation은 `0x0111`입니다.
이 값은 `tools/usb/usbip/configure.ac`에 정의되어 있습니다.
문서 version과 wire header 값입니다.
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
OP_REQ_DEVLIST format
140-156`OP_REQ_DEVLIST`는 export된 USB device 목록을 가져오는 request입니다.
모든 multi-byte field는 network byte order입니다.
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 format
157-227`OP_REP_DEVLIST`는 export된 USB device 목록을 반환합니다. offset 8의 `n`이 0이면 export된 장치가 없으며 message는 해당 field에서 끝납니다.
장치가 있으면 offset `0x0C`부터 n개의 장치가 이어집니다. 각 장치는 host의 sysfs `path`, `busid`, bus/device number, speed, USB device descriptor field, interface descriptor 묶음으로 기술됩니다.
`path`는 256-byte zero-terminated string이며 예는 `/sys/devices/pci0000:00/0000:00:1d.1/usb3/3-2`입니다. `busid`는 32-byte zero-terminated string이며 예는 `3-2`입니다. 두 field의 쓰지 않는 byte는 모두 0으로 채웁니다.
각 interface는 `bInterfaceClass`, `bInterfaceSubClass`, `bInterfaceProtocol`, alignment용 zero padding byte의 4 field로 표현하며 이 묶음을 `bNumInterfaces`번 반복합니다.
두 번째 이후 장치 i는 `0xC + i*0x138 + m_(i-1)*4`에서 path field로 시작합니다. 여기서 `m_(i-1)`은 앞선 장치들의 interface 수가 차지한 4-byte 묶음을 반영합니다.
장치 목록 전까지의 reply header입니다.
첫 번째 장치 record의 offset과 descriptor field입니다.
offset 0x144부터 interface마다 반복되는 4-byte 묶음입니다.
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 + | | | The second exported USB device starts at i=1 |
| i*0x138 + | | | with the path field. |
| m_(i-1)*4 | | | |
+-----------+--------+------------+---------------------------------------------------+
OP_REQ_IMPORT format
228-246`OP_REQ_IMPORT`는 remote USB device를 import, 즉 attach하도록 요청합니다.
offset 8의 32-byte `busid`는 remote host가 export한 장치의 Bus ID이며 `OP_REP_DEVLIST.busid`에서 받은 값 중 하나를 사용합니다. string은 zero byte로 끝내고 쓰지 않는 byte는 0으로 채웁니다.
remote 장치 attach request의 wire layout입니다.
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 format
247-300`OP_REP_IMPORT`는 remote USB device import 요청에 대한 reply입니다. status는 성공이면 0, error이면 1입니다.
status가 1이면 reply는 status field에서 끝납니다. status가 0이면 offset 8부터 import된 장치의 상세 정보가 이어집니다.
성공 record는 256-byte `path`, 32-byte `busid`, busnum/devnum/speed, USB device descriptor field로 구성됩니다. `path`와 `busid`는 NUL로 끝내고 나머지 byte를 0으로 채웁니다.
status가 error이면 이 header 뒤에서 message가 끝납니다.
성공한 import reply의 장치 descriptor입니다.
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 |
+-----------+--------+------------+---------------------------------------------------+
| 0x13A | 1 | | bDeviceClass |
+-----------+--------+------------+---------------------------------------------------+
| 0x13B | 1 | | bDeviceSubClass |
+-----------+--------+------------+---------------------------------------------------+
| 0x13C | 1 | | bDeviceProtocol |
+-----------+--------+------------+---------------------------------------------------+
| 0x13D | 1 | | bConfigurationValue |
+-----------+--------+------------+---------------------------------------------------+
| 0x13E | 1 | | bNumConfigurations |
+-----------+--------+------------+---------------------------------------------------+
| 0x13F | 1 | | bNumInterfaces |
+-----------+--------+------------+---------------------------------------------------+
usbip_header_basic
301-333다음 네 command는 `usbip_header_basic`이라는 공통 기본 header를 사용합니다. transfer_buffer payload 앞의 전체 header인 `usbip_header`는 네 command에서 길이가 같아야 하므로 짧은 command에는 padding이 필요합니다.
`seqnum`은 request와 대응 response를 식별하는 순차 번호이며 connection마다 증가합니다.
client request의 `devid`는 remote USB device를 고유하게 지정하며 `((busnum << 16) | devnum)`으로 만듭니다. server response에서는 0으로 설정합니다.
`direction`은 `0=USBIP_DIR_OUT`, `1=USBIP_DIR_IN`이며 client만 사용하고 server는 0으로 둡니다. `ep`는 endpoint number로 client만 사용하며 server와 UNLINK에서는 0입니다.
모든 USBIP_CMD/RET message 앞에 오는 20-byte header입니다.
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
334-374`USBIP_CMD_SUBMIT`은 URB를 제출하며 `usbip_header_basic.command`는 `0x00000001`입니다.
`transfer_flags` 값은 `USBIP_URB transfer_flags`에 따라 달라집니다. 정의와 의미는 `include/uapi/linux/usbip.h`, `Documentation/driver-api/usb/URB.rst`, `drivers/usb/usbip/usbip_common.c`의 `usbip_pack_cmd_submit()`과 `tweak_transfer_flags()`를 참고합니다.
`transfer_buffer_length`는 URB의 같은 field를 사용합니다. `start_frame`은 ISO transfer의 initial frame이며 ISO가 아니면 0입니다. `number_of_packets`는 ISO packet 수이며 ISO가 아니면 `0xffffffff`입니다.
`interval`은 server-side host controller에서 request의 maximum time이며 `setup`은 USB setup data 8 byte입니다. 사용하지 않으면 0으로 채웁니다.
offset `0x30`의 transfer buffer는 `USBIP_DIR_OUT`일 때 길이가 `transfer_buffer_length`, 그 밖에는 0입니다. ISO transfer에서는 각 ISO packet 사이 padding을 전송하지 않습니다. 그 뒤 `iso_packet_descriptor`가 이어집니다.
URB submit request의 header와 payload layout입니다.
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 |
| | | Documentation/driver-api/usb/URB.rst. |
| | | 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
375-408`USBIP_RET_SUBMIT`은 URB submit에 대한 reply이며 `usbip_header_basic.command`는 `0x00000003`입니다.
`status`가 0이면 URB transaction 성공이며 0이 아니면 어떤 error가 발생한 것입니다. `actual_length`는 URB data byte 수로 URB의 같은 field를 사용합니다.
`start_frame`과 `number_of_packets`의 ISO/non-ISO 규칙은 SUBMIT과 같습니다. `error_count` 뒤의 8 byte는 padding이며 반드시 0입니다.
offset `0x30`의 transfer buffer는 `USBIP_DIR_IN`이면 길이가 `actual_length`, 그 밖에는 0입니다. ISO packet 사이 padding은 전송하지 않으며 뒤에 `iso_packet_descriptor`가 이어집니다.
URB submit reply의 header와 payload layout입니다.
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
409-421`USBIP_CMD_UNLINK`는 URB를 unlink하며 `usbip_header_basic.command`는 `0x00000002`입니다.
offset `0x14`의 `unlink_seqnum`은 unlink할 SUBMIT request의 sequence number입니다. 나머지 24 byte는 전체 `usbip_header` 길이를 맞추는 padding이며 반드시 0입니다.
URB unlink request layout입니다.
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
422-438`USBIP_RET_UNLINK`는 URB unlink reply이며 `usbip_header_basic.command`는 `0x00000004`입니다.
offset `0x14`의 `status`는 `USBIP_RET_SUBMIT.status`와 같은 memory offset을 공유하며 의미도 유사합니다. UNLINK가 성공하면 `-ECONNRESET`, `USBIP_RET_SUBMIT` 뒤에 `USBIP_CMD_UNLINK`가 온 경우에는 0입니다.
offset `0x18`부터 24 byte는 padding이며 반드시 0입니다.
URB unlink reply layout입니다.
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 |
+-----------+--------+---------------------------------------------------+
HID wire capture 예
439-452마지막 data는 Human Interface Device(HID) payload를 wire에서 capture한 예입니다.
`CmdIntrIN`과 `CmdIntrOUT`은 command `00000001`, 즉 `USBIP_CMD_SUBMIT`이며 각각 direction `00000001`과 `00000000`을 가집니다. `RetIntrOut`과 `RetIntrIn`은 command `00000003`, 즉 `USBIP_RET_SUBMIT`입니다.
`CmdIntrOUT`과 `RetIntrIn`에는 header 다음의 실제 hexadecimal payload가 이어집니다. 아래 접을 수 있는 원문 block은 capture byte를 줄바꿈과 값까지 그대로 보존합니다.
예제의 네 message label과 protocol 역할입니다.
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
요약·해설
usbip_protocol.rst:1-452USB/IP는 server가 물리 USB device를 export하고 client의 virtual host controller가 import하는 protocol입니다. discovery connection은 목록 응답 뒤 닫히지만 성공한 import connection은 URB traffic을 위해 유지됩니다.
wire field는 모두 big endian이며 공통 20-byte `usbip_header_basic` 뒤에 command별 field와 선택적 payload가 이어집니다. 표는 원문의 offset, length, constant와 조건을 빠짐없이 보존합니다.
장치 발견부터 URB 전송·해제까지의 상위 흐름입니다.