Gamepad

Related articles
List of games
Video game platform emulators
Gaming
Many gamepads are working out-of-the-box nowadays, but there are still many potential problems and sources for errors since gamepad support in applications varies by a lot.
This article or section needs expansion.
Reason:
Need info about differences between API, how to switch between them. (Discuss in
Talk:Gamepad#Joystick API vibration support
)
Linux has two different input systems for gamepads – the original Joystick interface and the newer evdev-based interface.
/dev/input/jsX
maps to the Joystick API interface and
/dev/input/event*
maps to the evdev ones (this also includes other input devices such as mice and keyboards). Symbolic links to those devices are also available in
/dev/input/by-id/
and
/dev/input/by-path/
where the legacy Joystick API has names ending with
-joystick
while the evdev have names ending with
-event-joystick
.
Most new games will default to the evdev interface as it gives more detailed information about the buttons and axes available and also adds support for force feedback.
Many applications use SDL to access gamepads.
SDL1 defaults to the evdev interface, but it can be forced to use Joystick by setting the environment variable
SDL_JOYSTICK_DEVICE=/dev/input/js0
.
SDL2 and SDL3 default to using hidapi on the most popular controllers in order to get raw access. On other controllers, or if hidapi is disabled, they use evdev instead.
SDL itself offers different APIs, the selection of which depends on the application. Their usage is not mutually exclusive.
SDL_Joystick
is supported in all versions and maps the evdev (or Joystick) events 1:1 with SDL's own.
SDL_GameController
, supported on SDL2, offers standardardized mapping between devices. For a controller to be supported, it needs an evdev:SDL mapping in a database,
gamecontrollerdb.txt
. This API is replaced with
SDL_Gamepad
in SDL3.
Installation
Unless you are using very old joystick that uses
Gameport
or a proprietary USB protocol, you will need just the generic USB Human Interface Device (HID) modules.
For an extensive overview of all joystick related modules in Linux, you can browse a local copy in
/usr/lib/modules/$(uname -r)/build/Documentation/input/joydev/
if you have installed the
linux-docs
package. Alternatively, see
documentation from the latest kernel
.
Some joysticks need specific modules, such as the Microsoft Sidewinder controllers (
sidewinder
), or the Logitech digital controllers (
adi
). Many older joysticks will work with the simple
analog
module. If your joystick is plugging in to a gameport provided by your soundcard, you will need your soundcard drivers loaded — however, some cards, like the Soundblaster Live, have a specific gameport driver (
emu10k1-gp
). Older ISA soundcards may need the
ns558
module, which is a standard gameport module.
As you can see, there are many different modules related to getting your joystick working in Linux, so everything is not covered here. Please have a look at the documentation mentioned above for details.
Loading the modules for analogue devices
You need to load a module for your gameport (
ns558
,
emu10k1-gp
,
cs461x
, etc...), a module for your joystick (
analog
,
sidewinder
,
adi
, etc...), and finally the kernel joystick device driver (
joydev
). You can
load the module at boot
, or simply
modprobe
it. The
gameport
module should load automatically, as this is a dependency of the other modules.
USB gamepads
You need to get USB working, and then modprobe your gamepad driver, which is
usbhid
, as well as
joydev
.
If you use a usb mouse or keyboard,
usbhid
will be loaded already and you just have to load the
joydev
module.
Note
If your Xbox 360 gamepad is connected with the Play&Charge USB cable it will show up in
lsusb
but it will not show up as an input device in
/dev/input/js*
, see
#Xbox 360 controller
.
Configuration
Testing
Once the modules are loaded, you should be able to find a new device:
/dev/input/js0
and a file ending with
-event-joystick
in
/dev/input/by-id
directory. You can simply
cat
those devices to see if the joystick works — move the stick around, press all the buttons - you should see mojibake printed when you move the sticks or press buttons.
If you get a permission error, see
#Device permissions
.
If you are not able to find the aforementioned input devices for your gamepad, you might try to force USBHID driver to handle the gamepad with the following command (where
VID
and
PID
are the vendor ID and product ID of your gamepad retrievable using
lsusb
from
usbutils
). Make sure to physically reconnect your device after running this command.
# printf '
VID PID
' > /sys/bus/usb/drivers/usbhid/new_id
Wine
uses SDL for both DirectInput and XInput emulation, with evdev as a fallback. You can test them with
wine control joy.cpl
. For PlayStation 4 and 5 controllers, see
#Using with Wine
.
Joystick API
There are a lot of applications that can test this old API,
jstest
from the
joyutils
package is the simplest one. If the output is unreadable because the line printed is too long you can also use graphical tools. KDE Plasma has a built in one in
System Settings > Input Devices > Game Controller
. There is
jstest-gtk-git
AUR
as an alternative.
Use of
jstest
is fairly simple, you just run
jstest /dev/input/js0
and it will print a line with state of all the axes (normalised to
{-32767,32767}
) and buttons.
After you start
jstest-gtk
, it will just show you a list of joysticks available, you just need to select one and press Properties.
evdev API
The 'evdev' API can be tested using
evtest
from
evtest
or
evtest-qt
from
evtest-qt-git
AUR
.
To test force feedback on the device, use
fftest
from
linuxconsole
:
$ fftest /dev/input/by-id/usb-*event-joystick
SDL APIs
Install
sdl-jstest-git
AUR
. If more than one controller is connected, use
sdl2-jstest --list
to get their ID.
To test the
SDL_Joystick
API on device index 0:
$ sdl2-jstest --test 0
To test the
SDL_GameController
API instead:
$ sdl2-jstest --gamecontroller 0
HTML5 Gamepad API
Go to
https://gamepad-tester.com/
. Currently, testing vibration and producing a visual of the gamepad is supported in
Chromium
but not
Firefox
. Additionally, as of version 107.0.5304.121-1, Chromium can read Joystick devices but not evdev.
Setting up deadzones and calibration
This article or section needs expansion.
Reason:
Describe calibration instructions for evdev (Discuss in
Talk:Gamepad#Unclear instructions on how to calibrate
)
If you want to set up the deadzones (or remove them completely) of your analog input you have to do it separately for the xorg (for mouse and keyboard emulation), Joystick API and evdev API.
Wine deadzones
Add the following registry entry and set it to a string from
0
to
10000
(affects all axes):
HKEY_CURRENT_USER\Software\Wine\DirectInput\DefaultDeadZone
See
Useful Registry Keys
.
Xorg deadzones
Add a similar line to
/etc/X11/xorg.conf.d/51-joystick.conf
(create if it does not exist):
/etc/X11/xorg.conf.d/51-joystick.conf
Section "InputClass"
    Option "MapAxis1" "deadzone=1000"
