[Patch] Xpad Keyboard emulation

Richard Osborne <[email protected]> Mon, 18 Jul 2005 12:49:50 +0100
Newsgroups gmane.linux.ports.xbox.devel
Message-ID <[email protected]>
A while ago gary ng altered the xpad module to allow keyboard emulation 
for use with his HD Cloning tools 
(http://www.geocities.com/bononochimpanzee/). This allows the directions 
on the xpad to be mapped to the cursor keys and the 'A' button to be 
mapped to enter. While this clearly isn't enough for general text entry 
it is enough to navigate through a dialog based menu system. I was 
looking for something similar and so contacted him and obtained his 
patch for this. I've since spoken to a couple of people who have also 
been interested in this so I thought I'd post it here. The attached diff 
is generated against the 2.4.31 kernel.

Richard
xpad-keyboard.diff (text/x-patch, 4.3 KB)
Index: kernel/drivers/usb/xpad-core.c
===================================================================
RCS file: /cvsroot/xbox-linux/kernel/drivers/usb/xpad-core.c,v
retrieving revision 1.18
diff -u -r1.18 xpad-core.c
--- kernel/drivers/usb/xpad-core.c	12 Mar 2005 20:05:41 -0000	1.18
+++ kernel/drivers/usb/xpad-core.c	13 Jul 2005 14:50:00 -0000
@@ -100,7 +100,7 @@
 	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 */
+	KEY_DOWN,KEY_UP,KEY_LEFT,KEY_RIGHT,KEY_ENTER,KEY_ESC,KEY_SPACE, /* keyboard simulation */
 };
 
 /* these have no analogue inputs and only 10 buttons */
@@ -109,7 +109,7 @@
 	BTN_START, BTN_BACK, 		/* start/back */
 	BTN_0, BTN_1, BTN_2, BTN_3,	/* directions, LEFT/RIGHT is mouse
 					 * so we cannot use those! */
-	-1				/* terminating entry */
+	KEY_DOWN,KEY_UP,KEY_LEFT,KEY_RIGHT,KEY_ENTER,KEY_ESC,KEY_SPACE, /* keyboard simulation */
 };
 
 static signed short xpad_abs[] = {
@@ -291,6 +291,11 @@
 	remove_proc_entry( proc_name, xpad_procdir_units );
 }
 
+static int keyboard = 101;
+
+MODULE_PARM( keyboard, "i" );
+MODULE_PARM_DESC( keyboard, "set to zero to de-activate keyboard support on insmod (default 101)" );
+
 /*********************** the actual xpad functions ********************/
 /**
  *	xpad_process_packet
@@ -306,21 +311,44 @@
 	struct input_dev *dev = &xpad->dev;
 
 	/* digital pad: 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);
-	input_report_key(dev, BTN_2, (data[2] & 0x02) >> 1);
-	input_report_key(dev, BTN_3, (data[2] & 0x04) >> 2);	
-	
-	/* start/back buttons and stick press left/right */
-	input_report_key(dev, BTN_START, (data[2] & 0x10) >> 4);
-	input_report_key(dev, BTN_BACK, (data[2] & 0x20) >> 5);
+	if (keyboard) {
+		input_report_key(dev, KEY_RIGHT, (data[2] & 0x08) >> 3);
+		input_report_key(dev, KEY_LEFT, (data[2] & 0x04) >> 2);
+		input_report_key(dev, KEY_DOWN, (data[2] & 0x02) >> 1);
+		input_report_key(dev, KEY_UP, (data[2] & 0x01));
+	} else if (keyboard < 100) {
+		input_report_key(dev, BTN_0, (data[2] & 0x01));
+		input_report_key(dev, BTN_1, (data[2] & 0x08) >> 3);
+		input_report_key(dev, BTN_2, (data[2] & 0x02) >> 1);
+		input_report_key(dev, BTN_3, (data[2] & 0x04) >> 2);
+	}
+
+	/* start and back buttons */
+	if (keyboard%100 == 2) {
+		input_report_key(dev, KEY_ENTER, (data[2] & 0x10) >> 4);
+		input_report_key(dev, KEY_ESC, (data[2] & 0x20) >> 5);
+	} else if (keyboard < 100) {
+		input_report_key(dev, BTN_START, (data[2] & 0x10) >> 4);
+		input_report_key(dev, BTN_BACK, (data[2] & 0x20) >> 5);
+	}
 	
 	/* buttons A, B, X, Y digital mode */
-	input_report_key(dev, BTN_A, data[4]);
-	input_report_key(dev, BTN_B, data[5]);
-	input_report_key(dev, BTN_X, data[6]);
-	input_report_key(dev, BTN_Y, data[7]);
-	
+	if (keyboard%100 == 1 || keyboard%100 > 3) {
+		input_report_key(dev, KEY_ENTER, data[4]);
+		input_report_key(dev, KEY_ESC, data[5]);
+	} else if (keyboard < 100) {
+		input_report_key(dev, BTN_A, data[4]);
+		input_report_key(dev, BTN_B, data[5]);
+	}
+
+	if (keyboard%100 == 3) {
+		input_report_key(dev, KEY_ENTER, data[6]);
+		input_report_key(dev, KEY_ESC, data[7]);
+	} else if (keyboard < 100) {
+		input_report_key(dev, BTN_X, data[6]);
+		input_report_key(dev, BTN_Y, data[7]);
+	}
+
 	if (xpad->isMat)
 		return;
 
@@ -342,7 +370,9 @@
 
 	/* stick press left/right */
 	input_report_key(dev, BTN_THUMBL, (data[2] & 0x40) >> 6);
+	if (keyboard) input_report_key(dev, KEY_SPACE, (data[2] & 0x40) >> 6);
 	input_report_key(dev, BTN_THUMBR, data[2] >> 7);
+	if (keyboard) input_report_key(dev, KEY_SPACE, data[2] >> 7);
 	
 	/* buttons A, B, X, Y analogue mode */
 	input_report_abs(dev, ABS_HAT1X, data[4]);
@@ -351,11 +381,11 @@
 	input_report_abs(dev, ABS_HAT3X, data[7]);
 	
 	/* button C (black) digital/analogue mode */
-	input_report_key(dev, BTN_C, data[8]);
+	if (keyboard < 100) input_report_key(dev, BTN_C, data[8]);
 	input_report_abs(dev, ABS_HAT2X, data[8]);
 
 	/* button Z (white) digital/analogue mode */
-	input_report_key(dev, BTN_Z, data[9]);
+	if (keyboard < 100) input_report_key(dev, BTN_Z, data[9]);
 	input_report_abs(dev, ABS_HAT3Y, data[9]);
 	
 	/* process input data for mouse event generation */