All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vojtech Pavlik <vojtech@suse.cz>
To: torvalds@transmeta.com, linux-kernel@vger.kernel.org
Subject: [patch] Fixes for the input (joystick, USB) drivers
Date: Thu, 26 Oct 2000 23:57:28 +0200	[thread overview]
Message-ID: <20001026235728.A6232@suse.cz> (raw)

[-- Attachment #1: Type: text/plain, Size: 1537 bytes --]

Hi!

The attached patch fixes many different little bugs in the USB input,
joystick input and core input drivers maintained by me.

drivers/char/joystick/adi.c:
	Fix gamepad handling for Logitech ThunderPad Digital and WingMan Gamepad

drivers/char/joystick/gamecon.c
	Fix PSX gamepad support - patch by Nathan Hand

drivers/char/joystick/iforce.c
	Fix breakage caused by recent usb_submit_urb() changes

drivers/char/joystick/ns558.c
	Fix the already fixed 'oops on rmmod' problem in a slightly different way
	Fix another two possible causes for 'oops on rmmod'

drivers/char/joystick/sidewinder.c
	Fix a missing button for Microsoft ForceFeedback Wheel

drivers/char/joystick/tmdc.c
	Fix the ThrustMaster FragMaster by adding specific support,
	generic support isn't good enough

drivers/input/evdev.c
	Fix two possible overflow cases.
	Add event write() support, needed badly

drivers/input/joydev.c
	Fix two possible overflow cases.
	
drivers/input/mousedev.c
	Fix two possible overflow cases.
	Change 5-button support from GenPS/2 to ImExPS/2, making it
	finally useful with XFree (which only supports ImExPS/2 5-button mice)
	Add xmax and ymax module parameters, needed for binary distribution

drivers/usb/usbkbd.c
	Fix breakage caused by recent usb_submit_urb() changes

drivers/usb/usbmouse.c
	Unify the usb_submit_urb() fix to match usbkbd, wacom and others

drivers/usb/wacom.c
	Fix the Intuos 4DMouse and Intuos Lens tool behavior (James E. Blair)

The patch is against 2.4.0-test10-pre5.

TIA.

-- 
Vojtech Pavlik
SuSE Labs

[-- Attachment #2: joybig2.diff --]
[-- Type: text/plain, Size: 35639 bytes --]

diff -urN linux-test10-pre5-old/drivers/char/joystick/adi.c linux/drivers/char/joystick/adi.c
--- linux-test10-pre5-old/drivers/char/joystick/adi.c	Thu Jun 22 15:59:58 2000
+++ linux/drivers/char/joystick/adi.c	Thu Oct 26 23:02:11 2000
@@ -1,5 +1,5 @@
 /*
- * $Id: adi.c,v 1.12 2000/06/03 20:18:52 vojtech Exp $
+ * $Id: adi.c,v 1.14 2000/10/23 07:28:57 vojtech Exp $
  *
  *  Copyright (c) 1998-2000 Vojtech Pavlik
  *
@@ -418,7 +418,7 @@
 	adi->dev.private = port;
 	adi->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
-	for (i = 0; i < adi->axes10 + adi->axes8 + adi->hats * 2; i++)
+	for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad > 0)) * 2; i++)
 		set_bit(adi->abs[i], &adi->dev.absbit);
 
 	for (i = 0; i < adi->buttons; i++)
@@ -431,7 +431,7 @@
 
 	if (!adi->length) return;
 
-	for (i = 0; i < adi->axes10 + adi->axes8 + adi->hats * 2; i++) {
+	for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad > 0)) * 2; i++) {
 
 		t = adi->abs[i];
 		x = adi->dev.abs[t];
diff -urN linux-test10-pre5-old/drivers/char/joystick/gamecon.c linux/drivers/char/joystick/gamecon.c
--- linux-test10-pre5-old/drivers/char/joystick/gamecon.c	Mon Aug 14 22:55:01 2000
+++ linux/drivers/char/joystick/gamecon.c	Thu Oct 26 23:02:11 2000
@@ -1,11 +1,11 @@
 /*
- * $Id: gamecon.c,v 1.5 2000/06/25 09:56:58 vojtech Exp $
+ * $Id: gamecon.c,v 1.10 2000/08/19 19:51:02 vojtech Exp $
  *
  *  Copyright (c) 1999-2000 Vojtech Pavlik
  *
  *  Based on the work of:
  *  	Andree Borrmann		John Dahlstrom
- *  	David Kuder
+ *  	David Kuder		Nathan Hand
  *
  *  Sponsored by SuSE
  */
@@ -75,8 +75,7 @@
 static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 };
 
 static char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick",
-				"Multisystem 2-button joystick", "N64 controller", "PSX pad",
-				"PSX NegCon", "PSX Analog contoller" };
+				"Multisystem 2-button joystick", "N64 controller", "PSX controller" };
 /*
  * N64 support.
  */
@@ -205,22 +204,30 @@
 
 /*
  * PSX support
- */
-
-#define GC_PSX_DELAY	10
-#define GC_PSX_LENGTH	8	/* talk to the controller in bytes */
+ *
+ * See documentation at:
+ *	http://www.dim.com/~mackys/psxmemcard/ps-eng2.txt
+ *	http://www.gamesx.com/controldata/psxcont/psxcont.htm
+ *	ftp://milano.usal.es/pablo/
+ *	
+ */
+
+#define GC_PSX_DELAY	60		/* 60 usec */
+#define GC_PSX_LENGTH	8		/* talk to the controller in bytes */
+
+#define GC_PSX_MOUSE	1		/* Mouse */
+#define GC_PSX_NEGCON	2		/* NegCon */
+#define GC_PSX_NORMAL	4		/* Digital / Analog or Rumble in Digital mode  */
+#define GC_PSX_ANALOG	5		/* Analog in Analog mode / Rumble in Green mode */
+#define GC_PSX_RUMBLE	7		/* Rumble in Red mode */
+
+#define GC_PSX_CLOCK	0x04		/* Pin 4 */
+#define GC_PSX_COMMAND	0x01		/* Pin 1 */
+#define GC_PSX_POWER	0xf8		/* Pins 5-9 */
+#define GC_PSX_SELECT	0x02		/* Pin 3 */
 
