Skip to contentSkip to conversation

Fixes for the input (joystick, USB) drivers

PATCH In review Vojtech Pavlik 2 participants 3 messages Oct 26, 2000 – Nov 1, 2000

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Fixes for the input (joystick, USB) drivers

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.

Signature · 2 lines
Vojtech Pavlik
SuSE Labs
drivers/char/joystick/adi.c +3 -3
diff -urN linux-test10-pre5-old/drivers/char/joystick/adi.c linux/drivers/char/joystick/adi.c
@@ -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];
drivers/char/joystick/gamecon.c +85 -81

293 lines not on this page · raw message

drivers/char/joystick/iforce.c +4 -1
diff -urN linux-test10-pre5-old/drivers/char/joystick/iforce.c linux/drivers/char/joystick/iforce.c
@@ -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;
 }
drivers/char/joystick/ns558.c +14 -16
diff -urN linux-test10-pre5-old/drivers/char/joystick/ns558.c linux/drivers/char/joystick/ns558.c
@@ -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);
drivers/char/joystick/sidewinder.c +2 -2
diff -urN linux-test10-pre5-old/drivers/char/joystick/sidewinder.c linux/drivers/char/joystick/sidewinder.c
@@ -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;
drivers/char/joystick/tmdc.c +12 -1
diff -urN linux-test10-pre5-old/drivers/char/joystick/tmdc.c linux/drivers/char/joystick/tmdc.c
@@ -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];
drivers/input/evdev.c +16 -4
diff -urN linux-test10-pre5-old/drivers/input/evdev.c linux/drivers/input/evdev.c
@@ -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;
 	}
drivers/input/joydev.c +3 -3
diff -urN linux-test10-pre5-old/drivers/input/joydev.c linux/drivers/input/joydev.c
@@ -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;
 	}
drivers/input/mousedev.c +42 -32

166 lines not on this page · raw message

drivers/usb/usbkbd.c +6 -0
diff -urN linux-test10-pre5-old/drivers/usb/usbkbd.c linux/drivers/usb/usbkbd.c
@@ -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);
drivers/usb/usbmouse.c +5 -4
diff -urN linux-test10-pre5-old/drivers/usb/usbmouse.c linux/drivers/usb/usbmouse.c
@@ -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);
 
drivers/usb/wacom.c +91 -22

204 lines not on this page · raw message

#1 lore raw

mousedev uses userspace pointers without copy_{to,from}_user

static ssize_t mousedev_write(struct file * file, const char * buffer, size_t count, loff_t *ppos)

{
        struct mousedev_list *list = file->private_data;
        unsigned char c;
        int i;

        for (i = 0; i < count; i++) {

                c = buffer[i];

oops. Can we make this die horribly on x86, just for a few kernel releases? Along with turning on spinlock debugging, which would have shown up the USB audio problem months ago.

--
dwmw2

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
Please read the FAQ at http://www.tux.org/lkml/

#2 lore raw

Re: mousedev uses userspace pointers without copy_{to,from}_user

In reply to Vojtech Pavlik
Quoted 13 lines · David Woodhouse

static ssize_t mousedev_write(struct file * file, const char * buffer, size_t count, loff_t *ppos)

{
        struct mousedev_list *list = file->private_data;
        unsigned char c;
        int i;

        for (i = 0; i < count; i++) {

                c = buffer[i];
Quoted 3 lines

oops. Can we make this die horribly on x86, just for a few kernel releases? Along with turning on spinlock debugging, which would have shown up the USB audio problem months ago.

Ok, fixed in the CVS, a patch for the kernel to follow soon.

Signature · 6 lines
Vojtech Pavlik
SuSE Labs
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
Please read the FAQ at http://www.tux.org/lkml/