WSL2でBluetoothデバイスを使う(失敗)

# WSL2でBluetoothデバイスを使う(失敗)

やり方がダメなのか、うまくいかなかったけどなにかの参考になるかもしれないのでここに供養しておく。(うまくいった人がいたら教えてほしい)

## PC構成

* Dell Inspiron 14 5425 Ryzen 7 5825u
* Windows 11

ほかのPC(Bluetoothアダプタ)なら同じ手順でいけるかもしれないけど、未確認。


## 参考

以下を確認すると、WSL2でもBluetoothが使えるっぽいので試してみて手順をメモしておく。

https://github.com/dorssel/usbipd-win/issues/278
https://github.com/dorssel/usbipd-win/discussions/310


## 手順

### 必要パッケージのインストール

WSLのインストール https://learn.microsoft.com/ja-jp/windows/wsl/install
(管理者権限が必要)

```powershell
scoop install sudo
sudo wsl --install
```


usbipdをインストール https://github.com/dorssel/usbipd-win

```powershell
winget install usbipd
```

この時点で、Bluetoothアダプターが見えることを確認しておく。
以下のように`usbipd list`で`MediaTek Bluetooth Adapter`なるものが見えるので問題なさそう。
ここでBluetoothアダプターが見えない場合は残念ながらこの方法ではWSL2からBluetoothは扱えない。

```
PS C:\Users\saido> usbipd list
Connected:
BUSID  VID:PID    DEVICE                                                        STATE
1-4    0c45:6a1b  Integrated Webcam                                             Not shared
2-3    0489:e0c8  MediaTek Bluetooth Adapter                                    Not shared
2-4    27c6:639c  Goodix MOC Fingerprint                                        Not shared

Persisted:
GUID                                  DEVICE
```


WSL2内での操作 https://github.com/dorssel/usbipd-win/wiki/WSL-support

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

二行目の`sudo update-alternatives ...`はaptでパッケージをアップデートするごとに実行が必要っぽい？


### usbipdでUSBデバイスの接続

初回は`usbipd bind`する必要がある。(管理者権限が必要)

```powershell
sudo usbipd bind -b 2-3
```

これで、BluetoothアダプターがShared状態になる。

```powershell
PS C:\Users\saido> usbipd list
Connected:
BUSID  VID:PID    DEVICE                                                        STATE
1-4    0c45:6a1b  Integrated Webcam                                             Not shared
2-3    0489:e0c8  MediaTek Bluetooth Adapter                                    Shared   <---
2-4    27c6:639c  Goodix MOC Fingerprint                                        Not shared

Persisted:
GUID                                  DEVICE
```

Shared状態になっているUSBデバイスはWSL側にAttachすることができる。

```powershell
usbipd wsl attach -b 2-3
```

ちなみにAttachするときはWSLが起動状態(WSLのコンソールが開いている状態)でないといけない。
Attachが成功すると以下のようになる。

```powershell
PS C:\Users\saido> usbipd list
Connected:
BUSID  VID:PID    DEVICE                                                        STATE
1-4    0c45:6a1b  Integrated Webcam                                             Not shared
2-3    0489:e0c8  MediaTek Bluetooth Adapter                                    Attached   <---
2-4    27c6:639c  Goodix MOC Fingerprint                                        Not shared

Persisted:
GUID                                  DEVICE
```

この状態でWSL側で接続されているUSBデバイスを確認すると、ちゃんと見えるので大丈夫っぽい。
(当然だが、WSL側にBluetoothアダプターを接続してしまうとWindows側からはBluetooth機器に接続できなくなるので注意)

```sh
saido@Inspiron14:~$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 0489:e0c8 Foxconn / Hon Hai Wireless_Device
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
```

接続を元に戻したい場合は以下を実施する。

```powershell
usbipd wsl detach -b 2-3
```


### カーネル再コンパイル

sudo apt install bluez


saido@Inspiron14:/mnt/c/Users/saido$ hcitool lescan
Could not open device: No such device


