跳转至内容

手柄

来自 ArchWiki
(重定向自 Joy2key)

如今许多手柄都可以即插即用,但由于应用程序对游戏手柄的支持差异很大,仍然存在许多潜在问题和错误源。

本文章或章节需要扩充。

原因:需要关于 API 之间差异以及如何切换的信息。(在 Talk:Gamepad#Joystick API vibration support 中讨论)

Linux 有两个不同的手柄输入系统——原始的 Joystick 接口和较新的基于 evdev 的接口。

/dev/input/jsX 映射到 Joystick API 接口,而 /dev/input/event* 映射到 evdev 接口(这还包括鼠标和键盘等其他输入设备)。指向这些设备的符号链接也存在于 /dev/input/by-id//dev/input/by-path/ 中,其中旧的 Joystick API 的名称以 -joystick 结尾,而 evdev 的名称以 -event-joystick 结尾。

大多数新游戏将默认使用 evdev 接口,因为它提供了关于可用按钮和轴的更详细信息,并且还支持力反馈。

许多应用程序使用 SDL 来访问手柄。

  • SDL1 默认使用 evdev 接口,但可以通过设置环境变量 SDL_JOYSTICK_DEVICE=/dev/input/js0 来强制其使用 Joystick。
  • SDL2 和 SDL3 默认使用 hidapi 来访问最受欢迎的控制器,以获得原始访问权限。对于其他控制器,或当 hidapi 被禁用时,它们将改用 evdev。

SDL 本身提供了不同的 API,其选择取决于应用程序。它们的使用并非相互排斥。

  • SDL_Joystick 在所有版本中都受支持,并将 evdev(或 Joystick)事件 1:1 映射到 SDL 自有的事件。
  • SDL_GameController 在 SDL2 中受支持,它提供了设备之间的标准化映射。要使控制器受支持,它需要在数据库 gamecontrollerdb.txt 中具有 evdev:SDL 映射。此 API 在 SDL3 中被 SDL_Gamepad 取代。

安装

除非您使用的是使用 Gameport 或专有 USB 协议的非常旧的手柄,否则您只需要通用的 USB 人体学接口设备 (HID) 模块。

要全面了解 Linux 中所有与手柄相关的模块,您需要访问 Linux 内核源代码——特别是 Documentation 部分。不幸的是,官方内核包不包含我们所需的内容。如果您下载了内核源代码,请查看 Documentation/input/joydev/。您可以通过点击您正在使用的内核的“browse”(cgit - git 前端)链接,然后点击顶部附近的“tree”链接,在 kernel.org 上浏览内核源代码树。或者,请参阅 最新内核的文档

某些手柄需要特定的模块,例如 Microsoft Sidewinder 控制器(sidewinder)或 Logitech 数字控制器(adi)。许多旧手柄可以使用简单的 analog 模块。如果您的手柄插入声卡的 gameport,您将需要加载声卡驱动程序——然而,像 Soundblaster Live 这样的声卡有一个特定的 gameport 驱动程序(emu10k1-gp)。旧的 ISA 声卡可能需要 ns558 模块,这是一个标准的 gameport 模块。

如您所见,有许多与使您的手柄在 Linux 中正常工作相关的模块,因此此处未涵盖所有内容。请参阅上述文档了解详情。

加载模拟设备模块

您需要为您的 gameport(ns558emu10k1-gpcs461x 等)加载一个模块,为您的手柄(analogsidewinderadi 等)加载一个模块,最后加载内核手柄设备驱动程序(joydev)。您可以 在启动时加载模块,或直接 modprobe 它。gameport 模块应该会自动加载,因为它是其他模块的依赖项。

USB 手柄

您需要启用 USB,然后 modprobe 您的手柄驱动程序,即 usbhid,以及 joydev。如果您使用 USB 鼠标或键盘,usbhid 将已加载,您只需加载 joydev 模块。

注意: 如果您的 Xbox 360 手柄通过 Play&Charge USB 线连接,它将出现在 lsusb 中,但不会显示为 /dev/input/js* 中的输入设备,请参阅 #Xbox 360 控制器

配置

测试

加载模块后,您应该会找到一个新设备:/dev/input/js0/dev/input/by-id 目录中以 -event-joystick 结尾的文件。您可以简单地 cat 这些设备以查看手柄是否工作——移动摇杆,按下所有按钮——您应该会看到在移动摇杆或按下按钮时打印出乱码。

如果您遇到权限错误,请参阅 #设备权限

Wine 使用 SDL 进行 DirectInput 和 XInput 仿真,并以 evdev 作为后备。您可以使用 wine control joy.cpl 来测试它们。对于 PlayStation 4 和 5 控制器,请参阅 #与 Wine 一起使用

Joystick API

有很多应用程序可以测试这个旧 API,来自 joyutils 包的 jstest 是最简单的。如果输出无法读取,因为打印的行太长,您也可以使用图形工具。KDE Plasma 在 System Settings > Input Devices > Game Controller 中内置了一个。还有一个 jstest-gtk-gitAUR 作为替代。

使用 jstest 非常简单,只需运行 jstest /dev/input/js0 即可打印一行显示所有轴(归一化为 {-32767,32767})和按钮状态。

启动 jstest-gtk 后,它会显示一个可用的操纵杆列表,您只需选择一个并按“Properties”。

evdev API

可以使用来自 evtestevtest 或来自 evtest-qt-gitAURevtest-qt 来测试 'evdev' API。

要测试设备上的力反馈,请使用来自 linuxconsolefftest

$ fftest /dev/input/by-id/usb-*event-joystick

SDL API

安装 sdl-jstest-gitAUR。如果连接了多个控制器,请使用 sdl2-jstest --list 获取它们的 ID。

测试索引为 0 的设备上的 SDL_Joystick API

$ sdl2-jstest --test 0

或者测试 SDL_GameController API

$ sdl2-jstest --gamecontroller 0

HTML5 Gamepad API

访问 https://gamepad-tester.com/。目前,在 Chromium 中支持测试振动和生成手柄的可视化,但在 Firefox 中不支持。此外,截至版本 107.0.5304.121-1,Chromium 可以读取 Joystick 设备但不能读取 evdev。

设置死区和校准

本文章或章节需要扩充。

原因:描述 evdev 的校准说明(在 Talk:Gamepad#Unclear instructions on how to calibrate 中讨论)

如果您想设置模拟输入的死区(或完全删除它们),您必须分别为 xorg(用于鼠标和键盘模拟)、Joystick API 和 evdev API 单独设置。

Wine 死区

添加以下注册表项,并将其设置为从 010000 的字符串(影响所有轴)

HKEY_CURRENT_USER\Software\Wine\DirectInput\DefaultDeadZone

来源:Useful Registry Keys

Xorg 死区

将类似行添加到 /etc/X11/xorg.conf.d/51-joystick.conf(如果不存在则创建)

/etc/X11/xorg.conf.d/51-joystick.conf
Section "InputClass"
    Option "MapAxis1" "deadzone=1000"
EndSection

1000 是默认值,但您可以设置 030000 之间的任何值。要获取轴号,请参阅本文档的“测试您的配置”部分。如果您已经有一个带有特定轴的选项,只需在参数末尾输入 deadzone=value,并用空格分隔。

Joystick API 死区和校准

最简单的方法是使用来自 jstest-gtk-gitAURjstest-gtk。选择要编辑的操纵杆,点击 Properties 按钮。在此新窗口中,点击 Calibration 按钮(之后不要点击 Start Calibration)。然后您可以设置 CenterMinCenterMax 值,它们控制中心死区,以及 RangeMinRangeMax,它们控制行程末端的死区。请注意,校准设置在应用程序打开设备时应用,因此您需要重新启动游戏或测试应用程序才能看到更新的校准设置。

设置死区后,您还可以创建一个 udev 规则,使所有更改永久生效

首先,获取您的操纵杆的供应商 ID(将 X 替换为您的操纵杆编号,通常是 0

$ udevadm info -q property --property ID_VENDOR_ID --value /dev/input/jsX

同时获取型号 ID

$ udevadm info -q property --property ID_MODEL_ID --value /dev/input/jsX

如果上述命令输出为空,可能是因为您的控制器是通过蓝牙连接的,导致这些唯一属性仅在父设备上可见。要解决此问题,您可以尝试通过运行以下命令查找其他唯一属性:

$ udevadm info -a /dev/input/jsX

这将列出您设备(和父设备)的所有可用属性。因此,例如,如果您的操纵杆的父设备具有属性 ATTRS{uniq}=="a0:b1:c2:d3:e4:f5",或者可能是 ATTRS{idVendor}=="054c"ATTRS{idProduct}=="09cc",那么您可以使用这些代替 ENV{ID_VENDOR_ID} ENV{ID_MODEL_ID} 在下面的 udev 规则中。

您也可以同时拥有两条规则,只需用新的一行分隔它们。

无论如何,现在使用 jscal 转储您的操纵杆的新校准设置

$ jscal -p /dev/input/jsX

现在,用您获取的值修改此 udev 规则

/etc/udev/rules.d/85-jscal-custom-calibration.rules
ACTION=="add", KERNEL=="js[0-9]*", ENV{ID_VENDOR_ID}=="054c", ENV{ID_MODEL_ID}=="09cc", RUN+="/usr/bin/jscal -s 1,1,1,1 /dev/input/js%n"

此规则将在连接供应商 ID 为 054c 且型号 ID 为 09cc 的操纵杆时自动运行 /usr/bin/jscal -s 1,1,1,1 /dev/input/js%n/dev/input/js%n 部分是自动确定正确操纵杆所必需的,所以请勿删除它。

最后,加载此新的 udev 规则。

evdev API 死区和校准

来自 linuxconsole 包的 evdev-joystick 工具可用于查看和更改 evdev API 设备的死区和校准。

要查看您的设备配置

$ evdev-joystick --showcal /dev/input/by-id/usb-*-event-joystick

要更改特定轴的死区,请使用类似命令

$ evdev-joystick --evdev /dev/input/by-id/usb-*-event-joystick --axis 0 --deadzone 0

要一次性为所有轴设置相同的死区,请省略 --axis 0 选项。

使用 udev 规则文件在控制器连接时自动设置它们。

请注意,在内核中,该值称为 flatness,并且使用 EVIOCSABS ioctl 设置。

默认配置看起来会像这样

$ evdev-joystick --showcal /dev/input/by-id/usb-Madcatz_Saitek_Pro_Flight_X-55_Rhino_Stick_G0000090-event-joystick
Supported Absolute axes:
   Absolute axis 0x00 (0) (X Axis) (min: 0, max: 65535, flatness: 4095 (=6.25%), fuzz: 255)
   Absolute axis 0x01 (1) (Y Axis) (min: 0, max: 65535, flatness: 4095 (=6.25%), fuzz: 255)
   Absolute axis 0x05 (5) (Z Rate Axis) (min: 0, max: 4095, flatness: 255 (=6.23%), fuzz: 15)
   Absolute axis 0x10 (16) (Hat zero, x axis) (min: -1, max: 1, flatness: 0 (=0.00%), fuzz: 0)
   Absolute axis 0x11 (17) (Hat zero, y axis) (min: -1, max: 1, flatness: 0 (=0.00%), fuzz: 0)

而一个更合理的设置可以通过以下方式实现(对其他轴重复)

$ evdev-joystick --evdev /dev/input/by-id/usb-Madcatz_Saitek_Pro_Flight_X-55_Rhino_Stick_G0000090-event-joystick --axis 0 --deadzone 512
Event device file: /dev/input/by-id/usb-Madcatz_Saitek_Pro_Flight_X-55_Rhino_Stick_G0000090-event-joystick
 Axis index to deal with: 0
 New dead zone value: 512
 Trying to set axis 0 deadzone to: 512
   Absolute axis 0x00 (0) (X Axis) Setting deadzone value to : 512
 (min: 0, max: 65535, flatness: 512 (=0.78%), fuzz: 255)

xboxdrv 死区和校准

创建虚拟 Xbox 360 控制器的示例命令,其中 Y1 轴设置为死区 4000、最小可读值 -32768、中心 128 和最大值 29000

# xboxdrv --deadzone 4000 --calibration Y1=-32768:128:29000

有关更多选项,请参阅 xboxdrv(1) § AXIS FILTER

禁用手柄控制鼠标

如果您想用手柄玩游戏,您可能想禁用它对鼠标光标的控制。

最简单的方法是在 桌面环境 设置中禁用鼠标设备。否则,编辑 /etc/X11/xorg.conf.d/51-joystick.conf(如果不存在则创建),使其看起来像这样

/etc/X11/xorg.conf.d/51-joystick.conf 
Section "InputClass"
        Identifier "joystick catchall"
        MatchIsJoystick "on"
        MatchDevicePath "/dev/input/event*"
        Driver "joystick"
        Option "StartKeysEnabled" "False"
        Option "StartMouseEnabled" "False"
EndSection

使用手柄发送键盘按键

一些通用的 输入重映射工具,例如 Input Remapper,可以用于将手柄按钮映射到键盘按键。用于此目的的手柄专用工具包括:

所有这些工具都可以正常工作,无需额外的 X.org 配置。

Xorg 配置示例

这是适用于重启 Xorg 不频繁的系统的良好解决方案,因为它是一种静态配置,仅在 X 启动时加载。此示例在 Kodi 媒体 PC 上运行,由 Logitech Cordless RumblePad 2 控制。由于 d-pad(又称“hat”)被识别为另一个轴的问题,Joy2key 被用作一种解决方法。自 kodi 版本 11.0 和 joy2keyAUR 1.6.3-1 以来,此设置不再有效,并创建了以下内容,让 Xorg 处理手柄事件。

首先,安装 xf86-input-joystickAUR 包。然后,创建一个 X 配置文件

/etc/X11/xorg.conf.d/51-joystick.conf
Section "InputClass"
  Identifier "Joystick hat mapping"
  Option "StartKeysEnabled" "True"
  #MatchIsJoystick "on"
  Option "MapAxis5" "keylow=113 keyhigh=114"
  Option "MapAxis6" "keylow=111 keyhigh=116"
 EndSection
注意: MatchIsJoystick "on" 行似乎不是该设置正常工作所必需的,但您可能希望将其取消注释。

重新映射手柄按钮及更多

使用某些程序,您还可以进一步配置手柄,包括以下潜在功能:

  • 重新映射按钮和轴。
    • 为不同的游戏分配映射配置文件。
  • 模拟另一种类型的手柄。由于 Xbox 360 控制器是一种非常常见的控制器,许多游戏都经过测试,因此某些软件在被识别为 Xbox 360 控制器时可能会表现更好。
  • 其他功能,例如宏、屏幕显示等。

软件列表

  • SC Controller — 开源软件,支持按钮重新映射和 Xbox 360 控制器模拟。
https://github.com/Ryochan7/sc-controller || sc-controller
  • Steam — 专有商店,其客户端通过 Steam Input 支持重新绑定手柄输入。启用后,Steam 会将 Steam 控制器暴露给选择加入 Steam Input API 的游戏,并将模拟的 Xbox 360 控制器暴露给使用传统手柄 API 的游戏。有关更多详细信息,请参阅 Steam#Steam Input
https://store.steampowered.com/about/ || steam
  • xboxdrv — Xbox 360 控制器驱动程序,支持从其他输入控制器模拟控制器。请参阅 #模拟 Xbox 360 控制器。它也是重新映射和校准的灵活选项。
https://github.com/xiota/xboxdrv || xboxdrvAUR

SDL2 应用程序中的手柄按钮重新映射

可以使用 SDL_GAMECONTROLLERCONFIG 环境变量为 SDL2 应用程序重新映射手柄。每行包括手柄的 GUID、名称、按钮/轴映射和平台。可以通过安装 sdl-jstest-gitAUR 然后运行 sdl2-jstest --list 来检索控制器的 GUID。

例如,为具有不同 GUID 的 Microsoft Xbox 360 控制器进行映射

~/.bashrc
export SDL_GAMECONTROLLERCONFIG="
030000005e0400008e02000001000000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.1,dpleft:h0.2,dpright:h0.8,dpup:h0.4,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e0400008e02000004010000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
"

一些应用程序从 gamecontrollerdb.txt 文件中提取映射信息。可以使用 controllermapAUR 图形化编辑它。可以在 [1] 找到最新的数据库。

模拟 Xbox 360 控制器

#xboxdrv 可用于使任何控制器注册为 Xbox 360 控制器,使用 --mimic-xpad 开关。这对于能够即插即用 Xbox 360 控制器的游戏可能是有利的,但这些游戏难以检测或与非 Xbox 360 手柄一起工作。

您可以使用以下命令模拟 Xbox 360 控制器

$ xboxdrv --evdev /dev/input/event* --evdev-absmap ABS_RX=X2 --evdev-keymap BTN_THUMB2=a,BTN_THUMB=b,BTN_PINKIE=rt --mimic-xpad

上述示例不完整。它仅映射了一个轴和 3 个按钮用于演示目的。使用 xboxdrv --help-button 查看 Xbox 控制器按钮和轴的名称,并根据需要进行绑定,方法是扩展上述命令。轴映射应放在 --evdev-absmap 之后,按钮映射遵循 --evdev-keymap(逗号分隔列表;无空格)。

默认情况下,xboxdrv 将所有事件输出到终端。您可以使用此来测试映射是否正确。附加 --silent 选项以使其保持安静。

特定设备

虽然大多数手柄,尤其是基于 USB 的手柄应该都可以正常工作,但有些可能需要(或能获得更好的结果)使用替代驱动程序。

跳舞垫

大多数跳舞垫都应该可以工作。然而,一些垫子,特别是通过适配器从游戏机使用的垫子,倾向于将方向按钮映射为轴按钮。这会阻止同时按下左-右或上-下。对于 xpad 识别的设备,可以通过模块选项修复此行为

# modprobe -r xpad
# modprobe xpad dpad_to_buttons=1

如果那不起作用,您可以尝试 axisfix-gitAUR 或修补 joydev 内核模块(https://github.com/adiel-mittmann/dancepad)。

罗技 Thunderpad Digital

如果您使用 analog 模块,Logitech Thunderpad Digital 将不会显示所有按钮。请为此控制器使用特定于设备的 adi 模块。

任天堂 Gamecube 控制器

Dolphin Emulator 在其 wiki 上有一页,解释了如何使用官方任天堂 USB 适配器搭配 GameCube 控制器。此配置也适用于 Mayflash Controller Adapter,前提是将其开关设置为“Wii U”。

对于其他应用程序,您可以使用 wii-u-gc-adapterAUR

任天堂 Switch Pro 控制器和 Joy-Cons

自内核版本 5.16 起支持这些控制器。Switch Online NES、SNES 和 N64 控制器也自内核版本 6.12 起支持。

对于较早的内核版本,可以安装 DKMS 模块 hid-nintendo-nso-dkmsAUR

用户空间守护进程

joycond-gitAUR 是一个用户空间守护进程,为 Nintendo Switch 控制器提供更好的集成。当守护进程运行时,处于配对模式(LED 闪烁)的 Switch 控制器可以通过按住两个扳机键进行配对,然后即可供应用程序使用。请参阅 [2]

将 Joy-Cons 用作一个设备

hid-nintendo 内核驱动程序将两个 Joy-Cons 作为两个独立设备进行处理。

要将两个Joy-Cons配对,请确保joycond正在运行,并且两个Joy-Cons都处于配对模式。然后,同时按下每个Joy-Con上的一个扳机键。

在SDL2应用程序上使用位置布局

默认情况下,SDL2会根据游戏手柄的标签而不是按钮的位置来映射Nintendo控制器的按钮。这会导致A/B和X/Y按钮的映射与其他控制器相比被交换。如果这是不希望的,请设置环境变量SDL_GAMECONTROLLER_USE_BUTTON_LABELS=0

从SDL3开始,映射始终是基于位置的。[3]请注意,sdl2-compat保留了旧的行为。[4]

Steam控制器

注意 内核4.18提供了内核驱动程序,用于有线/无线使用Steam控制器作为控制器输入设备,而无需Steam

当Steam运行时,Steam客户端将识别控制器并提供键盘/鼠标/游戏手柄模拟。为了使游戏手柄模拟正常工作,需要启用并运行游戏内的Steam覆盖。如果控制器在安装和运行Steam后未立即工作,您可能需要以root权限运行udevadm trigger,或者拔插一次USB接收器。如果一切都失败了,请尝试在连接USB接收器的情况下重启计算机。

如果您使用的是通过蓝牙LE连接的控制器,请确保用户属于input组。

如果您无法让Steam控制器正常工作,请参阅#Steam控制器未配对或在游戏中无法识别(包括USB)

注意 如果您不使用Steam运行时,您可能需要禁用覆盖才能在某些游戏(如Rocket Wars、Rocket League、Binding of Isaac等)中使用控制器。右键单击库中的游戏,选择“属性”,然后取消选中“启用Steam覆盖”。

Xbox 360控制器

有线和无线(带有Xbox 360 Wireless Receiver for Windows)控制器都受xpad内核模块支持,无需额外软件包即可工作。请注意,使用Play&Charge USB线连接无线Xbox 360控制器将无法工作。该线仅用于充电,不会通过电线传输任何输入数据。

据报道,默认的xpad驱动程序在某些较新的有线和无线控制器上存在一些问题,例如

  • 按钮映射不正确。(Steam错误跟踪器的讨论
  • 同步无法工作。(Arch论坛的讨论
  • 所有四个LED灯都一直闪烁,但控制器工作。TLP的USB自动挂起是导致无线控制器出现此问题的一个确定原因。下面是解决方法。

如果您使用TLP电源管理工具,您可能会遇到与Microsoft无线适配器连接的问题(例如,指示灯LED在适配器连接几秒钟后熄灭,并且控制器连接尝试失败,四个LED灯一直闪烁但控制器工作)。这是由于TLP的USB自动挂起功能引起的,解决方法是将Microsoft无线适配器的设备ID添加到TLP黑名单中(要检查要黑名单的设备ID,请运行tlp-stat -u;对于原始MS无线接收器,只需将USB_DENYLIST="045e:0719"添加到/etc/tlp.conf),有关更多详细信息,请参阅TLP配置

如果您遇到此类问题,可以将#xboxdrv用作默认的xpad驱动程序。

要通过蓝牙连接,请添加以下内核参数bluetooth.disable_ertm=1

如果您在游戏中遇到振动功能不起作用的问题,可能需要设置环境变量SDL_JOYSTICK_HIDAPI=0

xboxdrv

本文或本节正考虑移除。

原因:xboxdrv的驱动程序部分已弃用。(请参阅Talk:Gamepad进行讨论)

xboxdrvxpad的替代品,它提供了更多功能,并且可能与某些控制器配合得更好。它在用户空间运行,并可作为系统服务启动。

使用xboxdrvAUR包进行安装。然后启动/启用xboxdrv.service

如果您在使用控制器时遇到被识别但无法在Steam游戏中工作,或者工作但映射不正确的问题,可能需要如下修改您的配置

/etc/default/xboxdrv
[xboxdrv]
silent = true
device-name = "Xbox 360 Wireless Receiver"
mimic-xpad = true
deadzone = 4000

[xboxdrv-daemon]
dbus = disabled

然后重启xboxdrv.service

多个控制器

xboxdrv支持多种控制器,但它们需要在/etc/default/xboxdrv中进行设置。对于每个额外的控制器,添加一行next-controller = true。例如,在使用4个控制器时,添加3次

[xboxdrv]
silent = true
next-controller = true
next-controller = true
next-controller = true
[xboxdrv-daemon]
dbus = disabled

然后重启xboxdrv.service

使用通用/克隆控制器

某些克隆游戏手柄可能需要特定的初始化序列才能工作(Super User回答)。为此,您应该以root用户身份运行以下Python脚本

#!/usr/bin/env python3

import usb.core

dev = usb.core.find(idVendor=0x045e, idProduct=0x028e)

if dev is None:
    raise ValueError('Device not found')
else:
    dev.ctrl_transfer(0xc1, 0x01, 0x0100, 0x00, 0x14)

Xbox无线控制器/Xbox One无线控制器

通过USB线连接Xbox无线控制器

这受到内核支持,无需额外软件包即可工作。

通过蓝牙连接Xbox无线控制器

通过Windows 10更新控制器固件

Xbox无线控制器的固件过去曾导致与Bluez的连接/断开循环。最好的解决方法是将控制器(通过USB线)连接到Windows 10计算机,通过Microsoft Store下载Xbox Accessories应用程序,然后更新控制器的固件。

xpadneo

一个相对较新的驱动程序,它通过蓝牙支持Xbox One S和Xbox Series X|S控制器,名为xpadneo。除了这两种型号外,它还对Xbox Elite Series 2无线控制器提供基本支持。为了弥补目前仅完全支持两种控制器,它允许读取正确的电池电量,支持振动(甚至是触发器上的振动 - L2/R2),纠正(有时是错误的)按钮映射等等。

使用DKMS进行安装:xpadneo-dkmsAUR

注意 首次配对新的Xbox One S控制器可能会很困难,从根本无法配对到进入连接/断开循环。这些问题在此处描述。最可靠的配对方法是先在Windows 10中配对。但是,这需要使用相同的蓝牙适配器。一种解决方案是安装Windows 10评估版的免费副本到虚拟机(使用QEMUVirtualBox,注意蓝牙适配器直通要求,例如作为USB设备),使用Arch Linux作为主机,先在Windows 10中配对,然后在Arch Linux系统下再次执行相同操作。然后配对将成功,并且不再需要进一步使用Windows 10。

通过Microsoft Xbox无线适配器连接Xbox无线控制器

xone是Xbox One和Xbox Series X|S配件的Linux内核驱动程序。它作为xpad和xow的现代替代品并取代了它们。目前通过有线连接或Microsoft Xbox无线适配器“接收器”工作。该驱动程序的错误修复现在由原始驱动程序的dlundqvist分支维护。

安装xone-dkmsAUR,如果使用无线接收器,则安装xone-dongle-firmwareAUR。安装需要重启系统。

  • 需要与您的内核对应的头文件;请参阅DKMS#安装
  • 适配器使用基于mt76的802.11/15芯片组,这可能导致与连接到同一系统或附近的其他无线适配器发生干扰。
配对后控制器性能不佳(轮询率低)

您需要使用Microsoft Store中的“Xbox Accessories”应用程序在Windows中更新控制器固件。理论上,这应该可以通过USB直通到Windows虚拟机来完成,但您可能需要双启动到实际的(裸机)Windows安装,以便Xbox Accessories应用程序能够看到控制器并进行固件更新。

与Windows双启动

在Windows中配对控制器和适配器可能会导致配对在Linux中丢失。当您重启到Linux时,您需要重新配对控制器和接收器。反之亦然——当控制器和接收器在Linux中配对后,下次要在Windows中使用它们时,需要重新配对。可以通过遵循双启动配对的说明来避免这种情况。

挂起后使用游戏手柄导致无法连接。

在某些平台上,挂起可能导致设备进入不正常响应状态。由于Linux将设备识别为蓝牙适配器,它会在挂起时自动进入断电状态,这也禁用了从游戏手柄唤醒系统。这可以通过在内核命令行中使用btusb.enable_autosuspend=n来缓解。注意:这将禁用系统上所有其他USB蓝牙适配器的电源挂起。

PlayStation 3控制器

通过USB配对

如果您拥有PS3控制器并通过USB连接,请将其插入计算机并按下PS按钮。控制器将启动,并且四个LED灯之一应该会亮起,指示控制器的编号。

通过蓝牙配对

安装bluezbluez-utils。确保蓝牙工作正常,方法是按照蓝牙#配对的前五个步骤操作,并保持bluetoothctl命令运行,然后通过按下中间的“PS”按钮(所有4个LED灯应快速闪烁约4 Hz)打开控制器,然后使用USB连接到您的计算机。最后,当被询问“Authorize service 00001124-0000-1000-8000-00805f9b34fb (yes/no)”时,在bluetoothctl提示符中输入yes。

在最新版本的bluez(截至2024/01/03)中,出于安全原因,ClassicBondedOnly的默认值已从false更改为true[5]。此更改使得无法配对Dual Shock 3控制器,因为bluetoothctl会要求PIN码并且无法继续。为了解决此问题,请通过在新创建的/etc/bluetooth/input.conf文件中添加以下行,将ClassicBondedOnly设置为false

截至2024-03-09,UserspaceHID的默认值也已更改为true。虽然连接成功,但除非将此值更改为false,否则控制器将无法进入操作模式。有关更多信息,请参阅GitHub上的issue #771

[General]
ClassicBondedOnly=false
UserspaceHID=false

请注意,此解决方案会降低安全性。有关详细信息,请参阅GitHub

提示 互联网上有很多关于设置PS3控制器的复杂说明,需要许多步骤,例如编译和安装qtsixa或sixpair以及手动设置控制器,或修补bluez。在现代Linux内核和安装bluez-utils之后,这些都不再是必需的。

PlayStation 3/4控制器

DualShock 3、DualShock 4和Sixaxis控制器通过USB连接时开箱即用(需要按下PS按钮才能开始)。它们也可以通过蓝牙无线使用。

Steam正确地将其识别为PS3手柄,并且可以使用PS按钮启动Big Picture模式。Big Picture模式和某些游戏可能会将其视为360控制器。鼠标的游戏手柄控制默认开启。您可能希望在玩游戏之前将其关闭,请参阅#禁用游戏手柄控制鼠标

通过蓝牙配对

安装bluezbluez-utils软件包,其中包含sixaxis插件。然后启动蓝牙服务并确保蓝牙已开启。如果使用bluetoothctl,请在终端中启动它,然后通过USB插入控制器。您应该会在bluetoothctl中被提示信任控制器。图形化蓝牙前端可能会自动将您PC的蓝牙地址编程到控制器中。按下PlayStation按钮,并检查控制器在插入时是否工作。

现在您可以断开控制器。下次按下PlayStation按钮时,它将无需再询问即可连接。

或者,对于PS4控制器,您可以同时按住Share按钮和PlayStation按钮(几秒钟)将游戏手柄置于配对模式,然后像往常一样配对。

GNOME的设置也提供了一个图形界面,用于在连接有线设备时配对sixaxis控制器。

请记住,完成后断开控制器,因为连接时控制器会一直开着并耗尽电池。

注意 如果控制器无法连接,请确保蓝牙接口已开启并且控制器已被信任。(参见蓝牙

使用通用/克隆控制器

可以使用通用/克隆Dualshock控制器,但是存在一个问题,可能需要安装一个修补过的软件包。默认的蓝牙协议栈无法检测到某些克隆控制器。bluez-ps3AUR包是经过修补以能够检测它们的版本。bluez-plugins-ps3AUR是另一个仅修补bluez-plugins的包,可能对某些控制器有效。

PlayStation 4/5控制器

通过USB配对

通过USB连接控制器并按PS按钮。

通过蓝牙配对

如果您想使用蓝牙模式,请同时按住PS按钮和Share按钮。控制器的白色LED灯将快速闪烁,并且无线控制器可以与您的蓝牙管理器配对。

与Wine一起使用

在这些控制器上,Wine默认使用hidraw(自8.0起),以便支持它们的Windows应用程序可以使用其所有功能。由于这种类似Windows的行为,它们不会被暴露为XInput设备,这阻止了它们在许多应用程序中工作。

要禁用此行为,请使用regedit将以下文本文件导入Wine注册表

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\winebus]
"DisableHidraw"=dword:1

从Wine 9.18开始,此设置可以通过wine control joy.cpl进行控制。

禁用触摸板作为鼠标

如果您使用libinputXorg,或者使用Wayland,那么您可以按照Libinput#使用环境变量来禁用触摸板设备。

请注意,由于触摸板只是控制器的一部分,按供应商和产品ID选择输入设备是不够的。相反,请考虑按名称选择设备。

有关可用的完整属性集,请参阅udevadm info --attribute-walk --name=device_path,其中device_path是设备的路径,例如/dev/input/eventn/dev/input/by-id/identifier

要查找设备路径,您可以使用类似evtest的工具,只需运行evtest即可。此命令还应打印设备名称。

示例片段

/etc/udev/rules.d/72-ds4tm.rules
# Disable DS4 touchpad acting as mouse
# USB
ATTRS{name}=="Sony Interactive Entertainment Wireless Controller Touchpad", ENV{LIBINPUT_IGNORE_DEVICE}="1"
# Bluetooth
ATTRS{name}=="Wireless Controller Touchpad", ENV{LIBINPUT_IGNORE_DEVICE}="1"

对于DualSense控制器,请将名称替换为Sony Interactive Entertainment DualSense Wireless Controller TouchpadDualSense Wireless Controller Touchpad

然后,重新加载udev规则。重新连接游戏手柄以应用更改。

dualsensectl

dualsensectl是一个可以切换灯条和麦克风(及其LED)、监控电池状态以及关闭控制器的工具。要使用它,请安装dualsensectl-gitAUR

技巧与窍门

网络游戏手柄

如果您想通过网络在另一台计算机上使用您的游戏手柄,可以使用USB/IPnetstick-gitAUR来实现。

通过gamepadla-polling测量控制器轮询率和延迟

另请参阅:鼠标轮询率

Gamepadla托管了一个关于控制器特定延迟和轮询数据的众包数据库。[6]用于生成这些报告的工具通过pygame/SDL读取evdev/hidraw事件,并且可以从gamepadla-pollingAUR获得。

故障排除

设备权限

游戏手柄设备会受到udev规则的影响:除非它们授予设备访问权限,否则用户根本无法读取它。本节将探讨您已拥有处理此问题的配置文件是否存在可能性。

任何游戏手柄设备,无论通过USB还是蓝牙连接,都由“内核的input子系统”处理,对应于/dev/input。udev规则也常常以“hidraw”内核模块为目标。结合这些,我们可以通过检查软件包提供的配置来理解udev对这些设备的处理。

$ grep --extended-regexp 'SUBSYSTEM=="input"|KERNEL=="hidraw' --recursive /usr/lib/udev/rules.d

一些提供值得注意的规则的应用程序示例

  • systemd的默认规则将所有input设备的组设置为input,并将操纵杆设备的模式设置为664[7]
  • Steam提供udev规则,允许访问各种控制器。有关规则内容的更多信息,请参阅此Steam讨论
  • Dolphin emulator提供udev规则,允许访问其支持的控制器。

如果您的系统尚未拥有您要使用的设备的udev规则,您可以自己编写一个,或者安装game-devices-udevAUR软件包并重启您的计算机。

注意 可以将用户添加到input组以授予他们访问所有设备的权限。但是,不建议这样做[8]

游戏手柄未被所有程序识别

某些软件,例如Steam,只会识别它遇到的第一个游戏手柄。由于Microsoft无线外设设备的驱动程序存在bug,这实际上可能是蓝牙适配器。如果您发现您的键盘蓝牙收发器拥有属于您的/dev/input/js*/dev/input/event*文件,您可以通过创建相应的udev规则来自动摆脱它

/etc/udev/rules.d/99-btcleanup.rules
ACTION=="add", KERNEL=="js[0-9]*", SUBSYSTEM=="input", KERNELS=="...", ATTRS{bInterfaceSubClass}=="00", ATTRS{bInterfaceProtocol}=="00", ATTRS{bInterfaceNumber}=="02", RUN+="/usr/bin/rm /dev/input/js%n"
ACTION=="add", KERNEL=="event*", SUBSYSTEM=="input", KERNELS=="...", ATTRS{bInterfaceSubClass}=="00", ATTRS{bInterfaceProtocol}=="00", ATTRS{bInterfaceNumber}=="02", RUN+="/usr/bin/rm /dev/input/event%n"

KERNELS=="..."修正以匹配您的设备。可以通过运行以下命令找到正确的值

# udevadm info -an /dev/input/js0

假设有问题的设备是/dev/input/js0。放置规则后,使用以下命令重新加载规则

# udevadm control --reload

然后重新插入有问题的设备。操纵杆和事件设备应该会消失,尽管它们的编号仍然被保留。但这些文件已不再碍事。

应用程序仅支持Xbox 360控制器

一些Windows游戏特别寻找Xbox 360控制器,否则将缺少功能(如振动)或根本无法工作。

有关解决方法,请参阅#模仿Xbox 360控制器

Nintendo Switch Pro控制器使用蓝牙时断开连接

Nintendo Switch Pro控制器及其变体在接收振动输入时可能会断开连接。

可以通过将蓝牙适配器的名称更改为“Nintendo”来解决此问题。[9]

Steam控制器

Steam控制器未配对或在游戏中无法识别(包括USB)

存在一些未知情况,Steam控制器的打包udev规则不起作用(FS#47330)。这可能导致许多问题,例如Steam控制器在桌面和Steam中功能正常,但在游戏中无效(包括USB控制器连接时)。最可靠的解决方法是使控制器可全局读取。将规则/usr/lib/udev/rules.d/70-steam-controller.rules以更高的优先级复制到/etc/udev/rules.d,并将任何说MODE="0660"的内容更改为MODE="0666",例如:

/etc/udev/rules.d/99-steam-controller-perms.rules
...
SUBSYSTEM=="usb", ATTRS{idVendor}=="28de", MODE="0666"
...

您可能需要重启才能使更改生效。

Steam控制器导致游戏崩溃或无法识别

如果您的Steam控制器在Steam Big Picture模式下工作良好,但在游戏中无法识别,或者插入控制器时游戏开始崩溃,这可能是由于Linux内核4.18中添加的原生驱动程序。尝试卸载它,重启Steam,然后重新插入控制器。

驱动程序的模块名称是hid_steam,所以要卸载它,您可以执行

# rmmod hid_steam

如果此模块尚未加载但控制器仍未在游戏中得到识别,请参考上一节在#Steam控制器未配对或在游戏中无法识别(包括USB)中的udev规则解决方案。

Xbox One无线游戏手柄被检测到但未识别任何输入

当使用第三方Xbox One控制器与xpad# xboxdrv驱动程序时,可能会发生这种情况。尝试切换到#xpadneo

PlayStation 4控制器

使用蓝牙时控制器未识别

安装ds4drvAUR软件包,并使用hidraw(ds4drv --hidraw)后端参数运行它。

运动控制接管游戏手柄控制和/或导致游戏手柄控制产生意外输入

本文或本节需要在语言、wiki 语法或风格方面进行改进。请参阅 Help:Style 获取参考。

原因:很可能可以使用与Gamepad#禁用触摸板作为鼠标相同的解决方案,该解决方案已在适当的情况下重构到其他页面。(请参阅Talk:Gamepad进行讨论)

在某些云游戏应用程序(如Parsec和Shadow)中,Dualshock 4 V1和V2的运动控制可能会与游戏手柄控制冲突,导致游戏手柄无法工作,并且在某些输入敏感的游戏中(尤其是赛车游戏)中,运动控制可能会在游戏手柄控制游戏时引起意外漂移。

可以通过添加以下udev规则来禁用运动控制和触摸板来解决此问题

/etc/udev/rules.d/51-disable-DS3-and-DS4-motion-controls.rules
SUBSYSTEM=="input", ATTRS{name}=="*Controller Motion Sensors", RUN+="/bin/rm %E{DEVNAME}", ENV{ID_INPUT_JOYSTICK}=""
SUBSYSTEM=="input", ATTRS{name}=="*Controller Touchpad", RUN+="/bin/rm %E{DEVNAME}", ENV{ID_INPUT_JOYSTICK}=""

然后重新加载规则或重启:这些规则应在USB和蓝牙模式下均有效。

多模式有线游戏手柄

某些游戏手柄在有线连接时有3种模式:Switch、Xbox 360/Windows、Android。

并且它们在*有线*连接时没有切换模式的热键。

ZD O+ Excellence

游戏手柄默认设置为Switch模式,并回退到XInput。在此模式下,游戏手柄输入未被正确处理。您可以在XInput模式下正常使用的其他绑定(例如键盘和鼠标输入)似乎都可以正常工作。

DirectInput

这可以通过每次使用时切换到DirectInput模式来修复,但这很麻烦,并且对某些HTML5游戏无效。

udev

添加以下udev规则,它将被视为Xbox 360控制器并使用xpad

/etc/udev/rules.d/99-zdO-xinput.rules
ACTION=="add", ATTRS{idVendor}=="11c0", ATTRS{idProduct}=="5505", RUN+="/sbin/modprobe xpad", RUN+="/bin/sh -c 'echo 11c0 5505 > /sys/bus/usb/drivers/xpad/new_id'"

重新加载您的udev规则.

然后重新插入您的游戏手柄。

ShanWan

本文或本节需要在语言、wiki 语法或风格方面进行改进。请参阅 Help:Style 获取参考。

原因:有许多需要改进的地方。(请参阅Talk:Gamepad进行讨论)

当您将此游戏手柄连接到Windows时,它处于Xbox 360控制器模式。

但是当您将此类游戏手柄连接到Linux时,它会进入回退模式(碰巧是Android模式),该模式的轮询率较低(100 Hz),Home按钮充当XF86Home;不暴露振动、陀螺仪和加速计;不支持*xboxdrv*(除非使用--evdev);并且标识自己为例如“SHANWAN Android Gamepad”,这不被某些游戏喜欢(尽管对于SDL2应用程序,您可以在SDL_GAMECONTROLLERCONFIG中设置名称)。

当您连接游戏手柄时,它首先尝试成为“Switch Pro Controller”,但由于某种原因,Linux内核认为(由游戏手柄发送的)描述符无效,因此断开了游戏手柄。这导致游戏手柄在上述回退模式下重新连接。

dmesg中,这看起来像

usb 1-5.3: new full-speed USB device number 37 using xhci_hcd
usb 1-5.3: unable to read config index 0 descriptor/start: -32
usb 1-5.3: chopping to 0 config(s)
usb 1-5.3: can't read configurations, error -32
usb 1-5.3: new full-speed USB device number 38 using xhci_hcd
usb 1-5.3: New USB device found, idVendor=0079, idProduct=181c, bcdDevice= 1.00
usb 1-5.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 1-5.3: Product: Android Gamepad
usb 1-5.3: Manufacturer: SHANWAN

请注意,“USB设备编号”在失败后会增加。对于某些USB集线器,错误代码为-32(EPIPE:broken pipe),对于其他一些则为-71(EPROTO:protocol error)。

可以通过在usbcore模块(而不是usbhid)中为Switch控制器设置USB ID的quirk来修复此错误

# If you have already *manually* set quirks for other devices,
# then do not forget to include them in the two commands below ↓
echo -n "057e:2009:ik" | sudo tee /sys/module/usbcore/parameters/quirks
# Optionally constant polling mode:
sudo modprobe -r usbhid ; sleep 4 ; sudo modprobe -v usbhid "quirks=0x057e:0x2009:0x400"

ik是两个标志(所有标志列表)。

标志i表示“允许无效描述符”。

标志k表示“禁用LPM”(链路电源管理)。之所以指定它,是因为它经常有助于其他类型的设备。此标志可能无效,因为并非所有USB控制器都具有LPM。之后您可以尝试不带k的方案。

您也可以尝试标志g(“读取描述符后暂停200 ms”),因为它经常有助于其他类型的设备,但至少在iPEGA PG-SW038C(一个10美元的游戏手柄)的情况下,标志g会导致其无限重连。

请注意,一旦游戏手柄降级到回退模式,它将永远不会改变其模式,直到您重新连接它。即使是echo 0 then 1 > %sysfsGamepadDir%/authorized也不起作用。这就是为什么将游戏手柄传递给Windows VM没有帮助的原因;usbcore在将USB设备传递给VM之前对其进行初始化。


现在重新连接游戏手柄,运行lsusb时,它最终应该被列为ID 057e:2009 Nintendo Co., Ltd Switch Pro Controller。如果属实,那么您可以使此quirk永久生效,方法是将此选项添加到GRUB

usbcore.quirks="057e:2009:ik"

以及(可选)usbhid.quirks="0x057e:0x2009:0x400",它会阻止在游戏手柄未使用时LED灯无意义地闪烁。

现在您的游戏手柄处于Switch模式,您会遇到SDL2决定成为用户空间驱动程序的问题(为此它使用libusb,就像xboxdrv一样),这会导致任何SDL2游戏都声称拥有整个游戏手柄(即/dev/input/*/dev/hidraw*消失,尽管仍然可以通过启动的游戏使用游戏手柄进行游戏),因此您不能再在多个应用程序中使用游戏手柄。

可以通过将以下内容添加到/etc/environment并重启来修复此问题:

SDL_HIDAPI_DISABLE_LIBUSB=1

并重启。

如果您安装了joycond-gitAUR,请将其删除,因为它对于此类Switch类游戏手柄没有用,而且joycond有一个udev规则,该规则禁止Steam提供自己的用户空间驱动程序。

与 SDL2(在其 2023 年首选的 /dev/hidraw* 方式下)不同,xboxdrv/dev/input/* 为右摇杆的 X 轴提供错误的值(总是 ≤0)。这很可能是 hid-nintendo 的一个 bug 或其他问题。因此,在大多数游戏中使用 Switch 模式的 xboxdrv 是不可用的。

你可以通过启动 antimicrox 来测试你的陀螺仪和加速计。在有线连接的其他游戏手柄模式下,它们是不可用的,因为它们的值是以特殊格式与其它事件数据(RX/RY/等)*混合*发送的,这种格式与 xpadhid-generic 不完全兼容。

如果你在 dmesg 中看到你的游戏手柄使用了 hid-generic,那么很可能是因为你使用自定义配置编译了 Linux 内核,而没有包含 hid-nintendo。不幸的是,Switch 模式 + hid-generic 和回退模式一样无用(甚至没有震动)。

Xbox 360 控制器模式

在完成以上所有操作(即 1-2 个 quirk,1 个环境变量)后,

blacklist hid_nintendo

添加到 /etc/modprobe.d/blacklist.conf

然后运行 sudo mkinitcpio -P 重建 /boot/initramfs*(内核仅从其自身的 initramfs 读取 /etc/modprobe.d/,而不是你的 rootfs)。

现在创建以下文件

/etc/udev/rules.d/10-disallow-generic-driver-for-switch.rules
# If
# 1. a gamepad is multi-mode (Switch, X360, PC) and defaults to USB ID 057e:2009
# AND at the same time
# 2. `hid-nintendo` module cannot be loaded (blacklisted or not compiled)
# AND at the same time
# 3. there is already a launched game that immediately grabs a gamepad,
#
# Then when you connect such gamepad, it will stay in "Switch Pro" mode,
# but using the fallback `hid-generic` module
# which would result in no vibration/etc
# despite still being listed as a "Switch Pro Controller".

# But by notifying the gamepad that we abandon to use it as an HID,
# it automatically downgrades to "Xbox 360 Controller" mode,
# which causes vibration and `xboxdrv` to work.
SUBSYSTEM=="hid", DRIVER=="hid-generic", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="2009", RUN="/bin/sh -c 'echo $id:1.0 > /sys/bus/usb/drivers/usbhid/unbind'"

然后运行 sudo udevadm control --reload-rules && sudo udevadm trigger

由于你可能不想重启,请运行 sudo modprobe -r hid_nintendo

从现在开始,要在 Switch 模式和 Xbox 360 模式之间切换(“降级”),只需运行 sudo modprobe -r hid_nintendo(甚至不需要重新连接它)。在 2 秒内,你将在 lsusb 中看到 045e:028e Microsoft Corp. Xbox360 Controller

如果你想反向切换

  1. sudo modprobe hid_nintendo(尽管它被列入了黑名单,但此命令仍然有效,因为黑名单仅表示“不要*自动*加载此模块”)。
  2. 重新连接。
备用无根解决方案

如果你没有 root 访问权限,那么

  1. 关闭你的 PC(不仅仅是挂起)
  2. 重新连接你的游戏手柄。
  3. 开启 PC。
  4. UEFI(就像非虚拟化的 Windows 一样)会自动成功初始化游戏手柄(即使它通过显示器中的 USB 集线器连接),尽管描述符无效。
  5. 游戏手柄会从 UEFI(或 GRUB)接收信息,表明它不再需要作为 HID 使用,这会导致它切换(“降级”)到 Xbox 360 控制器模式。在模式之间切换的方式是:游戏手柄断开连接,然后以不同的 USB ID 重新连接。
  6. 你甚至可以挂起(如果连接到显示器,则无需关闭显示器)然后唤醒 PC,它仍然会处于 Xbox 360 控制器模式。但如果你重新连接游戏手柄,它将处于回退模式,因此你必须再次按照说明操作。

USB 调试

你可能不需要知道这一点,但这个 USB ID (057e:2009) 是通过 USB 调试发现的

# Allow debugging of the kernel:
sudo ls /sys/kernel/debug/usb >/dev/null 2>&1 || sudo mount -t debugfs none_debugfs /sys/kernel/debug
# Load the module that allows sniffing of the traffic of USB buses:
sudo modprobe usbmon
# We need only connection events, and in these events
# we need only a USB ID which is in the pre-pre-last column:
sudo /bin/grep --line-buffered -Po '(?<=0 0 18 = .{18}).{8}' /sys/kernel/debug/usb/usbmon/99999u | /bin/sed -E 's/([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/\2\1:\4\3/'

其中 99999 必须替换为你的游戏手柄使用的 USB 总线号,例如 1(不带前导零)。可以通过运行 lsusb 来查找。

如果一切都无济于事,并且你的游戏手柄只能在 Windows 中以全部功能运行,你可以在 Windows 中捕获 USB 消息,然后在 Linux 中重放它们。请参阅 usbrply。为此,Windows 不能是虚拟机,因为 Linux 内核的 usbcore 会在将 USB 设备传递给虚拟机之前对其进行初始化。可以通过购买 PCI-E USB 控制器并将其传递(外部 USB 集线器无法传递)来避免这种情况。或者,你可以传递你的主板自己的 USB 控制器,如果它在一个没有你所需设备的 IOMMU 组中。

xboxdrv 配置示例

本文或本节正考虑移除。

原因:xboxdrv 很少需要,而这一部分占用了大量空间,因为它的特殊性。(在 Talk:Gamepad 中讨论)

为了给这些设备一个持久的名称,请在此格式下设置一个 udev 规则。

/etc/udev/rules.d/99-btjoy.rules
#Create a symlink to appropriate /dev/input/eventX at /dev/btjoy
ACTION=="add", SUBSYSTEM=="input", ATTRS{name}=="Bluetooth Gamepad", ATTRS{uniq}=="00:17:02:01:ae:2a", SYMLINK+="btjoy"

将“Bluetooth Gamepad”替换为你的设备名称,将“00:17:02:01:ae:2a”替换为你的设备的地址。

当你有了配置并且设备已连接后,可以这样启动 xboxdrv

# xboxdrv --evdev /dev/btjoy --config .config/xboxdrv/ipega.conf

iPEGA-9017s

~/.config/xboxdrv/ipega.conf
#iPEGA PG-9017S Config

[xboxdrv]
evdev-debug = true
evdev-grab = true
rumble = false
mimic-xpad = true

[evdev-absmap]
ABS_HAT0X = dpad_x
ABS_HAT0Y = dpad_y

ABS_X = X1
ABS_Y = Y1

ABS_Z  = X2
ABS_RZ = Y2

[axismap]
-Y1 = Y1
-Y2 = Y2

[evdev-keymap]
BTN_EAST=a
BTN_C=b
BTN_NORTH=y
BTN_SOUTH=x
BTN_TR2=start
BTN_TL2=back
BTN_Z=rt
BTN_WEST=lt

BTN_MODE = guide

iPEGA-9068 和 9087

~/.config/xboxdrv/ipega.conf
#iPEGA PG-9068 and PG-9087 Config

[xboxdrv]
evdev-debug = true
evdev-grab = true
rumble = false
mimic-xpad = true

[evdev-absmap]
ABS_HAT0X = dpad_x
ABS_HAT0Y = dpad_y

ABS_X = X1
ABS_Y = Y1

ABS_Z  = X2
ABS_RZ = Y2

[axismap]
-Y1 = Y1
-Y2 = Y2

[evdev-keymap]
BTN_A=a
BTN_B=b
BTN_Y=y
BTN_X=x
BTN_TR=rb
BTN_TL=lb
BTN_TR2=rt
BTN_TL2=lt
BTN_THUMBL=tl
BTN_THUMBR=tr
BTN_START=start
BTN_SELECT=back

BTN_MODE = guide

Defender X7

~/.config/xboxdrv/defender.conf
#Defender x7 xboxdrv config

[xboxdrv]
evdev-debug = true
evdev-grab = true
rumble = false
mimic-xpad = true

[evdev-absmap]
ABS_HAT0X = dpad_x
ABS_HAT0Y = dpad_y

ABS_X = X1
ABS_Y = Y1

ABS_Z  = X2
ABS_RZ = Y2

[axismap]
-Y1 = Y1
-Y2 = Y2

[evdev-keymap]
BTN_EAST=b
BTN_NORTH=x
BTN_SOUTH=a
BTN_WEST=y
BTN_TR2=rt
BTN_TL2=lt
BTN_TR=rb
BTN_TL=lb
BTN_THUMBL=tl
BTN_THUMBR=tr
BTN_START=start
BTN_SELECT=back

BTN_MODE = guide

Stadia Controller

~/.config/xboxdrv/stadia.conf
# Stadia xboxdrv config

[xboxdrv]
mimic-xpad=true
silent=true

[evdev-absmap]
ABS_X=x1
ABS_Y=y1
ABS_Z=x2
ABS_RZ=y2
ABS_GAS=rt
ABS_BRAKE=lt
ABS_HAT0X=dpad_x
ABS_HAT0Y=dpad_y

[axismap]
-y1=y1
-y2=y2

[evdev-keymap]
BTN_SOUTH=A
BTN_EAST=B
BTN_NORTH=X
BTN_WEST=Y

BTN_START=start
BTN_SELECT=back
BTN_MODE=guide

BTN_THUMBL=tl
BTN_THUMBR=tr
BTN_TR=rb
BTN_TL=lb

Logitech Dual Action

# xboxdrv --evdev /dev/input/event* \
   --evdev-absmap ABS_X=x1,ABS_Y=y1,ABS_RZ=x2,ABS_Z=y2,ABS_HAT0X=dpad_x,ABS_HAT0Y=dpad_y \
   --axismap -Y1=Y1,-Y2=Y2 \
   --evdev-keymap BTN_TRIGGER=x,BTN_TOP=y,BTN_THUMB=a,BTN_THUMB2=b,BTN_BASE3=back,BTN_BASE4=start,BTN_BASE=lt,BTN_BASE2=rt,BTN_TOP2=lb,BTN_PINKIE=rb,BTN_BASE5=tl,BTN_BASE6=tr \
   --mimic-xpad --silent

PlayStation 2 控制器

# xboxdrv --evdev /dev/input/event* \
   --evdev-absmap ABS_X=x1,ABS_Y=y1,ABS_RZ=x2,ABS_Z=y2,ABS_HAT0X=dpad_x,ABS_HAT0Y=dpad_y \
   --axismap -Y1=Y1,-Y2=Y2 \
   --evdev-keymap   BTN_TOP=x,BTN_TRIGGER=y,BTN_THUMB2=a,BTN_THUMB=b,BTN_BASE3=back,BTN_BASE4=start,BTN_BASE=lb,BTN_BASE2=rb,BTN_TOP2=lt,BTN_PINKIE=rt,BTN_BASE5=tl,BTN_BASE6=tr \
   --mimic-xpad --silent

PlayStation 4 控制器

# xboxdrv \
   --evdev /dev/input/by-id/usb-Sony_Computer_Entertainment_Wireless_Controller-event-joystick\
   --evdev-absmap ABS_X=x1,ABS_Y=y1                 \
   --evdev-absmap ABS_Z=x2,ABS_RZ=y2                \
   --evdev-absmap ABS_HAT0X=dpad_x,ABS_HAT0Y=dpad_y \
   --evdev-keymap BTN_A=x,BTN_B=a                   \
   --evdev-keymap BTN_C=b,BTN_X=y                   \
   --evdev-keymap BTN_Y=lb,BTN_Z=rb                 \
   --evdev-keymap BTN_TL=lt,BTN_TR=rt               \
   --evdev-keymap BTN_SELECT=tl,BTN_START=tr        \
   --evdev-keymap BTN_TL2=back,BTN_TR2=start        \
   --evdev-keymap BTN_MODE=guide                    \
   --axismap -y1=y1,-y2=y2                          \
   --mimic-xpad                                     \
   --silent

PlayStation 5 控制器

# xboxdrv \
  --evdev /dev/input/by-id/usb-Sony_Interactive_Entertainment_DualSense_Wireless_Controller-if03-event-joystick \
  --evdev-absmap ABS_HAT0X=dpad_x,ABS_HAT0Y=dpad_y,ABS_X=X1,ABS_Y=Y1,ABS_RX=X2,ABS_RY=Y2,ABS_Z=LT,ABS_RZ=RT \
  --evdev-keymap BTN_SOUTH=A,BTN_EAST=B,BTN_NORTH=Y,BTN_WEST=X,BTN_START=start,BTN_MODE=guide,BTN_SELECT=back \
  --evdev-keymap BTN_TL=LB,BTN_TR=RB,BTN_TL2=LT,BTN_TR2=RT,BTN_THUMBL=TL,BTN_THUMBR=TR \
  --axismap -y1=y1,-y2=y2                          \
  --mimic-xpad                                     \
  --silent