Don't want to see articles from a certain category? When logged in, go to your User Settings and adjust your feed in the Content Preferences section where you can block tags!
We do often include affiliate links to earn us some pennies. See more here.

Setting up a Bluetooth Controller for Linux Gaming

By - | Views: 50,330

Recently I solved an issue for setting up my Wireless (via Bluetooth) controller on Steam for Linux, and decided to elaborate a little better about my experience, and share my results and observations with you all.

The controller I have used as a reference for the procedures here below is the ASUS Gamepad TV500BG, whose specs are detailed here. Alternatively, I have verified that the same procedures apply with any other Bluetooth device.

The important thing I would like to highlight is that my approach was to find a procedure that could work in several scenarios, such as for both native games (with or without Steam) and games running via Wine or Proton/Steam Play.

According to the approach mentioned above, I discarded immediately the use of the x360ce driver, which it is largely used for games running on Wine but it represents a limited solution from an architectural point of view.

Using the Userspace driver xboxdrv

The xboxdrv driver is the Xbox/360 gamepad driver for Linux running on userspace. It is widely considered as a replacement of the linux kernel module xpad, and shows significant advantages on handling several types of devices, other than the Xbox-like gamepads.

The additional capability provided by the xboxdrv driver is to remap any of your controller button or axis, and tweak the default configuration for adding new functionalities to it. By using xboxdrv, the device will be recognised then by Steam as an Xbox controller.

The only inconvenience I noticed when using xboxdrv was that the driver was able to lock and consume the hardware resource just exactly 60 seconds after launching the xboxdrv executable from the command line. This is a very well known issue tracked in this bug. You'll also see that there's a workaround noted.

I started with a udev rule for linking the input/event* device of the hardware controller in an arbitrarily named symlink (so that it would be easier to identify). The device has few attributes that make easy to recognise it. They can be read by typing the following statement in a terminal emulator:

$ udevadm info -a /sys/class/input/event*

where you have to replace the * above with the device ID (the highest number you find as soon as you turn the device on might be the right one). The output might look similar to the following:

  looking at device '/devices/pci0000:40/0000:40:07.1/0000:42:00.3/usb7/7-1/7-1:1.0/bluetooth/hci0/hci0:11/0005:0B05:4500.000B/input/input30/event26':
    KERNEL=="event26"
    SUBSYSTEM=="input"
    DRIVER==""

  looking at parent device '/devices/pci0000:40/0000:40:07.1/0000:42:00.3/usb7/7-1/7-1:1.0/bluetooth/hci0/hci0:11/0005:0B05:4500.000B/input/input30':
    KERNELS=="input30"
    SUBSYSTEMS=="input"
    DRIVERS==""
    ATTRS{name}=="ASUS Gamepad"
    ATTRS{phys}=="5c:f3:70:8f:66:37"
    ATTRS{properties}=="0"
    ATTRS{uniq}=="38:2c:4a:8c:2e:87"

The lines above are telling that the device currently identified as "event26" has an attribute name ("ASUS Gamepad") which we can use to easily identify it in the udev rules. We can then open the user-defined rules file, as shown here below:

$ sudo nano /etc/udev/rules.d/75-input-events.rules

and add the following line to it:

KERNEL=="event*" , SUBSYSTEM=="input", MODE="0666"
KERNEL=="event*", ATTRS{name}=="ASUS Gamepad", SYMLINK+="input/event-asus-gamepad"

By specifying the last keyword in the rule, the system will automatically create the symlink /dev/input/event-asus-gamepad (named like that in a totally arbitrary way) pointing to the controller device any time it is turned on, regardless of the device current ID in the current session.

Now that we have a way for identifying the controller event device, we can restart the udev rules with the following command:

$ sudo udevadm control --reload-rules && sudo udevadm trigger

and then call the xboxdrv driver with this command:

$ xboxdrv --evdev "/dev/input/event-asus-gamepad" --config xboxdrv.config --debug

The --evdev option enables xboxdrv to read any input coming from the event-asus-gamepad device and convert it into an Xbox controller input. The Xbox-converted input signals are sent by a different char device, which is specified in the command output:

