ko-fi
If you want to support me or accelerate the development of a special feature, consider a small donation :heart:
Just leave a message if your donation is for a specific use, like support for Xbox One Wireless Elite.

Advanced Linux Driver for Xbox One Wireless Gamepad

Build Status Codacy Badge Average time to resolve an issue

This is the first and yet only driver for the Xbox One Wireless Gamepad (which is shipped with the Xbox One S). I wrote it for a student project at fortiss GmbH and it is fully functional but does only support the connection via Bluetooth as yet - more will follow.

Many thanks to Kai Krakow who sponsored me a Xbox One Wireless Controller :video_game: (including Wireless Adapter) and a pack of mouthwatering guarana cacao :coffee:

Advantages of this driver

Getting started

Prerequisites

Make sure you have installed dkms, linux headers and a bluetooth implementation (e.g. bluez) and their dependencies.

Please feel free to add other Distributions as well!

Installation

Connection

You know that everything works fine when you feel the gamepad rumble ;)

The gamepad did not rumble ? Secure Boot may be enabled on your computer. On most Linux distribution, running mokutil --sb-state will tell you if it is the case. When Secure Boot is enabled, unsigned kernel module cannot be loaded. Two options are available:

  1. Disable Secure Boot.
  2. Sign the module yourself. Instructions for both of these options are available here.

Secure Boot is not enabled and pairing still fails? See Debugging.

Configuration

The driver can be reconfigured at runtime by accessing the following sysfs files in /sys/module/hid_xpadneo/parameters:

Some settings may need to be changed at loading time of the module, take a look at the following example to see how that works:

Example To set the highest level of debug verbosity temporarily, run
echo 3 | sudo tee /sys/module/hid_xpadneo/parameters/debug_level
To make the setting permanent and applied at loading time, try
echo "options hid_xpadneo debug_level=3" | sudo tee /etc/modprobe.d/xpadneo.conf

Update

In order to update xpadneo, do the following

Uninstallation

Further information

If someone is interested in helping me getting this driver merged into the kernel, tell me. I would really appreciate that.

For further information, like instructions for troubleshooting, please visit the GitHub Page https://atar-axis.github.io/xpadneo/ which is generated automatically from the input of the /docs folder.

Debugging

Enable Debug Output

If you are asked to send debug info or want to fix bugs, enable debugging first in the driver and upon request send the xpadneo related part:

echo 3 | sudo tee /sys/module/hid_xpadneo/parameters/debug_level
dmesg | grep xpadneo > ~/xpadneo_log

where 3 is the most verbose debug level. Disable debugging by setting the value back to 0.

You may want to set the debug level at load time of the driver. You can do this by applying the setting to modprobe:

echo "options hid_xpadneo debug_level=3" | sudo tee /etc/modprobe.d/xpadneo.conf

Now, the driver will be initialized with debug level 3 during modprobe.

Useful information can now be aquired with the commands:

Generated Events

If you are asked to supply the events generated by xpadneo, please run the following command

perl -0777 -l -ne 'print "/dev/input/$1\n" if /Name="Xbox Wireless Controller".*Handlers.*(event[0-9]+)/s' /proc/bus/input/devices | xargs evtest

Do whatever you think does not behave correctly (e.g. move the sticks from left to right if you think the range is wrong) and upload the output.

HID device descriptor (including checksum)

If we ask you to supply the device descriptor, please post the output of the following command

sudo find "/sys/kernel/debug/hid/" -name "0005:045E:*" -exec sh -c 'echo "{}" && head -1 "{}/rdesc" | tee /dev/tty | cksum && echo' \;

Working with Secure Boot

Secure Boot is a verification mechanism used when your computer loads your operating system. The boot process of a Linux distribution usually goes like this: UEFI -> UEFI Shim loader -> your distribution. Now back to our two options: disabling Secure Boot or signing xpadneo with your own key.

Disabling Secure Boot

In order for Secure Boot to be active, it must be enabled both at the UEFI level and at the shim level. Which means you should be able to disable Secure Boot:

After choosing either of these two options, Secure Boot should be disabled. You may therefore try to connect your Xbox One gamepad.

Signing xpadneo with your own keys

