« Return to Thread: [patch] xpad: extended xbox 360 gamepad support

Re: [patch v3] xpad: extended xbox 360 gamepad support

by Matthew Nicholson-3 :: Rate this Message:

Reply to Author | View in Thread

Improved support for the xbox 360 gamepad.  Fine tuning of the axes and
triggers and removal of unused buttons from the 360 parts driver are
included.  The behavior of the original xbox gamepad should not be
affected.

Signed-off-by: Matthew Nicholson <matt@...>
---

>>> The drivers maps the left and right stick, up and right directions to
>>> positive values, this may not be how other drivers handle this.  I
>>> was not able to confirm if this is the case or not, but at least one
>>> game I have encountered expected the Y axis to be inverted although
>>> it makes more sense the way it is now.
>>
>> Here is another stab at the patch this time with the kernel directory
>> hierarchy correct.
>
> This version of the patch swaps the right stick's X and Y axes so that
> map to the X and Y axes on the controller properly.
This version has been updated to work with the latest xbox-linux tree
code from CVS.  Led initialization has been removed as that has been
added upstream already.  I have not gotten a chance to test this one,
but all that has changed is removing the led stuff from my code.

--
Matthew A. Nicholson
matt-land.com

diff -ruN a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c
--- a/drivers/usb/input/xpad.c 2006-10-05 14:38:07.000000000 -0500
+++ b/drivers/usb/input/xpad.c 2006-10-05 14:49:00.000000000 -0500
@@ -1,4 +1,4 @@
-/*
+/* vim: set noet sw=8:
  * Xbox input device driver for Linux - v0.1.6
  *
  * Copyright (c)  2002 - 2004  Marko Friedemann <mfr@...>
@@ -12,6 +12,7 @@
  * Ivan Hawkes <blackhawk@...>
  * Edgar Hucek <hostmaster@...>
  *       Niklas Lundberg <niklas@...>
+ * Matthew Nicholson <matt@...>
  *
  *
  * This program is free software; you can redistribute it and/or
@@ -31,6 +32,7 @@
  *
  * This driver is based on:
  *  - information from     http://euc.jp/periphs/xbox-controller.en.html
+ *  - information from     http://wiki.free60.org/Gamepad
  *  - the iForce driver    drivers/char/joystick/iforce.c
  *  - the skeleton-driver  drivers/usb/usb-skeleton.c
  *
@@ -112,6 +114,13 @@
  BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, /* analogue buttons */
  BTN_START, BTN_BACK, BTN_THUMBL, BTN_THUMBR, /* start/back/sticks */
  BTN_0, BTN_1, BTN_2, BTN_3, /* d-pad as buttons */
+ -1 /* terminating entry */
+};
+
+static const signed short x360_btn[] = {
+ BTN_A, BTN_B, BTN_X, BTN_Y, /* face buttons */
+ BTN_START, BTN_BACK, BTN_THUMBL, BTN_THUMBR, /* start/back/sticks */
+ BTN_0, BTN_1, BTN_2, BTN_3, /* d-pad as buttons */
  BTN_TL, BTN_TR, /* Button LB/RB */
  BTN_MODE, /* The big X */
  -1 /* terminating entry */
@@ -135,6 +144,13 @@
  -1 /* terminating entry */
 };
 
+static const signed short x360_abs[] = {
+ ABS_X, ABS_Y, /* left stick */
+ ABS_RX, ABS_RY, /* right stick */
+ ABS_Z, ABS_RZ, /* triggers left/right */
+ -1 /* terminating entry */
+};
+
 static struct usb_device_id xpad_table [] = {
  { USB_INTERFACE_INFO('X', 'B', 0) }, /* Xbox USB-IF not approved class */
  { USB_INTERFACE_INFO( 3 ,  0 , 0) }, /* for Joytech Advanced Controller */
@@ -168,6 +184,12 @@
  printk("\n");
  }
 
+ if (xpad->is360) {
+ /* make sure this is an input report message */
+ if (data[0] != 0x00)
+ return;
+ }
+
  /* digital pad (button mode) bits (3 2 1 0) (right left down up) */
  input_report_key(dev, BTN_0, (data[2] & 0x01));
  input_report_key(dev, BTN_1, (data[2] & 0x08) >> 3);
