前言
最近由于项目需要,要求在linux下连接xbox手柄去控制水下机器人(所以没有办法直接连在机器人上面)所以有了需要在WSL2上连接手柄的需求,下面这篇文章就记录一下笔者在WSL2上连接手柄所遇到了一些坑
笔者采用的手柄是北通的XBOX手柄,若有其他不一样的,可能遇到其他不一样的问题,但一般的XBOX手柄应该都是一样的
连接USB设备
关于WSL2如何连接USB设备,请仔细阅读微软的官方文档。连接USB设备
主要就是使用usbipd-win这个项目把USB转IP发送到WSL下面。
插入手柄到电脑上面,管理员模式下打开PowerShell,输入
usbipd wsl list
可以查看当前连接的所有USB设备
可以看到,笔者的手柄连接在了id 为2-1的地方,接着输入
usbipd wsl attach -b <your bus_id> -d <your distribution>
由于笔者WSL安装了多个发行版,所以这里指定了一下。然后我们可以看到usbipd 提示设备繁忙,这里在笔者翻阅许多资料后,大概是手柄插上后,windows会与手柄进行交互,相对于占用了手柄的端口,导致无法与WSL连接。这时候可以在设置中取消打开XBOX
但是笔者是WIN 11 的电脑,不知道为什么没有成功,还是显示占用,然而WIN 10的电脑上面却可以。如果还是显示占用,可以输入下面命令强制绑定端口
usbipd bind --force --busid <bus_id>
提示我们重启电脑,我们按照要求即可。
重启电脑后我们再次尝试连接,连接成功,在wsl输入 lsusb 也可以查看到手柄
此时我们查看dev目录下有没有手柄信息.
一般手柄会挂载为/dev/js* 或者 /devinput/js* ,但是目前两者都没有,这是为什么呢?
原来WSL的内核并没有使能手柄驱动,但是WSL都一直走过来了,我实在又不想使用笨重的VMWare,只能见山开山,遇水架桥了
重新编译内核
关于如何重新编译wsl的linux内核,网上有许多参考方法,这里介绍一下我参考的两篇
参考1
参考2
首先从微软的官方github上下载wsl内核源码(微软官方内核源码),建议下载比较新的内核(笔者是5.15),其他内核可能没有使能USB/IP,导致usbipd没办法使用,还需要自己打开。
文件比较大,这里怎么在wsl里面使用windows的代理进行科学上网,网上也有其他写的好的博客,笔者在此不过多赘述。
下载好了后,我们进入 WSL2-Linux-Kernel 文件夹内,编译前需要下载一些工具,在参考的博客里面都有提及,如果还缺少其他工具,根据提示自行下载即可。
进入文件夹后,输入
# 注意要指定 KCONFIG_CONFIG 参数
# 内核配置文件的默认位置是源码目录下的 .config,而 WSL 2 的内核配置文件在 Microsoft/config-wsl,如果不手动指定的话会载入默认配置文件
# 当然你也可以手动复制一份内核配置文件出来,或者进 menuconfig 之后再手动加载
sudo make menuconfig KCONFIG_CONFIG=Microsoft/config-wsl
进入图形化配置界面
按y选择使能下面两项:
Device Drivers—>Input device support—>Joystick interface
Device Drivers—>Input device support—>Joysticks/Gamepads—>X-Box gamepad support&&X-Box gamepad rumble support
按空格进入Joysticks/Gamepads选择X-Box gamepad support下面的几项
然后选择Save保存,或者一直按Esc,就会问你是否保存
然后开始编译内核
# 编译并生成压缩后的内核,我比较懒,就直接把这些驱动全编译进内核了
sudo make -j$(nproc) bzImage KCONFIG_CONFIG=Microsoft/config-wsl
# 作为内核模组编译的话,把模组编译出来,然后安装模组
sudo make -j$(nproc) modules KCONFIG_CONFIG=Microsoft/config-wsl
sudo make -j$(nproc) modules_install KCONFIG_CONFIG=Microsoft/config-wsl
编译好的内核存放在arch/x86/boot/bzImage 这里
我们把它拷贝出来,例如笔者考在自己windows下的系统盘里面,当然其他路径也可以
cp bzImage /mnt/u/kernel/joy-bzImage
接下来,我们指定wsl以我们编译好的内核启动即可
打开你的用户目录(在C盘下面,例如笔者的目录为C:\Users\Lion),打开.wslconfig文件(如果没有就自己创建)输入以下命令,其实就是指定内核的位置
最后重新启动wsl,输入 uname -a
可以看到内核的编译时间已经变了,所以已经从我们自己编译的内核上面启动
接着,我们插入手柄接收器,重新usbipd连接,可以发现/dev/input 目录下面已经可以找到js0了,说明手柄驱动重新使能
接着我们跑一下测试例程吧
sudo apt-get install joystick -y
然后输入
sudo jstest /dev/input/js0
和串口一样,操作dev下设备都是需要root权限,如果不加sudo,可能无法正常读取
手柄已经可以正常读取啦!