If you do not wish to disable Secure Boot, you will need to get the Shim to trust xpadneo. The process goes this way:

Xpadneo will need to be re-signed every time it is updated, and every time the kernel is updated. To simplify this process, we provide scripts which will help you generate your keys and automatically sign xpadneo when needed.

cd xpadneo
# Xpadneo will be signed each time it is installed, you should therefore uninstall it now if needed!
sudo ./uninstall.sh

# Copy a directory containing three helper scripts in the /root directory
sudo cp -r misc/module-signing /root

# Generate the keys and ask the shim to trust them.
# They will be saved as /root/module-signing/MOK.der (public key) and /root/module-signing/MOK.priv (private key)
# You will be asked to choose a password. This password will only be needed one time, just after the reboot.
sudo /root/module-signing/one-time-setup

# READ THIS BEFORE REBOOTING:
# Just after rebooting, you will be prompted to press a key to enter the Shim. Press any key, then select the `Enroll key` option. You will get a chance to review the key that you are about to trust. To accept the key, select Yes then enter the password you chose previously.
# /!\ WARNING: The keyboard layout used to type the password will be QWERTY, no matter what keyboard you use.

# Choose `Continue` to boot into your operating system.
# Your public key is now trusted by the shim.

# Ask DKMS to sign Xpadneo when needed.
echo "POST_BUILD=../../../../../../root/module-signing/dkms-sign-module" | sudo tee "/etc/dkms/hid_xpadneo"

# Go back to the xpadneo folder and install the module. It will be signed automatically.
cd xpadneo
sudo ./install.sh

Notes:

Third party Bugs

While developing this driver we recognized some bugs in KDE and linux itself, some of which are fixed now - others are not:

SDL Mapping

We fixed the following problem by faking the input device version to 0x1130 by default. If you want to go with the original one, please read the following:

Since after libSDL2 2.0.8, SDL contains a fix for the wrong mapping introduced by the generic hid driver. Thus, you may experience wrong button mappings again.

Also, Wine since version 3.3 supports using SDL for xinput*.dll, and with version 3.4 it includes a patch to detect the Xbox One S controller. Games running in Wine and using xinput may thus also see wrong mappings.

The Steam client includes a correction for SDL based games since some version, not depending on the SDL version. It provides a custom SDL mapping the same way we are describing here.

To fix this and have both SDL-based software and software using the legacy joystick interface using correct button mapping, you need to export an environment variable which then overrides default behavior:

export SDL_GAMECONTROLLERCONFIG="\
  050000005e040000fd02000003090000,Xbox One Wireless Controller,\
  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,"

You need to set this before starting the software. To apply it globally, put this line into your logon scripts.

The id 050000005e040000fd02000003090000 is crafted from your device id as four 32-bit words. It is, in LSB order, the bus number 5, the vendor id 045e, the device id 02fd, and the interface version or serial 0903 which is not a running number but firmware dependent. This version number is not the same as shown in dmesg as the fourth component.

You can find the values by looking at dmesg when xpadneo detects your device. In dmesg, find the device path, then change to the device path below /sys and look for the files in the id directory.

The name value after the id is purely cosmetical, you can name it whatever you like. It may show up in games as a visual identifier.

If running Wine games, to properly support xpadneo, ensure you have removed any previous xinput hacks (which includes redirecting xinput*.dll to native and placing a hacked xinput dll in the game directory. Also ensure your Wine built comes with SDL support compiled in.

If you do not want to apply this setting globally, you can instead put the SDL mapping inside Steam config.vdf. You can find this file in $STEAM_BASE/config/config.vdf. Find the line containing "SDL_GamepadBind" and adjust or add your own controller (see above). Ensure correct quoting, and Steam is not running while editing the file. This may not work for Steam in Wine because the Wine SDL layer comes first, you still need to export the variable before running Wine. An example with multiple controllers looks like this:

        "SDL_GamepadBind"               "030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),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,
03000000de280000fc11000001000000,Steam Controller,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,
03000000de280000ff11000001000000,Steam Virtual Gamepad,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,
030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,
050000005e040000fd02000003090000,Xbox One Wireless Controller,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,"