0%

通过网络共享 USB 设备的尝试

在网上冲浪时发现 VirtualHere,想起以前在 老毛子 Padavan 固件 上看到 VirtualHere 和网络共享打印机相关的内容,但还没尝试过。
搜索了一下,发现 VirtualHere 是商业软件,免费许可仅允许共享一个设备。
USB over IPUSB over Network 关键词搜索,发现了 USB/IP PROJECT,最终找到了 usbipd-win 项目,准备搭建测试。

想到的使用场景:

  • 局域网共享专有 USB 设备,如加密狗等
  • 通过端口映射或者 ZeroTier,将 USB 设备通过互联网共享

环境准备

这次测试的两台主机的系统都是 Windows 11 23H2,服务端(192.168.0.100)通过 WiFi 连接,客户端(192.168.0.101)通过有线网络,处于同一个局域网。
首先是共享 USB 设备的服务端,下载 usbipd-win 4.1.0 安装包进行安装,或者通过命令安装:

1
winget install usbipd

安装过程没有可以选择的设置,安装完成后会自动启用 usbipd 服务,监听 0.0.0.0:3240,并设置防火墙规则放行
根据作者的说明,这个服务端利用了 VirtualBox 的驱动,可以将 USB 设备共享到支持的 usbip 客户端。

然后设置需要使用被共享设备的客户端:
根据 USB/IP PROJECT 的介绍,usbip 功能已经被合并到 Linux 内核中,如果需要在 Linux 使用,使用包管理器安装二进制文件即可。
但该网站提供的 Windows 版 usbip 似乎和上面的 usbipd-win 不兼容。
这里有两个选择:cezanne/usbip-winvadimgrn/usbip-win2
首先安装 vadimgrn/usbip-win2 测试,发现需要启用 testsigning,否则完全无法使用。
在未启用 testsigning 时安装 usbip-win2 后重启,会导致所有 USB 设备不可用!
拯救 USB 不可用的系统以后或许可以写篇文章记录过程?
usbip-win2 对此的说明:Disable Windows Test Signing Mode without removing USB/IP

最终决定使用 cezanne/usbip-win,经过测试,无需手动安装证书和启用 testsigning 也可以正常使用。
首先安装软件,下载解压 usbip-win 0.3.6-dev 后进入目录安装:

1
2
cd usbip-win-0.3.6-dev
usbip.exe install

安装完成后,在设备管理器可以发现以下设备:
usbip 客户端设备

命令参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# dorssel/usbipd-win 服务端:
# 查看设备
usbipd list
# 共享设备
usbipd bind -i [VID:PID]
usbipd bind -b [BUSID]
# 取消共享
usbipd unbind -i [VID:PID]
usbipd unbind -b [BUSID]

# cezanne/usbip-win 客户端:
# 查看本地
usbip.exe list -l
# 查看共享
usbip.exe list -r [ip]
# 连接设备
usbip.exe attach -r [ip] -b [BUSID]
# 查看连接
usbip.exe port
# 断开设备
usbip.exe detach -p [port]

设备共享

先在服务端找到设备:

1
2
3
4
> usbipd list
Connected:
BUSID VID:PID DEVICE STATE
4-3 1a86:7523 USB-SERIAL CH340 (COM4) Not shared

这是一个 ESP32,通过 CH340 连接到 PC,可以通过 -i 指定 VID:PID-b 指定 BUSID 来选择设备,将该设备设置为共享模式:

1
2
> usbipd bind -i 1a86:7523
usbipd: info: Device with hardware-id '1a86:7523' found at busid '4-3'.

启用共享后,检查该设备的状态:

1
2
3
4
> usbipd list
Connected:
BUSID VID:PID DEVICE STATE
4-3 1a86:7523 USB-SERIAL CH340 (COM4) Shared

通过客户端检查设备共享情况:

1
2
3
4
5
6
7
8
> usbip.exe list -r 192.168.0.100
Exportable USB devices
======================
- 192.168.0.100
4-3: QinHeng Electronics : CH340 serial converter (1a86:7523)
: USB\VID_1A86&PID_7523\7&14135117&0&3
: Vendor Specific Class / unknown subclass / unknown protocol (ff/00/00)
: 0 - Vendor Specific Class / unknown subclass / unknown protocol (ff/01/02)

可以看到服务端已共享的设备以及对应的 BUSID。

现在使用服务端共享设备的 BUSID,将设备连接到客户端:

1
2
> usbip.exe attach -r 192.168.0.100 -b 4-3
succesfully attached to port 0

已成功将 BUSID 为 4-3 的设备连接到 port 0,可以通过命令检查:

1
2
3
4
5
6
7
> usbip.exe port
Imported USB devices
====================
Port 00: <Device in Use> at Full Speed(12Mbps)
QinHeng Electronics : CH340 serial converter (1a86:7523)
?-? -> unknown host, remote port and remote busid
-> remote bus/dev ???/???

通过客户端设备管理器也可以确认到:
已连接到 usbip 客户端的设备

而服务端的设备管理器发现设备已经消失,出现了 USBIP Shared Device
usbip 服务端设备

也可以通过命令检查状态和已连接的客户端 IP:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
> usbipd list
Connected:
BUSID VID:PID DEVICE STATE
4-3 1a86:7523 USB-SERIAL CH340 (COM4) Attached

