Revernus Feb 20 @ 3:36pm
Play with any USB controller on Linux using xboxdrv to emulate a XBOX controller
EDIT: This tutorial works for games you play from Steam Client and for games you play outside of the Steam Client. If you're willing to play only Steam Games, try this Steam Big Picture tutorial first. If it doesn't work, then xboxdrv is guaranteed to put your controller to work.

---------------------------------------

Some games are meant to be played using a XBOX controller by default. If you have one, excelent, but if you don't, some controllers won't work 100% out of the box. For example, there are games where a PS2 controller + USB adapter will missplace some buttons: A is where Y should be, X is where A should be etc. You can correct this by remapping all your buttons/axis to the right place. On Windows you would use a program called x360ce and on Linux you'll use xboxdrv. I'll explaing how to set xboxdrv for your USB controller on Linux.


1. Installing xboxdrv

If your distro already has xboxdrv packed, install it from the repositories. If it doesn't, download the source code from their website (http://pingus.seul.org/~grumbel/xboxdrv/) and compile it. Since this step is distro specific, I won't cover it. If you're not sure how to do it, ask for help in your distro's forum.


2. Avoiding xpad conflict

Check if your distro loads xpad module to handle XBOX controller events:

# lsmod | grep xpad

If it returns a blank line, you're fine, go straight to the next section. If it returns something else, you must unload xpad module before loading xboxdrv by executing this command:

# rmmod xpad


3. Finding the proper input event

List all your available input events:

# ls /dev/input/ | grep event*

It will probably range from event0 to event20. You'll have to test each one of them until you find out which one is the event associated with your USB controller. To do so, enter the following command and press your controller buttons (press CTRL+C to exit after checking):

# evtest /dev/input/event11

If you got the wrong event, nothing will happen when you press buttons. When you get the right event, you'll notice because as soon as you press a button there will be a corresponding terminal output. Keep testing your available events until you find out which one is correct. In my case, /dev/input/event11 is associated with my PS2 controller.


4. Mapping your USB controller

