USB/IP 協議¶
架構¶
USB/IP 協議遵循伺服器/客戶端架構。伺服器匯出 USB 裝置,客戶端匯入它們。匯出 USB 裝置的裝置驅動程式在客戶端機器上執行。
客戶端可以請求匯出 USB 裝置的列表。為了獲取列表,客戶端開啟與伺服器的 TCP/IP 連線,並在 TCP/IP 連線之上傳送 OP_REQ_DEVLIST 資料包(因此實際的 OP_REQ_DEVLIST 可能在底層傳輸層中以一個或多個片段傳送)。伺服器發回 OP_REP_DEVLIST 資料包,其中列出了匯出的 USB 裝置。最後,TCP/IP 連線關閉。
virtual host controller usb host
"client" "server"
(imports USB devices) (exports USB devices)
| |
| OP_REQ_DEVLIST |
| ----------------------------------------------> |
| |
| OP_REP_DEVLIST |
| <---------------------------------------------- |
| |
一旦客戶端知道匯出 USB 裝置的列表,它就可以決定使用其中一個。首先,客戶端開啟與伺服器的 TCP/IP 連線併發送 OP_REQ_IMPORT 資料包。伺服器回覆 OP_REP_IMPORT。如果匯入成功,則 TCP/IP 連線保持開啟狀態,並將用於在客戶端和伺服器之間傳輸 URB 流量。客戶端可以傳送兩種型別的資料包:USBIP_CMD_SUBMIT 以提交 URB,以及 USBIP_CMD_UNLINK 以取消連結先前提交的 URB。伺服器的答案可能是 USBIP_RET_SUBMIT 和 USBIP_RET_UNLINK 分別。
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,請注意,在成功執行 USBIP_RET_UNLINK 後,取消連結的 URB 提交將沒有相應的 USBIP_RET_SUBMIT(這在 drivers/usb/usbip/stub_rx.c 的函式 stub_recv_cmd_unlink 中進行了解釋)。
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) |
| <---------------------------------------------- |
| |
欄位採用網路(大端)位元組順序,這意味著最高有效位元組 (MSB) 儲存在最低地址。
協議版本¶
已記錄的 USBIP 版本為 v1.1.1。此版本在訊息頭中的二進位制表示形式為 0x0111。
這在 tools/usb/usbip/configure.ac 中定義。
訊息格式¶
- OP_REQ_DEVLIST
檢索匯出 USB 裝置的列表。
偏移量 |
長度 |
值 |
描述 |
|---|---|---|---|
0 |
2 |
USBIP 版本 |
|
2 |
2 |
0x8005 |
命令程式碼:檢索匯出 USB 裝置的列表。 |
4 |
4 |
0x00000000 |
狀態:未使用,應設定為 0 |
- OP_REP_DEVLIST
回覆匯出 USB 裝置的列表。
偏移量 |
長度 |
值 |
描述 |
|---|---|---|---|
0 |
2 |
USBIP 版本 |
|
2 |
2 |
0x0005 |
回覆程式碼:匯出 USB 裝置的列表。 |
4 |
4 |
0x00000000 |
狀態:0 表示 OK |
8 |
4 |
n |
匯出裝置的數量:0 表示沒有匯出裝置。 |
0x0C |
從現在開始,將描述匯出的 n 個裝置(如果存在)。如果沒有匯出裝置,則訊息以之前的“匯出裝置數量”欄位結束。 |
||
256 |
path:在匯出 USB 裝置的宿主機上裝置的路徑,以零位元組結尾的字串,例如“/sys/devices/pci0000:00/0000:00:1d.1/usb3/3-2”。未使用的位元組應填充零位元組。 |
||
0x10C |
32 |
busid:匯出裝置的匯流排 ID,以零位元組結尾的字串,例如“3-2”。未使用的位元組應填充零位元組。 |
|
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 |
從現在開始,每個介面都將被描述,總共 bNumInterfaces 次,包含以下 4 個欄位 |
|
1 |
bInterfaceClass |
||
0x145 |
1 |
bInterfaceSubClass |
|
0x146 |
1 |
bInterfaceProtocol |
|
0x147 |
1 |
對齊的填充位元組,應設定為零 |
|
0xC + i*0x138 + m_(i-1)*4 |
第二個匯出的 USB 裝置從 i=1 開始,包含 path 欄位。 |
- OP_REQ_IMPORT
請求匯入(連線)遠端 USB 裝置。
偏移量 |
長度 |
值 |
描述 |
|---|---|---|---|
0 |
2 |
USBIP 版本 |
|
2 |
2 |
0x8003 |
命令程式碼:匯入遠端 USB 裝置。 |
4 |
4 |
0x00000000 |
狀態:未使用,應設定為 0 |
8 |
32 |
busid:遠端主機上匯出裝置的 busid。可能的值取自訊息欄位 OP_REP_DEVLIST.busid。以零結尾的字串,未使用的位元組應填充零。 |
- OP_REP_IMPORT
回覆匯入(連線)遠端 USB 裝置。
偏移量 |
長度 |
值 |
描述 |
|---|---|---|---|
0 |
2 |
USBIP 版本 |
|
2 |
2 |
0x0003 |
回覆程式碼:回覆匯入。 |
4 |
4 |
0x00000000 |
狀態
|
8 |
從現在開始,將是匯入裝置的詳細資訊,如果之前的狀態欄位為 OK (0),否則回覆以狀態欄位結束。 |
||
256 |
path:在匯出 USB 裝置的宿主機上裝置的路徑,以零位元組結尾的字串,例如“/sys/devices/pci0000:00/0000:00:1d.1/usb3/3-2”。未使用的位元組應填充零位元組。 |
||
0x108 |
32 |
busid:匯出裝置的匯流排 ID,以零位元組結尾的字串,例如“3-2”。未使用的位元組應填充零位元組。 |
|
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”,並且它們的標頭,稱為“usbip_header”(在 transfer_buffer 有效負載之前),具有相同的長度,因此需要填充。
usbip_header_basic
偏移量 |
長度 |
描述 |
|---|---|---|
0 |
4 |
command |
4 |
4 |
seqnum:標識請求和相應響應的序列號;每次連線遞增 |
8 |
4 |
devid:唯一指定遠端 USB 裝置,而不是 busnum 和 devnum;對於客戶端(請求),此值為 ((busnum << 16) | devnum);對於伺服器(響應),應設定為 0 |
0xC |
4 |
direction
僅由客戶端使用,對於伺服器,此值應為 0 |
0x10 |
4 |
ep:端點號僅由客戶端使用,對於伺服器,此值應為 0;對於 UNLINK,此值應為 0 |
- USBIP_CMD_SUBMIT
提交 URB
偏移量 |
長度 |
描述 |
|---|---|---|
0 |
20 |
usbip_header_basic,“command”應為 0x00000001 |
0x14 |
4 |
transfer_flags:可能的值取決於 USBIP_URB transfer_flags。請參閱 include/uapi/linux/usbip.h 和 USB 請求塊 (URB)。請參閱 drivers/usb/usbip/ usbip_common.c 中的 usbip_pack_cmd_submit() 和 tweak_transfer_flags()。 |
0x18 |
4 |
transfer_buffer_length:使用 URB transfer_buffer_length |
0x1C |
4 |
start_frame:使用 URB start_frame;ISO 傳輸的初始幀;如果不是 ISO 傳輸,則應設定為 0 |
0x20 |
4 |
number_of_packets:ISO 資料包的數量;如果不是 ISO 傳輸,則應設定為 0xffffffff |
0x24 |
4 |
interval:伺服器端主機控制器上請求的最大時間 |
0x28 |
8 |
setup:USB 設定的資料位元組,如果未使用,則填充零。 |
0x30 |
n |
transfer_buffer。如果 direction 為 USBIP_DIR_OUT,則 n 等於 transfer_buffer_length;否則 n 等於 0。對於 ISO 傳輸,每個 ISO 資料包之間的填充不會傳輸。 |
0x30+n |
m |
iso_packet_descriptor |
- USBIP_RET_SUBMIT
提交 URB 的回覆
偏移量 |
長度 |
描述 |
|---|---|---|
0 |
20 |
usbip_header_basic,“command”應為 0x00000003 |
0x14 |
4 |
status:零表示成功的 URB 事務,否則會發生某種錯誤。 |
0x18 |
4 |
actual_length:URB 資料位元組數;使用 URB actual_length |
0x1C |
4 |
start_frame:使用 URB start_frame;ISO 傳輸的初始幀;如果不是 ISO 傳輸,則應設定為 0 |
0x20 |
4 |
number_of_packets:ISO 資料包的數量;如果不是 ISO 傳輸,則應設定為 0xffffffff |
0x24 |
4 |
error_count |
0x28 |
8 |
padding,應設定為 0 |
0x30 |
n |
transfer_buffer。如果 direction 為 USBIP_DIR_IN,則 n 等於 actual_length;否則 n 等於 0。對於 ISO 傳輸,每個 ISO 資料包之間的填充不會傳輸。 |
0x30+n |
m |
iso_packet_descriptor |
- USBIP_CMD_UNLINK
取消連結 URB
偏移量 |
長度 |
描述 |
|---|---|---|
0 |
20 |
usbip_header_basic,“command”應為 0x00000002 |
0x14 |
4 |
unlink_seqnum,要取消連結的 SUBMIT 請求的序列號 |
0x18 |
24 |
padding,應設定為 0 |
- USBIP_RET_UNLINK
URB 取消連結的回覆
偏移量 |
長度 |
描述 |
|---|---|---|
0 |
20 |
usbip_header_basic,“command”應為 0x00000004 |
0x14 |
4 |
status:這與 USBIP_RET_SUBMIT 的狀態類似(共享相同的記憶體偏移量)。當 UNLINK 成功時,status 為 -ECONNRESET;當 USBIP_CMD_UNLINK 在 USBIP_RET_SUBMIT 之後時,status 為 0 |
0x18 |
24 |
padding,應設定為 0 |
示例¶
以下資料是從 Human Interface Devices (HID) 有效負載的線路中捕獲的
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