@@ -186,8 +208,8 @@
  if(xpad->is360) {
  input_report_key(dev, BTN_A, (data[3] & 0x10) >> 4);
  input_report_key(dev, BTN_B, (data[3] & 0x20) >> 5);
- input_report_key(dev, BTN_X, (data[3] & 0x80) >> 7);
- input_report_key(dev, BTN_Y, (data[3] & 0x40) >> 6);
+ input_report_key(dev, BTN_X, (data[3] & 0x40) >> 6);
+ input_report_key(dev, BTN_Y, (data[3] & 0x80) >> 7);
  input_report_key(dev, BTN_TL, data[3] & 0x01 );
  input_report_key(dev, BTN_TR, (data[3] & 0x02) >> 1);
  input_report_key(dev, BTN_MODE, (data[3] & 0x04) >> 2);
@@ -201,19 +223,20 @@
  if (xpad->isMat)
  return;
 
- /* left stick (Y axis needs to be flipped) */
+ /* left stick */
  if(xpad->is360) {
  input_report_abs(dev, ABS_X, (__s16)(((__s16)data[7] << 8) | (__s16)data[6]));
- input_report_abs(dev, ABS_Y, ~(__s16)(((__s16)data[9] << 8) | data[8]));
+ input_report_abs(dev, ABS_Y, (__s16)(((__s16)data[9] << 8) | data[8]));
  } else {
+ /* Y axis needs to be flipped */
  input_report_abs(dev, ABS_X, (__s16)(((__s16)data[13] << 8) | (__s16)data[12]));
  input_report_abs(dev, ABS_Y, ~(__s16)(((__s16)data[15] << 8) | data[14]));
  }
 
  /* right stick */
  if(xpad->is360) {
- input_report_abs(dev, ABS_RX, (__s16)(((__s16)data[13] << 8) | (__s16)data[12]));
- input_report_abs(dev, ABS_RY, (__s16)(((__s16)data[11] << 8) | (__s16)data[10]));
+ input_report_abs(dev, ABS_RX, (__s16)(((__s16)data[11] << 8) | (__s16)data[10]));
+ input_report_abs(dev, ABS_RY, (__s16)(((__s16)data[13] << 8) | (__s16)data[12]));
  } else {
  input_report_abs(dev, ABS_RX, (__s16)(((__s16)data[17] << 8) | (__s16)data[16]));
  input_report_abs(dev, ABS_RY, (__s16)(((__s16)data[19] << 8) | (__s16)data[18]));
@@ -401,46 +424,71 @@
  set_bit(xpad_mat_btn[i], input_dev->keybit);
  } else {
  input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ if (xpad->is360) {
+ for (i = 0; x360_btn[i] >= 0; ++i)
+ set_bit(x360_btn[i], xpad->dev->keybit);
+
+ for (i = 0; x360_abs[i] >= 0; ++i) {
+ signed short t = x360_abs[i];
+
+ set_bit(t, xpad->dev->absbit);
+
+ switch (t) {
+ case ABS_X:
+ case ABS_Y:
+ case ABS_RX:
+ case ABS_RY: /* the two sticks */
+ input_set_abs_params(input_dev, t,
+ -32768, 32767, 16, 5000);
+ break;
+ case ABS_Z: /* left trigger */
+ case ABS_RZ: /* right trigger */
+ input_set_abs_params(input_dev, t,
+ -255, 255, 0, 0);
+ break;
+ }
+ }
 
- for (i = 0; xpad_btn[i] >= 0; ++i)
- set_bit(xpad_btn[i], input_dev->keybit);
-
- for (i = 0; xpad_abs[i] >= 0; ++i) {
-
- signed short t = xpad_abs[i];
-
- set_bit(t, input_dev->absbit);
-
- switch (t) {
- case ABS_X:
- case ABS_Y:
- case ABS_RX:
- case ABS_RY: /* the two sticks */
- input_set_abs_params(input_dev, t,
- -32768, 32767, 16, 12000);
- break;
- case ABS_Z: /* left trigger */
- case ABS_RZ: /* right trigger */
- case ABS_HAT1X: /* analogue button A */
- case ABS_HAT1Y: /* analogue button B */
- case ABS_HAT2X: /* analogue button C */
- case ABS_HAT2Y: /* analogue button X */
- case ABS_HAT3X: /* analogue button Y */
- case ABS_HAT3Y: /* analogue button Z */
- input_set_abs_params(input_dev, t,
- 0, 255, 0, 0);
- break;
- case ABS_HAT0X:
- case ABS_HAT0Y: /* the d-pad */
- input_set_abs_params(input_dev, t,
- -1, 1, 0, 0);
- break;
+ } else {
+ for (i = 0; xpad_btn[i] >= 0; ++i)
+ set_bit(xpad_btn[i], input_dev->keybit);
+
+ for (i = 0; xpad_abs[i] >= 0; ++i) {
+
+ signed short t = xpad_abs[i];
+
+ set_bit(t, input_dev->absbit);
+
+ switch (t) {
+ case ABS_X:
+ case ABS_Y:
+ case ABS_RX:
+ case ABS_RY: /* the two sticks */
+ input_set_abs_params(input_dev, t,
+ -32768, 32767, 16, 12000);
+ break;
+ case ABS_Z: /* left trigger */
+ case ABS_RZ: /* right trigger */
+ case ABS_HAT1X: /* analogue button A */
+ case ABS_HAT1Y: /* analogue button B */
+ case ABS_HAT2X: /* analogue button C */
+ case ABS_HAT2Y: /* analogue button X */
+ case ABS_HAT3X: /* analogue button Y */
+ case ABS_HAT3Y: /* analogue button Z */
+ input_set_abs_params(input_dev, t,
+ 0, 255, 0, 0);
+ break;
+ case ABS_HAT0X:
+ case ABS_HAT0Y: /* the d-pad */
+ input_set_abs_params(input_dev, t,
+ -1, 1, 0, 0);
+ break;
+ }
  }
- }
 
- if (!xpad->is360)
  if (xpad_rumble_probe(udev, xpad, ifnum) != 0)
  err("could not init rumble");
+ }
  }
 
  /* init input URB for USB INT transfer from device */
@@ -458,6 +506,7 @@
 
  /* Turn off the LEDs on xpad 360 controllers */
  if (xpad->is360) {
+ /* char ledcmd[] = {1, 3, 6}; /* The LED-1 on command for Xbox-360 controllers */
  char ledcmd[] = {1, 3, 0}; /* The LED-off command for Xbox-360 controllers */
      int j;
  usb_bulk_msg(udev, usb_sndintpipe(udev,2), ledcmd, 3, &j, 0);

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Xbox-linux-devel mailing list
Xbox-linux-devel@...
https://lists.sourceforge.net/lists/listinfo/xbox-linux-devel

 « Return to Thread: [patch] xpad: extended xbox 360 gamepad support