If you have a PS3 controller, you can skip this section and go stragth to section 5. If you have any other controller, you must map it. To do so, while using evtest with the event associated to your controller (for example, # evtest /dev/input/event11), each time you press a button you'll receive a terminal output like this:

Event: time 1380985017.964843, type 4 (EV_MSC), code 4 (MSC_SCAN), value 90003
Event: time 1380985017.964843, type 1 (EV_KEY), code 290 (BTN_THUMB2), value 1


In this case, I pressed the button corresponding to where the A button is on the XBOX controller, and this button is mapped as BTN_THUMB2. Then I pressed the button corresponding to where the B button is on the XBOX controller, and the output was this:

Event: time 1380985018.460841, type 4 (EV_MSC), code 4 (MSC_SCAN), value 90002
Event: time 1380985018.460841, type 1 (EV_KEY), code 289 (BTN_THUMB), value 1


This output tells me that this button is mapped with the name BTN_THUMB. Take note of all these names. Do this for all your buttons and all your axis. You must take note of their names to be able to map them properly later. In the end, you'll have a list with all names and the corresponding XBOX buttons. You must map these buttons to valid XBOX buttons symbols:

Buttons: A, B, X, Y, RB (frontal upper right), RT (posterior upper right), LB (frontal upper left), LT (posterior upper left), START, BACK

Directionals: DPAD_X (horizontal D-pad), DPAD_Y (vertical D-pad), X1 (left analog horizontal), Y1 (left analog vertical), X2 (right analog horizontal), Y2 (right analog vertical)

Analog clicks: TL (left analog click), TR (right analog click)

I made an image to illustrate these valid XBOX buttons symbols[lh4.googleusercontent.com] you'll use to map your controller events. For a PS2 + USB adapter, this is how the final mapping list will look:

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
ABS_X=x1
BTN_TOP=x
BTN_TRIGGER=y
ABS_Y=y1
ABS_RZ=x2
ABS_Z=y2
ABS_HAT0X=dpad_x
ABS_HAT0Y=dpad_y
-Y1=Y1
-Y2=Y2

Note that if you have a PS2 controller too, you won't have to map all your buttons again, since I already did this (just copy this list for further use). To see what each XBOX button is named after, you can use the built in xboxsrv help to see the valid names:

$ xboxsrv --help-button
$ xboxsrv --help-axis
$ xboxsrv --help-abs



5. Initializing xboxdrv

If you have a PS3 controller, you don't have to map your controller nor nothing. Just initialize xboxdrv like this and everything will be working:

# xboxdrv --silent --detach-kernel-driver

If you have any other controller, now that you have all your buttons and axis mapped, you must initialize xboxdrv properly. To do so, you'll have to initialize it like this:

# xboxdrv --evdev [EVENT] --evdev-absmap [ABS MAP] --axismap [AXIS MAP] --evdev-keymap [BUTTONS MAP] --mimic-xpad --silent &

[EVENT] is the event associated with your controller (section 3 of this post) and [ABS MAP], [AXIS MAP] and [BUTTONS MAP] are your controller mapping (section 4 of this post). In my case, my PS2 controller + USB adapter is associated with /dev/input/event11 and has the above mapping, so I initialize xboxdrv like this:

# xboxdrv --evdev /dev/input/event11 --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 &

Note that if you have a PS2 controller too, you will initialize xboxdrv exactly the same way I do, except for the event, which might be another one.


6. Initializing xboxdrv during system startup

Everytime you restart your computer, you must unload xpad module (section 2) if it's loaded in your distro and properly initialize xboxdrv (section 5). To do these things automatically, you can put them on /etc/rc.local or whatever your distro calls it. It's distro specific, so go to your distro's forum and ask them where is your /etc/rc.local if you can't find it. In my case, I use OpenSUSE 13.1 and this file is located at /etc/rc.d/boot.local


7. Final words

I hope this helps you. With these steps I was able to set my USB controller to be remaped and emulated as a XBOX controller. I would appreciate if some moderator fixed this topic, so other users could easily find it.
Last edited by Revernus; Apr 28 @ 8:10am
Showing 1-15 of 20 comments
< >
CrisFigueira Feb 20 @ 5:00pm 
Thanks! Excellent guide :-)
spl Feb 20 @ 7:06pm 
Great guide OP

I got my PS3 controller working a while ago, but I always had a permissions problem, where games could never read from event* because only root could.
I could do a quick workaround and just change the permissions for the controller event* to make it work with steam and everything else.

Does anyone know if there's a better way to do it? I also tried using the joystick modules but it seems that games would only ever look for /dev/input/event* and they would ignore anything else
Revernus Feb 20 @ 7:33pm 
Thanks for your support, guys!

@mearo have you tryed to add your user to the group games?

@MedicByCall I highly disencourage the use of Qjoypad, first because it's abandoned for several years (and it has even been removed from most distros official repositories), second because it was never a good program in the first place (no multiple keypress support, no macros, no multiple buttons, no pixel precision, no 8-way dpad etc) and third and most important because Qjoypad was never meant to correct XBOX controller emulation issues. It will only map your gamepad into keyboard/mouse events. The steps you suggested will not work with a generic USB controller, because it is not 100% compatible with a XBOX controller, so it will require remapping. xboxdrv is the one who will remap generic gamepad into xbox-like gamepad events and this is the only way of correcting XBOX controller emulation issues in games that require a XBOX controller, such as Mark of the Ninja. If someone can't stand the terminal for some reason, I sugget using xboxdrv-gui app then, which is a Qt front-end to xboxdrv mapping step. And if someone needs gamepad remapping into keyboard and mouse events, I suggest antimicro for this purpose, but again, this kind of program alone will not correct XBOX issues, only xboxdrv will succeed when xpad module fails.
Last edited by Revernus; Feb 20 @ 7:40pm
spl Feb 20 @ 9:23pm 
Ya, I'm in the games group already. It doesn't make a difference, but that's not surprising since all of my event* are owned by root and root group.

