WSLでUSB

WSLでUSBを使った時のメモ(バージョン 2.5.7.0)

概要

WSLのバージョンが2.5.7.0でカーネルバージョンが6.6.87.1-1になってカーネルの再ビルドしなくても 色々なUSBデバイスが使えるようになったので試してみた時のメモ。

参考:USB デバイスを接続する

準備

windows側の準備

usbipd-winのインストール

usbipd-winのgithubからダウンロード(使用したのは5.10)
インストールはファイルをダウンロードして実行するだけ。
WindowsTerminarが開いている場合は一旦すべて閉じる(PATHの変更を有効にするため)

Ubuntu側の準備

systemdの有効化

systemdを有効にするため、/etc/wsl.conf に以下の設定を追加。

[boot]
systemd=true

仮想USBホストコントローラインタフェースのインストール

ネットワーク経由でUSBデバイスを共有することを可能にするため、仮想USBホストコントローラインタフェース(vhci-hcd)をインストール (ドライバの組み込み)。

/etc/modules-load.d/usb.conf (ファイル名は何でも可)を以下の内容で作成し、WSLの再起動。

vhci-hcd

[!TIP] お試しで1回だけ読み込むなら以下。この場合は再起動不要(というか再起動したら消える)。

sudo modprobe vhci-hcd

USBユーティリティのインストール

lsusbとか使いたいので、インストール。

sudo apt install usbutils

仮想マシンの再起動

設定を有効にするため、仮想マシンを再起動する。
開いているすべての仮想マシンを閉じた後、Windwos側で wsl --shutdownを実行し、
wsl -l -vですべて仮想マシンのSTATEがStoppedになっていることを確認し仮想マシンを再度実行。

systemdが起動していることを確認する

systemctl

起動していればサービス一覧が表示される。
起動していなければ以下のようなメッセージが表示される。

System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: ホストが落ちています

vhci-hcdが組み込まれていることを確認する

lsmod

表示の中にvhci_hcdがあることを確認。
なければ組み込みの設定を確認。

USBカメラを使ってみる

今回は エレコムの UCAM-DLA200HBK を使用。
かなり古いカメラなのでもう売ってないけど…
UVC仕様のカメラなら基本的に同じはず。

Ubuntu側の準備

今回はカメラなので、自身にvideoグループを追加
(要 再ログイン、シャットダウンは不要)

sudo gpasswd -a $USER video

guvcviewのインストール

表示ツールは何でもいいけど、とりあえずguvcviewで。

sudo apt install guvcview 

Windows側の準備

PowerShellやコマンドプロンプト等を管理者として開く。
USBデバイスのリストを表示
(今回はカメラを使うのでそこだけ抜粋。IDとか名前は例)
Not sharedになっている。

usbipd.exe list
・・・・
9-2    056e:700a  Venus USB2.0 Camera   Not shared
・・・・

bindする(busidは上で調べたものを使用)

usbipd.exe bind  --busid 9-2
または 
usbipd.exe bind  --force --busid 9-2

[!NOTE] USBPcapがインストールされている(wiresharkなど)とwarningが表示されてbindできないので
--forceオプションを追加して実行する。
(warningで–forceオプションを付けろと教えてくれる)

確認
Shared または Shared (forced)になっている。

usbipd.exe list
・・・・
9-2    056e:700a  Venus USB2.0 Camera   Shared (forced)
・・・・

attachする(attachする前にWSLの仮想マシンが起動していること)

usbipd.exe attach --wsl --busid 9-2

[!TIP] 以下のようにbindするとUSB挿抜する度に自動でattachしてくれるらしい。確認してないけど。

usbipd.exe attach --wsl --busid 2-1 --auto-attach

確認する
Attachedになっている

usbipd.exe list
・・・・
9-2    056e:700a  Venus USB2.0 Camera   Attached
・・・・

Ubuntu側の実行

USB機器が割り当てられたことを確認する。

lsusb

こんな感じで表示される

Bus 001 Device 002: ID 056e:700a Elecom Co., Ltd Venus USB2.0 Camera

デバイスノードも確認しておく。

ls -la /dev/video*

こんな感じ

/dev/video0  /dev/video1

実際に表示してみる。
LANGja_JP.UTF8とかのままだと文字化けしてしまうので、Cに変更して実行。

LANG="C" guvcview

別ウィンドウが表示されるが、何も表示されない コンソールには「V4L2_CORE: Could not grab image (select timeout): リソースが一時的に利用できません」と表示され続ける

GuvcviewウィンドウのVideo Controls をクリックし、

[!NOTE] これらのパラメータが選択できるかは使用するカメラによる。
PCのスペック等によって、もうちょっと大きいサイズでも表示できることがある。

