wslのカーネルをカスタムビルドし、カメラ・ゲームパッドに対応する

# 概要
2025/02/12現在、通常のWSLではwebカメラやゲームパッドを正常に認識できません。ロボット関連の開発ではこれらを使用したいことも多いので、使えないのはやや困りものです。この問題に対処するために、wslカーネルをカスタムビルドします。
ビルド済カーネルは[私のgithub](https://github.com/OsawaKousei/wsl-custom-kernel-for-robotics-dev)で公開しています

# 動作環境・バージョン
### 動作環境
windows11

### バージョン
Windows11 24H2

WSL バージョン: 2.4.10.0
カーネル バージョン: 5.15.167.4-1

※windows11であってもバージョンが古い場合、wslの一部の機能が正常に動作しない可能性があります

### 使用機器
realsense D455f
logicool Gamepad F310

# 前提条件
wslを使用した経験があること

# コンテンツ
wsl内での操作とwindows側での操作があります。これを誤ると重大な問題が発生する可能性があるので、注意して下さい。windows側での操作は管理者権限を付与したpowershellを使用して下さい。

## カメラ対応
### ビルドツールの準備
以下wsl内で実行<br>
### ビルドの依存関係のインストール
`sudo apt install build-essential flex bison libssl-dev libelf-dev libncurses-dev autoconf libudev-dev libtool bc`
### ベースとなるカーネルのダウンロード
```
git clone --depth 1 -b linux-msft-wsl-5.15.y https://github.com/microsoft/WSL2-Linux-Kernel.git
cd WSL2-Linux-Kernel
```
### configファイルの作成

configファイルの編集が億劫な人は[私のgithub](https://github.com/OsawaKousei/wsl-custom-kernel-for-robotics-dev)から編集済ファイルを取得することもできます。

```
cp /proc/config.gz config.gz
gunzip config.gz
mv config .config
```
### configファイルの書き換え
`sudo make menuconfig`
ターミナル上でGUIを介してカーネルの編集を行えます
Selectで進むExitで戻る（必ずしもGUIが閉じらるわけではない）、Yでチェック、Nでチェック解除
「Kernel hacking > Compile-time checks and compiler options > General BTF typeinformation」のチェックをはずす
<img width="834" alt="image.png (84.5 kB)" src="https://img.esa.io/uploads/production/attachments/19744/2025/02/12/148658/63331071-215b-4517-a6f2-2b9e0a25a7e4.png">
「Device Drivers > Multimedia support」にチェックを付ける
<img width="832.5" alt="image.png (76.0 kB)" src="https://img.esa.io/uploads/production/attachments/19744/2025/02/12/148658/5b9d2a8f-46a4-4b6e-b642-ac4bda324a1e.png">
「Device Drivers > Multimedia support > Video4Linux options」内の３つすべてにチェックを付ける
<img width="834.75" alt="image.png (48.8 kB)" src="https://img.esa.io/uploads/production/attachments/19744/2025/02/12/148658/d12ac1b7-0f8d-4b12-8238-135adc67f51d.png">
「Device Drivers > Multimedia support > Media drivers > Media USB Adapters」にチェックを付ける
<img width="836.25" alt="image.png (63.3 kB)" src="https://img.esa.io/uploads/production/attachments/19744/2025/02/12/148658/9ce239a7-1b4c-453d-ac3b-d31981586aed.png">
「Device Drivers > Multimedia support > Media drivers > Media USB Adapters > USB Video Class(UVC)」にチェックを付ける
<img width="834" alt="image.png (91.8 kB)" src="https://img.esa.io/uploads/production/attachments/19744/2025/02/12/148658/f180a276-bbb2-4599-a607-b74ba3fd3e54.png">
SAVE->OK->EXITで保存しGUIが終了するまでEXIT


## ゲームパッド対応
※このセクションではカーネルの設定ファイルを直接編集します。私の環境ではうまくいきましたが、この操作は公式には非推奨であり、失敗した場合重大な不具合が発生する可能性があります。自己責任で行ってください。

configファイルの編集が億劫な人は[私のgithub](https://github.com/OsawaKousei/wsl-custom-kernel-for-robotics-dev)から編集済ファイルを取得することもできます。

カメラ対応のconfigファイル作成までを実行して下さい
任意のsudo権限を付与したエディタで以下の編集を行ってください。私はnanoでやりました。
編集する項目は「Userland interfaces」の下にあります
- 2011行目付近の`CONFIG_INPUT_JOYDEV is not set`を`CONFIG_INPUT_JOYDEV=y`に変更
- 2012行目付近の`CONFIG_INPUT_EVDEV is not set`を`CONFIG_INPUT_EVDEV=y`に変更
- `CONFIG_INPUT_JOYSTICK is not set`を`CONFIG_INPUT_JOYSTICK=y`に変更
- ↑の真下に`CONFIG_JOYSTICK_ANALOG=y`を新たな行として挿入
- ↑の真下に`CONFIG_JOYSTICK_XPAD=y`を新たな行として挿入
- ↑の真下に`CONFIG_JOYSTICK_XPAD_FF=y`を新たな行として挿入

## ビルド・反映
### ビルド
`sudo make -j$(nproc) && sudo make modules_install -j$(nproc) && sudo make install -j$(nproc)`
※ ゲームパッド対応を行っている場合、色々聞かれるので全てy

### カーネルの読み込み
下記のwindows-user-nameは自身のものに置き換えてください（全部で３か所あります）
`cp vmlinux /mnt/c/Users/<windows-user-name>/vmlinux`
`cat << 'EOT' > /mnt/c/Users/<windows-user-name>/.wslconfig`
`[wsl2]`
`kernel=C:\\Users\\<windows username>\\vmlinux`
`EOT`

windows側のpowershellに切り替えてください
`wsl --shutdown`
念のため、PCを再起動してください

wslを起動し、wsl内のターミナルに切り替えてください
`uname -a`で表示されるカーネルバージョンの末尾が`microsoft-standard-WSL2+`になっており（+が重要）。#以降の最終ビルド日時がビルドを行った時間帯と整合すれば反映されています

## 接続の確認
usbipdのインストールがまだの人・使い方が分からない人は[こちら](https://learn.microsoft.com/ja-jp/windows/wsl/connect-usb)を参照してください
使用したい機器をUSB接続しusbipdによってwslにアタッチしてください
※始めてゲームパッドを使用する際にはbindの際に`--force`オプションが必要になることがあります（例：` usbipd bind --force --busid 1-9`）

### カメラの接続確認
wsl内のターミナルで`ls /dev`を実行してください
<img width="797.25" alt="image.png (85.4 kB)" src="https://img.esa.io/uploads/production/attachments/19744/2025/02/12/148658/deb711db-f813-4f69-b83e-06f8f33860a9.png">
添付画像右側のようにvideo0~video5（何番まであるかはカメラによります）が表示されていれば成功

### ゲームパッドの接続確認
wsl内のターミナルで`ls /dev/input`を実行してください
<img width="272.25" alt="image.png (6.0 kB)" src="https://img.esa.io/uploads/production/attachments/19744/2025/02/12/148658/972a0456-e3e5-4053-a989-c68223270730.png">
添付画像のようにevent0,1及びjs0が表示されていれば成功

## 実際の使用に際して
実際に使用する際は必要に応じて
`sudo chmod 777 /dev/video*`
`sudo chmod 777 /dev/input/*`
によって権限を設定してください

# トラブルシューティング
WSLのデフォルトディストリビューションを確認し、想定と一致しているかチェック
1. `wsl -l`で確認
1. 想定と異なっていた場合`wsl -s Ubuntu-<dist>`で変更

WSLの再インストールが問題解決に有効なことがあります（WSL内のデータは保持されません）
1. wsl -l -v でインストールされているディストリビューションを確認
1. wsl --unregister <dist>
1. （あれば）microsoftストアでインストールしたアプリをアンインストール
1. PC再起動
1. microsofストアから再インストール



# 終わりに
これらのデバイスが使用できればWSLにおけるロボット開発の幅が広がるでしょう。

# 参考文献
[touch-sp様のブログ「パソコン関連もろもろ」より](https://touch-sp.hatenablog.com/entry/2024/01/07/155445)
[WSLのgithub issueより](https://github.com/microsoft/WSL/issues/7747)
[Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/wsl/connect-usb)