[[ Xbox/Xbox360 USB Gamepad Driver for Userspace ]] =================================================== This is a Xbox/Xbox360 gamepad driver for Linux that works in userspace. It is an alternative to the xpad kernel driver and has support for Xbox1 gamepads, Xbox360 USB gamepads and Xbox360 wireless gamepads. The Xbox360 guitar and some Xbox1 dancemats might work too. The Xbox360 chatpad does currently not work and the headset does neither. There has been some work on reverse enginiering, but no usable results. This driver is only of interest if the xpad kernel driver doesn't work for you or if you want some more configurabity, if the xpad kernel driver works for you there is no need to try this driver. Newest version of the driver can be found at: * http://pingus.seul.org/~grumbel/xboxdrv/ The development version can be optained via: * git clone http://pingus.seul.org/~grumbel/xboxdrv.git [[ Compilation ]] ----------------- Required libraries and tools: * libusb * boost * scons * uinput (userspace input kernel module) * git (only to download the development version) Once installed, you can compile by typing: % scons On Ubuntu 8.10 you can install all the required libraries via: % apt-get install libboost1.35-dev scons libusb-dev git-core To load the uinput kernel module automatically on boot add it /etc/modules, to load it manually type: % sudo modprobe uinput On other distributions exact install instructions might be slightly different. [[ Running XboxDrv ]] --------------------- First make sure that the xpad kernel module is not loaded, either by deleting, renaming it or blacklisting it. rmmod might not be enough since it might be automatically loaded again. Next you have to load the uinput kernel module which allows userspace programms to create input devices and the joydev module which gives you the /dev/input/jsX device: % modprobe uinput % modprobe joydev You also have to make sure that you have access rights to /dev/input/uinput, either add yourself to the appropriate group, adjust the permissions or run xboxdrv as root. Once ensured that xpad is out of the way and everything is in place plug in your Xbox360 gamepad and start the userspace driver with: % ./xboxdrv Or in case you don't have the neccesary rights (being in group root should often be enough) start the driver as root via: % sudo ./xboxdrv This will create /dev/input/js0 and allow you to access the gamepad from any game. To exit the driver press Ctrl-c. If you have multiple wired controllers you need to start multiple instances of the xboxdrv driver and append the -i argument like this: % ./xboxdrv -i 1 If you have multiple wireless controller you need to start multiple instances of the xboxdrv driver and append the --wid argument like this: % ./xboxdrv --wid 1 You have to sync the wireless controller as usual. This will then use the second detected controller, see to see which id your controller has: % ./xboxdrv --list-controller When everything works as expected it is recomment that you run xboxdrv with the silent option: % ./xboxdrv --silent This will suppress the logging of events to the console and will gurantee that no uneccesarry CPU cycles are wasted. If you want to abuse the led or rumble of the gamepad for notification in scripts you can do see via: % ./xboxdrv --led 10 --rumble 30,30 --quit This will cause a mild rumble and the led to rotate, you can stop it again via, which also happens to be the command you can use to stop your Xbox360 controller from blinking: % ./xboxdrv -q For rumble to work make sure you have connected the controller to a USB port that has enough power, i.e. an unpowered USB hub might not work. [[ Square Axis ]] ----------------- The Xbox360 gamepad, as most other current day gamepads, features a circular movment range, which restricts the movement so that the distance to the center never gets beyond 1. This means that when you have the controller at the top/left the value reported is (0.7, 0.7) (i.e. length 1, angle 45) instead of (1,1). This behaviour is different then most classic joysticks, which had a square range and allowed x and y to be handled completly indepened. Some old games (i.e. DOS stuff) require a square movement range and will thus not function properly with the Xbox360 gamepad. Via the --square-axis option you can work around this issue and diagonals will be reported as (1,1). [[ AutoFire Mapping ]] Autofire mapping allows you to let a button automatically fire with a given frequency in miliseconds: % ./xboxdrv --autofire A=250 Combining --autofire with button map allows you to have one button act as autofire while another one, emitting the same signal, acts normally. [[ Relative Axis Mapping ]] The function --relative-axis allows you to change the behaviour of an axis so that your movement of it moves its value up or down instead of applying it instantly. This is mostly useful for flightsim games that make use of a throttle control, which you can emulate by using the relative axis mapping. Since the axis might be upside down, you might want to use the --axismap function to reverse it. % ./xboxdrv --relative-axis y2=64000 [[ Button Remapping ]] ---------------------- Button remapping is available via the --buttonmap option. If you want to swap button A and B start with: % ./xboxdrv --buttonmap A=B,B=A If you want all face buttons send out A button events: % ./xboxdrv --buttonmap B=A,X=A,Y=A Possible button names are: Name | Description ---------------+------------------------------------------------------------------ start, back | start, back buttons guide | big X-button in the middle (Xbox360 only) a, b, x, y | face buttons black, white | black, white buttons (Xbox1 only, mapped to lb, rb on Xbox360) lb, rb | shoulder buttons (Xbox360 only, mapped to black, white on Xbox1) lt, rt | analog trigger (needs --trigger-as-button option) tl, tr | pressing the left or right analog stick du, dd, dl, dr | dpad directions (needs --dpad-as-button option) green, red, | guitar buttons yellow, blue, | orange | [[ Axis Remapping ]] -------------------- Axis remapping is available via --axismap and works the same as button mapping. In addition you can supply a sign to indicate that an axis should be inverted. So if you want to invert the y1 axis start with: % ./xboxdrv --axismap -Y1=Y1 If you want to swap the left and right stick start with: % ./xboxdrv --axismap X2=X1,Y2=Y1,X1=X2,Y1=Y2 Possible axis names are: x1, y1, x2, y2, lt, rt Swaping lt or rt with x1, y1, x2, y2 will not work properly. [[ UInput Mapping ]] -------------------- Another more low level form to remap buttons and axis comes in the form of --ui-buttonmap and --ui-axismap, these allow you to change the event code that is send to the kernel for a given button or axis. Usage is similar to the normal button mapping: % ./xboxdrv -s --ui-buttonmap X=KEY_A Except that the right hand side is an event name from /usr/include/linux/input.h. You can use all KEY_ or BTN_ codes for --ui-buttonmap and all ABS_ and REL_ ones for --ui-axismap. When you try to let a gamepad key send a keyboard event you might run into trouble with Xorg, for possible fixes see the section further down. In addition to just the event you can also pass additional configuration parameter seperated by colons, the exact parameter differ on the type of event: --ui-axismap REL_???:VALUE:REPEAT VALUE: the maximum value of the event (default: 10) REPEAT: number of milisecond to pass before the event is fired again (default: 5) --ui-buttonmap REL_???:VALUE:REPEAT VALUE: the maximum value of the event (default: 10) REPEAT: number of milisecond to pass before the event is fired again (default: 5) [[ Running InputDrv ]] ---------------------- The programs inputdrv and gui/inputcfg.py are part of an experiment to create a very flexible input configuration framework. They are still in development and not of any use unless you want to hack the source. Their compilation is disabled by default. [[ SDL Notes ]] --------------- To let SDL know which axis act as a hat and which act as normal axis you have to set an environment variable: % SDL_LINUX_JOYSTICK="'Xbox Gamepad (userspace driver)' 6 1 0" % export SDL_LINUX_JOYSTICK This will let the DPad act as Hat in SDL based application. For many games the driver will work without this, but especially in Dosbox this variable is very important. If you use options in xboxdrv that change the number of axis you have to adjust the variable accordingly, see: * ftp://ptah.lnf.kth.se/pub/misc/sdl-env-vars SDL_LINUX_JOYSTICK Special joystick configuration string for linux. The format is "name numaxes numhats numballs" where name is the name string of the joystick (possibly in single quotes), and the rest are the number of axes, hats and balls respectively. [[ Xorg Trouble ]] ------------------ If you start xboxdrv and instead of having a fully working joystick, you end up controlling the mouse that might be due to recent changes in Xorg and its device hotplug handling. There are three workarounds: Get the device id from hal: % hal-find-by-property --key 'info.product' --string 'Xbox Gamepad (userspace driver)' Then remove the device from hal with: % hal-device -r $DEVICEID Second workaround works with xinput: % xinput list % xinput set-int-prop $DEVICEID 'Device Enabled' 32 0 The former two workarounds are just temporary and have to be redone after each start of xboxdrv, the last workaround is a permanent one: You have to edit: /etc/hal/fdi/policy/preferences.fdi And insert the following lines: Note: The exact string will differ depending on the type of controller you use. [[ Mouse Emulation ]] --------------------- Mouse emulation can be done with something like this: ./xboxdrv \ --axismap -y2=y2 \ --ui-axismap x1=REL_X,y1=REL_Y,y2=REL_WHEEL:3:50 \ --ui-buttonmap a=BTN_LEFT,b=BTN_RIGHT,x=BTN_MIDDLE,y=KEY_ENTER \ --ui-buttonmap rb=KEY_FORWARD,lb=KEY_BACK \ --ui-buttonmap dl=KEY_LEFT,dr=KEY_RIGHT,du=KEY_UP,dd=KEY_DOWN \ -s --deadzone 5000 --dpad-as-button This will map the dpad to cursor keys, left analogstick to mouse cursor and right analogstick to mouse wheel. Note that if you have your mouse buttons switched you must adjust the above to match your mouse or the button events come out wrong. [[ Wacom Trouble ]] ------------------- In recent kernels a Wacom graphic tablet creates a joystick device, so xboxdrv or any other real joysticks ends up as /dev/input/js1 instead of /dev/input/js0. In many games this causes the joystick to not function any more. A temporary workaround for this is to simply delete the joystick device js0 and replace it with a symbolic link js1 via: % sudo ln -sf /dev/input/js1 /dev/input/js0 This workaround will only last till the next reboot, since the device names are dynamically created, but for the time being there doesn't seem to any other way to easily work around this issue. [[ Wine Trouble ]] ------------------ When using the Xbox360 gamepad in Wine it is not specially handled as Xbox360 gamepad, this means games will not display the proper button labels, but just numbers (i.e. 'Btn1' instead of 'A' for example). Asside from that it should work fine. Xinput support (the DirectInput replacment, not the Xorg xinput) might not work properly or not at all. It is currently unknown if this can be fixed by xboxdrv or if it requires patches to Wine. [[ Examples ]] -------------- Prince of Persia: Sands of Time (in Wine) Prince of Persia: Warrior Within (in Wine) Prince of Persia: The Two Thrones (in Wine) Tomb Raider Anniversary (in Wine) Tomb Raider Legend (in Wine) ---------------------------- % xboxdrv --trigger-as-button -s The triggers are not regonized in these games when they are analog, so we have to handle them as buttons. CH Flightstick emulation in Dosbox: ----------------------------------- In dosbox.conf set: [joystick] joysticktype = ch Start xboxdrv with: % xboxdrv -s --trigger-as-zaxis --square-axis --relative-axis y2=64000 --axismap -y2=x2,x2=y2 Your right analog stick will act as trottle control, the trigger as rudder. Sauerbraten ----------- First analogstick gets mapped te cursor keys, second analogstick gets mapped to mouse. % ./xboxdrv \ --ui-axismap x2=REL_X:10,y2=REL_Y:-10,x1=KEY_LEFT:KEY_RIGHT,y1=KEY_UP:KEY_DOWN \ --ui-buttonmap a=BTN_RIGHT,b=BTN_LEFT,x=BTN_EXTRA \ --ui-buttonmap rb=KEY_5,lb=KEY_6,lt=BTN_LEFT,rt=BTN_RIGHT \ --ui-buttonmap y=KEY_ENTER,dl=KEY_4,dr=KEY_2,du=KEY_1,dd=KEY_3,back=KEY_TAB,start=KEY_ESC \ -s --deadzone 6000 --dpad-as-button --trigger-as-button [[ Testing ]] ------------- Knowing how to test a xboxdrv configuration is absolutely crucial in understanding what is wrong in a given setup. Testing the configuration in a game is most often not helpful, since you won't see the true cause beyond endless layers of abstraction between you and the actual events. Luckily there are a few tools you can use to test, all of these are command line based and it is recomment that you get familar with them when you want to do any more complex configuration. evtest: ------- evtest lets you read raw input events from (/dev/input/eventX). The event devices are the very core of all event handling, things like the joystick devices are derived from the event device, so if you want to fix some issue on the joystick device, you have to fix the event device. jstest: ------- jstest lets you read the output out of a joystick event device (/dev/input/js0). sdl-jstest: ----------- sdl-jstest lets you see events as games using SDL see them. This is very important when you want to set and test the SDL_LINUX_JOYSTICK environment variables. xev: ---- xev lets you see the events that Xorg sees. Note however that you might not see all events, since some will be grapped by your Window manager before they reach xev, this is normal. jscalc: ------- Do not use this tool, for current day joysticks it doesn't do anything useful, so don't touch it and you will be happy. missing: -------- No tools for testing the output on /dev/input/mouseX are known. Note: ----- If the tools provide no output at all, this might not be due to a wrong configuration, but due to Xorg grabbing your event device and locking it, see Xorg section for possible fixes. [[ Troubleshooting ]] --------------------- 1) "No Xbox or Xbox360 controller found" ---------------------------------------- This means that either your controller isn't plugged in or not recognized by the driver. To fix this you need to know the idVendor and the idProduct numbers, which you can find out via: % lsusb -v Once done you can try to add them to the array: XPadDevice xpad_devices[] = { ... } in xboxdrv.c. If you have success with that, send a patch to grumbel@gmx.de, if not, contact me too, I might be able to provide additional help. As an alternative you can also use the --device and --type option to enforce a USB device as well as a controller type an bypass any auto detection. 2) "Unknown data: bytes: 3 Data: ..." ------------------------------------- This means that your controller is sending data that isn't understood by the driver. If your controller still works, you can just ignore it, the Xbox360 controller seems to send out useless data every now and then. If your controller does not work and you get plenty of those lines when you move the sticks or press buttons it means that your controller talks an un-understood protocol and some reverse enginiering is required. Contact grumbel@gmx.de and include the output of: % lsusb -v Along with all the "Unknown data" lines you get. 3) Program starts and then just does nothing -------------------------------------------- This is what the program is supposed to do. After you started it will give you basically two devices, a new /dev/input/eventX and a /dev/input/jsX. You can access and test your controller with jstest and evtest applications (available from your distribution or in the tools/ subdirectory). Or in case you want just see if your driver is working correctly you can pass the -v option: % ./xboxdrv -v This will cause the driver to output all the events that it received from the controller. 4) "Error: No stuitable uinput device found" -------------------------------------------- Make sure that uinput and joydev kernel modules are loaded. Make sure that you have a /dev/input/uinput, /dev/uinput or /dev/misc/uinput and permissions to access it. Before reporting this as a bug make sure you have tested if the driver itself works with: % ./xboxdrv --no-uinput -v 5) The wireless controller doesn't work ---------------------------------------- You have to sync the controller befor it can be used, restart of the driver isn't needed and the driver should let you now when it recieves a connection after you sync the controller. # EOF #