参考
https://github.com/dorssel/usbipd-win/wiki/WSL-support

ここからは念のため別の環境で作業

```powershell
wsl --export <current-distro> <temporary-path>\wsl2-usbip.tar
wsl --import wsl2-usbip <install-path> <temporary-path>\wsl2-usbip.tar
```

以下のようになった。

```powershell
PS C:\Users\saido> wsl --export Ubuntu .\OneDrive\Settings\wsl2-usbip.tar
エクスポートが進行中です。これには数分かかる場合があります。
この操作を正しく終了しました。
PS C:\Users\saido> wsl --import wsl2-usbip .\WSL\wsl2-usbip .\OneDrive\Settings\wsl2-usbip.tar
インポート中です。この処理には数分かかることがあります。
この操作を正しく終了しました。
PS C:\Users\saido> wsl --list
Linux 用 Windows サブシステム ディストリビューション:
Ubuntu (既定)
wsl2-usbip
```

作った環境で起動してカーネルビルド環境を構築。

```sh
wsl --distribution wsl2-usbip --user <user>

sudo apt update && sudo apt upgrade
sudo apt install build-essential flex bison libssl-dev libelf-dev libncurses-dev autoconf libudev-dev libtool
```

`uname -r`でカーネルバージョンを確認しておく。(ドライバーモジュールとかファームウェアの格納場所が変わるので)

```sh
saido@Inspiron14:~$ uname -r
5.15.62.1-microsoft-standard-WSL2
```

カーネルのソースをダウンロードしてコンフィグ。

```sh
git clone https://github.com/microsoft/WSL2-Linux-Kernel.git
cd WSL2-Linux-Kernel
git checkout linux-msft-wsl-5.15.62.1

cp /proc/config.gz config.gz
gunzip config.gz
mv config .config

sudo make menuconfig
```

#### 一回目(ダメだった)

Bluetoothデバイスのドライバーを有効にするためのオプションは以下を参考に設定した。(微妙に違う部分は勘で補間)

https://ubuntu.com/core/docs/bluez/reference/device-enablement/linux-kernel-configuration-options


