魔派赤兔 2 HD 在 Linux 上的蓝牙与按键折腾记录:从配对失败到正常玩地平线 6

笔记

本来只是想在 CachyOS 上连一下魔派赤兔 2 HD 手柄,玩《极限竞速:地平线 6》。这手柄之前在 Windows 上用过,我原以为蓝牙配好就能直接开车,没想到从 KDE 的连接失败一路查到了 BlueZ、HID 驱动和 Steam Input。

最后总算折腾好了。现在手柄能正常连接,游戏里的操作也恢复正常,重启电脑后仍然可以直接重连。趁还记得,把这次遇到的几个坑记下来。

先说环境

  • 系统:CachyOS,排查时的内核为 7.2.10-1-cachyos
  • 桌面:KDE Plasma 6.8,Wayland
  • 蓝牙:BlueZ 5.87
  • 手柄:魔派赤兔 2 HD(Mobapad Chitu 2 HD),Xbox/PC 蓝牙模式
  • 游戏:Steam 版《极限竞速:地平线 6》,Proton Experimental

下面有些命令是当时在我的机器上执行的,不保证所有第三方 Xbox 兼容手柄都需要相同的处理。

第一个坑:我连配对模式都没进对

一开始,KDE 蓝牙界面能搜到 Mobapad-Pro2-HD,但是点击配对就失败。换成命令行也没什么改善:

bluetoothctl
scan on

手柄可以被扫描到,信号强度也没问题,但执行 pair 时先后见过:

org.bluez.Error.AuthenticationFailed
org.bluez.Error.AuthenticationRejected

我还拿手机扫描过,结果差不多。当时越查越像是 Linux 的蓝牙兼容性问题,后来甚至开始怀疑固件。

直到我重新仔细看了一遍说明书。

正确操作是先短按 Home 开机,再长按 Home 三秒进入配对模式。 我之前一直直接长按,少了开机那一下。这个低级错误让我绕了好大一圈(笑)。

切到 Xbox/PC 档位、按说明书操作后,电脑终于看到了真正要连接的 Xbox Wireless Controller。它与 Mobapad-Pro2-HD 是不同的蓝牙设备地址。至少在这次测试里,后者并不是我要找的 Xbox 游戏控制器接口。

期间我还试过 USB-C 有线连接,内核曾识别出 057e:2009(Switch Pro Controller)和 2345:e06e,随后又报:

can't read configurations, error -71

设备当时经过 USB Hub,-71 属于 USB 协议层面的错误。这条线没有继续查到底,不能拿它证明手柄 USB 功能坏了。后面用蓝牙解决了问题。

第二个坑:已经配对了,却只能连上半秒

找到 Xbox Wireless Controller 后,命令行终于能配对成功,但 KDE 重新连接还是经常失败。我甚至遇到过关掉 bluetoothctl 所在的终端之后,手柄跟着断开的情况。

先检查设备状态:

bluetoothctl info <手柄在 Xbox 模式下的蓝牙 MAC 地址>

最初看到的是:

Paired: yes
Bonded: yes
Trusted: no
Connected: no

于是先把它设置为可信设备:

bluetoothctl trust <手柄在 Xbox 模式下的蓝牙 MAC 地址>

Trusted 确实变成了 yes,但重连问题没好。BlueZ 的日志里还能看到:

control_connect_cb(): Host is down (112)
control_connect_cb(): Operation already in progress (114)

有一次我专门通过 D-Bus 监视连接状态,不在 KDE 里点连接,只短按 Home 让手柄自己尝试重连。结果 BlueZ 先报告 Connected: true,大约 449 毫秒后又变成 Connected: false。

也就是说,手柄不是完全连不上,而是蓝牙链路短暂建立后又断开了。KDE 显示连接失败并不冤枉它。

我还测试了两个方向:

  • 保持一个 bluetoothctl 配对 Agent 常驻,依然失败。
  • 临时禁用经典蓝牙 L2CAP 的 ERTM,依然失败。

当时禁用 ERTM 使用的是:

echo Y | sudo tee /sys/module/bluetooth/parameters/disable_ertm

不过这个方法没有解决我的问题,不建议直接照搬成永久配置。后来重启后 ERTM 恢复默认状态,手柄仍然可以正常连接。

最后真正让连接恢复正常的操作反而很简单:在 KDE 里忘记已保存的 Xbox Wireless Controller,再按正确的 Home 键步骤重新配对一次。

重新配对后,Paired、Bonded、Trusted、Connected 都正常,Linux 也创建了游戏控制器输入设备。此前的配对记录可能与手柄状态不一致,但具体是密钥还是连接参数出了问题,现有日志不足以确定。

第三个坑:连接正常,游戏里按键却不正常

蓝牙搞定后我总算进了游戏,结果发现操作键位和以前在 Windows 上不一样。

我没急着在《地平线》里重设整套按键,而是直接测试 Linux 的输入事件,再用 GamepadTester.cn 对照。ABXY 和摇杆能响应,但 View(两个方框)、Menu(三横线)等功能键明显不对。

此时内核实际使用的是 hid_microsoft 驱动,手柄报告的 ID 是 045e:02e0。

随后找到 xpadneo Issue #628,里面讨论的正好是魔派赤兔 2 系列的按键映射。维护者与其他用户提到:这类设备使用旧版 Xbox HID 描述格式,却发送了另一套按钮位图,导致部分按键被错误解释。已有用户通过 quirks=+16 修好映射。

我这台 CachyOS 直接能从仓库安装 xpadneo:

sudo pacman -S xpadneo-dkms

安装的是 0.10.4。我的 DKMS 和内核头文件此前已经装好,因此不用再从 AUR 编译一个 Git 版本。