-#define GC_PSX_MOUSE	0x12	/* PSX Mouse */
-#define GC_PSX_NEGCON	0x23	/* NegCon pad */
-#define GC_PSX_NORMAL	0x41	/* Standard Digital controller */
-#define GC_PSX_ANALOGR	0x73	/* Analog controller in Red mode */
-#define GC_PSX_ANALOGG	0x53	/* Analog controller in Green mode */
-
-#define GC_PSX_CLOCK	0x04	/* Pin 3 */
-#define GC_PSX_COMMAND	0x01	/* Pin 1 */
-#define GC_PSX_POWER	0xf8	/* Pins 5-9 */
-#define GC_PSX_SELECT	0x02	/* Pin 2 */
-#define GC_PSX_NOPOWER  0x04
+#define GC_PSX_ID(x)	((x) >> 4)	/* High nibble is device type */
+#define GC_PSX_LEN(x)	((x) & 0xf)	/* Low nibble is length in words */
 
 static short gc_psx_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_HAT0X, ABS_HAT0Y };
 static short gc_psx_btn[] = { BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_A, BTN_B, BTN_X, BTN_Y,
@@ -233,19 +240,18 @@
 
 static int gc_psx_command(struct gc *gc, int b)
 {
-	int i, cmd, ret = 0;
+	int i, cmd, data = 0;
 
-	cmd = (b & 1) ? GC_PSX_COMMAND : 0;
-	for (i = 0; i < 8; i++) {
+	for (i = 0; i < 8; i++, b >>= 1) {
+		cmd = (b & 1) ? GC_PSX_COMMAND : 0;
 		parport_write_data(gc->pd->port, cmd | GC_PSX_POWER);
 		udelay(GC_PSX_DELAY);
-		ret |= ((parport_read_status(gc->pd->port) ^ 0x80) & gc->pads[GC_PSX]) ? (1 << i) : 0;
-		cmd = (b & 1) ? GC_PSX_COMMAND : 0;
+		if (parport_read_status(gc->pd->port) ^ 0x80) & gc->pads[GC_PSX])
+		data |= ((parport_read_status(gc->pd->port) ^ 0x80) & gc->pads[GC_PSX]) ? (1 << i) : 0;
 		parport_write_data(gc->pd->port, cmd | GC_PSX_CLOCK | GC_PSX_POWER);
 		udelay(GC_PSX_DELAY);
-		b >>= 1;
 	}
-	return ret;
+	return data;
 }
 
 /*
@@ -253,29 +259,31 @@
  * device identifier code.
  */
 
-static int gc_psx_read_packet(struct gc *gc, int length, unsigned char *data)
+static int gc_psx_read_packet(struct gc *gc, unsigned char *data)
 {
-	int i, ret;
+	int i, id;
 	unsigned long flags;
 
+	parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER);	/* Select pad */
+	udelay(GC_PSX_DELAY * 2);
+	parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_POWER);			/* Deselect, begin command */
+	udelay(GC_PSX_DELAY * 2);
+
 	__save_flags(flags);
 	__cli();
 
-	parport_write_data(gc->pd->port, GC_PSX_POWER);
-
-	parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER);	/* Select pad */
-	udelay(GC_PSX_DELAY * 2);
 	gc_psx_command(gc, 0x01);							/* Access pad */
-	ret = gc_psx_command(gc, 0x42);							/* Get device id */
-	if (gc_psx_command(gc, 0) == 'Z')						/* okay? */
-		for (i = 0; i < length; i++)
+	id = gc_psx_command(gc, 0x42);							/* Get device id */
+	if (gc_psx_command(gc, 0) == 0x5a) {						/* Okay? */
+		for (i = 0; i < GC_PSX_LEN(id) * 2; i++)
 			data[i] = gc_psx_command(gc, 0);
-	else ret = -1;
+	} else id = 0;
 
-	parport_write_data(gc->pd->port, GC_PSX_SELECT | GC_PSX_CLOCK | GC_PSX_POWER);
 	__restore_flags(flags);
 