```diff
--- //wsl.localhost/wsl2-usbip/home/saido/souces/WSL2-Linux-Kernel/.config.old	Sun Oct  2 00:53:53 2022
+++ //wsl.localhost/wsl2-usbip/home/saido/souces/WSL2-Linux-Kernel/.config	Sun Oct  2 01:10:03 2022
@@ -2,15 +2,17 @@
 # Automatically generated file; DO NOT EDIT.
 # Linux/x86 5.15.62.1 Kernel Configuration
 #
-CONFIG_CC_VERSION_TEXT="x86_64-msft-linux-gcc (GCC) 9.3.0"
+CONFIG_CC_VERSION_TEXT="gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0"
 CONFIG_CC_IS_GCC=y
-CONFIG_GCC_VERSION=90300
+CONFIG_GCC_VERSION=90400
 CONFIG_CLANG_VERSION=0
 CONFIG_AS_IS_GNU=y
 CONFIG_AS_VERSION=23400
 CONFIG_LD_IS_BFD=y
 CONFIG_LD_VERSION=23400
 CONFIG_LLD_VERSION=0
+CONFIG_CC_CAN_LINK=y
+CONFIG_CC_CAN_LINK_STATIC=y
 CONFIG_CC_HAS_ASM_GOTO=y
 CONFIG_CC_HAS_ASM_INLINE=y
 CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y
@@ -738,7 +740,6 @@
 # end of GCOV-based kernel profiling
 
 CONFIG_HAVE_GCC_PLUGINS=y
-# CONFIG_GCC_PLUGINS is not set
 # end of General architecture-dependent options
 
 CONFIG_RT_MUTEXES=y
@@ -1466,7 +1467,35 @@
 
 # CONFIG_HAMRADIO is not set
 # CONFIG_CAN is not set
-# CONFIG_BT is not set
+CONFIG_BT=m
+CONFIG_BT_BREDR=y
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+CONFIG_BT_HS=y
+CONFIG_BT_LE=y
+# CONFIG_BT_MSFTEXT is not set
+# CONFIG_BT_AOSPEXT is not set
+CONFIG_BT_DEBUGFS=y
+# CONFIG_BT_SELFTEST is not set
+# CONFIG_BT_FEATURE_DEBUG is not set
+
+#
+# Bluetooth device drivers
+#
+# CONFIG_BT_HCIBTUSB is not set
+# CONFIG_BT_HCIUART is not set
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_BT_MRVL is not set
+# CONFIG_BT_VIRTIO is not set
+# end of Bluetooth device drivers
+
 # CONFIG_AF_RXRPC is not set
 # CONFIG_AF_KCM is not set
 # CONFIG_MCTP is not set
@@ -2558,9 +2587,9 @@
 # HID support
 #
 CONFIG_HID=y
-# CONFIG_HID_BATTERY_STRENGTH is not set
-# CONFIG_HIDRAW is not set
-# CONFIG_UHID is not set
+CONFIG_HID_BATTERY_STRENGTH=y
+CONFIG_HIDRAW=y
+CONFIG_UHID=m
 CONFIG_HID_GENERIC=y
 
 #
@@ -2586,6 +2615,7 @@
 # CONFIG_HID_ELECOM is not set
 # CONFIG_HID_ELO is not set
 # CONFIG_HID_EZKEY is not set
+# CONFIG_HID_FT260 is not set
 # CONFIG_HID_GEMBIRD is not set
 # CONFIG_HID_GFRM is not set
 # CONFIG_HID_GLORIOUS is not set
@@ -3571,6 +3601,7 @@
 CONFIG_CRYPTO_AKCIPHER2=y
 CONFIG_CRYPTO_AKCIPHER=y
 CONFIG_CRYPTO_KPP2=y
+CONFIG_CRYPTO_KPP=m
 CONFIG_CRYPTO_ACOMP2=y
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_MANAGER2=y
@@ -3589,7 +3620,8 @@
 #
 CONFIG_CRYPTO_RSA=y
 # CONFIG_CRYPTO_DH is not set
-# CONFIG_CRYPTO_ECDH is not set
+CONFIG_CRYPTO_ECC=m
+CONFIG_CRYPTO_ECDH=m
 # CONFIG_CRYPTO_ECDSA is not set
 # CONFIG_CRYPTO_ECRDSA is not set
 # CONFIG_CRYPTO_SM2 is not set
@@ -3913,8 +3945,6 @@
 CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
 # CONFIG_DEBUG_INFO_DWARF4 is not set
 CONFIG_DEBUG_INFO_BTF=y
-CONFIG_PAHOLE_HAS_SPLIT_BTF=y
-CONFIG_DEBUG_INFO_BTF_MODULES=y
 # CONFIG_GDB_SCRIPTS is not set
 CONFIG_FRAME_WARN=1024
 # CONFIG_STRIP_ASM_SYMS is not set
```

ひとまずこれでビルドしてみる。

```sh
saido@Inspiron14:~/souces/WSL2-Linux-Kernel$ sudo make -j 16 && sudo make modules_install -j 16 && sudo make install -j 16
[sudo] password for saido:
  SYSHDR  arch/x86/include/generated/uapi/asm/unistd_32.h
  SYSHDR  arch/x86/include/generated/uapi/asm/unistd_64.h
  SYSHDR  arch/x86/include/generated/uapi/asm/unistd_x32.h

...

  GEN     modules.builtin
BTF: .tmp_vmlinux.btf: pahole (pahole) is not available
Failed to generate BTF for vmlinux
Try to disable CONFIG_DEBUG_INFO_BTF
make: *** [Makefile:1213: vmlinux] Error 1
```

なんかエラーになったのでググった https://stackoverflow.com/questions/61657707/btf-tmp-vmlinux-btf-pahole-pahole-is-not-available
以下が必要とのこと。

```sh
sudo apt install dwarves
```