I am using Gentoo so it's always possible I just don't have something configured right, do most people have event ownership listed as root:games or something?
Sensei Aizen Feb 21 @ 5:47am 
@Revernus

Thank you! This is good to know.

I have no problems with using qjoypad In my cases.

I can not find any serious source for 'xboxdrv-gui'.
http://kde-apps.org/ offering different packages.
Where to find official repositories which offering this?

However I am very strict in security.
I try to install only trusted software.
And I try to use only latest and stable Debian.

I know that I have to go without latest and newest packages.
There are good reasons for this. A stable system is more important than newst feautures
like you can do in Ubuntu / Arch or Debian (unstable/testing).

If I need newest feautures I have to go to official developer site of any popular software and downloaded those latest. Best comprise between safety or stability and up-to-dateness.
Revernus Feb 21 @ 6:44am 
@mearo this is probably a distro specific issue, but maybe the right way to deal with it is to change permissions. In OpenSUSE users can at least read from events:

$ ls -l /dev/input/ | grep event11
crw-r----- 1 root root 13, 75 Feb 21 08:35 event11


@MedicByCall do you run a server or have any particular reason to need Debian Stable's stability? Debian Testing is perfectly fine for desktop use and it's actually recommended for this purpose, since it has newer package versions. I used Debian Stable and Debian Testing alternatively for some years, and the only differences I noticed when using Testing were good. But you are right when you take care of not installing third party software carelessly. AFAIK xboxdrv-gui is a fresh app, I don't think it's in any distro repository right now, you would have to compile it from the source. I think its github is this one[github.com].
Last edited by Revernus; Feb 21 @ 6:45am
spl Feb 21 @ 10:36am 
So maybe I have to add my user to the "root" group? Can you tell me if you are in the "root" group on your system? Because by my understanding, it doesn't seem possible for you to read from event11 otherwise.