-	return ret;
+	parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER);
+
+	return GC_PSX_ID(id);
 }
 
 /*
@@ -316,8 +324,8 @@
 				input_report_abs(dev + i, ABS_X,  axes[0]);
 				input_report_abs(dev + i, ABS_Y, -axes[1]);
 
-				input_report_abs(dev + i, ABS_HAT0X, !!(s & data[7]) - !!(s & data[6]));
-				input_report_abs(dev + i, ABS_HAT0Y, !!(s & data[5]) - !!(s & data[4]));
+				input_report_abs(dev + i, ABS_HAT0X, !(s & data[6]) - !(s & data[7]));
+				input_report_abs(dev + i, ABS_HAT0Y, !(s & data[4]) - !(s & data[5]));
 
 				for (j = 0; j < 10; j++)
 					input_report_key(dev + i, gc_n64_btn[j], s & data[gc_n64_bytes[j]]);
@@ -338,8 +346,8 @@
 			s = gc_status_bit[i];
 
 			if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) {
-				input_report_abs(dev + i, ABS_X, !!(s & data[7]) - !!(s & data[6]));
-				input_report_abs(dev + i, ABS_Y, !!(s & data[5]) - !!(s & data[4]));
+				input_report_abs(dev + i, ABS_X, ! - !(s & data[6]) - !(s & data[7]));
+				input_report_abs(dev + i, ABS_Y, ! - !(s & data[4]) - !(s & data[5]));
 			}
 
 			if (s & gc->pads[GC_NES])
@@ -365,8 +373,8 @@
 			s = gc_status_bit[i];
 
 			if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) {
-				input_report_abs(dev + i, ABS_X, !!(s & data[3]) - !!(s & data[2]));
-				input_report_abs(dev + i, ABS_Y, !!(s & data[1]) - !!(s & data[0]));
+				input_report_abs(dev + i, ABS_X,  !(s & data[2]) - !(s & data[3]));
+				input_report_abs(dev + i, ABS_Y,  !(s & data[0]) - !(s & data[1]));
 				input_report_key(dev + i, BTN_TRIGGER, s & data[4]);
 			}
 
@@ -385,37 +393,37 @@
 	       		if (gc->pads[GC_PSX] & gc_status_bit[i])
 				break;
 
- 		switch (gc_psx_read_packet(gc, 6, data)) {
+ 		switch (gc_psx_read_packet(gc, data)) {
+
+			case GC_PSX_RUMBLE:
+
+				input_report_key(dev + i, BTN_THUMB,  ~data[0] & 0x04);
+				input_report_key(dev + i, BTN_THUMB2, ~data[0] & 0x02);
+
+			case GC_PSX_NEGCON:
+			case GC_PSX_ANALOG:
 
-			case GC_PSX_ANALOGG:
-	
 				for (j = 0; j < 4; j++)
 					input_report_abs(dev + i, gc_psx_abs[j], data[j + 2]);
 
-				input_report_abs(dev + i, ABS_HAT0X, !!(data[0]&0x20) - !!(data[0]&0x80));
-				input_report_abs(dev + i, ABS_HAT0Y, !!(data[0]&0x40) - !!(data[0]&0x10));
+				input_report_abs(dev + i, ABS_HAT0X, !(data[0] & 0x20) - !(data[0] & 0x80));
+				input_report_abs(dev + i, ABS_HAT0Y, !(data[0] & 0x40) - !(data[0] & 0x10));
 
 				for (j = 0; j < 8; j++)
-					input_report_key(dev + i, gc_psx_btn[j], ~data[1] & (1 << i));
+					input_report_key(dev + i, gc_psx_btn[j], ~data[1] & (1 << j));
 
 				input_report_key(dev + i, BTN_START,  ~data[0] & 0x08);
 				input_report_key(dev + i, BTN_SELECT, ~data[0] & 0x01);
 
 				break;
 
-			case GC_PSX_ANALOGR:
-
-				input_report_key(dev + i, BTN_THUMB,  ~data[0] & 0x04);
-				input_report_key(dev + i, BTN_THUMB2, ~data[0] & 0x02);
-
 			case GC_PSX_NORMAL:
-			case GC_PSX_NEGCON:
 
-				input_report_abs(dev + i, ABS_X, 128 + !!(data[0] & 0x20) * 127 - !!(data[0] & 0x80) * 128);
-				input_report_abs(dev + i, ABS_Y, 128 + !!(data[0] & 0x40) * 127 - !!(data[0] & 0x10) * 128);
+				input_report_abs(dev + i, ABS_X, 128 + !(data[0] & 0x20) * 127 - !(data[0] & 0x80) * 128);
+				input_report_abs(dev + i, ABS_Y, 128 + !(data[0] & 0x40) * 127 - !(data[0] & 0x10) * 128);
 
 				for (j = 0; j < 8; j++)
-					input_report_key(dev + i, gc_psx_btn[j], ~data[1] & (1 << i));
+					input_report_key(dev + i, gc_psx_btn[j], ~data[1] & (1 << j));
 
 				input_report_key(dev + i, BTN_START,  ~data[0] & 0x08);
 				input_report_key(dev + i, BTN_SELECT, ~data[0] & 0x01);
@@ -448,14 +456,12 @@
 	}
 }
 
-
-
 static struct gc __init *gc_probe(int *config)
 {
 	struct gc *gc;
 	struct parport *pp;
-	int i, j, psx, pbtn;
-	unsigned char data[2];
+	int i, j, psx;
+	unsigned char data[32];
 
 	if (config[0] < 0)
 		return NULL;
@@ -545,44 +551,42 @@
 
 			case GC_PSX:
 				
-				psx = gc_psx_read_packet(gc, 2, data);
+				psx = gc_psx_read_packet(gc, data);
 
 				switch(psx) {
 					case GC_PSX_NEGCON:
-						config[i + 1] += 1;
 					case GC_PSX_NORMAL:
-						pbtn = 10;
-						break;
+					case GC_PSX_ANALOG:
+					case GC_PSX_RUMBLE:
 
-					case GC_PSX_ANALOGG:
-					case GC_PSX_ANALOGR:
-						config[i + 1] += 2;
-						pbtn = 12;
 						for (j = 0; j < 6; j++) {
 							psx = gc_psx_abs[j];
 							set_bit(psx, gc->dev[i].absbit);
-							gc->dev[i].absmin[psx] = 4;
-							gc->dev[i].absmax[psx] = 252;
-							gc->dev[i].absflat[psx] = 2;
+							if (j < 4) {
+								gc->dev[i].absmin[psx] = 4;
+								gc->dev[i].absmax[psx] = 252;
+								gc->dev[i].absflat[psx] = 2;
+							} else {
+								gc->dev[i].absmin[psx] = -1;
+								gc->dev[i].absmax[psx] = 1;
+							}
 						}
+
+						for (j = 0; j < 12; j++)
+							set_bit(gc_psx_btn[j], gc->dev[i].keybit);
+
 						break;
 
-					case -1:
+					case 0:
 						gc->pads[GC_PSX] &= ~gc_status_bit[i];
-						pbtn = 0;
 						printk(KERN_ERR "gamecon.c: No PSX controller found.\n");
 						break;
 
 					default:
 						gc->pads[GC_PSX] &= ~gc_status_bit[i];
-						pbtn = 0;
 						printk(KERN_WARNING "gamecon.c: Unsupported PSX controller %#x,"
 							" please report to <vojtech@suse.cz>.\n", psx);
 				}
-
-				for (j = 0; j < pbtn; j++)
-					set_bit(gc_psx_btn[j], gc->dev[i].keybit);
-
 				break;
 		}
 
diff -urN linux-test10-pre5-old/drivers/char/joystick/iforce.c linux/drivers/char/joystick/iforce.c
--- linux-test10-pre5-old/drivers/char/joystick/iforce.c	Tue Aug 22 20:41:14 2000
+++ linux/drivers/char/joystick/iforce.c	Thu Oct 26 23:13:29 2000
@@ -54,6 +54,7 @@
 
 struct iforce {
 	signed char data[IFORCE_MAX_LENGTH];
+	struct usb_device *usbdev;
 	struct input_dev dev;
 	struct urb irq;
 	int open;
@@ -113,9 +114,11 @@
 {
 	struct iforce *iforce = dev->private;
 
-	if (dev->idbus == BUS_USB && !iforce->open++)
+	if (dev->idbus == BUS_USB && !iforce->open++) {
+		iforce->irq.dev = iforce->usbdev;
 		if (usb_submit_urb(&iforce->irq))
 			return -EIO;
+	}
 
 	return 0;
 }
diff -urN linux-test10-pre5-old/drivers/char/joystick/ns558.c linux/drivers/char/joystick/ns558.c
--- linux-test10-pre5-old/drivers/char/joystick/ns558.c	Thu Oct 26 23:04:19 2000
+++ linux/drivers/char/joystick/ns558.c	Thu Oct 26 23:02:53 2000
@@ -1,5 +1,5 @@
 /*
- * $Id: ns558.c,v 1.16 2000/08/17 20:03:56 vojtech Exp $
+ * $Id: ns558.c,v 1.21 2000/10/18 12:29:35 vojtech Exp $
  *
  *  Copyright (c) 1999-2000 Vojtech Pavlik
  *  Copyright (c) 1999 Brian Gerst
@@ -37,6 +37,7 @@
 #include <linux/ioport.h>
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 #include <linux/gameport.h>
 #include <linux/malloc.h>
 #include <linux/isapnp.h>
@@ -47,7 +48,7 @@
 #define NS558_PNP	2
 #define NS558_PCI	3
 
-static int ns558_isa_portlist[] = { 0x201, 0x202, 0x203, 0x204, 0x205, 0x207, 0x209,
+static int ns558_isa_portlist[] = { 0x200, 0x201, 0x202, 0x203, 0x204, 0x205, 0x207, 0x209,
 				    0x20b, 0x20c, 0x20e, 0x20f, 0x211, 0x219, 0x101, 0 };
 
 struct ns558 {
@@ -58,7 +59,7 @@
 };
 	
 static struct ns558 *ns558;
-static int have_pci_devices;
+static int ns558_pci;
 
 /*
  * ns558_isa_probe() tries to find an isa gameport at the
@@ -188,12 +189,10 @@
 	}
 	memset(port, 0, sizeof(struct ns558));
 
-	port->next = ns558;
 	port->type = NS558_PCI;
 	port->gameport.io = ioport;
 	port->gameport.size = iolen;
 	port->dev = pdev;
-	ns558 = port;
 
 	pdev->driver_data = port;
 
@@ -312,13 +311,10 @@
 #endif
 
 /*
- * Probe for PCI ports.  Always probe for PCI first,
- * it is the least-invasive probe.
+ * Probe for PCI ports.
  */
 