EndSection
1000
is the default value, but you can set anything between
0
and
30000
. To get the axis number see the "Testing Your Configuration" section of this article.
If you already have an option with a specific axis just type in the
deadzone=value
at the end of the parameter separated by a space.
Joystick API deadzones and calibration
The easiest way is using
jstest-gtk
from
jstest-gtk-git
AUR
. Select the joystick you want to edit, click the
Properties
button. On this new window, click the
Calibration
button (
do not
click
Start Calibration
after that). You can then set the
CenterMin
and
CenterMax
values, which control the center deadzone, and
RangeMin
and
RangeMax
, which control the end of throw deadzones. Note that the calibration settings are applied when the application opens the device, so you need to restart your game or test application to see updated calibration settings.
After you set the deadzones, you also can create an
udev
rule to make all changes permanent:
First, grab the vendor id of your joystick (replace
X
with your joystick's number, it is usually
0
):
$ udevadm info -q property --property ID_VENDOR_ID --value /dev/input/js
X
Also grab the model id:
$ udevadm info -q property --property ID_MODEL_ID --value /dev/input/js
X
If the commands above give you an empty output, it could be because your controller is connected via Bluetooth, making these unique attributes only visible on the parent device(s). To mitigate this, you could try finding other unique attributes by running:
$ udevadm info -a /dev/input/js
X
This will list all available attributes from your device (and parent devices). So, for example, if the parent device of your joystick has the attribute
ATTRS{uniq}=="a0:b1:c2:d3:e4:f5"
, or maybe both
ATTRS{idVendor}=="054c"
and
ATTRS{idProduct}=="09cc"
, then you can use these instead of
ENV{ID_VENDOR_ID}
and
ENV{ID_MODEL_ID}
in the
udev
rule below.
You can also have both rules at the same time, just separate them with a new line.
Anyway, now use
jscal
to dump the new calibration settings of your joystick:
$ jscal -p /dev/input/js
X
Now, modify this
udev
rule with the values you got:
/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"
This rule will automatically run
/usr/bin/jscal -s 1,1,1,1 /dev/input/js%n
whenever you connect a joystick with vendor id
054c
and model id
09cc
. The
/dev/input/js%n
part is required to automatically determine the correct joystick, so
do not
remove it.
Finally,
load
this new
udev
rule.
evdev API deadzones and calibration
The
evdev-joystick
tool from the
linuxconsole
package can be used to view and change deadzones and calibration for
evdev
API devices.
To view your device configuration:
$ evdev-joystick --showcal /dev/input/by-id/usb-*-event-joystick
To change the deadzone for a particular axis, use a command like:
$ evdev-joystick --evdev /dev/input/by-id/usb-*-event-joystick --axis 0 --deadzone 0
To set the same deadzone for all axes at once, omit the
--axis 0
option.
Use udev rules file to set them automatically when the controller is connected.
Note that inside the kernel, the value is called
flatness
and is set using the
EVIOCSABS
ioctl
.
Default configuration will look like similar to this:
$ 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)
While a more reasonable setting would be achieved with something like this (repeat for other axes):
$ 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 deadzones and calibration
Example command for creating a virtual Xbox 360 controller, with the
Y1
axis set with deadzone
4000
, minimum readable value
-32768
, center
128
, and maximum
29000
.
# xboxdrv --deadzone 4000 --calibration Y1=-32768:128:29000
See
xboxdrv(1) § AXIS FILTER
for more options.
Disable joystick from controlling mouse
If you want to play games with your gamepad, you might want to disable its joystick control over mouse cursor.
The simplest way is to disable the mouse device in the
desktop environment
settings. Otherwise, edit
/etc/X11/xorg.conf.d/51-joystick.conf
(create if it does not exists) so that it looks like this:
/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
Using gamepad to send keystrokes
Some of the generic
input remap utilities
, such as Input Remapper, work for mapping gamepad buttons to keyboard keys. Gamepad-specific tools for this include:
qjoypad
AUR
antimicrox
sc-controller
steam
- see
Steam#Steam Input
All work well without the need for additional X.org configuration.
Xorg configuration example
This is a good solution for systems where restarting Xorg is a rare event because it is a static configuration loaded only on X startup. The example runs on a
Kodi
media PC, controlled with a Logitech Cordless RumblePad 2. Due to a problem with the d-pad (a.k.a. "hat") being recognized as another axis,
Joy2key
was used as a workaround. Since
kodi
version 11.0 and
joy2key
AUR
1.6.3-1, this setup no longer worked and the following was created for letting Xorg handle joystick events.
First,
install
the
xf86-input-joystick
AUR
package. Then, create an X configuration file:
/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
Note
The
MatchIsJoystick "on"
line does not seem to be required for the setup to work, but you may want to uncomment it.
Remapping of gamepad buttons and more
With some programs you can also configure your gamepad further, including the following potential features:
Remapping buttons and axes.
Assigning mapping profiles to different games.
Emulating a different type of gamepad. Some software can often behave better when given an Xbox 360 Controller, as this is a very common controller that many games have been tested with.
Additional functionality such as Macros, On-Screen-Displays etc.
List of software:
SC Controller
— Open-source software supporting button remapping and Xbox 360 Controller emulation.
https://github.com/Ryochan7/sc-controller
||
sc-controller
Steam
— Proprietary storefront whose client supports rebinding gamepad inputs via
Steam Input
. When enabled, Steam exposes a Steam Controller to games that opt into the Steam Input API, as well as an emulated Xbox 360 Controller to games using traditional gamepad APIs. See
Steam#Steam Input
for further details.
https://store.steampowered.com/about/
||
steam
xboxdrv
— Xbox 360 controller driver which supports emulating the controller from a different input controller. See
#Mimic Xbox 360 controller
. It is also a flexible option for remapping and calibration.
https://github.com/xiota/xboxdrv
||
xboxdrv
AUR
Remapping of gamepad on SDL2 applications
Gamepads can be remapped for SDL2 applications using the
SDL_GAMECONTROLLERCONFIG
environment variable. For each line, it includes the gamepad's GUID, a name, button / axis mappings and a platform. The controller's GUID can be retrieved by installing
sdl-jstest-git
AUR
and then running
sdl2-jstest --list
.
For example, to map Microsoft Xbox 360 controllers with different GUIDs:
~/.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,
"
Some apps extract mapping information from a
gamecontrollerdb.txt
file. It can be edited graphically with
controllermap
AUR
. An up to date database can be found on
[1]
.
Mimic Xbox 360 controller
#xboxdrv
can be used to make any controller register as an Xbox 360 controller with the
--mimic-xpad
switch. This may be desirable for games that support Xbox 360 controllers out of the box, but have trouble detecting or working with other gamepads.
You can mimic an Xbox 360 controller with the following command:
$ xboxdrv --evdev /dev/input/event* --evdev-absmap ABS_RX=X2 --evdev-keymap BTN_THUMB2=a,BTN_THUMB=b,BTN_PINKIE=rt --mimic-xpad
The above example is incomplete. It only maps one axis and 3 buttons for demonstration purposes. Use
xboxdrv --help-button
to see the names of the Xbox controller buttons and axes and bind them accordingly by expanding the command above. Axes mappings should go after
--evdev-absmap
and button mappings follow
--evdev-keymap
(comma separated list; no spaces).
By default,
xboxdrv
outputs all events to the terminal. You can use this to test that the mappings are correct. Append the
--silent
option to keep it quiet.
Specific devices
While most gamepads, especially USB based ones should just work, some may require (or give better results) if you use alternative drivers.
Dance pads
Most dance pads should work. However some pads, especially those used from a video game console via an adapter, have a tendency to map the directional buttons as axis buttons. This prevents hitting left-right or up-down simultaneously. This behavior can be fixed for devices recognized by xpad via a module option:
# modprobe -r xpad
# modprobe xpad dpad_to_buttons=1
If that did not work, you can try
axisfix-git
AUR
or patching the
joydev
kernel module (
https://github.com/adiel-mittmann/dancepad
).
Logitech Thunderpad Digital
Logitech Thunderpad Digital will not show all the buttons if you use the
analog
module. Use the device specific
adi
module for this controller.
Nintendo Gamecube Controller
Dolphin Emulator has a
page on their wiki
that explains how to use the official Nintendo USB adapter with a GameCube controller. This configuration also works with the Mayflash Controller Adapter if the switch is set to "Wii U".
Steam Input supports the GameCube adapter, but it is not enabled by default since opening it is exclusive with other applications. To enable it anyway, launch Steam with the command line option
-enable-libusb-gamecube
.
[2]
For other applications, you can use
wii-u-gc-adapter
AUR
.
Nintendo Switch Pro Controller and Joy-Cons
These controllers are supported since kernel version 5.16. The Switch Online NES, SNES and N64 controllers are also supported since kernel version 6.12.
Userspace daemon
joycond-git
AUR
is a userspace daemon that provides better integration for Nintendo Switch Controllers. When the daemon is active, Switch controllers placed in a pairing mode (LEDs flashing) can have both their triggers pressed to be paired, and then ready to be used by apps. See
[3]
.
Use Joy-Cons as one device
The
hid-nintendo
kernel driver handles two Joy-Cons as two separate devices.
To pair two Joy-Cons together, make sure
joycond
is running and both Joy-Cons are in pairing mode. Then, press one trigger on each Joy-Con at the same time.
Use positional layout on SDL2 applications
By default, SDL2 maps buttons on Nintendo controllers according to the gamepad's label instead of the button's position. This causes the mapping of the buttons A/B and X/Y to be swapped compared to other controllers. If this is undesirable, set the
environment variable
SDL_GAMECONTROLLER_USE_BUTTON_LABELS=0
.
Starting from SDL3, mapping is always positional.
[4]
Note that
sdl2-compat
preserves the old behavior.
[5]
Steam Controller
Note
Kernel 4.18
provides a kernel driver
for wired/wireless use of the steam controller as a controller input device without
Steam
.
The
Steam
client will recognize the controller and provide keyboard/mouse/gamepad emulation while Steam is running. The in-game Steam overlay needs to be enabled and working in order for gamepad emulation to work. You may need to run
udevadm trigger
with root privileges or plug the dongle out and in again, if the controller does not work immediately after installing and running Steam. If all else fails, try restarting the computer while the dongle is plugged in.
If you are using the controller connected via Bluetooth LE, make sure the user is part of the
input
group.
If you cannot get the Steam Controller to work, see
#Steam Controller not pairing or recognized in games (including USB)
.
Note
If you do not use the
Steam runtime
, you might actually need to disable the overlay for the controller to work in certain games (Rocket Wars, Rocket League, Binding of Isaac, etc.). Right click on a game in your library, select "Properties", and uncheck "Enable Steam Overlay".
Xbox 360 controller
Both the wired and wireless (with the
Xbox 360 Wireless Receiver for Windows
) controllers are supported by the
xpad
kernel module and should work without additional packages. Note that using a wireless Xbox 360 controller with the Play&Charge USB cable will not work. The cable is for recharging only and does not transmit any input data over the wire.
It has been reported that the default xpad driver has some issues with a few newer wired and wireless controllers, such as:
incorrect button mapping. (
discussion in Steam bugtracker
)
not-working sync. (
discussion in Arch Forum
)
all four LEDs keep blinking, but controller works. TLP's USB autosuspend is one sure cause of this issue with wireless controllers. See below for fix.
If you use the
TLP
power management tool, you may experience connection issues with your Microsoft wireless adapter (e.g. the indicator LED will go out after the adapter has been connected for a few seconds, and controller connection attempts fail, four LEDs keep blinking but controller works). This is due to TLP's USB autosuspend functionality, and the solution is to add the Microsoft wireless adapter's device ID to TLP blacklist
(to check device ID to blacklist, run
tlp-stat -u
; for original MS wireless dongle just add
USB_DENYLIST="045e:0719"
to
/etc/tlp.conf
),
check
TLP configuration
for more details.
If you experience such issues, you can use
#xboxdrv
as the default
xpad
driver instead.
In order to connect via Bluetooth, add the following
kernel parameter
bluetooth.disable_ertm=1
.
If you experience problems with the rumble feature not working in games, it may be necessary to set the environment variable
SDL_JOYSTICK_HIDAPI=0
.
xboxdrv
This article or section is being considered for removal.
Reason:
The driver portion of xboxdrv is deprecated. (Discuss in
Talk:Gamepad
)
xboxdrv
is an alternative to
xpad
which provides more functionality and might work better with certain controllers. It works in userspace and can be launched as system service.
Install it with the
xboxdrv
AUR
package. Then
start
/
enable
xboxdrv.service
.
If you have issues with the controller being recognized but not working in steam games or working but with incorrect mappings, it may be required to modify you configuration as such:
/etc/default/xboxdrv
[xboxdrv]
silent = true
device-name = "Xbox 360 Wireless Receiver"
mimic-xpad = true
deadzone = 4000

