WSLでUSBデバイスを使う(その1:準備&USB-Serial編)
WSLでUSBを使う方法。あちこちに情報があるけど、なんとなく自分なりにまとめておく。
本家の説明
ますは、準備とLinuxカーネルのビルドが必要ないUSB-Serialデバイスから。
使用したWSLのバージョンは以下。
wsl --version
WSL バージョン: 2.2.4.0
カーネル バージョン: 5.15.153.1-2
WSLg バージョン: 1.0.61
MSRDC バージョン: 1.2.5326
Direct3D バージョン: 1.611.1-81528511
DXCore バージョン: 10.0.26091.1-240325-1447.ge-release
Windows バージョン: 10.0.19045.4529
使用したディストリビューションは「Ubuntu 22.04 LTS」
[!NOTE] インストールしたタイミングによっては既に有効化されているかも。
USBのホットプラグ処理は systemd + udev がよしなに行ってくれるみたいなので、systemdを有効化しておく。
使用するディストリビューションを起動し、/etc/wsl.conf
に以下の設定を行う。
デフォルト(古いデフォルト?)のSystemVinitだとバカチョンで動かなかった…udevサービス再起動とかやったら動いたけど。
[boot]
systemd=true
[!NOTE] systemdを有効にするか否かはディストリビューション毎の設定
設定後、WSLをシャットダウン(コマンドプロンプト等からwsl --shutdown
を実行)し、
再度ディストリビューションを起動する。
[!NOTE] systemdが動作しているか確認するには、
systemctl is-system-running
を実行する。
running
(起動中)degraded
(起動中だが失敗したサービスなどが存在) と表示されれば動作している。
offline
と表示されれば起動していない。
その他使い方についてはぐぐってちょ。
sudo apt install linux-tools-generic hwdata
[!NOTE] linux-tools-generic : usbipコマンド等が入る
hwdata : USB ID等のデータベースが入る
linux-tools-generic インストールしたら自動でhwdata入るけど….
参考にしたサイトにこう書いてあったので。
linux-tools-virtualと書いてあるサイトもあるけど、ubuntu 22.04だとchangelogとcopyrightしか違わないみたい。
pushd /usr/lib/linux-tools
sudo ln -s 5.15.0-113-generic $(uname -r)
popd
[!NOTE] あちこちに
sudo update-alternatives --install /usr/local/bin/usbip usbip `ls /usr/lib/linux-tools/*/usbip | tail -n1` 20
でコマンドのバージョン管理を行う例が書かれているけど、なんとなくシンボリックリンクを張る方がしっくりするのでこっちにした。本来、usbipを実行すると
/usr/bin/usbip
が/usr/lib/linux-tools/≪カーネルバージョン≫/usbip
を起動してくれるらしいのだけど、WSL環境では≪カーネルバージョン≫がカスタマイズバージョンでうまく働かないので
/usr/lib/linux-tools/≪カーネルバージョン≫をインストールされているバージョンに飛ばしてやればいい。
カーネルバージョンが変更されたら動かなくなるけど、そのときは、新しいカーネルバージョン名のシンボリックリンクを作ってやればよい。
もちろん、linux-tools-genericのアップデートが必要か判断して、必要ならアップデートする。
まずはUSBをTCP/IP経由で接続させるためのツール、usbipd-win をwindowsにインストールする。
インストールするには、ダウンロードページ から
最新版(以下の手順で使用したのは4.2.0)のmsiファイルをダウンロードして実行するだけ。
[!NOTE] インストール時PATHが変更されるので、既に開いているコマンドプロンプトorPowerShellは一旦閉じて再実行する。
WSLで使用したいUSBデバイスはあらかじめPCに接続しておく。
以下の処理はコマンドプロンプトorPowerShellで行う。
ただし、bind/unbindサブコマンドは管理者権限が必要なので、管理者として開いたコマンドプロンプトorPowerShellで実行する。
以下のコマンドを実行する。
結果は例。今回は3-4のUSB Serial Converter を使う。
usbipd list
≪結果≫
Connected:
BUSID VID:PID DEVICE STATE
2-1 1f75:0918 USB 大容量記憶装置 Not shared
2-2 056e:700a Venus USB2.0 Camera Not shared
3-4 0403:6001 USB Serial Converter Not shared
ここで表示されたWSLで使用したいUSBデバイスのBUSID(例えば3-4)を覚えておく。
管理者として開いたコマンドプロンプトorPowerShellで以下のコマンドを実行する。
usbipd bind --busid 3-4 # 3-4は接続するデバイスのBusID
[!NOTE]
usbipd: warning: USB filter 'USBPcap' is known to be incompatible with this software; 'bind --force' will be required.
と出た時は、一旦unbindして、–forceオプションを追加して実行
(うちのPCはWiresharkインストールしてUSBPcap入ってるからだろうなぁ…)
実行後、usbipd list
を実行すると、対象デバイスのステータスが Shared または Shared (forced) になっている
接続するためのWSLのディストリビューションを起動しておく。
[!NOTE] 起動してないと
usbipd: error: There is no WSL 2 distribution running; keep a command prompt to a WSL 2 distribution open to leave it running.
とエラーになる。
[!NOTE] このとき、複数のディストリビューションが起動していると変なことが起こりそうなので(未確認) 対象のディストリビューションだけ起動しておくのが良いと思う。
bindしただけではまだWSL側からはUSBデバイスは見えない。
usbipd attach --wsl --busid 3-4 # 3-4は接続するデバイスのBusID
sudo usbip attach -r 172.20.160.1 -b 3-4 # 172.20.160.1 はWindows側のIPアドレス
# 3-4は接続するデバイスのBusID
[!NOTE] Windows側のIPアドレスはコマンドプロンプトorPowerShellから
ipconfig
コマンドを実行し、
Ethernet adapter vEthernet (WSL):
に表示されているIPアドレスを使用する。
でもWSLがミラーネットワークモードになってたらどうなるんだろう???
linux側で以下を実行し、接続されたデバイスが表示されていることを確認する。
以下のように接続したデバイスが表示されていればOK
(以下では2行目のFT232 Serial (UART) IC)
lsusb
≪結果≫
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub```
上記操作で接続したUSBデバイスがUSB-Serialデバイス(上記の例では FT232 Serial (UART) IC) であれば、
/dev/ttyUSBx
(xは数字。通常0から順に割り当てられる)に割り当てられる。
ls -la /dev/ttyUSB*
≪結果≫
crw-rw---- 1 root dialout 188, 0 7月 3 11:02 /dev/ttyUSB0
一応、ログを確認してみる。
dmesg
≪結果≫
・・・・・・
[ 189.418189] vhci_hcd vhci_hcd.0: pdev(0) rhport(0) sockfd(3)
[ 189.418196] vhci_hcd vhci_hcd.0: devid(196612) speed(2) speed_str(full-speed)
[ 189.418249] vhci_hcd vhci_hcd.0: Device attached
[ 189.690366] vhci_hcd: vhci_device speed not set
[ 189.760405] usb 1-1: new full-speed USB device number 2 using vhci_hcd
[ 189.840475] vhci_hcd: vhci_device speed not set
[ 189.910358] usb 1-1: SetAddress Request (2) to port 0
[ 190.135906] usb 1-1: New USB device found, idVendor=0403, idProduct=6001, bcdDevice= 6.00
[ 190.135918] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 190.135921] usb 1-1: Product: FT232R USB UART
[ 190.135923] usb 1-1: Manufacturer: FTDI
[ 190.135924] usb 1-1: SerialNumber: A50285BI
[ 190.511832] usbcore: registered new interface driver ftdi_sio
[ 190.511852] usbserial: USB Serial support registered for FTDI USB Serial Device
[ 190.511881] ftdi_sio 1-1:1.0: FTDI USB Serial Device converter detected
[ 190.511904] usb 1-1: Detected FT232RL
[ 190.521353] usb 1-1: FTDI USB Serial Device converter now attached to ttyUSB0 ← /dev/ttyUSB0が割り当てられたことが分かる
デフォルトで使用できるUSB-Serialデバイスは、 Silicon Labs社製 CP210x、FTDI社製シリアルコンバータ(FT232)、CH34x(安い中国製Arduinoで使われているらしい)らしい。
/dev/ttyUSBxが割り当てられていない場合は、対応しているUSB-Serialデバイスか、systemdが有効になっているか、等を確認してください。
[!NOTE] 参考:Windows WSL2 の Ubuntu 22.04 上から USB-UART 経由で M5Stack に書き込みする
上記サイトではudevルールをplatform.ioのサイトから拝借してきているが、上記の製品なら持ってこなくても可。
互換品とかでうまく認識しないときは試してみると動くかも(試してないので無責任発言)。
シリアルポートを使うツールは色々あると思うけど、とりあえず動いているか確認するならこんな感じ。
sudo pyserial-miniterm --parity N /dev/ttyUSB0 115200
終了するにはCTRL+]を入力する。
[!NOTE] sudoなしで実行するには、自分のアカウントにdialoutグループを追加すればよい。
sudo gpasswd -a $USER dialout
一旦ログアウトして再ログイン必要。
WSLをシャットダウンしたら(ディストリビューションのシャットダウンではなくWSL全体)接続解除されるけど、 手動で接続解除するには以下のコマンドを実行する。
usbipd detach --busid 3-4 # 3-4は接続するデバイスのBusID
linuxから解除するには、まずポート番号を確認する。
sudo usbip port
≪結果≫
Imported USB devices
====================
Port 00: <Port in Use> at Full Speed(12Mbps)
Future Technology Devices International, Ltd : FT232 Serial (UART) IC (0403:6001)
1-1 -> usbip://172.20.160.1:3240/3-4 ← ホストアドレス
-> remote bus/dev 003/004 ← BusID
上記の例ではポート番号は00なので、これをportオプションに指定して以下のように実行する。
sudo usbip detach --port 00
USBデバイスを共有解除するには、管理者として開いたコマンドプロンプトorPowerShellで以下のコマンドを実行する。
usbipd unbind --busid 3-4 # 3-4は接続するデバイスのBusID
[!NOTE] デバイスの共有解除しなければ、PCを再起動しても共有設定されたままになる。
ただし、使用しているUSBポートに別のUSBデバイスを挿入すると共有解除されるが、再度同じUSBデバイスを挿入すれば共有設定される。
何言ってるか分からんと思うけど、USBデバイス挿抜してみて確かめてみて。