-	i = pci_module_init(&ns558_pci_driver);
-	if (i == 0)
-		have_pci_devices = 1;
+	ns558_pci = !pci_module_init(&ns558_pci_driver);
 
 /*
  * Probe for ISA ports.
@@ -339,12 +335,15 @@
 	}
 #endif
 
-	return ns558 ? 0 : -ENODEV;
+	return (ns558 || ns558_pci) ? 0 : -ENODEV;
 }
 
 void __exit ns558_exit(void)
 {
-	struct ns558 *port = ns558;
+	struct ns558 *next, *port = ns558;
+
+	if (ns558_pci)
+		pci_unregister_driver(&ns558_pci_driver);
 
 	while (port) {
 		gameport_unregister_port(&port->gameport);
@@ -365,11 +364,10 @@
 				break;
 		}
 		
-		port = port->next;
+		next = port->next;
+		kfree(port);
+		port = next;
 	}
-
-	if (have_pci_devices)
-		pci_unregister_driver(&ns558_pci_driver);
 }
 
 module_init(ns558_init);
diff -urN linux-test10-pre5-old/drivers/char/joystick/sidewinder.c linux/drivers/char/joystick/sidewinder.c
--- linux-test10-pre5-old/drivers/char/joystick/sidewinder.c	Mon Aug 14 22:55:01 2000
+++ linux/drivers/char/joystick/sidewinder.c	Thu Oct 26 23:02:53 2000
@@ -1,5 +1,5 @@
 /*
- * $Id: sidewinder.c,v 1.16 2000/07/14 09:02:41 vojtech Exp $
+ * $Id: sidewinder.c,v 1.17 2000/10/25 09:56:09 vojtech Exp $
  *
  *  Copyright (c) 1998-2000 Vojtech Pavlik
  *
@@ -102,7 +102,7 @@
 	{ BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_SELECT },
 	{ BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_SELECT },
 	{ BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE, BTN_SELECT },
-	{ BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_THUMB2, BTN_BASE, BTN_BASE2, BTN_BASE3 }};
+	{ BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_THUMB2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4 }};
 
 static struct {
 	int x;
diff -urN linux-test10-pre5-old/drivers/char/joystick/tmdc.c linux/drivers/char/joystick/tmdc.c
--- linux-test10-pre5-old/drivers/char/joystick/tmdc.c	Wed Jun 21 17:22:21 2000
+++ linux/drivers/char/joystick/tmdc.c	Thu Oct 26 23:24:34 2000
@@ -1,5 +1,5 @@
 /*
- * $Id: tmdc.c,v 1.18 2000/06/08 19:59:59 vojtech Exp $
+ * $Id: tmdc.c,v 1.20 2000/08/25 16:28:03 vojtech Exp $
  *
  *  Copyright (c) 1998-2000 Vojtech Pavlik
  *
@@ -49,6 +49,7 @@
 
 #define TMDC_MODE_M3DI		1
 #define TMDC_MODE_3DRP		3
+#define TMDC_MODE_FM		8
 #define TMDC_MODE_FGP		163
 
 #define TMDC_BYTE_ID		10
@@ -192,6 +193,15 @@
 
 					break;
 
+				case TMDC_MODE_FM:
+
+					for (i = 0; i < 8; i++)
+						input_report_key(dev, tmdc_btn_joy[i],
+							(data[j][tmdc_byte_d[0]] >> (i + 0)) & 1);
+					for (i = 0; i < 2; i++)
+						input_report_key(dev, tmdc_btn_joy[i + 8],
+							(data[j][tmdc_byte_d[1]] >> (i + 6)) & 1);
+
 				default:
 
 					for (i = 0; i < ((data[j][TMDC_BYTE_DEF] & 0xf) << 3) && i < TMDC_BTN_JOY; i++)
@@ -239,6 +249,7 @@
 		char padbtn;
 	} models[] = {	{   1, "ThrustMaster Millenium 3D Inceptor",	  6, 0, 6,  0 },
 			{   3, "ThrustMaster Rage 3D Gamepad",		  2, 0, 0, 10 },
+			{   8, "ThrustMaster FragMaster",		  4, 0, 0, 10 },
 			{ 163, "Thrustmaster Fusion GamePad",		  2, 0, 0, 10 },
 			{   0, "Unknown %d-axis, %d-button TM device %d", 0, 0, 0,  0 }};
 	unsigned char data[2][TMDC_MAX_LENGTH];
diff -urN linux-test10-pre5-old/drivers/input/evdev.c linux/drivers/input/evdev.c
--- linux-test10-pre5-old/drivers/input/evdev.c	Fri Jul 28 03:36:54 2000
+++ linux/drivers/input/evdev.c	Thu Oct 26 23:02:53 2000
@@ -1,5 +1,5 @@
 /*
- * $Id: evdev.c,v 1.10 2000/06/23 09:23:00 vojtech Exp $
+ * $Id: evdev.c,v 1.16 2000/10/17 07:41:53 vojtech Exp $
  *
  *  Copyright (c) 1999-2000 Vojtech Pavlik
  *
@@ -123,7 +123,7 @@
 	struct evdev_list *list;
 	int i = MINOR(inode->i_rdev) - EVDEV_MINOR_BASE;
 
-	if (i > EVDEV_MINORS || !evdev_table[i])
+	if (i >= EVDEV_MINORS || !evdev_table[i])
 		return -ENODEV;
 
 	if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL)))
@@ -145,7 +145,19 @@
 
 static ssize_t evdev_write(struct file * file, const char * buffer, size_t count, loff_t *ppos)
 {
-	return -EINVAL;
+	struct evdev_list *list = file->private_data;
+	struct input_event event;
+	int retval = 0;
+
+	while (retval < count) {
+
+		if (copy_from_user(&event, buffer + retval, sizeof(struct input_event)))
+			return -EFAULT;
+		input_event(list->evdev->handle.dev, event.type, event.code, event.value);
+		retval += sizeof(struct input_event);
+	}
+
+	return retval;
 }
 
 static ssize_t evdev_read(struct file * file, char * buffer, size_t count, loff_t *ppos)
@@ -288,7 +300,7 @@
 	int minor;
 
 	for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++);
-	if (evdev_table[minor]) {
+	if (minor == EVDEV_MINORS) {
 		printk(KERN_ERR "evdev: no more free evdev devices\n");
 		return NULL;
 	}
diff -urN linux-test10-pre5-old/drivers/input/joydev.c linux/drivers/input/joydev.c
--- linux-test10-pre5-old/drivers/input/joydev.c	Tue Aug 22 18:06:31 2000
+++ linux/drivers/input/joydev.c	Thu Oct 26 23:02:53 2000
@@ -1,5 +1,5 @@
 /*
- * $Id: joydev.c,v 1.13 2000/08/14 21:05:26 vojtech Exp $
+ * $Id: joydev.c,v 1.15 2000/10/17 07:41:53 vojtech Exp $
  *
  *  Copyright (c) 1999-2000 Vojtech Pavlik 
  *  Copyright (c) 1999 Colin Van Dyke 
@@ -193,7 +193,7 @@
 	struct joydev_list *list;
 	int i = MINOR(inode->i_rdev) - JOYDEV_MINOR_BASE;
 
-	if (i > JOYDEV_MINORS || !joydev_table[i])
+	if (i >= JOYDEV_MINORS || !joydev_table[i])
 		return -ENODEV;
 
 	if (!(list = kmalloc(sizeof(struct joydev_list), GFP_KERNEL)))
@@ -395,7 +395,7 @@
 		|| test_bit(BTN_1, dev->keybit)))) return NULL; 
 
 	for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
-	if (joydev_table[minor]) {
+	if (minor == JOYDEV_MINORS) {
 		printk(KERN_ERR "joydev: no more free joydev devices\n");
 		return NULL;
 	}
diff -urN linux-test10-pre5-old/drivers/input/mousedev.c linux/drivers/input/mousedev.c
--- linux-test10-pre5-old/drivers/input/mousedev.c	Tue Aug 22 18:06:31 2000
+++ linux/drivers/input/mousedev.c	Thu Oct 26 23:02:53 2000
@@ -1,9 +1,9 @@
 /*
- * $Id: mousedev.c,v 1.15 2000/08/14 21:05:26 vojtech Exp $
+ * $Id: mousedev.c,v 1.20 2000/10/18 12:12:26 vojtech Exp $
  *
  *  Copyright (c) 1999-2000 Vojtech Pavlik
  *
- *  Input driver to PS/2 or ImPS/2 device driver module.
+ *  Input driver to ImExPS/2 device driver module.
  *
  *  Sponsored by SuSE
  */