カーネルのコンパイルが終わったら、usbip関連の何か(謎)をしてから、ビルドしたカーネルをwslが読める場所においておく。

```sh
cd tools/usb/usbip
sudo ./autogen.sh
sudo ./configure
sudo make install -j 16

sudo cp libsrc/.libs/libusbip.so.0 /lib/libusbip.so.0

sudo apt-get install hwdata

cd -
sudo cp arch/x86/boot/bzImage /mnt/c/Users/saido/WSL/usbip-bzImage
```


`/mnt/c/Users/saido/.wslconfig`に以下を追記して、ビルドしたカーネルで起動できるようにしておく。

```conf
[wsl2]
kernel=c:\\users\\saido\\usbip-bzImage
```

wsl再起動(元の環境で起動させる)。

```powershell
wsl --shutdown
wsl
```

ドライバーモジュール読み込み。

```sh
sudo modprobe bluetooth
sudo modprobe btusb
```

`bluetooth`がないとかで失敗する。そういえば`btusb`とかも有効にした記憶がないので、もう一度カーネルのコンパイルが必要っぽい。


#### 二回目(`btusb`を追加してみるがダメだった)

一回目に追加して以下のコンフィグを追加した。

```diff
--- //wsl.localhost/wsl2-usbip/home/saido/souces/WSL2-Linux-Kernel/.config.old	Sun Oct  2 01:10:03 2022
+++ //wsl.localhost/wsl2-usbip/home/saido/souces/WSL2-Linux-Kernel/.config	Sun Oct  2 02:00:18 2022
@@ -1486,13 +1486,21 @@
 #
 # Bluetooth device drivers
 #
-# CONFIG_BT_HCIBTUSB is not set
+CONFIG_BT_INTEL=m
+CONFIG_BT_BCM=m
+CONFIG_BT_RTL=m
+CONFIG_BT_HCIBTUSB=m
+# CONFIG_BT_HCIBTUSB_AUTOSUSPEND is not set
+CONFIG_BT_HCIBTUSB_BCM=y
+CONFIG_BT_HCIBTUSB_MTK=y
+CONFIG_BT_HCIBTUSB_RTL=y
 # CONFIG_BT_HCIUART is not set
 # CONFIG_BT_HCIBCM203X is not set
 # CONFIG_BT_HCIBPA10X is not set
 # CONFIG_BT_HCIBFUSB is not set
 # CONFIG_BT_HCIVHCI is not set
 # CONFIG_BT_MRVL is not set
+# CONFIG_BT_ATH3K is not set
 # CONFIG_BT_VIRTIO is not set
 # end of Bluetooth device drivers
 
@@ -1626,6 +1634,7 @@
 # CONFIG_TEST_ASYNC_DRIVER_PROBE is not set
 CONFIG_GENERIC_CPU_AUTOPROBE=y
 CONFIG_GENERIC_CPU_VULNERABILITIES=y
+CONFIG_REGMAP=y
 CONFIG_DMA_SHARED_BUFFER=y
 # CONFIG_DMA_FENCE_TRACE is not set
 # end of Generic Driver Options
@@ -3945,6 +3954,8 @@
 CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
 # CONFIG_DEBUG_INFO_DWARF4 is not set
 CONFIG_DEBUG_INFO_BTF=y
+CONFIG_PAHOLE_HAS_SPLIT_BTF=y
+CONFIG_DEBUG_INFO_BTF_MODULES=y
 # CONFIG_GDB_SCRIPTS is not set
 CONFIG_FRAME_WARN=1024
 # CONFIG_STRIP_ASM_SYMS is not set
```

それから、`.ko`ファイルたちがいない、というか`/lib/modules/5.15.62.1-microsoft-standard-WSL2+`ディレクトリが存在しないので、以下のようにモジュールたちを固めて持っていく。


wsl2-usbip内

```sh
tar -zcvf /mnt/c/Users/saido/WSL/modules.tgz /lib/modules/
```

Ubuntu(元のディストリビューション)内