Your Xbox/Xbox360 controller should now be available as:
  /dev/input/js1
  /dev/input/event27

The new devices js1 and event27 above replace the old one, and will be automatically recognised by Steam.

The --config option defines a configuration file where I've specified all the mapping between the Asus Gamepad controller axes and buttons into the conventional Xbox ones:

[xboxdrv]
detach-kernel-driver=true
silent=true

[axismap]
-Y1 = Y1
-Y2 = Y2

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

[evdev-keymap]
BTN_SOUTH=a
BTN_EAST=b
BTN_NORTH=x
BTN_WEST=y
BTN_TL=lb
BTN_TR=rb
BTN_THUMBL=tl
BTN_THUMBR=tr
KEY_BACK=back
KEY_HOMEPAGE=start
BTN_MODE=guide

The content of the configuration above above might vary according to your local controller.

I can then launch Steam with the following script:

#!/bin/sh

if [ -h /dev/input/event-asus-gamepad ]
then
# remove any previous instance:
        killall -KILL xboxdrv

# start the new driver in userspace mode:
        xboxdrv --evdev "/dev/input/event-asus-gamepad" \
        --config xboxdrv.config &
fi

/usr/bin/steam %U

In the same way, we could define the additional logic for giving an arbitrary event symlink to the xboxdrv controller device as soon as the system loads the driver. We can maintain again the user-defined rules file, as shown here below:

$ sudo nano /etc/udev/rules.d/75-input-events.rules

and add the following new line at the bottom:

KERNEL=="event*", ATTRS{name}=="Xbox Gamepad (userspace driver)", SYMLINK+="input/event-xboxdrv-gamepad"

With the definition above, the system will automatically create the symlink /dev/input/event-xboxdrv-gamepad regardless of the device current ID in the current user session.

Some people might try to run the xboxdrv driver as a daemon (with the options: --daemon --detach). Unfortunately I didn't get a working controller when I tried to do it.

Alternatively, you could try to start xboxdrv as soon as you turn on (or plug) your controller. You can implement it by adding a RUN keyword on the udev rule above (please refer to the udev documentation for further information on it).

Although this approach looks more direct, I prefer to follow the recommendation to run the driver at the same moment you run your game. This can be particularly useful if you need a different keys mapping for each game.

Some additional consideration would apply according to the specific game category.

Games running natively on Linux

Some best examples of very well-known games belonging to this category are Bioshock Infinite, Tomb Raider (2013) and Borderlands 2 (but this is just a personal opinion).

You have nothing to do in this case. Some specific games might require a value for the SDL environment variable SDL_JOYSTICK_DEVICE as shown in the example here below:

SDL_JOYSTICK_DEVICE=/dev/input/event-xboxdrv-gamepad

Although Steam will automatically identify the virtual Xbox Controller for most of the games.

Additionally, you can configure Steam itself with the Xbox Controller support (configuration is available under the menu: Steam --> Settings --> Controller --> General Controller Settings) as shown in the picture here below. This will enable you to use the controller as a replacement for the mouse pointer in Steam:

Hopefully some of you find this useful.

Article taken from GamingOnLinux.com.
Tags: HOWTO, Steam, Ubuntu
15 Likes
The comments on this article are closed.
14 comments
Page: 1/2»
  Go to:

gustavoyaraujo Jan 24, 2019
Nice one.
hardpenguin Jan 24, 2019
Dear article author,

You are my god.

I collect gamepads that do not come from the three biggest console brands (Xbox, PlayStation or Switch). Connecting some via Bluetooth is fresh hell.

I am sure I will come back to your article multiple times. Great job ^_^





cprn Jan 25, 2019
Any way to connect two identical ones as separate devices? They generate events with same origin (as in: both pads controlling player one).
x4mer Jan 25, 2019
Nice article to help people through the issues of using Linux as their chosen platform. Seeing it all spelled out here though, reminds me that Linux (in some environments), has a long way to go before it can be usable for 99% of the population.

