Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

USB: xpad: dance pad support

Adds support for dance pads to the xpad driver. Dance pads require the
d-pad to be mapped to four buttons instead of two axes, so that
combinations of up/down and left/right can be hit simultaneously.
Known dance pads are detected, and there is a module parameter added
to default unknown xpad devices to map the d-pad to buttons if this is
desired. (dpad_to_buttons). Minor modifications were made to port the
changes in the original patch to a newer kernel version.

This patch was originally from Dominic Cerquetti originally written
for kernel 2.6.11.4, with minor modifications (API changes for USB,
spelling fixes to the documentation added in the original patch) made
to apply to the current kernel. I have modified Dominic's original
patch per some suggestions from Dmitry Torokhov. (There was nothing
in the patch format description about multiple From: lines, so I
haven't added myself.)

[akpm@osdl.org: cleanups]
Signed-off-by: Adam Buchbinder <adam.buchbinder@gmail.com>
Acked-by: Dmitry Torokhov <dtor@mail.ru>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Dominic Cerquetti and committed by
Greg Kroah-Hartman
deb8ee43 4550718f

+186 -68
+91 -24
Documentation/input/xpad.txt
··· 3 3 This is the very first release of a driver for X-Box gamepads. 4 4 Basically, this was hacked away in just a few hours, so don't expect 5 5 miracles. 6 + 6 7 In particular, there is currently NO support for the rumble pack. 7 8 You won't find many ff-aware linux applications anyway. 8 9 9 10 10 - 0. Status 11 - --------- 11 + 0. Notes 12 + -------- 12 13 13 - For now, this driver has only been tested on just one Linux-Box. 14 - This one is running a 2.4.18 kernel with usb-uhci on an amd athlon 600. 14 + Driver updated for kernel 2.6.17.11. (Based on a patch for 2.6.11.4.) 15 15 16 - The jstest-program from joystick-1.2.15 (jstest-version 2.1.0) reports 17 - 8 axes and 10 buttons. 16 + The number of buttons/axes reported varies based on 3 things: 17 + - if you are using a known controller 18 + - if you are using a known dance pad 19 + - if using an unknown device (one not listed below), what you set in the 20 + module configuration for "Map D-PAD to buttons rather than axes for unknown 21 + pads" (module option dpad_to_buttons) 18 22 19 - Alls 8 axes work, though they all have the same range (-32768..32767) 23 + If you set dpad_to_buttons to 0 and you are using an unknown device (one 24 + not listed below), the driver will map the directional pad to axes (X/Y), 25 + if you said N it will map the d-pad to buttons, which is needed for dance 26 + style games to function correctly. The default is Y. 27 + 28 + dpad_to_buttons has no effect for known pads. 29 + 30 + 0.1 Normal Controllers 31 + ---------------------- 32 + With a normal controller, the directional pad is mapped to its own X/Y axes. 33 + The jstest-program from joystick-1.2.15 (jstest-version 2.1.0) will report 8 34 + axes and 10 buttons. 35 + 36 + All 8 axes work, though they all have the same range (-32768..32767) 20 37 and the zero-setting is not correct for the triggers (I don't know if that 21 38 is some limitation of jstest, since the input device setup should be fine. I 22 39 didn't have a look at jstest itself yet). ··· 47 30 play first person shooters with a pad. Your mileage may vary. 48 31 49 32 33 + 0.2 Xbox Dance Pads 34 + ------------------- 35 + When using a known dance pad, jstest will report 6 axes and 14 buttons. 36 + 37 + For dance style pads (like the redoctane pad) several changes 38 + have been made. The old driver would map the d-pad to axes, resulting 39 + in the driver being unable to report when the user was pressing both 40 + left+right or up+down, making DDR style games unplayable. 41 + 42 + Known dance pads automatically map the d-pad to buttons and will work 43 + correctly out of the box. 44 + 45 + If your dance pad is recognized by the driver but is using axes instead 46 + of buttons, see section 0.3 - Unknown Controllers 47 + 48 + I've tested this with Stepmania, and it works quite well. 49 + 50 + 51 + 0.3 Unkown Controllers 52 + ---------------------- 53 + If you have an unkown xbox controller, it should work just fine with 54 + the default settings. 55 + 56 + HOWEVER if you have an unknown dance pad not listed below, it will not 57 + work UNLESS you set "dpad_to_buttons" to 1 in the module configuration. 58 + 59 + PLEASE if you have an unkown controller, email Dom <binary1230@yahoo.com> with 60 + a dump from /proc/bus/usb and a description of the pad (manufacturer, country, 61 + whether it is a dance pad or normal controller) so that we can add your pad 62 + to the list of supported devices, ensuring that it will work out of the 63 + box in the future. 64 + 65 + 50 66 1. USB adapter 51 67 -------------- 52 68 53 69 Before you can actually use the driver, you need to get yourself an 54 - adapter cable to connect the X-Box controller to your Linux-Box. 70 + adapter cable to connect the X-Box controller to your Linux-Box. You 71 + can buy these online fairly cheap, or build your own. 55 72 56 - Such a cable is pretty easy to build. The Controller itself is a USB compound 57 - device (a hub with three ports for two expansion slots and the controller 58 - device) with the only difference in a nonstandard connector (5 pins vs. 4 on 59 - standard USB connector). 73 + Such a cable is pretty easy to build. The Controller itself is a USB 74 + compound device (a hub with three ports for two expansion slots and 75 + the controller device) with the only difference in a nonstandard connector 76 + (5 pins vs. 4 on standard USB connector). 60 77 61 78 You just need to solder a USB connector onto the cable and keep the 62 79 yellow wire unconnected. The other pins have the same order on both ··· 102 51 you can still use the controller with your X-Box, if you have one ;) 103 52 104 53 105 - 2. driver installation 54 + 2. Driver Installation 106 55 ---------------------- 107 56 108 57 Once you have the adapter cable and the controller is connected, you need 109 58 to load your USB subsystem and should cat /proc/bus/usb/devices. 110 59 There should be an entry like the one at the end [4]. 111 60 112 - Currently (as of version 0.0.4), the following three devices are included: 61 + Currently (as of version 0.0.6), the following devices are included: 113 62 original Microsoft XBOX controller (US), vendor=0x045e, product=0x0202 63 + smaller Microsoft XBOX controller (US), vendor=0x045e, product=0x0289 114 64 original Microsoft XBOX controller (Japan), vendor=0x045e, product=0x0285 115 65 InterAct PowerPad Pro (Germany), vendor=0x05fd, product=0x107a 66 + RedOctane Xbox Dance Pad (US), vendor=0x0c12, product=0x8809 116 67 117 - If you have another controller that is not listed above and is not recognized 118 - by the driver, please drop me a line with the appropriate info (that is, include 119 - the name, vendor and product ID, as well as the country where you bought it; 120 - sending the whole dump out of /proc/bus/usb/devices along would be even better). 68 + The driver should work with xbox pads not listed above as well, however 69 + you will need to do something extra for dance pads to work. 121 70 122 - In theory, the driver should work with other controllers than mine 123 - (InterAct PowerPad pro, bought in Germany) just fine, but I cannot test this 124 - for I only have this one controller. 71 + If you have a controller not listed above, see 0.3 - Unknown Controllers 125 72 126 73 If you compiled and installed the driver, test the functionality: 127 74 > modprobe xpad 128 75 > modprobe joydev 129 76 > jstest /dev/js0 130 77 131 - There should be a single line showing 18 inputs (8 axes, 10 buttons), and 132 - it's values should change if you move the sticks and push the buttons. 78 + If you're using a normal controller, there should be a single line showing 79 + 18 inputs (8 axes, 10 buttons), and its values should change if you move 80 + the sticks and push the buttons. If you're using a dance pad, it should 81 + show 20 inputs (6 axes, 14 buttons). 133 82 134 - It works? Voila, your done ;) 83 + It works? Voila, you're done ;) 135 84 136 85 137 86 3. Thanks ··· 162 111 E: Ad=81(I) Atr=03(Int.) MxPS= 32 Ivl= 10ms 163 112 E: Ad=02(O) Atr=03(Int.) MxPS= 32 Ivl= 10ms 164 113 114 + 5. /proc/bus/usb/devices - dump from Redoctane Xbox Dance Pad (US): 115 + 116 + T: Bus=01 Lev=02 Prnt=09 Port=00 Cnt=01 Dev#= 10 Spd=12 MxCh= 0 117 + D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 118 + P: Vendor=0c12 ProdID=8809 Rev= 0.01 119 + S: Product=XBOX DDR 120 + C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA 121 + I: If#= 0 Alt= 0 #EPs= 2 Cls=58(unk. ) Sub=42 Prot=00 Driver=xpad 122 + E: Ad=82(I) Atr=03(Int.) MxPS= 32 Ivl=4ms 123 + E: Ad=02(O) Atr=03(Int.) MxPS= 32 Ivl=4ms 124 + 165 125 -- 166 126 Marko Friedemann <mfr@bmx-chemnitz.de> 167 127 2002-07-16 128 + - original doc 129 + 130 + Dominic Cerquetti <binary1230@yahoo.com> 131 + 2005-03-19 132 + - added stuff for dance pads, new d-pad->axes mappings
+95 -44
drivers/usb/input/xpad.c
··· 1 1 /* 2 - * X-Box gamepad - v0.0.5 2 + * X-Box gamepad - v0.0.6 3 3 * 4 4 * Copyright (c) 2002 Marko Friedemann <mfr@bmx-chemnitz.de> 5 - * 5 + * 2005 Dominic Cerquetti <binary1230@yahoo.com> 6 + * 2006 Adam Buchbinder <adam.buchbinder@gmail.com> 6 7 * 7 8 * This program is free software; you can redistribute it and/or 8 9 * modify it under the terms of the GNU General Public License as ··· 31 30 * - Greg Kroah-Hartman - usb-skeleton driver 32 31 * 33 32 * TODO: 34 - * - fine tune axes 33 + * - fine tune axes (especially trigger axes) 35 34 * - fix "analog" buttons (reported as digital now) 36 35 * - get rumble working 36 + * - need USB IDs for other dance pads 37 37 * 38 38 * History: 39 39 * ··· 59 57 #include <linux/kernel.h> 60 58 #include <linux/init.h> 61 59 #include <linux/slab.h> 60 + #include <linux/stat.h> 62 61 #include <linux/module.h> 62 + #include <linux/moduleparam.h> 63 63 #include <linux/smp_lock.h> 64 64 #include <linux/usb/input.h> 65 65 66 - #define DRIVER_VERSION "v0.0.5" 66 + #define DRIVER_VERSION "v0.0.6" 67 67 #define DRIVER_AUTHOR "Marko Friedemann <mfr@bmx-chemnitz.de>" 68 68 #define DRIVER_DESC "X-Box pad driver" 69 69 70 70 #define XPAD_PKT_LEN 32 71 71 72 + /* xbox d-pads should map to buttons, as is required for DDR pads 73 + but we map them to axes when possible to simplify things */ 74 + #define MAP_DPAD_TO_BUTTONS 0 75 + #define MAP_DPAD_TO_AXES 1 76 + #define MAP_DPAD_UNKNOWN -1 77 + 78 + static int dpad_to_buttons; 79 + module_param(dpad_to_buttons, bool, S_IRUGO); 80 + MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads"); 81 + 72 82 static const struct xpad_device { 73 83 u16 idVendor; 74 84 u16 idProduct; 75 85 char *name; 86 + u8 dpad_mapping; 76 87 } xpad_device[] = { 77 - { 0x045e, 0x0202, "Microsoft X-Box pad (US)" }, 78 - { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)" }, 79 - { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)" }, 80 - { 0x0000, 0x0000, "X-Box pad" } 88 + { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", MAP_DPAD_TO_AXES }, 89 + { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES }, 90 + { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES }, 91 + { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", MAP_DPAD_TO_AXES }, 92 + { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS }, 93 + { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN } 81 94 }; 82 95 83 96 static const signed short xpad_btn[] = { ··· 101 84 -1 /* terminating entry */ 102 85 }; 103 86 87 + /* only used if MAP_DPAD_TO_BUTTONS */ 88 + static const signed short xpad_btn_pad[] = { 89 + BTN_LEFT, BTN_RIGHT, /* d-pad left, right */ 90 + BTN_0, BTN_1, /* d-pad up, down (XXX names??) */ 91 + -1 /* terminating entry */ 92 + }; 93 + 104 94 static const signed short xpad_abs[] = { 105 95 ABS_X, ABS_Y, /* left stick */ 106 96 ABS_RX, ABS_RY, /* right stick */ 107 97 ABS_Z, ABS_RZ, /* triggers left/right */ 108 - ABS_HAT0X, ABS_HAT0Y, /* digital pad */ 98 + -1 /* terminating entry */ 99 + }; 100 + 101 + /* only used if MAP_DPAD_TO_AXES */ 102 + static const signed short xpad_abs_pad[] = { 103 + ABS_HAT0X, ABS_HAT0Y, /* d-pad axes */ 109 104 -1 /* terminating entry */ 110 105 }; 111 106 ··· 129 100 MODULE_DEVICE_TABLE (usb, xpad_table); 130 101 131 102 struct usb_xpad { 132 - struct input_dev *dev; /* input device interface */ 133 - struct usb_device *udev; /* usb device */ 103 + struct input_dev *dev; /* input device interface */ 104 + struct usb_device *udev; /* usb device */ 134 105 135 - struct urb *irq_in; /* urb for interrupt in report */ 136 - unsigned char *idata; /* input data */ 106 + struct urb *irq_in; /* urb for interrupt in report */ 107 + unsigned char *idata; /* input data */ 137 108 dma_addr_t idata_dma; 138 109 139 - char phys[65]; /* physical device path */ 110 + char phys[65]; /* physical device path */ 111 + 112 + int dpad_mapping; /* map d-pad to buttons or to axes */ 140 113 }; 141 114 142 115 /* ··· 168 137 input_report_abs(dev, ABS_RZ, data[11]); 169 138 170 139 /* digital pad */ 171 - input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); 172 - input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01)); 140 + if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) { 141 + input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); 142 + input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01)); 143 + } else /* xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS */ { 144 + input_report_key(dev, BTN_LEFT, data[2] & 0x04); 145 + input_report_key(dev, BTN_RIGHT, data[2] & 0x08); 146 + input_report_key(dev, BTN_0, data[2] & 0x01); // up 147 + input_report_key(dev, BTN_1, data[2] & 0x02); // down 148 + } 173 149 174 150 /* start/back buttons and stick press left/right */ 175 - input_report_key(dev, BTN_START, (data[2] & 0x10) >> 4); 176 - input_report_key(dev, BTN_BACK, (data[2] & 0x20) >> 5); 177 - input_report_key(dev, BTN_THUMBL, (data[2] & 0x40) >> 6); 178 - input_report_key(dev, BTN_THUMBR, data[2] >> 7); 151 + input_report_key(dev, BTN_START, data[2] & 0x10); 152 + input_report_key(dev, BTN_BACK, data[2] & 0x20); 153 + input_report_key(dev, BTN_THUMBL, data[2] & 0x40); 154 + input_report_key(dev, BTN_THUMBR, data[2] & 0x80); 179 155 180 156 /* "analog" buttons A, B, X, Y */ 181 157 input_report_key(dev, BTN_A, data[4]); ··· 244 206 usb_kill_urb(xpad->irq_in); 245 207 } 246 208 209 + static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) 210 + { 211 + set_bit(abs, input_dev->absbit); 212 + 213 + switch (abs) { 214 + case ABS_X: 215 + case ABS_Y: 216 + case ABS_RX: 217 + case ABS_RY: /* the two sticks */ 218 + input_set_abs_params(input_dev, abs, -32768, 32767, 16, 128); 219 + break; 220 + case ABS_Z: 221 + case ABS_RZ: /* the triggers */ 222 + input_set_abs_params(input_dev, abs, 0, 255, 0, 0); 223 + break; 224 + case ABS_HAT0X: 225 + case ABS_HAT0Y: /* the d-pad (only if MAP_DPAD_TO_AXES) */ 226 + input_set_abs_params(input_dev, abs, -1, 1, 0, 0); 227 + break; 228 + } 229 + } 230 + 247 231 static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) 248 232 { 249 233 struct usb_device *udev = interface_to_usbdev (intf); ··· 295 235 goto fail2; 296 236 297 237 xpad->udev = udev; 238 + xpad->dpad_mapping = xpad_device[i].dpad_mapping; 239 + if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN) 240 + xpad->dpad_mapping = dpad_to_buttons; 298 241 xpad->dev = input_dev; 299 242 usb_make_path(udev, xpad->phys, sizeof(xpad->phys)); 300 243 strlcat(xpad->phys, "/input0", sizeof(xpad->phys)); ··· 312 249 313 250 input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); 314 251 252 + /* set up buttons */ 315 253 for (i = 0; xpad_btn[i] >= 0; i++) 316 254 set_bit(xpad_btn[i], input_dev->keybit); 255 + if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) 256 + for (i = 0; xpad_btn_pad[i] >= 0; i++) 257 + set_bit(xpad_btn_pad[i], input_dev->keybit); 317 258 318 - for (i = 0; xpad_abs[i] >= 0; i++) { 319 - 320 - signed short t = xpad_abs[i]; 321 - 322 - set_bit(t, input_dev->absbit); 323 - 324 - switch (t) { 325 - case ABS_X: 326 - case ABS_Y: 327 - case ABS_RX: 328 - case ABS_RY: /* the two sticks */ 329 - input_set_abs_params(input_dev, t, -32768, 32767, 16, 128); 330 - break; 331 - case ABS_Z: 332 - case ABS_RZ: /* the triggers */ 333 - input_set_abs_params(input_dev, t, 0, 255, 0, 0); 334 - break; 335 - case ABS_HAT0X: 336 - case ABS_HAT0Y: /* the d-pad */ 337 - input_set_abs_params(input_dev, t, -1, 1, 0, 0); 338 - break; 339 - } 340 - } 259 + /* set up axes */ 260 + for (i = 0; xpad_abs[i] >= 0; i++) 261 + xpad_set_up_abs(input_dev, xpad_abs[i]); 262 + if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) 263 + for (i = 0; xpad_abs_pad[i] >= 0; i++) 264 + xpad_set_up_abs(input_dev, xpad_abs_pad[i]); 341 265 342 266 ep_irq_in = &intf->cur_altsetting->endpoint[0].desc; 343 267 usb_fill_int_urb(xpad->irq_in, udev, ··· 355 305 usb_kill_urb(xpad->irq_in); 356 306 input_unregister_device(xpad->dev); 357 307 usb_free_urb(xpad->irq_in); 358 - usb_buffer_free(interface_to_usbdev(intf), XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); 308 + usb_buffer_free(interface_to_usbdev(intf), XPAD_PKT_LEN, 309 + xpad->idata, xpad->idata_dma); 359 310 kfree(xpad); 360 311 } 361 312 }