Xbox controller S causes SIGFPE in Xorg
Nathan Lay
nslay at comcast.net
Sat Apr 5 18:01:29 UTC 2008
Hey everybody,
I have a bunch of these Xbox Controller S gamepads lying around and got
a break-away <-> USB adapter. I plugged it in and at first, uhid did
not recognize the controller so I googled and found some information
about it here:
http://euc.jp/periphs/xbox-controller.ja.html
I grabbed the report descriptor there and made it into a C struct
(attached) much like the xbox360 gamepad has. I added the following
#defines in usb.h
#define UICLASS_XBOXS 0x58
#define UISUBCLASS_XBOXS_CONTROLLER 0x42
#define UIPROTO_XBOXS_GAMEPAD 0x00
I added a few lines of code uhid.c's match and attach functions (similar
to the 360 case) and voila, it attached as uhid.
So I setup an InputDevice section in xorg.conf for the joystick and
added the SendCoreEvents line to ServerLayout as noted in joystick(4x).
Everytime I launch Xorg, as soon as I touch the controller, Xorg dies
due to a SIGFPE.
To make sure everything works, I wrote a simple C program to read from
uhid (attached) and everything seems to work correctly. Where might I
look to find the SIGFPE problem?
Best Regards,
Nathan Lay
-------------- next part --------------
static const uByte uhid_xbgp_report_descr[] = {
0x05, 0x01, /* Usage Page (Generic Desktop) */
0x09, 0x05, /* Usage (Game Pad) */
0xA1, 0x01, /* Collection (Application) */
0x05, 0x01, /* Usage Page (Generic Desktop) */
0x09, 0x3A, /* Usage (Counted Buffer) ;XXX */
0xA1, 0x02, /* Collection (Logical) */
/* ; padding */
0x75, 0x08, /* Report Size (8) */
0x95, 0x01, /* Report Count (1) */
0x81, 0x01, /* Input (Constant) */
/* ; byte count */
0x75, 0x08, /* Report Size (8) */
0x95, 0x01, /* Report Count (1) */
0x05, 0x01, /* Usage Page (Generic Desktop) */
0x09, 0x3B, /* Usage (Byte Count) ;XXX */
0x81, 0x01, /* Input (Constant) */
/* ; D-pad */
0x05, 0x01, /* Usage Page (Generic Desktop) */
0x09, 0x01, /* Usage (Pointer) */
0xA1, 0x00, /* Collection (Physical) */
0x75, 0x01, /* Report Size (1) */
0x15, 0x00, /* Logical Minimum (0) */
0x25, 0x01, /* Logical Maximum (1) */
0x35, 0x00, /* Physical Minimum (0) */
0x45, 0x01, /* Physical Maximum (1) */
0x95, 0x04, /* Report Count (4) */
0x05, 0x01, /* Usage Page (Generic Desktop) */
0x09, 0x90, /* Usage (D-pad Up) */
0x09, 0x91, /* Usage (D-pad Down) */
0x09, 0x93, /* Usage (D-pad Left) */
0x09, 0x92, /* Usage (D-pad Right) */
0x81, 0x02, /* Input (Data,Variable,Absolute) */
0xC0, /* End Collection */
/* ; start, back, stick press */
0x75, 0x01, /* Report Size (1) */
0x15, 0x00, /* Logical Minimum (0) */
0x25, 0x01, /* Logical Maximum (1) */
0x35, 0x00, /* Physical Minimum (0) */
0x45, 0x01, /* Physical Maximum (1) */
0x95, 0x04, /* Report Count (4) */
0x05, 0x09, /* Usage Page (Button) */
0x19, 0x07, /* Usage Minimum (Button 7) */
0x29, 0x0A, /* Usage Maximum (Button 10) */
0x81, 0x02, /* Input (Data,Variable,Absolute) */
/* ; reserved */
0x75, 0x01, /* Report Size (1) */
0x95, 0x08, /* Report Count (8) */
0x81, 0x01, /* Input (Constant) */
/* ; analog buttons */
0x75, 0x08, /* Report Size (8) */
0x15, 0x00, /* Logical Minimum (0) */
0x26, 0xFF, 0x00, /* Logical Maximum (255) */
0x35, 0x00, /* Physical Minimum (0) */
0x46, 0xFF, 0x00, /* Physical Maximum (255) */
0x95, 0x06, /* Report Count (6) */
0x05, 0x09, /* Usage Page (Button) */
0x19, 0x01, /* Usage Minimum (Button 1) */
0x29, 0x06, /* Usage Minimum (Button 6) */
0x81, 0x02, /* Input (Data,Variable,Absolute) */
/* ; triggers */
0x75, 0x08, /* Report Size (8) */
0x15, 0x00, /* Logical Minimum (0) */
0x26, 0xFF, 0x00, /* Logical Maximum (255) */
0x35, 0x00, /* Physical Minimum (0) */
0x46, 0xFF, 0x00, /* Physical Maximum (255) */
0x95, 0x02, /* Report Count (2) */
0x05, 0x01, /* Usage Page (Generic Desktop) */
0x09, 0x32, /* Usage (Z) */
0x09, 0x35, /* Usage (Rz) */
0x81, 0x02, /* Input (Data,Variable,Absolute) */
/* ; sticks */
0x75, 0x10, /* Report Size (16) */
0x16, 0x00, 0x80, /* Logical Minimum (-32768) */
0x26, 0xFF, 0x7F, /* Logical Maximum (32767) */
0x36, 0x00, 0x80, /* Physical Minimum (-32768) */
0x46, 0xFF, 0x7F, /* Physical Maximum (32767) */
0x05, 0x01, /* Usage Page (Generic Desktop) */
0x09, 0x01, /* Usage (Pointer) */
0xA1, 0x00, /* Collection (Physical) */
0x95, 0x02, /* Report Count (2) */
0x05, 0x01, /* Usage Page (Generic Desktop) */
0x09, 0x30, /* Usage (X) */
0x09, 0x31, /* Usage (Y) ;north positive */
0x81, 0x02, /* Input (Data,Variable,Absolute) */
0xC0, /* End Collection */
0x05, 0x01, /* Usage Page (Generic Desktop) */
0x09, 0x01, /* Usage (Pointer) */
0xA1, 0x00, /* Collection (Physical) */
0x95, 0x02, /* Report Count (2) */
0x05, 0x01, /* Usage Page (Generic Desktop) */
0x09, 0x33, /* Usage (Rx) */
0x09, 0x34, /* Usage (Ry) ;north positive */
0x81, 0x02, /* Input (Data,Variable,Absolute) */
0xC0, /* End Collection */
0xC0, /* End Collection */
0x05, 0x01, /* Usage Page (Generic Desktop) */
0x09, 0x3A, /* Usage (Counted Buffer) ;XXX */
0xA1, 0x02, /* Collection (Logical) */
/* ; padding */
0x75, 0x08, /* Report Size (8) */
0x95, 0x01, /* Report Count (1) */
0x91, 0x01, /* Output (Constant) */
/* ; byte count */
0x75, 0x08, /* Report Size (8) */
0x95, 0x01, /* Report Count (1) */
0x05, 0x01, /* Usage Page (Generic Desktop) */
0x09, 0x3B, /* Usage (Byte Count) ;XXX */
0x91, 0x01, /* Output (Constant) */
/* ; padding */
0x75, 0x08, /* Report Size (8) */
0x95, 0x01, /* Report Count (1) */
0x91, 0x01, /* Output (Constant) */
/* ; left actuator */
0x75, 0x08, /* Report Size (8) */
0x15, 0x00, /* Logical Minimum (0) */
0x26, 0xFF, 0x00, /* Logical Maximum (255) */
0x35, 0x00, /* Physical Minimum (0) */
0x46, 0xFF, 0x00, /* Physical Maximum (255) */
0x95, 0x01, /* Report Count (1) */
0x06, 0x00, 0xFF, /* Usage Page (vendor-defined) */
0x09, 0x01, /* Usage (1) */
0x91, 0x02, /* Output (Data,Variable,Absolute) */
/* ; padding */
0x75, 0x08, /* Report Size (8) */
0x95, 0x01, /* Report Count (1) */
0x91, 0x01, /* Output (Constant) */
/* ; right actuator */
0x75, 0x08, /* Report Size (8) */
0x15, 0x00, /* Logical Minimum (0) */
0x26, 0xFF, 0x00, /* Logical Maximum (255) */
0x35, 0x00, /* Physical Minimum (0) */
0x46, 0xFF, 0x00, /* Physical Maximum (255) */
0x95, 0x01, /* Report Count (1) */
0x06, 0x00, 0xFF, /* Usage Page (vendor-defined) */
0x09, 0x02, /* Usage (2) */
0x91, 0x02, /* Output (Data,Variable,Absolute) */
0xC0, /* End Collection */
0xC0 /* End Collection */
};
-------------- next part --------------
#include <stdio.h>
#include <inttypes.h>
#define ARROWUP 0x01
#define ARROWDOWN 0x02
#define ARROWLEFT 0x04
#define ARROWRIGHT 0x08
#define START 0x10
#define BACK 0x20
#define LEFTJOY 0x40
#define RIGHTJOY 0x80
#define ABUTTON 4
#define BBUTTON 5
#define XBUTTON 6
#define YBUTTON 7
#define BLACKBUTTON 8
#define WHITEBUTTON 9
#define LEFTTRIGGER 10
#define RIGHTTRIGGER 11
#define LEFTJOYX 12
#define RIGHTJOYX 16
#define DEBUG
int main( int argc, char **argv ) {
unsigned long i;
uint8_t buf[20];
FILE *file = fopen( "/dev/uhid0", "r" );
if ( file == NULL ) {
perror( "fopen" );
return -1;
}
while ( !feof( file ) ) {
fread( buf, 1, sizeof(buf), file );
#ifdef DEBUG
for ( i = 0; i < sizeof(buf); ++i )
printf( "0x%02x ", buf[i] );
printf( "\n" );
#else
if ( buf[2] & ARROWUP ) printf( "UP is pressed.\n" );
if ( buf[2] & ARROWDOWN ) printf( "DOWN is pressed.\n" );
if ( buf[2] & ARROWLEFT ) printf( "LEFT is pressed.\n" );
if ( buf[2] & ARROWRIGHT ) printf( "RIGHT is pressed.\n" );
if ( buf[2] & START ) printf( "START is pressed.\n" );
if ( buf[2] & BACK ) printf( "BACK is pressed.\n" );
if ( buf[2] & LEFTJOY ) printf( "LEFTJOY is pressed.\n" );
if ( buf[2] & RIGHTJOY ) printf( "RIGHTJOY is pressed.\n" );
if ( buf[ABUTTON] ) printf( "ABUTTON is pressed with force %d.\n", buf[ABUTTON] );
if ( buf[BBUTTON] ) printf( "BBUTTON is pressed with force %d.\n", buf[BBUTTON] );
if ( buf[XBUTTON] ) printf( "XBUTTON is pressed with force %d.\n", buf[XBUTTON] );
if ( buf[YBUTTON] ) printf( "YBUTTON is pressed with force %d.\n", buf[YBUTTON] );
if ( buf[BLACKBUTTON] ) printf( "BLACKBUTTON is pressed with force %d.\n", buf[BLACKBUTTON] );
if ( buf[WHITEBUTTON] ) printf( "WHITEBUTTON is pressed with force %d.\n", buf[WHITEBUTTON] );
if ( buf[LEFTTRIGGER] ) printf( "LEFTTRIGGER is pressed with force %d.\n", buf[LEFTTRIGGER] );
if ( buf[RIGHTTRIGGER] ) printf( "RIGHTTRIGGER is pressed with force %d.\n", buf[RIGHTTRIGGER] );
printf( "LEFTJOY X = %d\tY = %d\n", *(int16_t *)(buf+LEFTJOYX), *(int16_t *)(buf+LEFTJOYX+2) );
printf( "RIGHTJOY X = %d\tY = %d\n", *(int16_t *)(buf+RIGHTJOYX), *(int16_t *)(buf+RIGHTJOYX+2) );
#endif
}
return 0;
}
More information about the freebsd-drivers
mailing list