@@ -65,20 +65,22 @@
 	signed char ps2[6];
 	unsigned long buttons;
 	unsigned char ready, buffer, bufsiz;
-	unsigned char mode, genseq, impseq;
+	unsigned char mode, imexseq, impsseq;
 };
 
-#define MOUSEDEV_GENIUS_LEN	5
-#define MOUSEDEV_IMPS_LEN	6
+#define MOUSEDEV_SEQ_LEN	6
 
-static unsigned char mousedev_genius_seq[] = { 0xe8, 3, 0xe6, 0xe6, 0xe6 };
 static unsigned char mousedev_imps_seq[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 };
+static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 };
 
 static struct input_handler mousedev_handler;
 
 static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
 static struct mousedev mousedev_mix;
 
+static int xres = CONFIG_INPUT_MOUSEDEV_SCREEN_X;
+static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y;
+
 static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
 {
 	struct mousedev *mousedevs[3] = { handle->private, &mousedev_mix, NULL };
@@ -96,12 +98,12 @@
 					switch (code) {
 						case ABS_X:	
 							size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X];
-							list->dx += (value * CONFIG_INPUT_MOUSEDEV_SCREEN_X - list->oldx) / size;
+							list->dx += (value * xres - list->oldx) / size;
 							list->oldx += list->dx * size;
 							break;
 						case ABS_Y:
 							size = handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y];
-							list->dy -= (value * CONFIG_INPUT_MOUSEDEV_SCREEN_Y - list->oldy) / size;
+							list->dy -= (value * yres - list->oldy) / size;
 							list->oldy -= list->dy * size;
 							break;
 					}
@@ -121,12 +123,12 @@
 						case BTN_TOUCH:
 						case BTN_LEFT:   index = 0; break;
 						case BTN_4:
-						case BTN_EXTRA:  if (list->mode > 1) { index = 4; break; }
+						case BTN_EXTRA:  if (list->mode == 2) { index = 4; break; }
 						case BTN_STYLUS:
 						case BTN_1:
 						case BTN_RIGHT:  index = 1; break;
 						case BTN_3:
-						case BTN_SIDE:   if (list->mode > 1) { index = 3; break; }
+						case BTN_SIDE:   if (list->mode == 2) { index = 3; break; }
 						case BTN_2:
 						case BTN_STYLUS2:
 						case BTN_MIDDLE: index = 2; break;	
@@ -213,7 +215,7 @@
 	struct mousedev_list *list;
 	int i = MINOR(inode->i_rdev) - MOUSEDEV_MINOR_BASE;
 
-	if (i > MOUSEDEV_MINORS || !mousedev_table[i])
+	if (i >= MOUSEDEV_MINORS || !mousedev_table[i])
 		return -ENODEV;
 
 	if (!(list = kmalloc(sizeof(struct mousedev_list), GFP_KERNEL)))
@@ -254,14 +256,19 @@
 	list->dy -= list->ps2[off + 2];
 	list->bufsiz = off + 3;
 
-	if (list->mode > 1)
-		list->ps2[off] |= ((list->buttons & 0x18) << 3);
+	if (list->mode == 2) {
+		list->ps2[off + 3] = (list->dz > 7 ? 7 : (list->dz < -7 ? -7 : list->dz)) & 0x0f;
+		list->dz -= list->ps2[off + 3];
+		list->ps2[off + 3] |= ((list->buttons & 0x18) << 1);
+		list->bufsiz++;
+	}
 	
-	if (list->mode) {
+	if (list->mode == 1) {
 		list->ps2[off + 3] = (list->dz > 127 ? 127 : (list->dz < -127 ? -127 : list->dz));
-		list->bufsiz++;
 		list->dz -= list->ps2[off + 3];
+		list->bufsiz++;
 	}
+
 	if (!list->dx && !list->dy && (!list->mode || !list->dz)) list->ready = 0;
 	list->buffer = list->bufsiz;
 }
@@ -277,24 +284,23 @@
 
 		c = buffer[i];
 