```sh
cd /
sudo tar -zxvf /mnt/c/Users/saido/WSL/modules.tgz
```

これで以下を実行してみたけど、認識されない。
ちなみにカーネル再起動ごとに`usbipd wsl attach -b 2-3`が必要なので注意。


```
sudo service dbus start
sudo service bluetooth restart

sudo modprobe bluetooth
sudo modprobe btusb
```

`hcitool lescan`を実行してみるが、以下のエラーになる。

```
saido@Inspiron14:/$ hcitool lescan
Could not open device: No such device
```

#### 三回目(ドライバーにパッチをあててみるが、ダメだった)

搭載されているBluetoothアダプタには以下のパッチが必要っぽい？？？

https://patchwork.kernel.org/project/linux-mediatek/patch/1b7d9428ba0c6d572d7da1da166240833350786e.1651082524.git.objelf@gmail.com/

```diff
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 3b0af9f05ea8..e25fcd49db70 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -451,6 +451,9 @@ static const struct usb_device_id blacklist_table[] = {
                 BTUSB_VALID_LE_STATES },
 
  /* Additional MediaTek MT7921 Bluetooth devices */
+ { USB_DEVICE(0x0489, 0xe0c8), .driver_info = BTUSB_MEDIATEK |
+                BTUSB_WIDEBAND_SPEECH |
+                BTUSB_VALID_LE_STATES },
  { USB_DEVICE(0x04ca, 0x3802), .driver_info = BTUSB_MEDIATEK |
                 BTUSB_WIDEBAND_SPEECH |
                 BTUSB_VALID_LE_STATES },
```

同様に再ビルドしてモジュールを固めてみたけど、、、

```sh
sudo service dbus start
sudo service bluetooth restart

sudo modprobe bluetooth
sudo modprobe btusb

sudo bluetoothd &
sudo bluetoothctl
```

ダメっぽい。

```
[bluetooth]# show
No default controller available
```

ここらへんで`hciconfig`なるものを見つけたけど、見えてない模様。

```log
saido@Inspiron14:/$ hciconfig -a
hci0:   Type: Primary  Bus: USB
        BD Address: 00:00:00:00:00:00  ACL MTU: 0:0  SCO MTU: 0:0
        DOWN
        RX bytes:0 acl:0 sco:0 events:0 errors:0
        TX bytes:0 acl:0 sco:0 commands:0 errors:0
        Features: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
        Packet type: DM1 DH1 HV1
        Link policy:
        Link mode: SLAVE ACCEPT
```

`dmesg`では`mediatek/BT_RAM_CODE_MT7961_1_2_hdr.bin`がないって言ってるけど、ちゃんと配置してるつもりなんだけどなー。

```log
saido@Inspiron14:~/Download$ dmesg | grep hci0
[   43.650340] bluetooth hci0: Direct firmware load for mediatek/BT_RAM_CODE_MT7961_1_2_hdr.bin failed with error -2
[   43.651478] Bluetooth: hci0: Failed to load firmware file (-2)
[   43.652104] Bluetooth: hci0: Failed to set up firmware (-2)
[  376.906249] bluetooth hci0: Direct firmware load for mediatek/BT_RAM_CODE_MT7961_1_2_hdr.bin failed with error -2
[  376.907332] Bluetooth: hci0: Failed to load firmware file (-2)
[  376.907922] Bluetooth: hci0: Failed to set up firmware (-2)
[  698.579311] bluetooth hci0: Direct firmware load for mediatek/BT_RAM_CODE_MT7961_1_2_hdr.bin failed with error -2
[  698.580802] Bluetooth: hci0: Failed to load firmware file (-2)
[  698.581478] Bluetooth: hci0: Failed to set up firmware (-2)
```

手動で配置してみてもダメだった。

```sh
wget https://anduin.linuxfromscratch.org/sources/linux-firmware/mediatek/BT_RAM_CODE_MT7961
_1_2_hdr.bin
sudo mkdir -p /lib/firmware/mediatek/
```