[!TIP] 日本語で表示するには、例えば以下のように日本語フォントをインストールして LANGを指定せずに実行すれば良い。

sudo apt install fonts-noto-cjk

Windows側の後始末

USBカメラを取り外すためにアタッチ解除とバインド解除

usbipd.exe detach --busid 9-2
usbipd.exe unbind  --busid 9-2

ということで

あまり実用的とは言い難い結果となってしまった。

USBカメラをUbuntu PCからエクスポートしてみる

試しに、Ubuntu PCからUSBカメラをエクスポートしてWSLで表示してみる。

[!NOTE] 「Netive UbuntuあるならWSL使わんでも良いやん」という気もするが…

カメラを接続

USBカメラを接続し、認識されているか確認する。

lsusb 

こんな感じで表示される

・・・
Bus 003 Device 006: ID 056e:700a Elecom Co., Ltd Venus USB2.0 Camera
・・・

デバイスノードの確認。

ls /dev/video*

こんな感じ。
カメラが他にも接続されているので2×2表示されてるけど…
今回接続されたのは2と3のはず(今はこれを使わないので気にしない)

/dev/video0  /dev/video1  /dev/video2  /dev/video3

必要ならguvcviewをインストールして試してみてちょ。

linux-toolsのインストール

sudo apt install linux-tools-generic

usbipを実行してみる

usbip

※ linux-tools-≪バージョン≫-generic をインストールしろと言われたら従う。例えば

sudo apt install linux-tools-6.5.0-41-generic

ドライバの組み込みとdaemonの起動

sudo modprobe usbip-host        # ドライバ組み込み
sudo usbipd -D                  # daemon起動

[!NOTE] 起動時に自動で組み込み&実行したいときはsystemdでサービス登録するとできそうだけど、
本筋じゃないのでやめとく。
ここ とか参考になるかも。

接続されているデバイスを表示

sudo usbip list --local         # ※ usbipdではないので注意

こんな感じで表示される

・・・
 - busid 3-11 (056e:700a)
   Elecom Co., Ltd : unknown product (056e:700a)
・・・

[!NOTE] 表示される製品名等が不明確な場合はlsusbの結果と突き合わせてみると良い。
(IDはどちらも表示されているので、これを頼りに)

バインド

sudo usbip bind --busid 3-11    # ※ usbipdではないので注意

WSL Ubuntuでの操作

linux-toolsのインストール

usbipはWindows側でインストールしたusbipd-winに含まれているのでインストール不要。
別途aptでインストールしても使えるけど結構メンドクサイ。
使いたくなることもあるかもしれんので、手順は残しておく。

[!NOTE]

usbipが入っているパッケージをインストール

sudo apt install linux-tools-generic

usbipを実行してみる

usbip

たぶんこんなメッセージが出る

WARNING: usbip not found for kernel 6.6.87.1-microsoft

  You may need to install the following packages for this specific kernel:
    linux-tools-6.6.87.1-microsoft-standard-WSL2
    linux-cloud-tools-6.6.87.1-microsoft-standard-WSL2

  You may also want to install one of the following packages to keep up to date:
    linux-tools-standard-WSL2
    linux-cloud-tools-standard-WSL2

しかし、指定されたパッケージをインストールしようとしても「そんなもんはない」と怒られる。
しかたないのでゴマカシ。

cd /usr/lib/linux-tools

ls -la
合計 12
drwxr-xr-x  3 root root 4096  6月  6 13:11 .
drwxr-xr-x 65 root root 4096  6月  6 13:11 ..
drwxr-xr-x  2 root root 4096  6月  6 13:11 6.8.0-60-generic    ← これを覚えておく

isbipを実行した時のメッセージとlsしたときのディレクトリ名から以下のようなシンボリックリンクを作成する
(カーネルバージョンが変わると変更しないといけないので注意)

ln -s 6.8.0-60-generic 6.6.87.1-microsoft-standard-WSL2

再度usbipを実行してみる

usbip

USAGEが表示されたらOK。
またWARNINGが表示されたらシンボリックリンクの名前が間違っていると思うので、再確認。

[!TIP] usbipコマンドへのpathを設定してもsudoで実行するときは無効なので、設定せずfullpathで指定する

アタッチ可能なバス番号を調べる

/mnt/c/Program\ Files/usbipd-win/WSL/usbip list -r ≪UbuntuPCのIPアドレス≫

こんな感じで表示される(BUSIDは例。以下同じ)

Exportable USB devices
======================
 - ≪UbuntuPCのIPアドレス≫
       3-11: Elecom Co., Ltd : unknown product (056e:700a)
           : /sys/devices/pci0000:00/0000:00:14.0/usb3/3-11
           : Miscellaneous Device / ? / Interface Association (ef/02/01)