I gave up AmigaOS for Windows over 20 years ago now. Years before that, I couldn't fathom why anyone would willingly use a Windows PC over an Amiga. In retrospect, it's obvious that a desktop computing platform with a non-X86 arch with proprietary bus interfaces, was doomed. Apple somehow made the transition & F'ed over their user base (TWICE 68K ->PPC -->X86), but still retained enough to be an option in the current day. Sadly C= did not (Sorry for the anti-Apple rant but ^%#(@*$#^#).:-)

Since coming to Linux a little over a year ago, I feel the feeling I haven't felt since my Amiga days. However, this time I'm on an underdog that has "open" access to all the CPU and GFX power the industry has to offer, as well as access to every bus interface under the sun.

I hope there comes a day when "JUST WORKS" is a thing with Linux >90% of the time, the way it is with Windows. Until then, we can edit our startup-sequence with appropriate commands to run Enforcer and Segtracker, as well as running SnoopDOS, to help the devs "MAKE IT RIGHT" whenever we can. (Shout out to Amigans!)
smokinglizards Jan 25, 2019
Makes me think I'll stick to wired controllers for now. But prolly not. Still, I was surprised by the amount of steps :o. Shedding light is a good thing here though, maybe it'll help move things towards being a little more automagic.
theghost Jan 25, 2019
Oh boi, that reminds me of the old days messsing with my xbox controller and xboxdrv. What a crap. Didn't know that xboxdrv is still a thing today.
Since I got the Steam controller I never looked back.


Last edited by theghost on 25 January 2019 at 6:44 am UTC
omicron-b Jan 25, 2019
Quoting: cprnAny way to connect two identical ones as separate devices? They generate events with same origin (as in: both pads controlling player one).
Maybe this will work?

Quoting: smokinglizardsMakes me think I'll stick to wired controllers for now. But prolly not. Still, I was surprised by the amount of steps :o. Shedding light is a good thing here though, maybe it'll help move things towards being a little more automagic.
There are lots of wireless controllers described here and probably working. I personally use Steam Controller, there is an open source driver available if someone prefers open source to Steam provided driver.
LordDaveTheKind Jan 25, 2019
View PC info
  • Supporter Plus
Quoting: GuestThe Generic gamepad configuration support is enough in Steam big picture mode. No need for the user space xboxdrv driver once you have set the controller to work with jstest-gtk. You can modify the ~/.steam/steam/config/config.vdf file to remap buttons if UI settings are not enough.

I can actually confirm that was the first thing I tried. It has worked correctly for the games running natively on Linux, but not for those games running on Wine or Steam Play, in particular for those which require the support of either the Microsoft DirectInput or the Xinput API.

For the latter in particular the mapping was always wrong: axes mapped as triggers and vice versa, and changing the controller configuration in Steam hasn't ever worked. The advantage I found with the xboxdrv layer is that remaps the device in a new one, easier to be supported by the in-game Xinput API.

I was going to write a follow-up to the article today that explains what to do for games which support DirectInput or Xinput. I'll keep you all posted of course.
RealmSpyderYT Jan 25, 2019
Quoting: hardpenguinDear article author,

You are my god.

I collect gamepads that do not come from the three biggest console brands (Xbox, PlayStation or Switch). Connecting some via Bluetooth is fresh hell.

I am sure I will come back to your article multiple times. Great job ^_^







You should get a 8bitdo controller. They are great. 8bitdo.com
LordDaveTheKind Jan 25, 2019
View PC info
  • Supporter Plus
Quoting: cprnAny way to connect two identical ones as separate devices? They generate events with same origin (as in: both pads controlling player one).

Have you already tried with the following udev rule?

KERNEL=="event*", ATTRS{name}=="Your Gamepad Name", SYMLINK+="input/event-gamepad-%n"

The outcome should be a symlink that looks like /dev/input/event-gamepad-* with the kernel number of the attached device.


Last edited by LordDaveTheKind on 25 January 2019 at 12:46 pm UTC
While you're here, please consider supporting GamingOnLinux on:

Reward Tiers: Patreon. Plain Donations: PayPal.

This ensures all of our main content remains totally free for everyone! Patreon supporters can also remove all adverts and sponsors! Supporting us helps bring good, fresh content. Without your continued support, we simply could not continue!

You can find even more ways to support us on this dedicated page any time. If you already are, thank you!
The comments on this article are closed.