--- 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 ```