Support us on Patreon to keep GamingOnLinux alive. This ensures all of our main content remains free for everyone. Just good, fresh content! Alternatively, you can donate through PayPal. You can also buy games using our partner links for GOG and Humble Store.
We do often include affiliate links to earn us some pennies. See more here.

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.
All posts need to follow our rules. For users logged in: please hit the Report Flag icon on any post that breaks the rules or contains illegal / harmful content. Guest readers can email us for any issues.
14 comments

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 ^_^

![](https://i.imgur.com/Htv4Bru.jpg)

![](https://i.imgur.com/sY3VN6G.jpg)

![](https://i.imgur.com/cDMzw4V.jpg)
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
Any 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?

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.
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
The 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
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 ^_^

![](https://i.imgur.com/Htv4Bru.jpg)

![](https://i.imgur.com/sY3VN6G.jpg)

![](https://i.imgur.com/cDMzw4V.jpg)


You should get a 8bitdo controller. They are great. 8bitdo.com
LordDaveTheKind Jan 25, 2019
View PC info
  • Supporter Plus
Any 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
TurtleShark Jan 25, 2019
Slightly off-topic, but has ANYONE been able to get force-feedback/rumble working on their controllers? I can get it working via Jtest, but I am starting to think that most games don't support it.
cprn Jan 25, 2019
Maybe this will work?

Nah, they need to be separate devices in OS first.

Have you already tried with the following udev rule?

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

This looks promising! :) Will check when I get home on Monday. I saw %k, %p and %n in the man pages but I didn't understand you can use those when writing rules :D Thank you!
Cyba.Cowboy Jan 28, 2019
Seriously, why all the code? You're just making things harder to be than they need to be!

Whilst I can't speak for other controllers (though my understanding is that it is generally the same)(in my experience, wired USB gamepads of various types "just work"), all you need to do is put a Sony DUALSHOCK 4 into "pairing" mode and "pair" it with your computer over bluetooth using the usual process... As you can see from my Ask Ubuntu post ( https://askubuntu.com/a/546832 ), everything works pretty seamlessly, with most games.

I'm sure your heart is in the right place, but it's articles like this which keep people thinking that Linux-based operating systems are harder to use than they are... If you're going to post an article like this, you post the KISS solution first, then post the Terminal-based solution for those of us that prefer that method (I prefer Terminal for a lot of - but not all - things).


Last edited by Cyba.Cowboy on 28 January 2019 at 3:18 am UTC
LordDaveTheKind Jan 28, 2019
View PC info
  • Supporter Plus
I'm sure your heart is in the right place, but it's articles like this which keep people thinking that Linux-based operating systems are harder to use than they are... If you're going to post an article like this, you post the KISS solution first, then post the Terminal-based solution for those of us that prefer that method (I prefer Terminal for a lot of - but not all - things).

The KISS approach has been the first one I tried, but (as I have already mentioned above) it wasn't working: the controller mapping was completely wrong, with axes mapped on triggers and buttons on the wrong positions. The mapping/configuration tool provided by Steam was easily working with the keys, but not that easily with either the axes or the triggers (and you could tell that having the camera controls on a trigger can give some motion sickness).

Speaking about the article purpose, the main reason was for sharing experiences on how to make things work. Are there easier way to achieve the same results? Of course they are. That's why I ask everyone to share their observations.
I totally understand that a KISS solution would be better (and that would be appealing also to a less-skilled user), but if that solution does not exist, a workaround can be an alternative. Does this workaround require some basic skills with either the terminal or the recompiling of source code? So be it.
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.