---
tags: USB, WSL, WSL2, tty permission, usbipd
---
# WSL2 中連接 USB 的疑難雜症
## Reference
- [issue: udev not working on WSL2](https://github.com/microsoft/WSL/issues/8502)
- [知乎: 连接USB设备到WSL2权限问题](https://zhuanlan.zhihu.com/p/585972926)
- [CDSN: wsl2添加usb串口驱动后如何免root使用串口](https://blog.csdn.net/chubbykkk/article/details/125215180)
## 前言
WSL 是一個能在 windows 撰寫 linux 程式並測試的優秀平台,搭配 VsCode 能夠在 Windows 和 Linux 來回切換,然而 WSL 預設是不會將掛載於 Windows 的外部設備直接掛載到 Linux 的內核之中,例如 USB 就需要透過 usbipd-win 這個專案來協助將外部設備掛載到 WSL 之中。
## 安裝 usbipd-win
- [Official GitHub](https://github.com/dorssel/usbipd-win)
- [MicroSoft Doc](https://learn.microsoft.com/zh-cn/windows/wsl/connect-usb)
- [工作原理](https://devblogs.microsoft.com/commandline/connecting-usb-devices-to-wsl/#how-it-works)
### In Windows
該軟體可以透過 winget 進行安裝
```ps
winget install usbipd
```
安裝完成後 Windows 系統中將多出一個名為 usbipd 的 service
到此 Windows 作業系統上的操作完成
### In Linux
接下來切換到 WSL 中,以 Ubuntu 作業系統為例
```
sudo apt install linux-tools-generic hwdata
sudo update-alternatives --install /usr/local/bin/usbip usbip /usr/lib/linux-tools/*-generic/usbip 20
```
### How to use?
安裝完成後依循下列步驟:
1. ==確認 WSL 已經開啟==
2. ```usbipd wsl list``` 找出你要掛載到 WSL 的 USB budid
```
BUSID VID:PID DEVICE STATE
1-1 0483:374f ST-Link Debug, USB Mass Storage Device, STMicroelectronic... Not attached
1-3 0483:bdda USB 序列裝置 (COM5) Attached - Ubuntu
1-9 13d3:5463 USB2.0 HD UVC WebCam, Camera DFU Device Not attached
1-10 8087:0026 Intel(R) Wireless Bluetooth(R) Not attached
```
3. 若想掛載 USB 序列裝置 (COM5),輸入以下指令
```bash
# mnt for one time, not functioning after replug
usbipd wsl attach --busid 1-3
# unmnt
usbipd wsl detach --busid 1-3
# mnt specific usb once it plugs in
usbipd wsl attach --busid 1-3 --auto-attach
```
- flag --auto-attach 能夠在==不關閉輸入該指令的 powershell== 時,持續監測指定 bus-id 的 usb 插拔情況,並在偵測到時自動掛載到 WSL 中,是 usbipd-win 專案中能夠自動掛載的最適選項 。
```ps
//call usbipd wsl attach --busid 1-3 --auto-attach
Attached
Detached // remove usb
usbip: error: Attach Request for 1-3 failed - Device busy (exported)
usbip: error: Attach Request for 1-3 failed - Device not found
Attached // plug in again
```
以下是相關 issue
- [issue: Add WSL --auto-attach option](https://github.com/dorssel/usbipd-win/pull/351)
- [issue: feature request - WSL auto attach based on VID:PID](https://github.com/microsoft/WSL/issues/8502)
4. 回到 WSL,使用 ```lsusb``` 指令應該就能看到被掛載的 USB 裝置
## USB 裝置無法開啟
當我們結束上述動作後,欣喜的嘗試讀寫 USB 就會發現 permission denied 出現在 terminal 中,但可以用 sudo 讀寫...
於是我們開始檢查使用者是否在 dialout 之中,發現我們已經存在於該群組之中,理論上應該不用 sudo 即可讀寫 tty 設備
最後我們會發現,所有 tty 相關設備的權限都是 600,而且所屬都不是 dialout,只有 root 可以讀寫,似乎是一個 bug QQ
- [issue: /dev/tty default permissions](https://github.com/microsoft/WSL/issues/617)
- [issue: Win11/WSL2/Ubuntu 20.04 serial ports have wrong group ownership](https://github.com/microsoft/WSL/issues/9247)
```bash
crw------- 1 root root 166, 0 Mar 25 08:00 ttyACM0
crw------- 1 root root 4, 64 Mar 23 22:06 ttyS0
crw------- 1 root root 4, 65 Mar 23 22:06 ttyS1
crw------- 1 root root 4, 66 Mar 23 22:06 ttyS2
crw------- 1 root root 4, 67 Mar 23 22:06 ttyS3
```
但好在我們可以通過 udev 修復,以下修復請搭配
- [Reference 中的知乎 & CSDN 文章](#Reference)
- [libusb cannot open USB device, permission isse. NetBeans/Ubuntu](https://stackoverflow.com/questions/22713834/libusb-cannot-open-usb-device-permission-isse-netbeans-ubuntu)
- [issue: udev rule to allow non-root access to libusb devices being ignored/not working](https://github.com/microsoft/WSL/issues/8502)
1. WSL2 中是沒有 udev 的,需要手動調用 ``` sudo service udev start ```,當然可以將其設置為開啟 WSL 時調用,參考 [How to enable a service to start with WSL2?](https://superuser.com/questions/1701853/how-to-enable-a-service-to-start-with-wsl2)
```bash
# 在 /etc/wsl.conf 新增 or 修改
# 注意不可以有空格
[boot]
command="service udev start"
```
之後用 ```sudo service udev status``` 檢測是否開啟
2. 設定 udev 規則在 ```/etc/udev/rules.d```
a. 文件名 ```<0~99>-<some_name_you_want>.rules```,數字低表優先級高
例如: ```10-tty-usb.rules```
b. 在文件裡寫入
```conf
# modify usb related permission
SUBSYSTEM=="usb", GROUP="dialout", MODE="0660"
SUBSYSTEM=="usb_device", GROUP="dialout", MODE="0660"
```
這樣修改完,/dev 下的 USB/ACM (where libserial open) 和 /dev/bus/usb/xxx (where libusb open) 都會被修改成 group dialout
3. 確認目前使用者在 dialout 裡面
4. 重新開啟 WSL (```wsl --shutdown``` in powershell),注意-[八秒規則](https://learn.microsoft.com/zh-tw/windows/wsl/wsl-config#the-8-second-rule)
就可以得到 (group from root -> dialout):
```bash
# under /dev
crw-rw---- 1 root dialout 166, 0 Mar 25 16:07 ttyACM0
crw-rw---- 1 root dialout 4, 64 Mar 25 16:06 ttyS0
crw-rw---- 1 root dialout 4, 65 Mar 25 16:06 ttyS1
crw-rw---- 1 root dialout 4, 66 Mar 25 16:06 ttyS2
crw-rw---- 1 root dialout 4, 67 Mar 25 16:06 ttyS3
# under /dev/bus/usb/???
crw-rw-r-- 1 root dialout 189, 0 Mar 25 17:10 001
crw-rw---- 1 root dialout 189, 1 Mar 25 17:10 002
```
## usbip client not correctly installed
> usbipd: error: WSL 'usbip' client not correctly installed. See https://github.com/dorssel/usbipd-win/wiki/WSL-support for the latest instructions.
```
sudo apt install linux-tools-virtual hwdata
sudo update-alternatives --install /usr/local/bin/usbip usbip `ls /usr/lib/linux-tools/*/usbip | tail -n1` 22
// powershell
wsl --shutdown
```
請重開 WSL 之後重開 windows terminal
## 使更新 usbip 可以被 script 執行
```sh
sudo apt install linux-tools-virtual hwdata
sudo update-alternatives --install /usr/local/bin/usbip usbip `ls /usr/lib/linux-tools/*/usbip | tail -n1` 22
# reboot cmd
cd /mnt/c/ && cmd.exe /c start "rebooting WSL" cmd /c "timeout 5 && wsl -d $WSL_DISTRO_NAME" && wsl.exe --terminate $WSL_DISTRO_NAME
```