Featured image of post 将 USB 设备连接到 WSL

将 USB 设备连接到 WSL

使用 WSL 2 进行嵌入式开发时,如何将 USB 连接从 Windows 转移到 WSL 上?

最近在尝试使用 WSL 2 作为开发 ESP-32 的工具,但是 WSL 不像 VMWare 虚拟机那样可以直接访问硬件,而是一个纯虚拟环境,无法直接访问 USB 设备,所以需要一些额外的工具来实现 USB 设备的共享。

参考资料:WSL/连接 USB 设备 - Microsoft Learn

2024.1.10 更新:usbipd 更新到了 4.0.0 版本,指令有所变化,本文已更新。

# 先决条件

  • Windows 11(内部版本 22000 或更高版本)
  • 具有 x64/x86 处理器的计算机
  • Linux 发行版已安装并设置为 WSL 2(本次使用的是 Ubuntu 20.04 LTS)

# 安装 USPIPD-WIN 项目

# 方法 1:从 GitHub 下载安装

仓库链接:usbipd-win

# 方法 2:使用 Windows 程序包管理器程序 (winget) 安装

打开 PowerShell 并运行以下命令:

1
winget install --interactive --exact dorssel.usbipd-win

# 在 Linux 中安装 USBIP 工具和硬件数据库

在 Ubuntu 中,运行以下命令安装工具和硬件数据库:

1
sudo apt install linux-tools-generic hwdata

为了启用 USBIP 服务,运行以下命令:

1
sudo update-alternatives --install /usr/local/bin/usbip usbip /usr/lib/linux-tools/*-generic/usbip 20

# 附加 USB 设备

  1. 通过管理员模式打开 PowerShell 并运行以下命令,列出所有连接到 Windows 的 USB 设备:

    1
    
    usbipd list
    

    本次实验连接的是一个 ESP-32 DevKit-C,输出如下:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    Connected:
    BUSID  VID:PID    DEVICE                                                        STATE
    1-3    0b05:19b6  USB 输入设备                                                  Not shared
    2-1    10c4:ea60  CP2102 USB to UART Bridge Controller                          Not shared
    2-2    258a:0049  USB 输入设备                                                  Not shared
    2-3    13d3:3568  MediaTek Bluetooth Adapter                                    Not shared
    3-1    13d3:56eb  USB2.0 HD UVC WebCam, USB2.0 IR UVC WebCam, Camera DFU De...  Not shared
    
    Persisted:
    GUID                                  DEVICE
    2ca6f2f5-41c6-431c-ac86-44107478c8da  USB-SERIAL CH340 (COM5)
    

    这里面 CP2102 USB to UART Bridge Controller 就是我们想要连接的开发板了,它的设备总线 ID 是 2-1

  2. 选择要附加到 WSL 的设备总线 ID,然后共享出去:

    1
    
    usbipd bind -b <bus_id>
    

    其中 <bus_id> 是要共享的设备总线 ID,即步骤 1 中输出的“2-1”。

    这一步对于一个 USB 设备只需要执行一次,它的 STATE 就会变成 Shared

  3. 然后运行以下命令:

    1
    
    usbipd attach -b <bus_id> --wsl
    

    同样,<bus_id> 是要附加的设备总线 ID,即“2-1”。 此时设备就会从 Windows 上断开连接,并且在 WSL 上显示为一个 USB 设备。

    如果没有执行第 2 步的命令,那么 usbipd 会报错:

    1
    
    usbipd: error: Device is not shared; run 'usbipd bind -b 2-1' as administrator first.
    
  4. 在 Ubuntu 中,运行以下命令,列出所有连接到 WSL 的 USB 设备:

    1
    
    lsusb
    

    然后就成功显示到了开发板:

    lsusb

# 测试连接以及断开连接

我提前在 WSL 上用 esp-idf 工具链编译了一个简单的 hello-world 程序,现在尝试用 esp-idf 工具链将 WSL 中的项目烧录到开发板上。

通过 ls /dev/tty* 命令查找到开发板的串口设备为 /dev/ttyUSB0,所以可以运行以下命令烧录程序:

1
idf.py -p /dev/ttyUSB0 flash

flash

我也尝试了直接使用设备总线 ID 来烧录程序,但没有成功……

1
idf.py -p /dev/bus/usb/002/001 flash

输出如下:

1
2
3
4
5
6
esptool.py v3.3.4-dev
Serial port /dev/bus/usb/002/001
Traceback (most recent call last):
  File "/home/jay/.espressif/python_env/idf4.4_py3.8_env/lib/python3.8/site-packages/serial/serialposix.py", line 322, in open
    self.fd = os.open(self.portstr, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK)
PermissionError: [Errno 13] Permission denied: '/dev/bus/usb/002/001'

嘛,不管那个了,运行串口监视器,可以看到开发板是正常运行的:

1
idf.py -p /dev/ttyUSB0 monitor

serial-monitor

使用结束后,其实可以直接将 USB 设备从电脑上拔出,或者在管理员模式下运行 PowerSheell 命令来断开连接:

1
usbipd detach -b <busid>

粗暴一点,可以直接断开所有的 USB 设备:

1
usbipd detach --all

实际操作下来,使用命令断开 WSL 的 USB 连接后,Windows 上的设备管理器中又显示出了设备。

device-manager

# (新功能)自动重连

usbipd 在 4.0.0 版本后增加了自动重连功能,也就是说,我们可以仅通过运行一个命令让电脑一直检测 USB 设备的连接状态,如果设备被物理断连后重新接入,则自动重新连接到 WSL。

1
usbipd attach -a --busid <bus_id> --wsl

其中 -a 等效于 --auto-attach,表示在设备断开连接后自动重新连接。

演示效果:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
usbipd: info: Using WSL distribution 'Ubuntu-20.04' to attach; the device will be available in all WSL 2 distributions.
usbipd: info: Using IP address 172.30.208.1 to reach the host.
usbipd: info: Starting endless attach loop; press Ctrl+C to quit.
WSL wsl: hKm0R localhost NtMn
                                FO*g\��P0R WSL0NAT !j_
                                                    Nv WSL
WSL N/ec localhost Nt0
WSL
WSL Attached
WSL Detached <- 设备此时被拔出
WSL usbip: error: Attach Request for 2-1 failed - Device not found <- 系统发现设备断开
WSL Attached <- 重新插入设备后再次连接

这对于需要反复插拔的单片机开发板来说就相当方便了。

Maxwell Jay at his most tender.
使用 Hugo 构建
主题 StackJimmy 设计