接着添加配置文件:

sudoedit /etc/modprobe.d/99-mobapad-xpadneo.conf

内容如下:

options hid_xpadneo quirks=AA:BB:CC:DD:EE:FF+16

注意把 AA:BB:CC:DD:EE:FF 换成你自己手柄在 Xbox 模式下的蓝牙 MAC 地址。 不要填前面那个 Mobapad-Pro2-HD 的地址。+16 对应 xpadneo 的 Linux 按键映射兼容选项。

加载驱动:

sudo modprobe hid_xpadneo

这里还有个小坑。起初内核已经打印:

loaded hid-xpadneo v0.10.4

但 GamepadTester 的情况仍然没有变化。继续看 sysfs 才发现,手柄当时仍绑定在 hid_microsoft 上,光把 xpadneo 模块加载进内核是不够的。

断开手柄蓝牙再重连后,重新检查:

for dev in /sys/bus/hid/devices/*045E:02E0*; do
    [ -e "$dev" ] || continue
    readlink -f "$dev/driver"
done

这次终于得到:

/sys/bus/hid/drivers/xpadneo

内核日志也确认了配置已生效:

xpadneo: gamepad detected
xpadneo: consumer control added
xpadneo: keyboard added
xpadneo: mouse added
xpadneo: controller quirks: 0x00000010

设备在系统里的产品 ID 还从 045e:02e0 变成了 045e:028e,这是 xpadneo 为兼容性做的身份处理,并不是手柄真的换了一套硬件。

回到测试网页,之前失效的 View 和 Menu 按钮恢复了。游戏内的基本控制也终于正常。

为什么 Home 和截图键在测试网页上还可能不亮?

最后还有个小插曲:GamepadTester 上的 Guide/Home 和 Share/截图图标没有像普通按钮一样亮起来,我差点以为又剩下两个按键没修好。

xpadneo 实际会给手柄创建几类不同的输入设备:

Xbox Wireless Controller
Xbox Wireless Controller Consumer Control
Xbox Wireless Controller Keyboard
Xbox Wireless Controller Mouse

普通游戏按键、系统控制和模拟键盘事件可能走不同的输入接口。网页里的 Gamepad API 可视化不一定能显示 Guide 或截图操作,Steam 也可能接管其中的快捷键。

后来实际使用下来,功能已经正常,所以我没有为了让网页上两个图标变色继续改驱动。disable_shift_mode 之类的额外参数也没有永久开启。

终于能玩了,Steam 代理又来捣乱

手柄修好以后,游戏登录时又碰到了网络连接问题。

这次倒是比较容易定位:Steam 进程继承了系统设置的 http_proxy、https_proxy、all_proxy 等环境变量,Proton 启动的游戏也可能继承它们。把代理变量去掉再启动游戏,登录就正常了。

但我不想为了《地平线》把整个 Steam 的代理配置清掉,毕竟有些游戏确实需要这些变量。

最后只给《地平线 6》设置单独的 Steam 启动选项:

env -u http_proxy -u https_proxy -u all_proxy -u HTTP_PROXY -u HTTPS_PROXY -u ALL_PROXY %command%

Steam 本身和其他游戏的环境不受影响。NO_PROXY / no_proxy 作为代理绕过规则保留即可。

后来还短暂遇到过一次游戏内的云存档上传失败:

Uploading
0x80070057: E_INVALIDARG

当时本地 ForzaHorizon6/PlayFabSaveStorage_*/ 目录里的存档仍在更新,因此没有贸然删除 Proton 前缀、清空本地记录或者强行覆盖云存档。这个问题后来暂时自行消失,底层原因并没有查明,所以这里不把它写成什么已验证的修复教程。

重启之后的结果

排查结束后,我又正常重启了一次电脑。

手柄可以重新连接,按键正常,游戏也能玩。 而且之前只是临时关闭的 ERTM 并没有持久化,重启后不再需要关它。

真正保留下来的关键改动是 xpadneo 和它的配置:

# /etc/modprobe.d/99-mobapad-xpadneo.conf
options hid_xpadneo quirks=AA:BB:CC:DD:EE:FF+16

DKMS 模块已经针对当时安装的 CachyOS 普通内核和 LTS 内核构建;蓝牙配对信息也由 BlueZ 保存,下次开机不需要重新 pair 或手动 modprobe。

如果以后同样在 Linux 上折腾赤兔 2 HD,我会按这个顺序检查:

  1. 先看说明书,确认进入的是 Xbox/PC 游戏蓝牙配对模式,而不是只看到了 Mobapad-Pro2-HD。
  2. 已经配对但秒断,先尝试在 KDE 里忘记 Xbox Wireless Controller 并重新配对,不急着改 BlueZ 内核参数。
  3. 连得上但按键错乱,再检查驱动绑定,考虑 xpadneo 与 quirks=+16。
  4. 不要仅凭 GamepadTester 上的 Home/Share 图标判断特殊按键坏了,最好结合实际功能和输入事件一起测试。
  5. 游戏无法登录时,再单独排查 Steam/Proton 继承的代理变量。

最让我无语的还是开头。我查蓝牙协议、看日志、折腾配对 Agent,后来发现自己只是少短按了一次 Home。等把这个问题修完,才真正轮到驱动兼容性的问题登场。

好在最后都解决了。我是真的不想为了玩个赛车游戏,又启动一次 Windows。


AI 辅助说明:本次排查使用了 ChatGPT 和 Chat-With-CLI 辅助读取 BlueZ、内核及 Steam 日志,也用于整理本文。我负责操作手柄、复现问题,并在实际游戏及系统重启后验证结果。部分蓝牙瞬断与云同步问题的具体原因尚未完全确认。