(maybe adding a user to "root" group is a part of the setup process for "sudo"? I don't have "sudo" on my system so perhaps that could be it)
Revernus Feb 21 @ 11:00am 
Originally posted by mearo:
So maybe I have to add my user to the "root" group? Can you tell me if you are in the "root" group on your system? Because by my understanding, it doesn't seem possible for you to read from event11 otherwise.

(maybe adding a user to "root" group is a part of the setup process for "sudo"? I don't have "sudo" on my system so perhaps that could be it)

$ cat /etc/group | grep renatov
audio:x:17:renatov
games:x:40:renatov
video:x:33:gdm,renatov
users:x:100:renatov
bumblebee:x:1000:renatov
vboxusers:x:481:renatov

I don't think sudo has something to do with this.
spl Feb 21 @ 11:08am 
and you can actually read from event11 on your normal user account without using 'sudo'?

That makes no sense to me at all, I would think it's impossible. If you aren't root, and you aren't in the root group then according to the permissions crw-r----- you shouldn't be able to read, write, or execute that file.

Any ideas? This shatters my previous notions about linux file permissions
Revernus Feb 21 @ 7:37pm 
Oh sorry, I thought you were talking about a different thing. I can only use evtest as root, but XBOX controller emulation works as user.
Sublime Apr 11 @ 12:30pm 
Thanks for the guide, but I've encountered some problems.

First of all, here's mapping of my controller (SPEEDLINK STRIKE FX):

A = BTN_A
B = BTN_B
X = BTN_X
Y = BTN_Y
LB = BTN_TL
RB = BTN_TR
LT = ABS_Z
RT = ABS_RZ
START = BTN_START
BACK = BTN_SELECT
DPAD_X = ABS_HAT0X
DPAD_Y = ABS_HAT0Y
X1 = ABS_X
Y1 = ABS_Y
X2 = ABS_RX
Y2 = ABS_RY
TL = BTN_THUMBL
TR = BTN_THUMBR

Here's the command I'm using:

# xboxdrv --evdev event18 --evdev-absmap ABS_X=X1,ABS_Y=Y1,ABS_RX=X2,ABS_RY=Y2,ABS_HAT0X=DPAD_X,ABS_HAT0Y=DPAD_Y --axismap -Y1=Y1,-Y2=Y2 --evdev-keymap BTN_A=A,BTN_B=B,BTN_X=X,BTN_Y=Y,BTN_TL=LB,BTN_TR=RB,ABS_Z=LT,ABS_RZ=RT,BTN_START=START,BTN_SELECT=BACK,TL=BTN_THUMBL,TR=BTN_THUMBR --mimic-xpad --silent &

I get this error:

-- [ ERROR ] ------------------------------------------------------
str2key: couldn't convert string: 'ABS_Z'

If I remove ABS_Z=LT from the line, I get this error:

-- [ ERROR ] ------------------------------------------------------
str2key: couldn't convert string: 'ABS_RZ'

If I remove ABS_RZ=RT from the line as well, I get this error:

-- [ ERROR ] ------------------------------------------------------
event18: No such file or directory

It's worth noting that when I press and hold right trigger, my mouse pointer goes vertically down and when I let it go, my mouse pointer goes vertically up and keeps doing so until I unplug the controller. This doesn't happen with left trigger.

My controller has XInput / DirectInput switch, btw. I'm using xinput.

It seems that my PC recognizes the controller as a mouse (left analog is mouse pointer, A is left click, X is right click).

If I just run the "xboxdrv" command, I get this:

-- [ ERROR ] ------------------------------------------------------
USBController::USBController(): libusb_open() failed: LIBUSB_ERROR_ACCESS

I have libusb installed.
Last edited by Sublime; Apr 12 @ 4:04am
Revernus Apr 11 @ 2:19pm 
Have you tryed to configure it using Steam Big Picture? It's a graphical alternative that uses SDL and it's much simpler. You should use xboxdrv only when Steam Big Picture fails.
Sublime Apr 12 @ 3:01am 
Originally posted by Revernus:
Have you tryed to configure it using Steam Big Picture? It's a graphical alternative that uses SDL and it's much simpler. You should use xboxdrv only when Steam Big Picture fails.
It says that controller is detected as Xbox controller, but it still acts as a mouse and doesn't work in game (tested in Cave Story+).

I found solution for this error:

-- [ ERROR ] ------------------------------------------------------
event18: No such file or directory

I had to use "--evdev /dev/input/event18" instead of just "--evdev event18", so that's fixed.

However, I'm still puzzled why left and right triggers are detected as ABS_Z and ABS_RZ, respectively. I think I'm getting errors because you can't assign ABS to --evdev-keymap.

I also did this[wiki.archlinux.org] which fixed the problem with mouse pointer and triggers, but they still get detected as ABS.

Edit: Works flawlessly in Super Meat Boy as long as I don't use "ABS_Z=LT,ABS_RZ=RT" in "--evdev-keymap".

Edit 2: I've used Jstest-gtk to calibrate my gamepad and everything works just fine even without the instructions from OP, but left and right trigger still get recognized as ABS_Z and ABS_RZ for some reason. I'm not sure if this is a problem with gamepad or Linux. I'll have to look into it.

Edit 3: Cave Story+ seems to work just fine when I switch my gamepad to DirectInput, including the trigger buttons. I suppose it's a legacy title. Still, newer games that prefer Xbox 360 gamepad and XInput are going to be problematic when it comes to triggers.

Edit 4: PROBLEM SOLVED! :)

To find device ID, I used this:

# lsusb

Then, I used this, where [ID] is replaced by actual device ID from last command:

# xboxdrv --device-by-id [ID] --type xbox360 --trigger-as-button --detach-kernel-driver --no-extra-events --silent

After that, triggers were registered as buttons both in Jstest-gtk and in actual games. Cave Story+ now works perfectly with both XInput and DirectInput.
Last edited by Sublime; Apr 12 @ 4:44am
Revernus Apr 12 @ 6:30am 
Nice, I'm glad the problem is solved now. Thanks for sharing your solution :)
Showing 1-15 of 20 comments
< >
Per page: 15 30 50