-		if (c == mousedev_genius_seq[list->genseq]) {
-			if (++list->genseq == MOUSEDEV_GENIUS_LEN) {
-				list->genseq = 0;
-				list->ready = 1;
+		if (c == mousedev_imex_seq[list->imexseq]) {
+			if (++list->imexseq == MOUSEDEV_SEQ_LEN) {
+				list->imexseq = 0;
 				list->mode = 2;
 			}
-		} else list->genseq = 0;
+		} else list->imexseq = 0;
 
-		if (c == mousedev_imps_seq[list->impseq]) {
-			if (++list->impseq == MOUSEDEV_IMPS_LEN) {
-				list->impseq = 0;
-				list->ready = 1;
+		if (c == mousedev_imps_seq[list->impsseq]) {
+			if (++list->impsseq == MOUSEDEV_SEQ_LEN) {
+				list->impsseq = 0;
 				list->mode = 1;
 			}
-		} else list->impseq = 0;
+		} else list->impsseq = 0;
 
 		list->ps2[0] = 0xfa;
 		list->bufsiz = 1;
+		list->ready = 1;
 
 		switch (c) {
 
@@ -303,16 +309,16 @@
 				break;
 
 			case 0xf2: /* Get ID */
-				list->ps2[1] = (list->mode == 1) ? 3 : 0;
+				switch (list->mode) {
+					case 0: list->ps2[1] = 0;
+					case 1: list->ps2[1] = 3;
+					case 2: list->ps2[1] = 4;
+				}
 				list->bufsiz = 2;
 				break;
 
 			case 0xe9: /* Get info */
-				if (list->mode == 2) {
-					list->ps2[1] = 0x00; list->ps2[2] = 0x33; list->ps2[3] = 0x55;
-				} else {
-					list->ps2[1] = 0x60; list->ps2[2] = 3; list->ps2[3] = 200;
-				}
+				list->ps2[1] = 0x60; list->ps2[2] = 3; list->ps2[3] = 200;
 				list->bufsiz = 4;
 				break;
 		}
@@ -407,7 +413,7 @@
 		return NULL;
 
 	for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
-	if (mousedev_table[minor]) {
+	if (minor == MOUSEDEV_MINORS) {
 		printk(KERN_ERR "mousedev: no more free mousedev devices\n");
 		return NULL;
 	}
@@ -487,3 +493,7 @@
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 MODULE_DESCRIPTION("Input driver to PS/2 or ImPS/2 device driver");
+MODULE_PARM(xres, "i");
+MODULE_PARM_DESC(xres, "Horizontal screen resolution");
+MODULE_PARM(yres, "i");
+MODULE_PARM_DESC(yres, "Vertical screen resolution");
diff -urN linux-test10-pre5-old/drivers/usb/usbkbd.c linux/drivers/usb/usbkbd.c
--- linux-test10-pre5-old/drivers/usb/usbkbd.c	Wed Aug 23 00:19:52 2000
+++ linux/drivers/usb/usbkbd.c	Thu Oct 26 23:11:19 2000
@@ -59,6 +59,7 @@
 
 struct usb_kbd {
 	struct input_dev dev;
+	struct usb_device *usbdev;
 	unsigned char new[8];
 	unsigned char old[8];
 	struct urb irq, led;
@@ -116,6 +117,7 @@
 		return 0;
 
 	kbd->leds = kbd->newleds;
+	kbd->led.dev = kbd->usbdev;
 	if (usb_submit_urb(&kbd->led))
 		err("usb_submit_urb(leds) failed");
 
@@ -133,6 +135,7 @@
 		return;
 
 	kbd->leds = kbd->newleds;
+	kbd->led.dev = kbd->usbdev;
 	if (usb_submit_urb(&kbd->led))
 		err("usb_submit_urb(leds) failed");
 }
@@ -144,6 +147,7 @@
 	if (kbd->open++)
 		return 0;
 
+	kbd->irq.dev = kbd->usbdev;
 	if (usb_submit_urb(&kbd->irq))
 		return -EIO;
 
@@ -186,6 +190,8 @@
 
 	if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL;
 	memset(kbd, 0, sizeof(struct usb_kbd));
+
+	kbd->usbdev = dev;
 
 	kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
 	kbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA);
diff -urN linux-test10-pre5-old/drivers/usb/usbmouse.c linux/drivers/usb/usbmouse.c
--- linux-test10-pre5-old/drivers/usb/usbmouse.c	Thu Oct 26 23:04:25 2000
+++ linux/drivers/usb/usbmouse.c	Thu Oct 26 23:10:38 2000
@@ -1,5 +1,5 @@
 /*
- * $Id: usbmouse.c,v 1.5 2000/05/29 09:01:52 vojtech Exp $
+ * $Id: usbmouse.c,v 1.6 2000/08/14 21:05:26 vojtech Exp $
  *
  *  Copyright (c) 1999-2000 Vojtech Pavlik
  *
@@ -41,9 +41,9 @@
 struct usb_mouse {
 	signed char data[8];
 	char name[128];
+	struct usb_device *usbdev;
 	struct input_dev dev;
 	struct urb irq;
-	struct usb_device *my_usb_device;	// for resubmitting my urb
 	int open;
 };
 
@@ -73,7 +73,7 @@
 	if (mouse->open++)
 		return 0;
 
-	mouse->irq.dev = mouse->my_usb_device;
+	mouse->irq.dev = mouse->usbdev;
 	if (usb_submit_urb(&mouse->irq))
 		return -EIO;
 
@@ -116,6 +116,8 @@
 	if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) return NULL;
 	memset(mouse, 0, sizeof(struct usb_mouse));
 
+	mouse->usbdev = dev;
+
 	mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
 	mouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
 	mouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
@@ -150,7 +152,6 @@
 
 	kfree(buf);
 
-	mouse->my_usb_device = dev;
 	FILL_INT_URB(&mouse->irq, dev, pipe, mouse->data, maxp > 8 ? 8 : maxp,
 		usb_mouse_irq, mouse, endpoint->bInterval);
 
diff -urN linux-test10-pre5-old/drivers/usb/wacom.c linux/drivers/usb/wacom.c
--- linux-test10-pre5-old/drivers/usb/wacom.c	Thu Oct 26 23:04:25 2000
+++ linux/drivers/usb/wacom.c	Thu Oct 26 23:27:27 2000
@@ -1,10 +1,11 @@
 /*
- * $Id: wacom.c,v 1.9 2000/05/29 09:01:52 vojtech Exp $
+ * $Id: wacom.c,v 1.11 2000/10/18 12:12:26 vojtech Exp $
  *
  *  Copyright (c) 2000 Vojtech Pavlik		<vojtech@suse.cz>
  *  Copyright (c) 2000 Andreas Bach Aaen	<abach@stofanet.dk>
  *  Copyright (c) 2000 Clifford Wolf		<clifford@clifford.at>
  *  Copyright (c) 2000 Sam Mosel		<sam.mosel@computer.org>
+ *  Copyright (c) 2000 James E. Blair		<corvus@gnu.org>
  *
  *  USB Wacom Graphire and Wacom Intuos tablet support
  *
@@ -21,23 +22,25 @@
  *	v1.8 (vp)  - Submit URB only when operating, moved to CVS,
  *			use input_report_key instead of report_btn and
  *			other cleanups
+ *	v1.11 (vp) - Add URB ->dev setting for new kernels
+ *	v1.11 (jb) - Add support for the 4D Mouse & Lens
  */
 
 /*
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or 
+ * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
+ *
  * Should you need to contact me, the author, you can do so either by
  * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
  * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
@@ -70,17 +73,17 @@
  * byte 5: Y high bits
  * byte 6: pen pressure low bits / mouse wheel
  * byte 7: pen presure high bits / mouse distance
- * 
+ *
  * There are also two single-byte feature reports (2 and 3).
  *
  * Wacom Intuos status packet:
  *
  * byte 0: report ID (2)
- * byte 1: bit7		1 - sync bit 
+ * byte 1: bit7		1 - sync bit
  *	   bit6		pointer in range
  *	   bit5		pointer type report
  *	   bit4		0 ?
- *	   bit3		0 ?
+ *	   bit3		mouse packet type
  *	   bit2		pen button2
  *	   bit1		pen button1
  *	   bit0		0 ?
@@ -88,12 +91,38 @@
  * byte 3: X low bits
  * byte 4: Y high bits
  * byte 5: Y low bits
+ *
+ * Pen packet:
+ *
  * byte 6: bits 0-7: pressure	(bits 2-9)
  * byte 7: bits 6-7: pressure	(bits 0-1)
  * byte 7: bits 0-5: X tilt	(bits 1-6)
  * byte 8: bit    7: X tilt	(bit  0)
  * byte 8: bits 0-6: Y tilt	(bits 0-6)
  * byte 9: bits 4-7: distance
+ *
+ * Mouse packet type 0:
+ *
+ * byte 6: bits 0-7: wheel	(bits 2-9)
+ * byte 7: bits 6-7: wheel	(bits 0-1)
+ * byte 7: bits 0-5: 0
+ * byte 8: bits 6-7: 0
+ * byte 8: bit    5: left extra button
+ * byte 8: bit    4: right extra button
+ * byte 8: bit    3: wheel      (sign)
+ * byte 8: bit    2: right button
+ * byte 8: bit    1: middle button
+ * byte 8: bit    0: left button
+ * byte 9: bits 4-7: distance
+ *
+ * Mouse packet type 1:
+ *
+ * byte 6: bits 0-7: rotation	(bits 2-9)
+ * byte 7: bits 6-7: rotation	(bits 0-1)
+ * byte 7: bit    5: rotation	(sign)
+ * byte 7: bits 0-4: 0
+ * byte 8: bits 0-7: 0
+ * byte 9: bits 4-7: distance
  */
 
 #define USB_VENDOR_ID_WACOM	0x056a
@@ -192,7 +221,7 @@
 			case 0x0fa: wacom->tool = BTN_TOOL_RUBBER;	break;	/* Eraser */
 			case 0x112: wacom->tool = BTN_TOOL_AIRBRUSH;	break;	/* Airbrush */
 			default:    wacom->tool = BTN_TOOL_PEN;		break;	/* Unknown tool */
-		}			
+		}	
 		input_report_key(dev, wacom->tool, 1);
 		return;
 	}