> usbipd state
{
"Devices": [
{
"BusId": "4-3",
"ClientIPAddress": "192.168.0.101",
"Description": "USB-SERIAL CH340 (COM4)",
"InstanceId": "USB\\VID_1A86&PID_7523\\7&14135117&0&3",
"IsForced": false,
"PersistedGuid": "133343a8-f4d5-47de-915c-538b2c9d39aa",
"StubInstanceId": "USB\\Vid_80EE&Pid_CAFE\\7&14135117&0&3"
}
]
}

设备测试

通过 Arduino IDE 2.3.2 使用 esptool.py v4.5.1 上传固件,成功上传:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Sketch uses 300821 bytes (9%) of program storage space. Maximum is 3145728 bytes.
Global variables use 23968 bytes (7%) of dynamic memory, leaving 303712 bytes for local variables. Maximum is 327680 bytes.
esptool.py v4.5.1
Serial port COM4
Connecting.....
Chip is ESP32-D0WD (revision v1.0)
...
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 921600
Changed.
Configuring flash size...
Flash will be erased from 0x00001000 to 0x00005fff...
Flash will be erased from 0x00008000 to 0x00008fff...
Flash will be erased from 0x0000e000 to 0x0000ffff...
Flash will be erased from 0x00010000 to 0x00059fff...
Compressed 17568 bytes to 12204...
Writing at 0x00001000... (100 %)
Wrote 17568 bytes (12204 compressed) at 0x00001000 in 0.6 seconds (effective 253.2 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 145...
Writing at 0x00008000... (100 %)
Wrote 3072 bytes (145 compressed) at 0x00008000 in 0.4 seconds (effective 66.7 kbit/s)...
Hash of data verified.
Compressed 8192 bytes to 47...
Writing at 0x0000e000... (100 %)
Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.4 seconds (effective 146.6 kbit/s)...
Hash of data verified.
Compressed 301184 bytes to 170116...
Writing at 0x00010000... (9 %)
...
Writing at 0x0005775e... (100 %)
Wrote 301184 bytes (170116 compressed) at 0x00010000 in 3.6 seconds (effective 666.2 kbit/s)...
Hash of data verified.

在客户端的设备管理器修改 COM 序号会导致设备管理器卡死,但更改有效,需要断开后重新连接才能使用:

1
2
3
4
5
> usbip.exe detach -p 0
port 0 is succesfully detached

> usbip.exe attach -r 192.168.0.100 -b 4-3
succesfully attached to port 0

测试通过,后续对 ESP32 进行数据收发操作都正常。

测试完成后,服务端停止共享设备:

1
2
> usbipd unbind -i 1a86:7523
usbipd: info: Device with hardware-id '1a86:7523' found at busid '4-3'.

一些其他的测试

U 盘

共享设备:

1
2
3
4
5
6
7
> usbipd list
Connected:
BUSID VID:PID DEVICE STATE
4-3 325d:6300 USB 大容量存储设备 Not shared

> usbipd bind -i 325d:6300
usbipd: info: Device with hardware-id '325d:6300' found at busid '4-3'.

连接设备:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
> usbip.exe list -r 192.168.0.100
Exportable USB devices
======================
- 192.168.0.100
4-3: unknown vendor : unknown product (325d:6300)
: USB\VID_325D&PID_6300\32DE96949C89EEE6
: (Defined at Interface level) (00/00/00)
: 0 - Mass Storage / SCSI / Bulk-Only (08/06/50)

> usbip.exe attach -r 192.168.0.100 -b 4-3
succesfully attached to port 0

> usbip.exe port
Imported USB devices
====================
Port 00: <Device in Use> at High Speed(480Mbps)
unknown vendor : unknown product (325d:6300)
?-? -> unknown host, remote port and remote busid
-> remote bus/dev ???/???

通过网络共享的 U 盘
在客户端连接后,可以正常格式化重新分区,读写文件。对文件进行哈希校验通过,但速度很慢。
在服务端通过 USB 进行读取,速度在 30 MiB/s,而客户端通过网络连接,实际上设备的磁盘读取速度只有 5 MiB/s。

USB 摄像头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
> usbip.exe list -r 192.168.0.100
Exportable USB devices
======================
- 192.168.0.100
4-3: unknown vendor : unknown product (1224:2a25)
: USB\VID_1224&PID_2A25\7&14135117&0&3
: Miscellaneous Device / ? / Interface Association (ef/02/01)
: 0 - Video / Video Control / unknown protocol (0e/01/00)
: 1 - Video / Video Streaming / unknown protocol (0e/02/00)
: 2 - Audio / Control Device / unknown protocol (01/01/00)
: 3 - Audio / Streaming / unknown protocol (01/02/00)

> usbip.exe port
Imported USB devices
====================
Port 00: <Device in Use> at High Speed(480Mbps)
unknown vendor : unknown product (1224:2a25)
?-? -> unknown host, remote port and remote busid
-> remote bus/dev ???/???

可以用,但是延迟很大(2s 左右),只是拍照的话应该没问题。

Android 设备

经过测试,服务端未安装相关驱动,adb 和 MTP 共享给已安装驱动的客户端,都可以正常使用。

通过 ZeroTier 共享指纹模块

两台主机分别连接不同网络,安装 ZeroTier 建立虚拟局域网。
服务端 USB 连接指纹模块,未安装驱动的情况下,共享给客户端,客户端通过 ZeroTier 的 IP 地址成功连接,指纹模块可以正常使用。