Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 05 Apr 2008 13:51:09 -0400
From:      Nathan Lay <nslay@comcast.net>
To:        freebsd-drivers@freebsd.org, freebsd-x11@freebsd.org
Subject:   Xbox controller S causes SIGFPE in Xorg
Message-ID:  <47F7BC0D.1090907@comcast.net>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------090803010606010008020202
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

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


--------------090803010606010008020202
Content-Type: text/plain;
 name="uxbgp_rdesc.h"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="uxbgp_rdesc.h"

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 */
};


--------------090803010606010008020202
Content-Type: text/plain;
 name="xbox.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="xbox.c"

#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;
}


--------------090803010606010008020202--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?47F7BC0D.1090907>