@@ -205,31 +234,63 @@
 
 	input_report_abs(dev, ABS_X, ((__u32)data[2] << 8) | data[3]);
 	input_report_abs(dev, ABS_Y, ((__u32)data[4] << 8) | data[5]);
-	input_report_abs(dev, ABS_PRESSURE, t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3));
 	input_report_abs(dev, ABS_DISTANCE, data[9] >> 4);
-	input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7));
-	input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f);
 
-	input_report_key(dev, BTN_STYLUS, data[1] & 2);
-	input_report_key(dev, BTN_STYLUS2, data[1] & 4);
-	input_report_key(dev, BTN_TOUCH, t > 10);
+	switch (wacom->tool) {
+
+		case BTN_TOOL_PENCIL:
+		case BTN_TOOL_PEN:
+		case BTN_TOOL_BRUSH:
+		case BTN_TOOL_RUBBER:
+		case BTN_TOOL_AIRBRUSH:
+
+			input_report_abs(dev, ABS_PRESSURE, t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3));
+			input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7));
+			input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f);
+			input_report_key(dev, BTN_STYLUS, data[1] & 2);
+			input_report_key(dev, BTN_STYLUS2, data[1] & 4);
+			input_report_key(dev, BTN_TOUCH, t > 10);
+			break;
+
+		case BTN_TOOL_MOUSE:
+		case BTN_TOOL_LENS:
+
+			if (data[1] & 0x02) {			/* Rotation packet */
+				input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ?
+					((__u32)data[6] << 2) | ((data[7] >> 6) & 3):
+					(-(((__u32)data[6] << 2) | ((data[7] >> 6) & 3))) - 1);
+				break;
+			}
+
+			input_report_key(dev, BTN_LEFT,   data[8] & 0x01);
+			input_report_key(dev, BTN_MIDDLE, data[8] & 0x02);
+			input_report_key(dev, BTN_RIGHT,  data[8] & 0x04);
+			input_report_key(dev, BTN_SIDE,   data[8] & 0x20);
+			input_report_key(dev, BTN_EXTRA,  data[8] & 0x10);
+			input_report_abs(dev, ABS_THROTTLE,  (data[8] & 0x08) ?
+				((__u32)data[6] << 2) | ((data[7] >> 6) & 3) :
+				-((__u32)data[6] << 2) | ((data[7] >> 6) & 3));
+			break;
+	  }
 }
 
 #define WACOM_INTUOS_TOOLS	(BIT(BTN_TOOL_BRUSH) | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS))
+#define WACOM_INTUOS_BUTTONS	(BIT(BTN_SIDE) | BIT(BTN_EXTRA))
+#define WACOM_INTUOS_ABS	(BIT(ABS_TILT_X) | BIT(ABS_TILT_Y) | BIT(ABS_RZ) | BIT(ABS_THROTTLE))
 
 struct wacom_features wacom_features[] = {
 	{ "Wacom Graphire",     0x10,  8, 10206,  7422,  511, 32, wacom_graphire_irq,
-		BIT(EV_REL), 0, BIT(REL_WHEEL), BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE), 0 },
+		BIT(EV_REL), 0, 0, 0 },
 	{ "Wacom Intuos 4x5",   0x20, 10, 12700, 10360, 1023, 15, wacom_intuos_irq,
-		0, BIT(ABS_TILT_X) | BIT(ABS_TILT_Y), 0, 0, WACOM_INTUOS_TOOLS },
+		0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
 	{ "Wacom Intuos 6x8",   0x21, 10, 20320, 15040, 1023, 15, wacom_intuos_irq,
-		0, BIT(ABS_TILT_X) | BIT(ABS_TILT_Y), 0, 0, WACOM_INTUOS_TOOLS },
+		0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
 	{ "Wacom Intuos 9x12",  0x22, 10, 30480, 23060, 1023, 15, wacom_intuos_irq,
-		0, BIT(ABS_TILT_X) | BIT(ABS_TILT_Y), 0, 0, WACOM_INTUOS_TOOLS },
+		0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
 	{ "Wacom Intuos 12x12", 0x23, 10, 30480, 30480, 1023, 15, wacom_intuos_irq,
-		0, BIT(ABS_TILT_X) | BIT(ABS_TILT_Y), 0, 0, WACOM_INTUOS_TOOLS },
+		0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
 	{ "Wacom Intuos 12x18", 0x24, 10, 47720, 30480, 1023, 15, wacom_intuos_irq,
-		0, BIT(ABS_TILT_X) | BIT(ABS_TILT_Y), 0, 0, WACOM_INTUOS_TOOLS },
+		0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
 	{ NULL , 0 }
 };
 
@@ -275,7 +336,7 @@
 	wacom->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | wacom->features->evbit;
 	wacom->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE) | wacom->features->absbit;
 	wacom->dev.relbit[0] |= wacom->features->relbit;
-	wacom->dev.keybit[LONG(BTN_LEFT)] |= wacom->features->btnbit;
+	wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | wacom->features->btnbit;
 	wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) |
 		BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2) | wacom->features->digibit;
 
@@ -285,6 +346,14 @@
 	wacom->dev.absmax[ABS_DISTANCE] = wacom->features->distance_max;
 	wacom->dev.absmax[ABS_TILT_X] = 127;
 	wacom->dev.absmax[ABS_TILT_Y] = 127;
+
+	wacom->dev.absmin[ABS_RZ] = -900;
+	wacom->dev.absmax[ABS_RZ] = 899;
+	wacom->dev.absmin[ABS_THROTTLE] = -1023;
+	wacom->dev.absmax[ABS_THROTTLE] = 1023;
+
+	wacom->dev.absfuzz[ABS_X] = 4;
+	wacom->dev.absfuzz[ABS_Y] = 4;
 
 	wacom->dev.private = wacom;
 	wacom->dev.open = wacom_open;

             reply	other threads:[~2000-10-26 21:58 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2000-10-26 21:57 Vojtech Pavlik [this message]
2000-10-27 13:17 ` mousedev uses userspace pointers without copy_{to,from}_user David Woodhouse
2000-11-01 12:58   ` Vojtech Pavlik

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20001026235728.A6232@suse.cz \
    --to=vojtech@suse.cz \
    --cc=linux-kernel@vger.kernel.org \
    --cc=torvalds@transmeta.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.