[xboxdrv-daemon]
dbus = disabled
Then
restart
xboxdrv.service
.
Multiple controllers
xboxdrv
supports a multitude of controllers, but they need to be set up in
/etc/default/xboxdrv
. For each extra controller, add an
next-controller = true
line. For example, when using 4 controllers, add it 3 times:
[xboxdrv]
silent = true
next-controller = true
next-controller = true
next-controller = true
[xboxdrv-daemon]
dbus = disabled
Then
restart
xboxdrv.service
.
Using generic/clone controllers
Some clone gamepads might require a specific initialization sequence in order to work (
Super User answer
). For that you should run the following python script as the root user:
#!/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 Wireless Controller / Xbox One Wireless Controller
Connect Xbox Wireless Controller with USB cable
This is supported by the kernel and works without any additional packages.
Connect Xbox Wireless Controller with Bluetooth
Update controller firmware via Windows 10
The firmware of the Xbox Wireless Controller used to cause loops of connecting/disconnecting with Bluez. The best workaround is to plug the controller (via a USB cord) to a Windows 10 computer, download the
Xbox Accessories
application through the Microsoft Store, and update the firmware of the controller.
xpadneo
A relatively new driver which does support the Xbox One S and Xbox Series X|S controller via Bluetooth is called
xpadneo
. In addition to these two models, it has also basic support for the Xbox Elite Series 2 Wireless controller. In exchange for fully supporting just two controllers so far, it enables one to read out the correct battery level, supports rumble (even the one on the trigger buttons - L2/R2), corrects the (sometimes wrong) button mapping and more.
Installation is done using DKMS:
xpadneo-dkms
AUR
.
Note
Pairing a new Xbox One S controller for the first time may prove difficult, from not pairing at all to entering a connect/disconnect loop. These problems are described
there
. The best way to reliably pair the controller is to first pair it in Windows 10. However, this needs be done using the same Bluetooth adapter. A solution is to install a free copy of Windows 10 Evaluation on a Virtual machine (using
QEMU
or
VirtualBox
, taking care of the Bluetooth adapter passthrough requirements,
e.g.
as an USB device) using Arch Linux as your host, and pair in Windows 10 first, then do the same again under your Arch Linux system. Then pairing will succeed and there will be no need of further Windows 10 use.
Connect Xbox Wireless Controller with Microsoft Xbox Wireless Adapter
xone
is a Linux kernel driver for Xbox One and Xbox Series X|S accessories. It serves as a modern replacement for and supersedes xpad and xow. Currently working via wired or with the Microsoft Xbox Wireless Adapter "dongle". Bugfixes for this driver are now being mainted by the
dlundqvist fork
of the original driver.
Install
xone-dkms
AUR
and, if using the wireless dongle,
xone-dongle-firmware
AUR
. Installation requires a reboot of your system.
Note
The headers corresponding to your kernel are required; see
DKMS#Installation
.
The adapter uses a mt76 based 802.11/15 chipset which can result in interference with other wireless adapters connected to the same system or close by.
Controller performs poorly (low polling rate) after being paired
You will need to
update the controller's firmware
in Windows using the "Xbox Accessories" app from the Microsoft Store. Theoretically this should be possible with USB passthrough to a Windows virtual machine, but you may need to dual boot to an actual (baremetal) Windows installation for the Xbox Accessories application to see the controller and do the firmware update.
Dual boot with Windows
Pairing the controller & adapter in Windows may cause the pairing to be lost in Linux. You will need to re-pair the controller & dongle when you reboot into Linux. This also happens in the other direction — when the controller & dongle are paired in Linux, they will need to be re-paired the next time you want to use them in Windows. This can be avoided by following the instructions for
dual boot pairing
.
Failure to connect after Suspend and wake on gamepad use.
On some platforms, supending can cause the device to enter a state where it does not respond properly. As the device is recognised by Linux as a bluetooth adapter, it is automatically put into power-off state on suspend, which also disables waking the system from the gamepad. This can be mitigated by use of
btusb.enable_autosuspend=n
on the kernel command line. Note: This will disable power suspend on all other USB Bluetooth adapters on the system.
PlayStation 3 controller
Pairing via USB
If you own a PS3 controller and can connect with USB, plug it to your computer and press the PS button. The controller will power up and one of the four LEDs should light up indicating the controller's number.
Pairing via Bluetooth
Install
bluez
and
bluez-utils
. Make sure bluetooth is working by following the first five steps of
Bluetooth#Pairing
and leave the bluetoothctl command running, then turn on the controller by pressing the middle 'PS' button(all 4 leds should be blinking quickly ~4 hz) and connect to your computer using usb. Lastly, type yes in the bluetoothctl prompt when asked '
Authorize service 00001124-0000-1000-8000-00805f9b34fb (yes/no)
'.
Note
In the latest version of
bluez
(as of 2024/01/03), the default value for
ClassicBondedOnly
was changed from
false
to
true
for security reasons
[6]
. This change makes it impossible to pair a Dual Shock 3 controller, as
bluetoothctl
asks for a PIN and cannot proceed. To work around this, set
ClassicBondedOnly
to
false
by adding the following lines in the newly created file at
/etc/bluetooth/input.conf
.
As of 2024-03-09, the default value for
UserspaceHID
has also changed to
true
. While the connection succeeds, controllers can no longer be set into operational mode unless this value is changed to
false
. See
issue #771 on Github
for more information.
[General]
ClassicBondedOnly=false
UserspaceHID=false
Note this solution regress on security. For the details, please refer to
GitHub
Tip
There are many complicated instructions on the internet on setting up a PS3 controller that require many steps such as compiling and installing qtsixa or sixpair and setting up the controller manually, or patching bluez with some specific patches. None of this is necessary on a modern Linux kernel and after installing bluez-utils.
PlayStation 3/4 controller
The DualShock 3, DualShock 4 and Sixaxis controllers work out of the box when plugged in via USB (the PS button will need to be pushed to begin). They can also be used wirelessly via Bluetooth.
Steam properly recognizes it as a PS3 pad and Big Picture can be launched with the PS button. Big Picture and some games may act as if it was a 360 controller. Gamepad control over mouse is on by default. You may want to turn it off before playing games, see
#Disable joystick from controlling mouse
.
Pairing via Bluetooth
Install the
bluez
and
bluez-utils
packages, which includes the
sixaxis
plugin. Then
start
the
bluetooth
service and ensure bluetooth is powered on. If using
bluetoothctl
start it in a terminal and then plug the controller in via USB. You should be prompted to trust the controller in bluetoothctl. A graphical bluetooth front-end may program your PC's bluetooth address into the controller automatically. Hit the PlayStation button and check that the controller works while plugged in.
You can now disconnect your controller. The next time you hit the PlayStation button it will connect without asking anything else.
Alternatively, on a PS4 controller you can hold the share button and the PlayStation button simultaneously (for a few seconds) to put the gamepad in pairing mode, and pair as you would normally.
GNOME's Settings also provides a graphical interface to pair sixaxis controllers when connected by wire.
Remember to disconnect the controller when you are done as the controller will stay on when connected and drain the battery.
Note
If the controller does not connect, make sure the bluetooth interface is turned on and the controllers have been trusted. (See
Bluetooth
)
Using generic/clone controllers
Using generic/clone Dualshock controllers is possible, however there is an issue that may require to install a patched package. The default Bluetooth protocol stack does not detect some of the clone controllers. The
bluez-ps3
AUR
package is a version patched to be able to detect them.
bluez-plugins-ps3
AUR
is another package that only patch the bluez-plugins may work for some controllers.
PlayStation 4/5 controller
Pairing via USB
Connect your controller via USB and press the
PS
button.
Pairing via Bluetooth
If you want to use Bluetooth mode, hold down the
PS
button and
Share
button together. The white LED of the controller should blink very quickly, and the wireless controller can be paired with your Bluetooth manager.
Using with Wine
On these controllers, Wine uses hidraw by default (since 8.0), so that Windows applications that support them can use all of their features. Due to this Windows-like behavior, they are not exposed as XInput devices, which prevents them from working in many applications.
To disable this behavior, import the following text file into the Wine registry with
regedit
:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\winebus]
"DisableHidraw"=dword:1
Since Wine 9.18, this setting can be controlled from
wine control joy.cpl
.
Disable touchpad acting as mouse
If using
libinput
with
Xorg
, or if using
Wayland
, then you can follow
Libinput#Using environment variable
to disable the touchpad device.
Note that, since the touchpad is just one part of the controller, selecting the input device by vendor and product IDs will not suffice. Instead, consider selecting the device by name.
For a full set of attributes you can use, consult
udevadm info --attribute-walk --name=
device_path
, where
device_path
is the path to the device, such as
/dev/input/event
n
or
/dev/input/by-id/
identifier
.
To find the device path, you can use a tool such as
evtest
by just running
evtest
. This command should also print out the name of the device.
Example snippet:
/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"
With DualSense controllers, replace the names with
Sony Interactive Entertainment DualSense Wireless Controller Touchpad
and
DualSense Wireless Controller Touchpad
.
Then,
reload udev rules
. Reconnect the gamepad to apply changes.
dualsensectl
dualsensectl
is a tool that can toggle the lightbar and microphone (and its LED), monitor the battery status, and power off the controller. To use it,
install
dualsensectl-git
AUR
.
Tips and tricks
Gamepad over network
If you want to use your gamepad with another computer over a network, you can use
USB/IP
or
netstick-git
AUR
to do this.
Measure controller polling rates and latencies via gamepadla-polling
See also:
Mouse polling rate
Gamepadla hosts a crowdsourced database for controller-specific latency, and polling data.
[7]
The tool for making these reports reads evdev/hidraw events via pygame/SDL and it can be obtained from
gamepadla-polling
AUR
.
Overclock controller polling rates via usb_oc-dkms
usb_oc-dkms
AUR
can be used to override bInterval on controller's USB device endpoints, effectively overclocking their polling rates, if the device will allow itself to be polled at a higher rate and give the host more data.
Most notably popular devices like Sony DualSense can be overclocked (from 250 Hz to 1000 Hz, or partially to 8000 Hz).
Troubleshooting
Device permissions
Gamepad devices are affected by
udev rules
: unless they grant access to the device, it simply will not be readable by users. This section investigates the possibility of you already having a configuration file handling this.
Any gamepad device, regardless of whether it is over USB or Bluetooth, is handled by the
"input" subsystem of the kernel
, corresponding with
/dev/input
. It is also common for udev rules to target the
"hidraw" kernel module
. Combining these, we can understand udev's handling of these devices by inspecting the configuration shipped by packages:
$ grep --extended-regexp 'SUBSYSTEM=="input"|KERNEL=="hidraw' --recursive /usr/lib/udev/rules.d
Some examples of applications which ship noteworthy rules:
systemd
's default rules set the group of all
input
devices to
input
, and the mode of joystick devices to
664
[8]
.
Steam
ships udev rules allowing access to a variety of controllers. See
this Steam discussion
for further info about the contents of the rules.
Dolphin emulator
ships udev rules allowing access to controllers it supports.
If your system does not already happen to have a udev rule for the device you want to use, you can either write one yourself or install the
game-devices-udev
AUR
package and restart your computer.
Note
It is possible to add a user to the
input
group in order to give them access to all devices. However, this is not recommended
[9]
.
Gamepad is not recognized by all programs
Some software, Steam for example, will only recognize the first gamepad it encounters. Due to a bug in the driver for Microsoft wireless periphery devices this can in fact be the bluetooth dongle. If you find you have a
/dev/input/js*
and
/dev/input/event*
belonging to you keyboard's bluetooth transceiver you can get automatically get rid of it by creating according udev rules:
/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"
Correct the
KERNELS=="..."
to match your device. The correct value can be found by running
# udevadm info -an /dev/input/js0
Assuming the device in question is
/dev/input/js0
. After you placed the rule reload the rules with
# udevadm control --reload
Then replug the device making you trouble. The joystick and event devices should be gone, although their number will still be reserved. But the files are out of the way.
Application only supports Xbox 360 controllers
Some Windows games look for an Xbox 360 controller in particular, missing functionality (like vibration) or not working at all otherwise.
For a workaround, see
#Mimic Xbox 360 controller
.
Nintendo Switch Pro Controller disconnects when using Bluetooth
The Nintendo Switch Pro Controller and variants may disconnect when receiving rumble inputs.
This can be worked around by changing the name of the Bluetooth adapter to "Nintendo".
[10]
Steam Controller
Steam Controller not pairing or recognized in games (including USB)
There are some unknown cases where the packaged udev rule for the Steam controller does not work (
FS#47330
). This can result in many issues, such as the Steam Controller behaving functionally in the desktop and in Steam, but failing to have any effect in games (including over USB controller connections).  The most reliable workaround is to make the controller world readable. Copy the rule
/usr/lib/udev/rules.d/70-steam-controller.rules
to
/etc/udev/rules.d
with a later priority and change anything that says
MODE="0660"
to
MODE="066
6
"
e.g.
/etc/udev/rules.d/99-steam-controller-perms.rules
...
SUBSYSTEM=="usb", ATTRS{idVendor}=="28de", MODE="0666"
...
You may have to reboot in order for the change to take effect.
Steam Controller makes a game crash or not recognized
If your Steam Controller is working well in Steam Big Picture mode, but not recognized by a game or the game starts crashing when you plug in the controller, this may be because of the native driver that has been added to the Linux kernel 4.18. Try to unload it, restart Steam and replug the controller.
The module name of the driver is
hid_steam
, so to unload it you may perform:
# rmmod hid_steam
If this module is not already loaded but the controller is still not recognized by games, refer to the previous section's udev rule solution in
#Steam Controller not pairing or recognized in games (including USB)
.
Xbox One Wireless Gamepad detected but no inputs recognized
This can occur when using a third party Xbox One controller with the
xpad
or
#xboxdrv
drivers. Try switching to
#xpadneo
.
PlayStation 4 Controllers
Controller not recognized when using Bluetooth
Install
the
ds4drv
AUR
package and run it with the hidraw (
ds4drv --hidraw
) backend parameter.
Motion controls taking over joypad controls and/or causing unintended input with joypad controls
This article or section needs language, wiki syntax or style improvements. See
Help:Style
for reference.
Reason:
Could likely use the same solution as
Gamepad#Disable touchpad acting as mouse
, which is already refactored into other pages where appropriate. (Discuss in
Talk:Gamepad
)
With certain cloud gaming applications such as Parsec and Shadow, the Dualshock 4 V1 and V2 motion controls can conflict with the joypad controls resulting in the joypad not working, and with certain input sensitive games, especially racing games, the motion controls can cause unintentional drift during joypad control gameplay.
This can be worked around by disabling the motion controls and the touchpad by adding the following udev rules:
/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}=""
Then
reload the rules
or reboot: these rules should work in both USB and Bluetooth mode.
Multi-mode wired gamepads
Some gamepads have 3 modes when wired: Switch, Xbox 360/Windows, Android.
And they also do not have hotkeys to switch between them when connected
wired
.
ZD O+ Excellence
The gamepad defaults to Switch mode and falls back to XInput. The gamepad inputs are not handled properly in this mode. The rest of the rebinds you can make, e.g. keyboard and mouse inputs all seem to work properly in XInput mode by default.
DirectInput
This can be fixed by switching to DirectInput mode every time you use it, but that is annoying and does not work for some HTML5 games.
udev
Add the following udev rule and it will be handled as an Xbox 360 controller using 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'"
Reload your udev rules
.
Then replug your gamepad.
ShanWan
This article or section needs language, wiki syntax or style improvements. See
Help:Style
for reference.
Reason:
Multiple improvements to be made. (Discuss in
Talk:Gamepad
)
When you connect this gamepad to Windows, it is in Xbox 360 Controller mode.
But when you connect such gamepad to Linux, it enters the fallback mode (which happens to be the Android mode), which has a worse polling rate (100 Hz), the Home button acting as
XF86Home
; doesn't expose vibration, gyroscope, and accelerometer; doesn't support
xboxdrv
without
--evdev
; and identifies itself as e.g. "SHANWAN Android Gamepad" which is not liked by some games (though for SDL2 apps you can set a name in
SDL_GAMECONTROLLERCONFIG
).
When you connect the gamepad, it first tries to be a "Switch Pro Controller", but for some reason the Linux kernel considers the descriptors (sent by the gamepad) invalid, and therefore disconnects the gamepad. This causes the gamepad to reconnect in the aforementioned fallback mode.
In
dmesg
this looks like:
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
Notice that the "USB Device number" gets increased after the failure. For some USB hubs the error code is
-32
(EPIPE: broken pipe), for others it is
-71
(EPROTO: protocol error).
This error can be fixed by setting a quirk in
usbcore
module (not
usbhid
) for Switch controller's USB ID:
# 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
are 2 flags (
List of all flags
).
The flag
i
means "allow bad descriptors".
And the flag
k
means "disable LPM" (link power management). It is specified in the command because it often helps devices of other types. This flag might do nothing because not all USB controllers even have LPM. You can try without
k
aftewards.
You could also try the flag
g
("200 ms pause after reading the descriptors") because it often helps devices of other types, but at least in the case of iPEGA PG-SW038C (a $10 gamepad) flag
g
causes it infinitely reconnect.
Note that once the gamepad downgrades to the fallback mode, it will never change its mode until you reconnect it. Even
echo 0 then 1 > %sysfsGamepadDir%/authorized
doesn't work. And that's why passing the gamepad to a Windows VM would not help;
usbcore
inits USB devices before passing them to a VM.
Now reconnect the gamepad, it should be finally listed now as
ID 057e:2009 Nintendo Co., Ltd Switch Pro Controller
when you run
lsusb
. If that's true, then you can make this quirk permanent by add this option to GRUB:
usbcore.quirks="057e:2009:ik"
along with (optionally)
usbhid.quirks="0x057e:0x2009:0x400"
which stops the pointless blinking of LEDs when the gamepad is unused.
Now that your gamepad is in Switch mode, you will run into a problem of SDL2 deciding to become a user-space driver (for this it uses
libusb
, just like
xboxdrv
), which causes any SDL2 game to claim the whole gamepad (that is:
/dev/input/*
and
/dev/hidraw*
disappear, yet it is still possible to play this launched game with the gamepad), so you cannot use the gamepad in multiple apps anymore.
This can be fixed by adding
SDL_HIDAPI_DISABLE_LIBUSB=1
into
/etc/environment
, and rebooting.
If you have
joycond-git
AUR
, then delete it, because it is useless for such Switch-like gamepads, moreover
joycond
has a
udev
rule that disallows Steam to provide its own user-space driver.
Unlike SDL2 (when it uses
/dev/hidraw*
which is its preferred way in 2023),
xboxdrv
and
/dev/input/*
provide incorrect values for the right stick's X axis (it is always ≤0). Probably a bug in
hid-nintendo
or something. For this reason
xboxdrv
is unusable in most games when in Switch mode.
You can test your gyroscope and accelerometer by launching
antimicrox
. They are not available in other gamepad modes when connected wired because their values are sent
mixed
with other event data (RX/RY/etc) in a special format that is not fully compatible with
xpad
and
hid-generic
.
If you see in
dmesg
that
hid-generic
is used by your gamepad, then it is probably because you have built Linux kernel with your own config without
hid-nintendo
. Unfortuately, Switch mode +
hid-generic
is as useless as the fallback mode (even no vibration).
Xbox 360 Controller mode
After having completed everything above (i.e. 1-2 quirks, 1 envvar),
add
blacklist hid_nintendo
into
/etc/modprobe.d/blacklist.conf
then run
sudo mkinitcpio -P
to rebuild
/boot/initramfs*
(kernel reads
/etc/modprobe.d/
only from its own initramfs, not your rootfs)
Now create the following file:
/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'"
then run
sudo udevadm control --reload-rules && sudo udevadm trigger
Since you probably do not want to reboot, run
sudo modprobe -r hid_nintendo
From now on, to switch ("downgrade") from Switch mode to Xbox 360 mode, just run
sudo modprobe -r hid_nintendo
(you do not even need to reconnect it). Within 2 seconds you will have
045e:028e Microsoft Corp. Xbox360 Controller
in
lsusb
And if you want to switch vice versa:
sudo modprobe hid_nintendo
(even though it is blacklisted, this command still works because blacklisting just means "do not load this module
automatically
").
Reconnect.
Alternative rootless solution
If you do not have root access, then:
Power off your PC (not just suspend)
Reconnect your gamepad.
Power the PC on.
UEFI (just like non-virtualized Windows) automatically and successfully initializes the gamepad (even if it is connected through a USB hub in your monitor) despite the invalid descriptors.
The gamepad receives info from UEFI (or maybe GRUB) that it is no longer needed as an HID, which causes it to switch ("downgrade") to Xbox 360 Controller mode. Switching between modes is done this way: the gamepad disconnects, then connects under a different USB ID.
You can even suspend (without turning off the monitor if that's what it is connected to) and then wake-up the PC, and it will still be in Xbox 360 Controller mode. But if you reconnect the gamepad, it will be in the fallback mode, so you will have to follow the instruction again.
USB debugging
You will probably not need to know this, but this USB ID (
057e:2009
) was discovered by USB debugging:
# 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/
99999
u | /bin/sed -E 's/([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/\2\1:\4\3/'
where
99999
must be replaced with the USB Bus number that your gamepad uses, e.g.
1
(without leading zeroes). It can be found by running
lsusb
.
If nothing helped and your gamepad still works in full capacity only in Windows, you can catch USB messages while in Windows, and then replay them while in Linux. See
usbrply
. For this, Windows must not be in a virtual machine because Linux kernel's
usbcore
initializes a USB device before passing it to a virtual machine. This could be avoided by buying a PCIe USB controller and passing it through (External USB hubs cannot be passed through). Or you can pass-through your motherboard's own USB controller if it is in a IOMMU group without devices important for you:
Script which lists IOMMU groups
list-iommu-groups.sh
#!/bin/bash
shopt -s nullglob
for g in $(find /sys/kernel/iommu_groups/* -maxdepth 0 -type d | sort -V); do
  echo "IOMMU Group ${g##*/}:"
  for d in $g/devices/*; do
      echo -e "\t$(lspci -nns ${d##*/})"
  done;
done;
Example xboxdrv configurations
This article or section is being considered for removal.
Reason:
xboxdrv is very rarely needed, and this section takes up a lot of space for how specific it is. (Discuss in
Talk:Gamepad
)
To give these devices a persistent name, set an udev rule in this format.
/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"
Replace "Bluetooth Gamepad" with your device name and "00:17:02:01:ae:2a" with your device's address.
When you have the configuration and your device is connected you can start
xboxdrv
like so:
# 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 and 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 controller
# 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 controller
# 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 controller
# 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