アタッチする

sudo /mnt/c/Program\ Files/usbipd-win/WSL/usbip attach -r ≪UbuntuPCのIPアドレス≫ --busid 3-11

確認

アタッチできたか確認する

lsusb
・・・
Bus 001 Device 003: ID 056e:700a Elecom Co., Ltd Venus USB2.0 Camera
・・・

前と同様にguvcviewを実行してみる。

LANG="C" guvcview

別ウィンドウが表示され、画像が表示される。
それなりに大きなサイズに切り替えても表示できている。

後片付け

usbipのポートの確認

/mnt/c/Program\ Files/usbipd-win/WSL/usbip port

こんな感じで表示される。

Imported USB devices
====================
Port 00: <Port in Use> at High Speed(480Mbps)
       Elecom Co., Ltd : unknown product (056e:700a)
       1-1 -> unknown host, remote port and remote busid
           -> remote bus/dev 003/006

ポートは0であることが分かる。

デタッチする

sudo /mnt/c/Program\ Files/usbipd-win/WSL/usbip detach --port 0

まとめ

ということで、どうも、USBIPD-WINの転送速度が遅いようだ。

Bluetoothを使ってみる

カメラはビミョーな結果だったので、今度はBluetoothで試してみる。 使用したのは Buffalo BSBT4D09BK(4.0+EDR/LEのアダプタ、中身はCSR製)。
これも結構古いのでもう売ってない。 中身がCSRのアダプタなら動く可能性高い。
Realtekのも使えそうだけど、試してないのでなんとも…

Ubuntu側の準備

今回はBluetoothなのでBluetooth関連のライブラリ類をインストールしておく。

sudo apt install bluez

Windows側の準備

USBipd-win

PowerShellやコマンドプロンプト等を管理者として開く。
USBデバイスのリストを表示
(今回はカメラを使うのでそこだけ抜粋。IDとか名前は例)
Not sharedになっている。

usbipd.exe list
・・・・
9-2    0a12:0001  Generic Bluetooth Radio       Not shared
・・・・

bindする(busidは上で調べたものを使用)

usbipd.exe bind  --busid 9-2
または 
usbipd.exe bind  --force --busid 9-2

[!NOTE] USBPcapがインストールされている(wiresharkなど)とwarningが表示されてbindできないので
--forceオプションを追加して実行する。
(warningで–forceオプションを付けろと教えてくれる)

確認
Shared または Shared (forced)になっている。

usbipd.exe list
・・・・
9-2    0a12:0001  Generic Bluetooth Radio       Shared (forced)
・・・・

attachする(attachする前にWSLの仮想マシンが起動していること)

usbipd.exe attach --wsl --busid 9-2

[!TIP] 以下のようにbindするとUSB挿抜する度に自動でattachしてくれるらしい。確認してないけど。

usbipd.exe attach --wsl --busid 2-1 --auto-attach

確認する
Attachedになっている

usbipd.exe list
・・・・
9-2    056e:700a  Venus USB2.0 Camera   Attached
・・・・

Ubuntu側の実行

USB機器が割り当てられたことを確認する。

lsusb

こんな感じで表示される

Bus 001 Device 003: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)

動かしてみる

ローカルデバイスの一覧表示をしてみる。

hcitool dev

例えばこんな感じで表示される。

Devices:
        hci0    XX:XX:XX:XX:XX:XX

スキャンしてみる。

bluetoothctl

bluetoothctlが起動され、プロンプトが[bluetooth]#になる。
スキャンしてデバイス一覧を見てみる

scan on
≪スキャンされたデバイスが表示される≫
≪しばらく待つ≫
scan off
≪表示が止まる≫

list
≪スキャンされたデバイスが表示される≫

exit
≪終了してshellに戻る≫

pythonで動かしてみる。

pyenvでpythonをインストールする場合は pyenvのインストール の注意書きにあるように、コンパイル前に以下を実行しておく。

sudo apt install libbluetooth-dev libglib2.0-dev libboost-python-dev libboost-thread-dev

新しくプログラム作るのは面倒なので以前作った
AndroidでpythonでBLE
を実行してみる。

必要なモジュール類をインストールして

sudo apt install libmtdev-dev
pip install kivy bleak

実行

python kivy_ble.py

動いた。メデタシメデタシ。

Windows側の後始末

USBカメラを取り外すためにアタッチ解除とバインド解除

usbipd.exe detach --busid 9-2
usbipd.exe unbind  --busid 9-2

その他

USB接続のSDカードリーダを使えばRaspberryPiのブート用SDカードをWSLにマウントして操作することも可能なはず。
メンドクサくなってきたので試すのはやめておくけど。