* Hotplugging for the input subsystem
@ 2001-09-28 13:07 Vojtech Pavlik
2001-09-28 16:29 ` David Brownell
2001-09-28 18:09 ` Vojtech Pavlik
0 siblings, 2 replies; 3+ messages in thread
From: Vojtech Pavlik @ 2001-09-28 13:07 UTC (permalink / raw)
To: linux-hotplug
[-- Attachment #1: Type: text/plain, Size: 540 bytes --]
Hi!
For a long time there was the problem that while upon inserting an USB
keyboard the HID driver was auto-loaded OK, the mousedev, joydev, etc
drivers were not.
This patch implements (among other things) hotplugging for the input
subsystem.
I can provide some docs if it isn't obvious how it works.
It'd be nice if someone could add support for this to the hotplug tools.
Patch attached, you can try it out, it's against 2.4.10.
Hotplug for gameport and serio subsystems will follow sometime later ...
--
Vojtech Pavlik
SuSE Labs
[-- Attachment #2: hotplug-input.diff --]
[-- Type: text/plain, Size: 197138 bytes --]
diff -urN linux-2.4.10/drivers/char/joystick/a3d.c linux/drivers/char/joystick/a3d.c
--- linux-2.4.10/drivers/char/joystick/a3d.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/a3d.c Tue Sep 25 12:45:10 2001
@@ -1,9 +1,7 @@
/*
- * $Id: a3d.c,v 1.14 2001/04/26 10:24:46 vojtech Exp $
+ * $Id: a3d.c,v 1.19 2001/09/25 10:12:07 vojtech Exp $
*
* Copyright (c) 1998-2001 Vojtech Pavlik
- *
- * Sponsored by SuSE
*/
/*
@@ -26,8 +24,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/kernel.h>
@@ -37,6 +35,10 @@
#include <linux/gameport.h>
#include <linux/input.h>
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("FP-Gaming Assasin 3D joystick driver");
+MODULE_LICENSE("GPL");
+
#define A3D_MAX_START 400 /* 400 us */
#define A3D_MAX_STROBE 60 /* 40 us */
#define A3D_DELAY_READ 3 /* 3 ms */
@@ -63,6 +65,8 @@
int used;
int reads;
int bads;
+ char phys[32];
+ char adcphys[32];
};
/*
@@ -280,10 +284,12 @@
if (!a3d->mode || a3d->mode > 5) {
printk(KERN_WARNING "a3d.c: Unknown A3D device detected "
- "(gameport%d, id=%d), contact <vojtech@suse.cz>\n", gameport->number, a3d->mode);
+ "(%s, id=%d), contact <vojtech@ucw.cz>\n", gameport->phys, a3d->mode);
goto fail2;
}
+ sprintf(a3d->phys, "%s/input0", gameport->phys);
+ sprintf(a3d->adcphys, "%s/gameport0", gameport->phys);
if (a3d->mode == A3D_MODE_PXL) {
@@ -329,11 +335,17 @@
a3d->adc.cooked_read = a3d_adc_cooked_read;
a3d->adc.fuzz = 1;
+ a3d->adc.name = a3d_names[a3d->mode];
+ a3d->adc.phys = a3d->adcphys;
+ a3d->adc.idbus = BUS_GAMEPORT;
+ a3d->adc.idvendor = GAMEPORT_ID_VENDOR_MADCATZ;
+ a3d->adc.idproduct = a3d->mode;
+ a3d->adc.idversion = 0x0100;
+
a3d_read(a3d, data);
gameport_register_port(&a3d->adc);
- printk(KERN_INFO "gameport%d: %s on gameport%d.0\n",
- a3d->adc.number, a3d_names[a3d->mode], gameport->number);
+ printk(KERN_INFO "gameport: %s on %s\n", a3d_names[a3d->mode], gameport->phys);
}
a3d->dev.private = a3d;
@@ -341,14 +353,14 @@
a3d->dev.close = a3d_close;
a3d->dev.name = a3d_names[a3d->mode];
+ a3d->dev.phys = a3d->phys;
a3d->dev.idbus = BUS_GAMEPORT;
a3d->dev.idvendor = GAMEPORT_ID_VENDOR_MADCATZ;
a3d->dev.idproduct = a3d->mode;
a3d->dev.idversion = 0x0100;
input_register_device(&a3d->dev);
- printk(KERN_INFO "input%d: %s on gameport%d.0\n",
- a3d->dev.number, a3d_names[a3d->mode], gameport->number);
+ printk(KERN_INFO "input: %s on %s\n", a3d_names[a3d->mode], a3d->phys);
return;
fail2: gameport_close(gameport);
@@ -384,5 +396,3 @@
module_init(a3d_init);
module_exit(a3d_exit);
-
-MODULE_LICENSE("GPL");
diff -urN linux-2.4.10/drivers/char/joystick/adi.c linux/drivers/char/joystick/adi.c
--- linux-2.4.10/drivers/char/joystick/adi.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/adi.c Tue Sep 25 12:45:10 2001
@@ -1,9 +1,7 @@
/*
- * $Id: adi.c,v 1.15 2001/01/09 13:32:39 vojtech Exp $
+ * $Id: adi.c,v 1.21 2001/09/25 10:12:07 vojtech Exp $
*
- * Copyright (c) 1998-2000 Vojtech Pavlik
- *
- * Sponsored by SuSE
+ * Copyright (c) 1998-2001 Vojtech Pavlik
*/
/*
@@ -26,8 +24,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/delay.h>
@@ -39,6 +37,10 @@
#include <linux/gameport.h>
#include <linux/init.h>
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Logitech ADI joystick family driver");
+MODULE_LICENSE("GPL");
+
/*
* Times, array sizes, flags, ids.
*/
@@ -55,6 +57,7 @@
#define ADI_MIN_ID_LENGTH 66
#define ADI_MAX_NAME_LENGTH 48
#define ADI_MAX_CNAME_LENGTH 16
+#define ADI_MAX_PHYS_LENGTH 32
#define ADI_FLAG_HAT 0x04
#define ADI_FLAG_10BIT 0x08
@@ -118,6 +121,7 @@
short *key;
char name[ADI_MAX_NAME_LENGTH];
char cname[ADI_MAX_CNAME_LENGTH];
+ char phys[ADI_MAX_PHYS_LENGTH];
unsigned char data[ADI_MAX_LENGTH];
};
@@ -392,7 +396,7 @@
}
}
-static void adi_init_input(struct adi *adi, struct adi_port *port)
+static void adi_init_input(struct adi *adi, struct adi_port *port, int half)
{
int i, t;
char buf[ADI_MAX_NAME_LENGTH];
@@ -403,6 +407,7 @@
sprintf(buf, adi_names[t], adi->id);
sprintf(adi->name, "Logitech %s", buf);
+ sprintf(adi->phys, "%s/input%d", port->gameport->phys, half);
adi->abs = adi_abs[t];
adi->key = adi_key[t];
@@ -411,6 +416,7 @@
adi->dev.close = adi_close;
adi->dev.name = adi->name;
+ adi->dev.phys = adi->phys;
adi->dev.idbus = BUS_GAMEPORT;
adi->dev.idvendor = GAMEPORT_ID_VENDOR_LOGITECH;
adi->dev.idproduct = adi->id;
@@ -495,7 +501,7 @@
for (i = 0; i < 2; i++) {
adi_id_decode(port->adi + i, port);
- adi_init_input(port->adi + i, port);
+ adi_init_input(port->adi + i, port, i);
}
if (!port->adi[0].length && !port->adi[1].length) {
@@ -514,8 +520,8 @@
if (port->adi[i].length > 0) {
adi_init_center(port->adi + i);
input_register_device(&port->adi[i].dev);
- printk(KERN_INFO "input%d: %s [%s] on gameport%d.%d\n",
- port->adi[i].dev.number, port->adi[i].name, port->adi[i].cname, gameport->number, i);
+ printk(KERN_INFO "input: %s [%s] on %s\n",
+ port->adi[i].name, port->adi[i].cname, gameport->phys);
}
}
@@ -553,5 +559,3 @@
module_init(adi_init);
module_exit(adi_exit);
-
-MODULE_LICENSE("GPL");
diff -urN linux-2.4.10/drivers/char/joystick/amijoy.c linux/drivers/char/joystick/amijoy.c
--- linux-2.4.10/drivers/char/joystick/amijoy.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/amijoy.c Tue Sep 25 12:45:10 2001
@@ -1,9 +1,7 @@
/*
- * $Id: amijoy.c,v 1.5 2000/07/21 22:52:24 vojtech Exp $
+ * $Id: amijoy.c,v 1.12 2001/09/25 10:12:07 vojtech Exp $
*
- * Copyright (c) 1998-2000 Vojtech Pavlik
- *
- * Sponsored by SuSE
+ * Copyright (c) 1998-2001 Vojtech Pavlik
*/
/*
@@ -26,8 +24,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/types.h>
@@ -40,13 +38,15 @@
#include <asm/system.h>
#include <asm/amigahw.h>
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Driver for Amiga joysticks");
MODULE_PARM(amijoy, "1-2i");
MODULE_LICENSE("GPL");
static int amijoy[2] = { 0, 1 };
static int amijoy_used[2] = { 0, 0 };
static struct input_dev amijoy_dev[2];
+static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" };
static char *amijoy_name = "Amiga joystick";
@@ -64,9 +64,9 @@
input_report_key(amijoy_dev + i, BTN_TRIGGER, button);
- input_report_abs(amijoy_dev + i, ABS_X, ((data >> 1) & 1) - ((data >> 9) & 1);
+ input_report_abs(amijoy_dev + i, ABS_X, ((data >> 1) & 1) - ((data >> 9) & 1));
data = ~(data ^ (data << 1));
- input_report_abs(amijoy_dev + i, ABS_Y, ((data >> 1) & 1) - ((data >> 9) & 1);
+ input_report_abs(amijoy_dev + i, ABS_Y, ((data >> 1) & 1) - ((data >> 9) & 1));
}
}
@@ -133,6 +133,7 @@
}
amijoy->dev[i].name = amijoy_name;
+ amijoy->dev[i].phys = amijoy_phys[i];
amijoy->dev[i].idbus = BUS_AMIGA;
amijoy->dev[i].idvendor = 0x0001;
amijoy->dev[i].idproduct = 0x0003;
@@ -141,7 +142,7 @@
amijoy_dev[i].private = amijoy_used + i;
input_register_device(amijoy_dev + i);
- printk(KERN_INFO "input%d: %s at joy%ddat\n", amijoy_dev[i].number, amijoy_name, i);
+ printk(KERN_INFO "input: %s at joy%ddat\n", amijoy_name, i);
}
return 0;
}
diff -urN linux-2.4.10/drivers/char/joystick/analog.c linux/drivers/char/joystick/analog.c
--- linux-2.4.10/drivers/char/joystick/analog.c Fri Sep 14 23:40:00 2001
+++ linux/drivers/char/joystick/analog.c Tue Sep 25 12:45:10 2001
@@ -1,9 +1,7 @@
/*
- * $Id: analog.c,v 1.52 2000/06/07 13:07:06 vojtech Exp $
+ * $Id: analog.c,v 1.65 2001/09/25 10:15:22 vojtech Exp $
*
- * Copyright (c) 1996-2000 Vojtech Pavlik
- *
- * Sponsored by SuSE
+ * Copyright (c) 1996-2001 Vojtech Pavlik
*/
/*
@@ -26,8 +24,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/config.h>
@@ -41,8 +39,8 @@
#include <linux/gameport.h>
#include <asm/timex.h>
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("Analog joystick and gamepad driver for Linux");
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Analog joystick and gamepad driver");
MODULE_LICENSE("GPL");
/*
@@ -95,6 +93,7 @@
#define ANALOG_FUZZ_MAGIC 36 /* 36 u*ms/loop */
#define ANALOG_MAX_NAME_LENGTH 128
+#define ANALOG_MAX_PHYS_LENGTH 32
static short analog_axes[] = { ABS_X, ABS_Y, ABS_RUDDER, ABS_THROTTLE };
static short analog_hats[] = { ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y };
@@ -111,6 +110,7 @@
int mask;
short *buttons;
char name[ANALOG_MAX_NAME_LENGTH];
+ char phys[ANALOG_MAX_PHYS_LENGTH];
};
struct analog_port {
@@ -138,7 +138,7 @@
#ifdef __i386__
#define TSC_PRESENT (test_bit(X86_FEATURE_TSC, &boot_cpu_data.x86_capability))
-#define GET_TIME(x) do { if (TSC_PRESENT) rdtscl(x); else outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8; } while (0)
+#define GET_TIME(x) do { if (TSC_PRESENT) rdtscl(x); else { outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8; } } while (0)
#define DELTA(x,y) (TSC_PRESENT?((y)-(x)):((x)-(y)+((x)<(y)?1193180L/HZ:0)))
#define TIME_NAME (TSC_PRESENT?"TSC":"PIT")
#elif __x86_64__
@@ -418,10 +418,12 @@
int i, j, t, v, w, x, y, z;
analog_name(analog);
+ sprintf(analog->phys, "%s/input%d", port->gameport->phys, index);
analog->buttons = (analog->mask & ANALOG_GAMEPAD) ? analog_pad_btn : analog_joy_btn;
analog->dev.name = analog->name;
+ analog->dev.phys = analog->phys;
analog->dev.idbus = BUS_GAMEPORT;
analog->dev.idvendor = GAMEPORT_ID_VENDOR_ANALOG;
analog->dev.idproduct = analog->mask >> 4;
@@ -491,8 +493,7 @@
input_register_device(&analog->dev);
- printk(KERN_INFO "input%d: %s at gameport%d.%d",
- analog->dev.number, analog->name, port->gameport->number, index);
+ printk(KERN_INFO "input: %s at %s", analog->name, port->gameport->phys);
if (port->cooked)
printk(" [ADC port]\n");
@@ -517,12 +518,13 @@
if ((port->mask & 3) != 3 && port->mask != 0xc) {
printk(KERN_WARNING "analog.c: Unknown joystick device found "
- "(data=%#x, gameport%d), probably not analog joystick.\n",
- port->mask, port->gameport->number);
+ "(data=%#x, %s), probably not analog joystick.\n",
+ port->mask, port->gameport->phys);
return -1;
}
- i = port->gameport->number < ANALOG_PORTS ? analog_options[port->gameport->number] : 0xff;
+
+ i = analog_options[0]; /* FIXME !!! - need to specify options for different ports */
analog[0].mask = i & 0xfffff;
@@ -602,8 +604,8 @@
gameport_trigger(gameport);
while ((gameport_read(port->gameport) & port->mask) && (v < t)) v++;
- if (v < (u >> 1) && port->gameport->number < ANALOG_PORTS) {
- analog_options[port->gameport->number] |=
+ if (v < (u >> 1)) { /* FIXME - more than one port */
+ analog_options[0] |= /* FIXME - more than one port */
ANALOG_SAITEK | ANALOG_BTNS_CHF | ANALOG_HBTN_CHF | ANALOG_HAT1_CHF;
return 0;
}
@@ -664,9 +666,9 @@
if (port->analog[i].mask)
input_unregister_device(&port->analog[i].dev);
gameport_close(gameport);
- printk(KERN_INFO "analog.c: %d out of %d reads (%d%%) on gameport%d failed\n",
+ printk(KERN_INFO "analog.c: %d out of %d reads (%d%%) on %s failed\n",
port->bads, port->reads, port->reads ? (port->bads * 100 / port->reads) : 0,
- port->gameport->number);
+ port->gameport->phys);
kfree(port);
}
diff -urN linux-2.4.10/drivers/char/joystick/cobra.c linux/drivers/char/joystick/cobra.c
--- linux-2.4.10/drivers/char/joystick/cobra.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/cobra.c Tue Sep 25 12:45:10 2001
@@ -1,13 +1,11 @@
/*
- * $Id: cobra.c,v 1.10 2000/06/08 10:23:45 vojtech Exp $
+ * $Id: cobra.c,v 1.18 2001/09/25 10:12:07 vojtech Exp $
*
- * Copyright (c) 1999-2000 Vojtech Pavlik
- *
- * Sponsored by SuSE
+ * Copyright (c) 1999-2001 Vojtech Pavlik
*/
/*
- * Creative Labd Blaster GamePad Cobra driver for Linux
+ * Creative Labs Blaster GamePad Cobra driver for Linux
*/
/*
@@ -26,8 +24,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/kernel.h>
@@ -37,6 +35,10 @@
#include <linux/gameport.h>
#include <linux/input.h>
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Creative Labs Blaster GamePad Cobra driver");
+MODULE_LICENSE("GPL");
+
#define COBRA_MAX_STROBE 45 /* 45 us max wait for first strobe */
#define COBRA_REFRESH_TIME HZ/50 /* 20 ms between reads */
#define COBRA_LENGTH 36
@@ -53,6 +55,7 @@
int reads;
int bads;
unsigned char exists;
+ char phys[2][32];
};
static unsigned char cobra_read_packet(struct gameport *gameport, unsigned int *data)
@@ -121,6 +124,7 @@
if ((r = cobra_read_packet(cobra->gameport, data)) != cobra->exists)
cobra->bads++;
+ else
for (i = 0; i < 2; i++)
if (cobra->exists & r & (1 << i)) {
@@ -177,8 +181,8 @@
for (i = 0; i < 2; i++)
if ((cobra->exists >> i) & data[i] & 1) {
- printk(KERN_WARNING "cobra.c: Device on gameport%d.%d has the Ext bit set. ID is: %d"
- " Contact vojtech@suse.cz\n", gameport->number, i, (data[i] >> 2) & 7);
+ printk(KERN_WARNING "cobra.c: Device %d on %s has the Ext bit set. ID is: %d"
+ " Contact vojtech@ucw.cz\n", i, gameport->phys, (data[i] >> 2) & 7);
cobra->exists &= ~(1 << i);
}
@@ -188,11 +192,14 @@
for (i = 0; i < 2; i++)
if ((cobra->exists >> i) & 1) {
+ sprintf(cobra->phys[i], "%s/input%d", gameport->phys, i);
+
cobra->dev[i].private = cobra;
cobra->dev[i].open = cobra_open;
cobra->dev[i].close = cobra_close;
cobra->dev[i].name = cobra_name;
+ cobra->dev[i].phys = cobra->phys[i];
cobra->dev[i].idbus = BUS_GAMEPORT;
cobra->dev[i].idvendor = GAMEPORT_ID_VENDOR_CREATIVE;
cobra->dev[i].idproduct = 0x0008;
@@ -208,11 +215,9 @@
cobra->dev[i].absmin[ABS_Y] = -1; cobra->dev[i].absmax[ABS_Y] = 1;
input_register_device(cobra->dev + i);
- printk(KERN_INFO "input%d: %s on gameport%d.%d\n",
- cobra->dev[i].number, cobra_name, gameport->number, i);
+ printk(KERN_INFO "input: %s on %s\n", cobra_name, gameport->phys);
}
-
return;
fail2: gameport_close(gameport);
fail1: kfree(cobra);
@@ -248,5 +253,3 @@
module_init(cobra_init);
module_exit(cobra_exit);
-
-MODULE_LICENSE("GPL");
diff -urN linux-2.4.10/drivers/char/joystick/cs461x.c linux/drivers/char/joystick/cs461x.c
--- linux-2.4.10/drivers/char/joystick/cs461x.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/cs461x.c Tue Sep 25 12:45:10 2001
@@ -25,8 +25,6 @@
#define CS461X_FULL_MAP
*/
-#define COOKED_MODE
-
#ifndef PCI_VENDOR_ID_CIRRUS
#define PCI_VENDOR_ID_CIRRUS 0x1013
@@ -122,6 +120,9 @@
static unsigned long ba0_addr;
static unsigned int *ba0;
+static char phys[32];
+static char name[] = "CS416x Gameport";
+
#ifdef CS461X_FULL_MAP
static unsigned long ba1_addr;
static union ba1_t {
@@ -206,14 +207,11 @@
static int cs461x_gameport_open(struct gameport *gameport, int mode)
{
switch (mode) {
-#ifdef COOKED_MODE
- case GAMEPORT_MODE_COOKED:
- return 0;
-#endif
- case GAMEPORT_MODE_RAW:
- return 0;
- default:
- return -1;
+ case GAMEPORT_MODE_COOKED:
+ case GAMEPORT_MODE_RAW:
+ return 0;
+ default:
+ return -1;
}
return 0;
}
@@ -274,9 +272,7 @@
return -ENOMEM;
}
#endif
- printk(KERN_INFO "CS461x PCI: %lx[%d]\n",
- ba0_addr, CS461X_BA0_SIZE);
-
+
if (!(port = kmalloc(sizeof(struct gameport), GFP_KERNEL))) {
printk(KERN_ERR "Memory allocation failed.\n");
cs461x_free(pdev);
@@ -287,19 +283,25 @@
pdev->driver_data = port;
port->open = cs461x_gameport_open;
- port->read = cs461x_gameport_read;
port->trigger = cs461x_gameport_trigger;
-#ifdef COOKED_MODE
+ port->read = cs461x_gameport_read;
port->cooked_read = cs461x_gameport_cooked_read;
-#endif
+
+ sprintf(phys, "pci%s/gameport0", pdev->slot_name);
+
+ port->name = name;
+ port->phys = phys;
+ port->idbus = BUS_PCI;
+ port->idvendor = pdev->vendor;
+ port->idproduct = pdev->device;
cs461x_pokeBA0(BA0_JSIO, 0xFF); // ?
cs461x_pokeBA0(BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW);
gameport_register_port(port);
- printk(KERN_INFO "gameport%d: CS461x Gameport speed %d kHz\n",
- port->number, port->speed);
+ printk(KERN_INFO "gameport: %s on pci%s speed %d kHz\n",
+ name, pdev->slot_name, port->speed);
return 0;
}
@@ -310,22 +312,22 @@
}
static struct pci_driver cs461x_pci_driver = {
- name: "PCI Gameport",
+ name: "CS461x Gameport",
id_table: cs461x_pci_tbl,
probe: cs461x_pci_probe,
remove: cs461x_pci_remove,
};
-int __init js_cs461x_init(void)
+int __init cs461x_init(void)
{
return pci_module_init(&cs461x_pci_driver);
}
-void __exit js_cs461x_exit(void)
+void __exit cs461x_exit(void)
{
pci_unregister_driver(&cs461x_pci_driver);
}
-module_init(js_cs461x_init);
-module_exit(js_cs461x_exit);
+module_init(cs461x_init);
+module_exit(cs461x_exit);
diff -urN linux-2.4.10/drivers/char/joystick/db9.c linux/drivers/char/joystick/db9.c
--- linux-2.4.10/drivers/char/joystick/db9.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/db9.c Tue Sep 25 12:45:10 2001
@@ -1,12 +1,10 @@
/*
- * $Id: db9.c,v 1.6 2000/06/25 10:57:50 vojtech Exp $
+ * $Id: db9.c,v 1.11 2001/09/25 10:12:07 vojtech Exp $
*
- * Copyright (c) 1999 Vojtech Pavlik
+ * Copyright (c) 1999-2001 Vojtech Pavlik
*
* Based on the work of:
* Andree Borrmann Mats Sjövall
- *
- * Sponsored by SuSE
*/
/*
@@ -29,8 +27,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/kernel.h>
@@ -40,8 +38,10 @@
#include <linux/parport.h>
#include <linux/input.h>
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver");
MODULE_LICENSE("GPL");
+
MODULE_PARM(db9, "2i");
MODULE_PARM(db9_2, "2i");
MODULE_PARM(db9_3, "2i");
@@ -87,6 +87,7 @@
struct pardevice *pd;
int mode;
int used;
+ char phys[2][32];
};
static struct db9 *db9_base[3];
@@ -342,11 +343,14 @@
for (i = 0; i < 1 + (db9->mode == DB9_MULTI_0802_2); i++) {
+ sprintf(db9->phys[i], "%s/input%d", db9->pd->port->name, i);
+
db9->dev[i].private = db9;
db9->dev[i].open = db9_open;
db9->dev[i].close = db9_close;
db9->dev[i].name = db9_name[db9->mode];
+ db9->dev[i].phys = db9->phys[i];
db9->dev[i].idbus = BUS_PARPORT;
db9->dev[i].idvendor = 0x0002;
db9->dev[i].idproduct = config[1];
@@ -362,8 +366,7 @@
db9->dev[i].absmin[ABS_Y] = -1; db9->dev[i].absmax[ABS_Y] = 1;
input_register_device(db9->dev + i);
- printk(KERN_INFO "input%d: %s on %s\n",
- db9->dev[i].number, db9_name[db9->mode], db9->pd->port->name);
+ printk(KERN_INFO "input: %s on %s\n", db9->dev[i].name, db9->pd->port->name);
}
return db9;
diff -urN linux-2.4.10/drivers/char/joystick/emu10k1-gp.c linux/drivers/char/joystick/emu10k1-gp.c
--- linux-2.4.10/drivers/char/joystick/emu10k1-gp.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/emu10k1-gp.c Tue Sep 25 12:45:10 2001
@@ -1,9 +1,7 @@
/*
- * $Id: emu10k1-gp.c,v 1.2 2001/04/24 07:48:56 vojtech Exp $
+ * $Id: emu10k1-gp.c,v 1.6 2001/09/25 10:12:07 vojtech Exp $
*
* Copyright (c) 2001 Vojtech Pavlik
- *
- * Sponsored by SuSE
*/
/*
@@ -27,7 +25,7 @@
*
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <asm/io.h>
@@ -41,6 +39,7 @@
#include <linux/pci.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("EMU10k1 gameport driver");
MODULE_LICENSE("GPL");
struct emu {
@@ -48,6 +47,7 @@
struct emu *next;
struct gameport gameport;
int size;
+ char phys[32];
};
static struct pci_device_id emu_tbl[] __devinitdata = {
@@ -59,49 +59,53 @@
static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- int ioport, iolen;
- int rc;
- struct emu *port;
+ int ioemu, iolen;
+ struct emu *emu;
- rc = pci_enable_device(pdev);
- if (rc) {
- printk(KERN_ERR "emu10k1-gp: Cannot enable emu10k1 gameport (bus %d, devfn %d) error=%d\n",
- pdev->bus->number, pdev->devfn, rc);
- return rc;
- }
+ if (pci_enable_device(pdev))
+ return -EBUSY;
- ioport = pci_resource_start(pdev, 0);
+ ioemu = pci_resource_start(pdev, 0);
iolen = pci_resource_len(pdev, 0);
- if (!request_region(ioport, iolen, "emu10k1-gp"))
+ if (!request_region(ioemu, iolen, "emu10k1-gp"))
return -EBUSY;
- if (!(port = kmalloc(sizeof(struct emu), GFP_KERNEL))) {
+ if (!(emu = kmalloc(sizeof(struct emu), GFP_KERNEL))) {
printk(KERN_ERR "emu10k1-gp: Memory allocation failed.\n");
- release_region(ioport, iolen);
+ release_region(ioemu, iolen);
return -ENOMEM;
}
- memset(port, 0, sizeof(struct emu));
+ memset(emu, 0, sizeof(struct emu));
+
+ sprintf(emu->phys, "pci%s/gameport0", pdev->slot_name);
+
+ emu->size = iolen;
+ emu->dev = pdev;
+
+ emu->gameport.io = ioemu;
+ emu->gameport.name = pdev->name;
+ emu->gameport.phys = emu->phys;
+ emu->gameport.idbus = BUS_PCI;
+ emu->gameport.idvendor = pdev->vendor;
+ emu->gameport.idproduct = pdev->device;
- port->gameport.io = ioport;
- port->size = iolen;
- port->dev = pdev;
- pdev->driver_data = port;
+ pdev->driver_data = emu;
- gameport_register_port(&port->gameport);
+ gameport_register_port(&emu->gameport);
- printk(KERN_INFO "gameport%d: Emu10k1 Gameport at %#x size %d speed %d kHz\n",
- port->gameport.number, port->gameport.io, iolen, port->gameport.speed);
+ printk(KERN_INFO "gameport: %s at pci%s speed %d kHz\n",
+ pdev->name, pdev->slot_name, emu->gameport.speed);
return 0;
}
static void __devexit emu_remove(struct pci_dev *pdev)
{
- struct emu *port = (struct emu *)pdev->driver_data;
- gameport_unregister_port(&port->gameport);
- release_region(port->gameport.io, port->size);
- kfree(port);
+ struct emu *emu = (void *)pdev->driver_data;
+ gameport_unregister_port(&emu->gameport);
+ release_region(emu->gameport.io, emu->size);
+ kfree(emu);
}
static struct pci_driver emu_driver = {
diff -urN linux-2.4.10/drivers/char/joystick/gamecon.c linux/drivers/char/joystick/gamecon.c
--- linux-2.4.10/drivers/char/joystick/gamecon.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/gamecon.c Tue Sep 25 12:45:10 2001
@@ -1,17 +1,15 @@
/*
- * $Id: gamecon.c,v 1.14 2001/04/29 22:42:14 vojtech Exp $
+ * $Id: gamecon.c,v 1.20 2001/09/25 10:12:07 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*
* Based on the work of:
* Andree Borrmann John Dahlstrom
* David Kuder Nathan Hand
- *
- * Sponsored by SuSE
*/
/*
- * NES, SNES, N64, Multi1, Multi2, PSX gamepad driver for Linux
+ * NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux
*/
/*
@@ -30,8 +28,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/kernel.h>
@@ -41,8 +39,10 @@
#include <linux/parport.h>
#include <linux/input.h>
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver");
MODULE_LICENSE("GPL");
+
MODULE_PARM(gc, "2-6i");
MODULE_PARM(gc_2,"2-6i");
MODULE_PARM(gc_3,"2-6i");
@@ -65,6 +65,7 @@
struct timer_list timer;
unsigned char pads[GC_MAX + 1];
int used;
+ char phys[5][32];
};
static struct gc *gc_base[3];
@@ -585,12 +586,15 @@
default:
gc->pads[GC_PSX] &= ~gc_status_bit[i];
printk(KERN_WARNING "gamecon.c: Unsupported PSX controller %#x,"
- " please report to <vojtech@suse.cz>.\n", psx);
+ " please report to <vojtech@ucw.cz>.\n", psx);
}
break;
}
+ sprintf(gc->phys[i], "%s/input%d", gc->pd->port->name, i);
+
gc->dev[i].name = gc_names[config[i + 1]];
+ gc->dev[i].phys = gc->phys[i];
gc->dev[i].idbus = BUS_PARPORT;
gc->dev[i].idvendor = 0x0001;
gc->dev[i].idproduct = config[i + 1];
@@ -608,7 +612,7 @@
for (i = 0; i < 5; i++)
if (gc->pads[0] & gc_status_bit[i]) {
input_register_device(gc->dev + i);
- printk(KERN_INFO "input%d: %s on %s\n", gc->dev[i].number, gc->dev[i].name, gc->pd->port->name);
+ printk(KERN_INFO "input: %s on %s\n", gc->dev[i].name, gc->pd->port->name);
}
return gc;
diff -urN linux-2.4.10/drivers/char/joystick/gameport.c linux/drivers/char/joystick/gameport.c
--- linux-2.4.10/drivers/char/joystick/gameport.c Fri Sep 14 23:40:00 2001
+++ linux/drivers/char/joystick/gameport.c Tue Sep 25 12:45:10 2001
@@ -1,9 +1,7 @@
/*
- * $Id: gameport.c,v 1.5 2000/05/29 10:54:53 vojtech Exp $
+ * $Id: gameport.c,v 1.17 2001/09/25 10:12:07 vojtech Exp $
*
- * Copyright (c) 1999-2000 Vojtech Pavlik
- *
- * Sponsored by SuSE
+ * Copyright (c) 1999-2001 Vojtech Pavlik
*/
/*
@@ -26,8 +24,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <asm/io.h>
@@ -40,7 +38,8 @@
#include <linux/stddef.h>
#include <linux/delay.h>
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Generic gameport layer");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(gameport_register_port);
@@ -54,7 +53,6 @@
static struct gameport *gameport_list;
static struct gameport_dev *gameport_dev;
-static int gameport_number;
/*
* gameport_measure_speed() measures the gameport i/o speed.
@@ -122,7 +120,6 @@
void gameport_register_port(struct gameport *gameport)
{
- gameport->number = gameport_number++;
gameport->next = gameport_list;
gameport_list = gameport;
@@ -140,8 +137,6 @@
if (gameport->dev && gameport->dev->disconnect)
gameport->dev->disconnect(gameport);
-
- gameport_number--;
}
void gameport_register_device(struct gameport_dev *dev)
diff -urN linux-2.4.10/drivers/char/joystick/gf2k.c linux/drivers/char/joystick/gf2k.c
--- linux-2.4.10/drivers/char/joystick/gf2k.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/gf2k.c Tue Sep 25 12:45:10 2001
@@ -1,9 +1,7 @@
/*
- * $Id: gf2k.c,v 1.12 2000/06/04 14:53:44 vojtech Exp $
+ * $Id: gf2k.c,v 1.18 2001/09/25 10:12:07 vojtech Exp $
*
- * Copyright (c) 1998-2000 Vojtech Pavlik
- *
- * Sponsored by SuSE
+ * Copyright (c) 1998-2001 Vojtech Pavlik
*/
/*
@@ -26,8 +24,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/delay.h>
@@ -38,6 +36,10 @@
#include <linux/input.h>
#include <linux/gameport.h>
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Genius Flight 2000 joystick driver");
+MODULE_LICENSE("GPL");
+
#define GF2K_START 400 /* The time we wait for the first bit [400 us] */
#define GF2K_STROBE 40 /* The time we wait for the first bit [40 us] */
#define GF2K_TIMEOUT 4 /* Wait for everything to settle [4 ms] */
@@ -85,6 +87,7 @@
int used;
unsigned char id;
unsigned char length;
+ char phys[32];
};
/*
@@ -278,11 +281,13 @@
#endif
if (gf2k->id > GF2K_ID_MAX || !gf2k_axes[gf2k->id]) {
- printk(KERN_WARNING "gf2k.c: Not yet supported joystick on gameport%d. [id: %d type:%s]\n",
- gameport->number, gf2k->id, gf2k->id > GF2K_ID_MAX ? "Unknown" : gf2k_names[gf2k->id]);
+ printk(KERN_WARNING "gf2k.c: Not yet supported joystick on %s. [id: %d type:%s]\n",
+ gameport->phys, gf2k->id, gf2k->id > GF2K_ID_MAX ? "Unknown" : gf2k_names[gf2k->id]);
goto fail2;
}
+ sprintf(gf2k->phys, "%s/input0", gameport->phys);
+
gf2k->length = gf2k_lens[gf2k->id];
gf2k->dev.private = gf2k;
@@ -291,6 +296,7 @@
gf2k->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
gf2k->dev.name = gf2k_names[gf2k->id];
+ gf2k->dev.phys = gf2k->phys;
gf2k->dev.idbus = BUS_GAMEPORT;
gf2k->dev.idvendor = GAMEPORT_ID_VENDOR_GENIUS;
gf2k->dev.idproduct = gf2k->id;
@@ -323,8 +329,7 @@
}
input_register_device(&gf2k->dev);
- printk(KERN_INFO "input%d: %s on gameport%d.0\n",
- gf2k->dev.number, gf2k_names[gf2k->id], gameport->number);
+ printk(KERN_INFO "input: %s on %s\n", gf2k_names[gf2k->id], gameport->phys);
return;
fail2: gameport_close(gameport);
@@ -357,5 +362,3 @@
module_init(gf2k_init);
module_exit(gf2k_exit);
-
-MODULE_LICENSE("GPL");
diff -urN linux-2.4.10/drivers/char/joystick/grip.c linux/drivers/char/joystick/grip.c
--- linux-2.4.10/drivers/char/joystick/grip.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/grip.c Tue Sep 25 12:45:10 2001
@@ -1,9 +1,7 @@
/*
- * $Id: grip.c,v 1.14 2000/06/06 21:13:36 vojtech Exp $
+ * $Id: grip.c,v 1.20 2001/09/25 10:12:07 vojtech Exp $
*
- * Copyright (c) 1998-2000 Vojtech Pavlik
- *
- * Sponsored by SuSE
+ * Copyright (c) 1998-2001 Vojtech Pavlik
*/
/*
@@ -26,8 +24,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/kernel.h>
@@ -37,6 +35,10 @@
#include <linux/gameport.h>
#include <linux/input.h>
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Gravis GrIP protocol joystick driver");
+MODULE_LICENSE("GPL");
+
#define GRIP_MODE_GPP 1
#define GRIP_MODE_BD 2
#define GRIP_MODE_XT 3
@@ -59,6 +61,7 @@
int used;
int reads;
int bads;
+ char phys[2][32];
};
static int grip_btn_gpp[] = { BTN_START, BTN_SELECT, BTN_TR2, BTN_Y, 0, BTN_TL2, BTN_A, BTN_B, BTN_X, 0, BTN_TL, BTN_TR, -1 };
@@ -340,12 +343,15 @@
for (i = 0; i < 2; i++)
if (grip->mode[i]) {
+ sprintf(grip->phys[i], "%s/input%d", gameport->phys, i);
+
grip->dev[i].private = grip;
grip->dev[i].open = grip_open;
grip->dev[i].close = grip_close;
grip->dev[i].name = grip_name[grip->mode[i]];
+ grip->dev[i].phys = grip->phys[i];
grip->dev[i].idbus = BUS_GAMEPORT;
grip->dev[i].idvendor = GAMEPORT_ID_VENDOR_GRAVIS;
grip->dev[i].idproduct = grip->mode[i];
@@ -382,8 +388,8 @@
input_register_device(grip->dev + i);
- printk(KERN_INFO "input%d: %s on gameport%d.%d\n",
- grip->dev[i].number, grip_name[grip->mode[i]], gameport->number, i);
+ printk(KERN_INFO "input: %s on %s\n",
+ grip_name[grip->mode[i]], gameport->phys);
}
return;
@@ -421,5 +427,3 @@
module_init(grip_init);
module_exit(grip_exit);
-
-MODULE_LICENSE("GPL");
diff -urN linux-2.4.10/drivers/char/joystick/iforce.c linux/drivers/char/joystick/iforce.c
--- linux-2.4.10/drivers/char/joystick/iforce.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/iforce.c Tue Sep 25 12:45:10 2001
@@ -1,12 +1,10 @@
/*
- * $Id: iforce.c,v 1.56 2001/05/27 14:41:26 jdeneux Exp $
+ * $Id: iforce.c,v 1.82 2001/09/25 10:12:07 vojtech Exp $
*
- * Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz>
* Copyright (c) 2001 Johann Deneux <deneux@ifrance.com>
*
* USB/RS232 I-Force joysticks and wheels.
- *
- * Sponsored by SuSE
*/
/*
@@ -25,8 +23,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/kernel.h>
@@ -38,6 +36,10 @@
#include <linux/usb.h>
#include <linux/serio.h>
#include <linux/config.h>
+#include <linux/circ_buf.h>
+#include <asm/semaphore.h>
+
+#include "usbpath.h"
/* FF: This module provides arbitrary resource management routines.
* I use it to manage the device's memory.
@@ -45,7 +47,7 @@
*/
#include <linux/ioport.h>
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>, Johann Deneux <deneux@ifrance.com>");
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>, Johann Deneux <deneux@ifrance.com>");
MODULE_DESCRIPTION("USB/RS232 I-Force joysticks and wheels driver");
MODULE_LICENSE("GPL");
@@ -66,14 +68,23 @@
#define FF_MOD1_IS_USED 0
#define FF_MOD2_IS_USED 1
#define FF_CORE_IS_USED 2
-#define FF_CORE_IS_PLAYED 3
-#define FF_MODCORE_MAX 3
+#define FF_CORE_IS_PLAYED 3 /* Effect is actually being played */
+#define FF_CORE_SHOULD_PLAY 4 /* User wants the effect to be played */
+#define FF_CORE_UPDATE 5 /* Effect is being updated */
+#define FF_MODCORE_MAX 5
+
+#define CHECK_OWNERSHIP(i, iforce) \
+ ((i) < FF_EFFECTS_MAX && i >= 0 && \
+ test_bit(FF_CORE_IS_USED, (iforce)->core_effects[(i)].flags) && \
+ (current->pid == 0 || \
+ (iforce)->core_effects[(i)].owner == current->pid))
struct iforce_core_effect {
/* Information about where modifiers are stored in the device's memory */
struct resource mod1_chunk;
struct resource mod2_chunk;
unsigned long flags[NBITS(FF_MODCORE_MAX)];
+ pid_t owner;
};
#define FF_CMD_EFFECT 0x010e
@@ -89,10 +100,19 @@
#define FF_CMD_QUERY 0xff01
+/* Buffer for async write */
+#define XMIT_SIZE 256
+#define XMIT_INC(var, n) (var)+=n; (var)&= XMIT_SIZE -1
+/* iforce::xmit_flags */
+#define IFORCE_XMIT_RUNNING 0
+#define IFORCE_XMIT_AGAIN 1
+
static signed short btn_joystick[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE,
BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_BASE5, BTN_A, BTN_B, BTN_C, BTN_DEAD, -1 };
static signed short btn_wheel[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE,
BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_BASE5, BTN_A, BTN_B, BTN_C, -1 };
+static signed short btn_avb_tw[] = { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE,
+ BTN_BASE2, BTN_BASE3, BTN_BASE4, -1 };
static signed short abs_joystick[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 };
static signed short abs_wheel[] = { ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_HAT0X, ABS_HAT0Y, -1 };
static signed short ff_iforce[] = { FF_PERIODIC, FF_CONSTANT, FF_SPRING, FF_FRICTION,
@@ -106,10 +126,13 @@
signed short *abs;
signed short *ff;
} iforce_device[] = {
+ { 0x044f, 0xa01c, "Thrustmaster Motor Sport GT", btn_wheel, abs_wheel, ff_iforce },
{ 0x046d, 0xc281, "Logitech WingMan Force", btn_joystick, abs_joystick, ff_iforce },
+ { 0x046d, 0xc285, "Logitech WingMan Strike Force 3D", btn_joystick, abs_joystick, ff_iforce },
{ 0x046d, 0xc291, "Logitech WingMan Formula Force", btn_wheel, abs_wheel, ff_iforce },
{ 0x05ef, 0x020a, "AVB Top Shot Pegasus", btn_joystick, abs_joystick, ff_iforce },
{ 0x05ef, 0x8884, "AVB Mag Turbo Force", btn_wheel, abs_wheel, ff_iforce },
+ { 0x05ef, 0x8888, "AVB Top Shot Force Feedback Racing Wheel", btn_avb_tw, abs_wheel, ff_iforce },
{ 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce },
{ 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce }
};
@@ -118,6 +141,7 @@
struct input_dev dev; /* Input device interface */
struct iforce_device *type;
char name[64];
+ char phys[64];
int open;
int bus;
@@ -136,10 +160,17 @@
struct urb irq, out, ctrl;
devrequest dr;
#endif
+ spinlock_t xmit_lock;
+ /* Buffer used for asynchronous sending of bytes to the device */
+ struct circ_buf xmit;
+ unsigned char xmit_data[XMIT_SIZE];
+ long xmit_flags[1];
+
/* Force Feedback */
wait_queue_head_t wait;
struct resource device_memory;
struct iforce_core_effect core_effects[FF_EFFECTS_MAX];
+ struct semaphore mem_mutex;
};
static struct {
@@ -154,6 +185,10 @@
/* Encode a time value */
#define TIME_SCALE(a) ((a) == 0xffff ? 0xffff : (a) * 1000 / 256)
+/* Forward declarations */
+static int iforce_erase_effect(struct input_dev *dev, int effect_id);
+static int iforce_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
+
static void dump_packet(char *msg, u16 cmd, unsigned char *data)
{
int i;
@@ -164,71 +199,203 @@
printk(")\n");
}
-/*
- * Send a packet of bytes to the device
- */
-static void send_packet(struct iforce *iforce, u16 cmd, unsigned char* data)
+#ifdef IFORCE_USB
+static void iforce_usb_xmit(struct iforce *iforce)
{
- switch (iforce->bus) {
+ int n, c;
+ unsigned long flags;
+
+ spin_lock_irqsave(&iforce->xmit_lock, flags);
+
+ if (iforce->xmit.head == iforce->xmit.tail) {
+ spin_unlock_irqrestore(&iforce->xmit_lock, flags);
+ return;
+ }
+
+ ((char *)iforce->out.transfer_buffer)[0] = iforce->xmit.buf[iforce->xmit.tail];
+ XMIT_INC(iforce->xmit.tail, 1);
+ n = iforce->xmit.buf[iforce->xmit.tail];
+ XMIT_INC(iforce->xmit.tail, 1);
+
+ iforce->out.transfer_buffer_length = n + 2;
+ iforce->out.dev = iforce->usbdev;
+
+ /* Copy rest of data then */
+ c = CIRC_CNT_TO_END(iforce->xmit.head, iforce->xmit.tail, XMIT_SIZE);
+ if (n < c) c=n;
+
+ memcpy(iforce->out.transfer_buffer + 1,
+ &iforce->xmit.buf[iforce->xmit.tail],
+ c);
+ if (n != c) {
+ memcpy(iforce->out.transfer_buffer + 1 + c,
+ &iforce->xmit.buf[0],
+ n-c);
+ }
+ XMIT_INC(iforce->xmit.tail, n);
+
+ if ( (n=usb_submit_urb(&iforce->out)) ) {
+ printk(KERN_WARNING "iforce.c: iforce_usb_xmit: usb_submit_urb failed %d\n", n);
+ }
+
+ spin_unlock_irqrestore(&iforce->xmit_lock, flags);
+}
+#endif
#ifdef IFORCE_232
- case IFORCE_232: {
+static void iforce_serial_xmit(struct iforce *iforce)
+{
+ unsigned char cs;
+ int i;
+ unsigned long flags;
- int i;
- unsigned char csum = 0x2b ^ HI(cmd) ^ LO(cmd);
+ if (test_and_set_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags)) {
+ set_bit(IFORCE_XMIT_AGAIN, iforce->xmit_flags);
+ return;
+ }
- serio_write(iforce->serio, 0x2b);
- serio_write(iforce->serio, HI(cmd));
- serio_write(iforce->serio, LO(cmd));
-
- for (i = 0; i < LO(cmd); i++) {
- serio_write(iforce->serio, data[i]);
- csum = csum ^ data[i];
- }
+ spin_lock_irqsave(&iforce->xmit_lock, flags);
+
+again:
+ if (iforce->xmit.head == iforce->xmit.tail) {
+ clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
+ spin_unlock_irqrestore(&iforce->xmit_lock, flags);
+ return;
+ }
+
+ cs = 0x2b;
+
+ serio_write(iforce->serio, 0x2b);
+
+ serio_write(iforce->serio, iforce->xmit.buf[iforce->xmit.tail]);
+ cs ^= iforce->xmit.buf[iforce->xmit.tail];
+ XMIT_INC(iforce->xmit.tail, 1);
+
+ for (i=iforce->xmit.buf[iforce->xmit.tail]; i >= 0; --i) {
+ serio_write(iforce->serio, iforce->xmit.buf[iforce->xmit.tail]);
+ cs ^= iforce->xmit.buf[iforce->xmit.tail];
+ XMIT_INC(iforce->xmit.tail, 1);
+ }
+
+ serio_write(iforce->serio, cs);
+
+ if (test_and_clear_bit(IFORCE_XMIT_AGAIN, iforce->xmit_flags))
+ goto again;
+
+ clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
+
+ spin_unlock_irqrestore(&iforce->xmit_lock, flags);
+}
+
+static void iforce_serio_write_wakeup(struct serio *serio)
+{
+ iforce_serial_xmit((struct iforce *)serio->private);
+}
- serio_write(iforce->serio, csum);
- return;
- }
#endif
-#ifdef IFORCE_USB
- case IFORCE_USB: {
- DECLARE_WAITQUEUE(wait, current);
- int timeout = HZ; /* 1 second */
+/*
+ * Send a packet of bytes to the device
+ */
+static void send_packet(struct iforce *iforce, u16 cmd, unsigned char* data)
+{
+ /* Copy data to buffer */
+ int n = LO(cmd);
+ int c;
+ int empty;
+ int head, tail;
+ unsigned long flags;
+
+/*
+ * Update head and tail of xmit buffer
+ */
+ spin_lock_irqsave(&iforce->xmit_lock, flags);
+
+ head = iforce->xmit.head;
+ tail = iforce->xmit.tail;
+
+ if (CIRC_SPACE(head, tail, XMIT_SIZE) < n+2) {
+ printk(KERN_WARNING "iforce.c: not enough space in xmit buffer to send new packet\n");
+ spin_unlock_irqrestore(&iforce->xmit_lock, flags);
+ return;
+ }
- memcpy(iforce->out.transfer_buffer + 1, data, LO(cmd));
- ((char*)iforce->out.transfer_buffer)[0] = HI(cmd);
- iforce->out.transfer_buffer_length = LO(cmd) + 2;
- iforce->out.dev = iforce->usbdev;
+ empty = head == tail;
+ XMIT_INC(iforce->xmit.head, n+2);
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&iforce->wait, &wait);
+ spin_unlock_irqrestore(&iforce->xmit_lock, flags);
- if (usb_submit_urb(&iforce->out)) {
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&iforce->wait, &wait);
- return;
- }
- while (timeout && iforce->out.status == -EINPROGRESS)
- timeout = schedule_timeout(timeout);
+/*
+ * Store packet in xmit buffer
+ */
+ iforce->xmit.buf[head] = HI(cmd);
+ XMIT_INC(head, 1);
+ iforce->xmit.buf[head] = LO(cmd);
+ XMIT_INC(head, 1);
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&iforce->wait, &wait);
+ c = CIRC_SPACE_TO_END(head, tail, XMIT_SIZE);
+ if (n < c) c=n;
- if (!timeout)
- usb_unlink_urb(&iforce->out);
+ memcpy(&iforce->xmit.buf[head],
+ data,
+ c);
+ if (n != c) {
+ memcpy(&iforce->xmit.buf[0],
+ data,
+ n - c);
+ }
+ XMIT_INC(head, n);
- return;
+/*
+ * If necessary, start the transmission
+ */
+ switch (iforce->bus) {
+
+#ifdef IFORCE_232
+ case IFORCE_232:
+ if (empty)
+ iforce_serial_xmit(iforce);
+ break;
+#endif
+#ifdef IFORCE_USB
+ case IFORCE_USB:
+
+ if (empty & !iforce->out.status) {
+ iforce_usb_xmit(iforce);
}
+ break;
#endif
}
}
+/* Mark an effect that was being updated as ready. That means it can be updated
+ * again */
+static int mark_core_as_ready(struct iforce *iforce, unsigned short addr)
+{
+ int i;
+ for (i=0; i<iforce->dev.ff_effects_max; ++i) {
+ if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags) &&
+ (iforce->core_effects[i].mod1_chunk.start == addr ||
+ iforce->core_effects[i].mod2_chunk.start == addr)) {
+ clear_bit(FF_CORE_UPDATE, iforce->core_effects[i].flags);
+printk(KERN_DEBUG "iforce.c: marked effect %d as ready\n", i);
+ return 0;
+ }
+ }
+ printk(KERN_DEBUG "iforce.c: unused effect %04x updated !!!\n", addr);
+ return -1;
+}
+
static void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data)
{
struct input_dev *dev = &iforce->dev;
int i;
+ static int being_used = 0;
+
+ if (being_used)
+ printk(KERN_WARNING "iforce.c: re-entrant call to iforce_process %d\n", being_used);
+ being_used++;
#ifdef IFORCE_232
if (HI(iforce->expect_packet) == HI(cmd)) {
@@ -267,10 +434,39 @@
break;
case 0x02: /* status report */
-
input_report_key(dev, BTN_DEAD, data[0] & 0x02);
+
+ /* Check if an effect was just started or stopped */
+ i = data[1] & 0x7f;
+ if (data[1] & 0x80) {
+ if (!test_and_set_bit(FF_CORE_IS_PLAYED, iforce->core_effects[i].flags)) {
+ /* Report play event */
+ input_report_ff_status(dev, i, FF_STATUS_PLAYING);
+printk(KERN_DEBUG "iforce.c: effect %d started to play\n", i);
+ }
+ }
+ else {
+ if (!test_bit(FF_CORE_SHOULD_PLAY, iforce->core_effects[i].flags)) {
+ if (test_and_clear_bit(FF_CORE_IS_PLAYED, iforce->core_effects[i].flags)) {
+ /* Report stop event */
+ input_report_ff_status(dev, i, FF_STATUS_STOPPED);
+printk(KERN_DEBUG "iforce.c: effect %d stopped to play\n", i);
+ }
+ }
+ else {
+printk(KERN_WARNING "iforce.c: effect %d stopped, while it should not\nStarting again\n", i);
+ }
+ }
+ if (LO(cmd) > 3) {
+ int j;
+ for (j=3; j<LO(cmd); j+=2) {
+ if (mark_core_as_ready(iforce, data[j] | (data[j+1]<<8)))
+ dump_packet("ff status", cmd, data);
+ }
+ }
break;
}
+ being_used--;
}
static int get_id_packet(struct iforce *iforce, char *packet)
@@ -350,6 +546,34 @@
break;
#endif
}
+
+ /* Reset device */
+ send_packet(iforce, FF_CMD_ENABLE, "\004");
+
+ return 0;
+}
+
+static int iforce_flush(struct input_dev *dev, struct file *file)
+{
+ struct iforce *iforce = dev->private;
+ int i;
+
+ /* Erase all effects this process owns */
+ for (i=0; i<dev->ff_effects_max; ++i) {
+
+ if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags) &&
+ current->pid == iforce->core_effects[i].owner) {
+
+ /* Stop effect */
+ iforce_input_event(dev, EV_FF, i, 0);
+
+ /* Free ressources assigned to effect */
+ if (iforce_erase_effect(dev, i)) {
+ printk(KERN_WARNING "iforce_flush: (%s) erase effect %d failed\n", dev->phys, i);
+ }
+ }
+
+ }
return 0;
}
@@ -357,6 +581,12 @@
{
struct iforce *iforce = dev->private;
+ printk(KERN_DEBUG "iforce.c: in iforce_close\n");
+
+ /* Disable force feedback playback */
+ send_packet(iforce, FF_CMD_ENABLE, "\001");
+
+
switch (iforce->bus) {
#ifdef IFORCE_USB
case IFORCE_USB:
@@ -367,10 +597,6 @@
}
}
-/*
- * Start or stop playing an effect
- */
-
static int iforce_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
struct iforce* iforce = (struct iforce*)(dev->private);
@@ -402,11 +628,17 @@
return 0;
- default: /* Play an effect */
+ default: /* Play or stop an effect */
- if (code >= iforce->dev.ff_effects_max)
+ if (!CHECK_OWNERSHIP(code, iforce)) {
return -1;
-
+ }
+ if (value > 0) {
+ set_bit(FF_CORE_SHOULD_PLAY, iforce->core_effects[code].flags);
+ }
+ else {
+ clear_bit(FF_CORE_SHOULD_PLAY, iforce->core_effects[code].flags);
+ }
data[0] = LO(code);
data[1] = (value > 0) ? ((value > 1) ? 0x41 : 0x01) : 0;
data[2] = LO(value);
@@ -426,14 +658,19 @@
*/
static int make_magnitude_modifier(struct iforce* iforce,
- struct resource* mod_chunk, __s16 level)
+ struct resource* mod_chunk, int no_alloc, __s16 level)
{
unsigned char data[3];
- if (allocate_resource(&(iforce->device_memory), mod_chunk, 2,
- iforce->device_memory.start, iforce->device_memory.end, 2L,
- NULL, NULL)) {
- return -ENOMEM;
+ if (!no_alloc) {
+ down(&iforce->mem_mutex);
+ if (allocate_resource(&(iforce->device_memory), mod_chunk, 2,
+ iforce->device_memory.start, iforce->device_memory.end, 2L,
+ NULL, NULL)) {
+ up(&iforce->mem_mutex);
+ return -ENOMEM;
+ }
+ up(&iforce->mem_mutex);
}
data[0] = LO(mod_chunk->start);
@@ -449,17 +686,23 @@
* Upload the component of an effect dealing with the period, phase and magnitude
*/
-static int make_period_modifier(struct iforce* iforce, struct resource* mod_chunk,
+static int make_period_modifier(struct iforce* iforce,
+ struct resource* mod_chunk, int no_alloc,
__s16 magnitude, __s16 offset, u16 period, u16 phase)
{
unsigned char data[7];
period = TIME_SCALE(period);
- if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0c,
- iforce->device_memory.start, iforce->device_memory.end, 2L,
- NULL, NULL)) {
- return -ENOMEM;
+ if (!no_alloc) {
+ down(&iforce->mem_mutex);
+ if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0c,
+ iforce->device_memory.start, iforce->device_memory.end, 2L,
+ NULL, NULL)) {
+ up(&iforce->mem_mutex);
+ return -ENOMEM;
+ }
+ up(&iforce->mem_mutex);
}
data[0] = LO(mod_chunk->start);
@@ -481,7 +724,8 @@
* Uploads the part of an effect setting the shape of the force
*/
-static int make_shape_modifier(struct iforce* iforce, struct resource* mod_chunk,
+static int make_shape_modifier(struct iforce* iforce,
+ struct resource* mod_chunk, int no_alloc,
u16 attack_duration, __s16 initial_level,
u16 fade_duration, __s16 final_level)
{
@@ -490,10 +734,15 @@
attack_duration = TIME_SCALE(attack_duration);
fade_duration = TIME_SCALE(fade_duration);
- if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0e,
- iforce->device_memory.start, iforce->device_memory.end, 2L,
- NULL, NULL)) {
- return -ENOMEM;
+ if (!no_alloc) {
+ down(&iforce->mem_mutex);
+ if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0e,
+ iforce->device_memory.start, iforce->device_memory.end, 2L,
+ NULL, NULL)) {
+ up(&iforce->mem_mutex);
+ return -ENOMEM;
+ }
+ up(&iforce->mem_mutex);
}
data[0] = LO(mod_chunk->start);
@@ -517,15 +766,20 @@
*/
static int make_interactive_modifier(struct iforce* iforce,
- struct resource* mod_chunk,
+ struct resource* mod_chunk, int no_alloc,
__s16 rsat, __s16 lsat, __s16 rk, __s16 lk, u16 db, __s16 center)
{
unsigned char data[10];
- if (allocate_resource(&(iforce->device_memory), mod_chunk, 8,
- iforce->device_memory.start, iforce->device_memory.end, 2L,
- NULL, NULL)) {
- return -ENOMEM;
+ if (!no_alloc) {
+ down(&iforce->mem_mutex);
+ if (allocate_resource(&(iforce->device_memory), mod_chunk, 8,
+ iforce->device_memory.start, iforce->device_memory.end, 2L,
+ NULL, NULL)) {
+ up(&iforce->mem_mutex);
+ return -ENOMEM;
+ }
+ up(&iforce->mem_mutex);
}
data[0] = LO(mod_chunk->start);
@@ -609,13 +863,15 @@
struct resource* mod2_chunk = &(iforce->core_effects[core_id].mod2_chunk);
int err = 0;
- err = make_period_modifier(iforce, mod1_chunk,
+ err = make_period_modifier(iforce, mod1_chunk,
+ test_bit(FF_MOD1_IS_USED, iforce->core_effects[core_id].flags),
effect->u.periodic.magnitude, effect->u.periodic.offset,
effect->u.periodic.period, effect->u.periodic.phase);
if (err) return err;
set_bit(FF_MOD1_IS_USED, core_effect->flags);
err = make_shape_modifier(iforce, mod2_chunk,
+ test_bit(FF_MOD2_IS_USED, iforce->core_effects[core_id].flags),
effect->u.periodic.shape.attack_length,
effect->u.periodic.shape.attack_level,
effect->u.periodic.shape.fade_length,
@@ -659,11 +915,14 @@
printk(KERN_DEBUG "iforce.c: make constant effect\n");
- err = make_magnitude_modifier(iforce, mod1_chunk, effect->u.constant.level);
+ err = make_magnitude_modifier(iforce, mod1_chunk,
+ test_bit(FF_MOD1_IS_USED, iforce->core_effects[core_id].flags),
+ effect->u.constant.level);
if (err) return err;
set_bit(FF_MOD1_IS_USED, core_effect->flags);
err = make_shape_modifier(iforce, mod2_chunk,
+ test_bit(FF_MOD2_IS_USED, iforce->core_effects[core_id].flags),
effect->u.constant.shape.attack_length,
effect->u.constant.shape.attack_level,
effect->u.constant.shape.fade_length,
@@ -706,6 +965,7 @@
}
err = make_interactive_modifier(iforce, mod_chunk,
+ test_bit(FF_MOD1_IS_USED, iforce->core_effects[core_id].flags),
effect->u.interactive.right_saturation,
effect->u.interactive.left_saturation,
effect->u.interactive.right_coeff,
@@ -774,22 +1034,34 @@
printk(KERN_DEBUG "iforce.c: upload effect\n");
/*
- * Get a free id
+ * If we want to create a new effect, get a free id
*/
+ if (effect->id == -1) {
- for (id=0; id < FF_EFFECTS_MAX; ++id)
- if (!test_bit(FF_CORE_IS_USED, iforce->core_effects[id].flags)) break;
+ for (id=0; id < FF_EFFECTS_MAX; ++id)
+ if (!test_and_set_bit(FF_CORE_IS_USED, iforce->core_effects[id].flags)) break;
- if ( id == FF_EFFECTS_MAX || id >= iforce->dev.ff_effects_max)
- return -ENOMEM;
-
- effect->id = id;
- set_bit(FF_CORE_IS_USED, iforce->core_effects[id].flags);
+ if ( id == FF_EFFECTS_MAX || id >= iforce->dev.ff_effects_max)
+ return -ENOMEM;
+
+ effect->id = id;
+ iforce->core_effects[id].owner = current->pid;
+ iforce->core_effects[id].flags[0] = (1<<FF_CORE_IS_USED); /* Only IS_USED bit must be set */
+ }
+ else {
+ /* We want to update an effect */
+ if (!CHECK_OWNERSHIP(effect->id, iforce)) return -1;
+
+ /* Check the effect is not allready being updated */
+ if (test_and_set_bit(FF_CORE_UPDATE, iforce->core_effects[effect->id].flags)) {
+ printk(KERN_DEBUG "iforce.c: update too frequent refused\n");
+ return -1;
+ }
+ }
/*
* Upload the effect
*/
-
switch (effect->type) {
case FF_PERIODIC:
@@ -817,6 +1089,12 @@
int err = 0;
struct iforce_core_effect* core_effect;
+ /* Check who is trying to erase this effect */
+ if (iforce->core_effects[effect_id].owner != current->pid) {
+ printk(KERN_WARNING "iforce.c: %d tried to erase an effect belonging to %d\n", current->pid, iforce->core_effects[effect_id].owner);
+ return -EACCES;
+ }
+
printk(KERN_DEBUG "iforce.c: erase effect %d\n", effect_id);
if (effect_id < 0 || effect_id >= FF_EFFECTS_MAX)
@@ -835,14 +1113,35 @@
return err;
}
+
static int iforce_init_device(struct iforce *iforce)
{
unsigned char c[] = "CEOV";
+ char path[64];
int i;
init_waitqueue_head(&iforce->wait);
+ spin_lock_init(&iforce->xmit_lock);
+ init_MUTEX(&iforce->mem_mutex);
+ iforce->xmit.buf = iforce->xmit_data;
+
iforce->dev.ff_effects_max = 10;
+ switch (iforce->bus) {
+#ifdef IFORCE_232
+ case IFORCE_232:
+ strcpy(path, iforce->serio->phys);
+ break;
+#endif
+#ifdef IFORCE_USB
+ case IFORCE_USB:
+ usb_make_path(iforce->usbdev, path, 64);
+ break;
+#endif
+ }
+
+ sprintf(iforce->phys, "%s/input0", path);
+
/*
* Input device fields.
*/
@@ -850,8 +1149,10 @@
iforce->dev.idbus = BUS_USB;
iforce->dev.private = iforce;
iforce->dev.name = iforce->name;
+ iforce->dev.name = iforce->phys;
iforce->dev.open = iforce_open;
iforce->dev.close = iforce_close;
+ iforce->dev.flush = iforce_flush;
iforce->dev.event = iforce_input_event;
iforce->dev.upload_effect = iforce_upload_effect;
iforce->dev.erase_effect = iforce_erase_effect;
@@ -895,6 +1196,13 @@
if (!get_id_packet(iforce, "N"))
iforce->dev.ff_effects_max = iforce->edata[1];
+ /* Check if the device can store more effects than the driver can really handle */
+ if (iforce->dev.ff_effects_max > FF_EFFECTS_MAX) {
+ printk(KERN_WARNING "input??: Device can handle %d effects, but N_EFFECTS_MAX is set to %d in iforce.c\n",
+ iforce->dev.ff_effects_max, FF_EFFECTS_MAX);
+ iforce->dev.ff_effects_max = FF_EFFECTS_MAX;
+ }
+
/*
* Display additional info.
*/
@@ -909,7 +1217,6 @@
*/
send_packet(iforce, FF_CMD_AUTOCENTER, "\004\000");
- send_packet(iforce, FF_CMD_ENABLE, "\004");
/*
* Find appropriate device entry
@@ -929,7 +1236,7 @@
* Set input device bitfields and ranges.
*/
- iforce->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_FF);
+ iforce->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_FF) | BIT(EV_FF_STATUS);
for (i = 0; iforce->type->btn[i] >= 0; i++) {
signed short t = iforce->type->btn[i];
@@ -982,6 +1289,10 @@
input_register_device(&iforce->dev);
+ printk(KERN_INFO "input: %s [%d effects, %ld bytes memory] on %s\n",
+ iforce->dev.name, iforce->dev.ff_effects_max,
+ iforce->device_memory.end, path);
+
return 0;
}
@@ -998,7 +1309,11 @@
static void iforce_usb_out(struct urb *urb)
{
struct iforce *iforce = urb->context;
+
if (urb->status) return;
+
+ iforce_usb_xmit(iforce);
+
if (waitqueue_active(&iforce->wait))
wake_up(&iforce->wait);
}
@@ -1045,10 +1360,6 @@
return NULL;
}
- printk(KERN_INFO "input%d: %s [%d effects, %ld bytes memory] on usb%d:%d.%d\n",
- iforce->dev.number, iforce->dev.name, iforce->dev.ff_effects_max,
- iforce->device_memory.end, dev->bus->busnum, dev->devnum, ifnum);
-
return iforce;
}
@@ -1061,10 +1372,13 @@
}
static struct usb_device_id iforce_usb_ids [] = {
+ { USB_DEVICE(0x044f, 0xa01c) }, /* Thrustmaster Motor Sport GT */
{ USB_DEVICE(0x046d, 0xc281) }, /* Logitech WingMan Force */
+ { USB_DEVICE(0x046d, 0xc285) }, /* Logitech WingMan Strike Force 3D */
{ USB_DEVICE(0x046d, 0xc291) }, /* Logitech WingMan Formula Force */
{ USB_DEVICE(0x05ef, 0x020a) }, /* AVB Top Shot Pegasus */
{ USB_DEVICE(0x05ef, 0x8884) }, /* AVB Mag Turbo Force */
+ { USB_DEVICE(0x05ef, 0x8888) }, /* AVB Top Shot FFB Racing Wheel */
{ USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */
{ } /* Terminating entry */
};
@@ -1151,10 +1465,6 @@
kfree(iforce);
return;
}
-
- printk(KERN_INFO "input%d: %s [%d effects, %ld bytes memory] on serio%d\n",
- iforce->dev.number, iforce->dev.name, iforce->dev.ff_effects_max,
- iforce->device_memory.end, serio->number);
}
static void iforce_serio_disconnect(struct serio *serio)
@@ -1167,6 +1477,9 @@
}
static struct serio_dev iforce_serio_dev = {
+#ifdef IFORCE_232
+ write_wakeup: iforce_serio_write_wakeup,
+#endif
interrupt: iforce_serio_irq,
connect: iforce_serio_connect,
disconnect: iforce_serio_disconnect,
diff -urN linux-2.4.10/drivers/char/joystick/interact.c linux/drivers/char/joystick/interact.c
--- linux-2.4.10/drivers/char/joystick/interact.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/interact.c Tue Sep 25 12:45:10 2001
@@ -1,12 +1,10 @@
/*
- * $Id: interact.c,v 1.8 2000/05/29 11:19:51 vojtech Exp $
+ * $Id: interact.c,v 1.15 2001/09/25 10:12:07 vojtech Exp $
*
- * Copyright (c) 2000 Vojtech Pavlik
+ * Copyright (c) 2001 Vojtech Pavlik
*
* Based on the work of:
* Toby Deshane
- *
- * Sponsored by SuSE
*/
/*
@@ -29,8 +27,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/kernel.h>
@@ -41,6 +39,10 @@
#include <linux/gameport.h>
#include <linux/input.h>
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("InterAct digital joystick driver");
+MODULE_LICENSE("GPL");
+
#define INTERACT_MAX_START 400 /* 400 us */
#define INTERACT_MAX_STROBE 40 /* 40 us */
#define INTERACT_MAX_LENGTH 32 /* 32 bits */
@@ -58,6 +60,7 @@
int reads;
unsigned char type;
unsigned char length;
+ char phys[32];
};
static short interact_abs_hhfx[] =
@@ -137,40 +140,41 @@
if (interact_read_packet(interact->gameport, interact->length, data) < interact->length) {
interact->bads++;
- } else
+ } else {
- for (i = 0; i < 3; i++)
- data[i] <<= INTERACT_MAX_LENGTH - interact->length;
+ for (i = 0; i < 3; i++)
+ data[i] <<= INTERACT_MAX_LENGTH - interact->length;
- switch (interact->type) {
+ switch (interact->type) {
- case INTERACT_TYPE_HHFX:
+ case INTERACT_TYPE_HHFX:
- for (i = 0; i < 4; i++)
- input_report_abs(dev, interact_abs_hhfx[i], (data[i & 1] >> ((i >> 1) << 3)) & 0xff);
+ for (i = 0; i < 4; i++)
+ input_report_abs(dev, interact_abs_hhfx[i], (data[i & 1] >> ((i >> 1) << 3)) & 0xff);
- for (i = 0; i < 2; i++)
- input_report_abs(dev, ABS_HAT0Y - i,
- ((data[1] >> ((i << 1) + 17)) & 1) - ((data[1] >> ((i << 1) + 16)) & 1));
+ for (i = 0; i < 2; i++)
+ input_report_abs(dev, ABS_HAT0Y - i,
+ ((data[1] >> ((i << 1) + 17)) & 1) - ((data[1] >> ((i << 1) + 16)) & 1));
- for (i = 0; i < 8; i++)
- input_report_key(dev, interact_btn_hhfx[i], (data[0] >> (i + 16)) & 1);
+ for (i = 0; i < 8; i++)
+ input_report_key(dev, interact_btn_hhfx[i], (data[0] >> (i + 16)) & 1);
- for (i = 0; i < 4; i++)
- input_report_key(dev, interact_btn_hhfx[i + 8], (data[1] >> (i + 20)) & 1);
+ for (i = 0; i < 4; i++)
+ input_report_key(dev, interact_btn_hhfx[i + 8], (data[1] >> (i + 20)) & 1);
- break;
+ break;
- case INTERACT_TYPE_PP8D:
+ case INTERACT_TYPE_PP8D:
- for (i = 0; i < 2; i++)
- input_report_abs(dev, interact_abs_pp8d[i],
- ((data[0] >> ((i << 1) + 20)) & 1) - ((data[0] >> ((i << 1) + 21)) & 1));
+ for (i = 0; i < 2; i++)
+ input_report_abs(dev, interact_abs_pp8d[i],
+ ((data[0] >> ((i << 1) + 20)) & 1) - ((data[0] >> ((i << 1) + 21)) & 1));
- for (i = 0; i < 8; i++)
- input_report_key(dev, interact_btn_pp8d[i], (data[1] >> (i + 16)) & 1);
+ for (i = 0; i < 8; i++)
+ input_report_key(dev, interact_btn_pp8d[i], (data[1] >> (i + 16)) & 1);
- break;
+ break;
+ }
}
mod_timer(&interact->timer, jiffies + INTERACT_REFRESH_TIME);
@@ -235,11 +239,13 @@
break;
if (!interact_type[i].length) {
- printk(KERN_WARNING "interact.c: Unknown joystick on gameport%d. [len %d d0 %08x d1 %08x i2 %08x]\n",
- gameport->number, i, data[0], data[1], data[2]);
+ printk(KERN_WARNING "interact.c: Unknown joystick on %s. [len %d d0 %08x d1 %08x i2 %08x]\n",
+ gameport->phys, i, data[0], data[1], data[2]);
goto fail2;
}
+ sprintf(interact->phys, "%s/input0", gameport->phys);
+
interact->type = i;
interact->length = interact_type[i].length;
@@ -248,6 +254,7 @@
interact->dev.close = interact_close;
interact->dev.name = interact_type[i].name;
+ interact->dev.phys = interact->phys;
interact->dev.idbus = BUS_GAMEPORT;
interact->dev.idvendor = GAMEPORT_ID_VENDOR_INTERACT;
interact->dev.idproduct = interact_type[i].id;
@@ -270,8 +277,8 @@
set_bit(t, interact->dev.keybit);
input_register_device(&interact->dev);
- printk(KERN_INFO "input%d: %s on gameport%d.0\n",
- interact->dev.number, interact_type[interact->type].name, gameport->number);
+ printk(KERN_INFO "input: %s on %s\n",
+ interact_type[interact->type].name, gameport->phys);
return;
fail2: gameport_close(gameport);
@@ -304,5 +311,3 @@
module_init(interact_init);
module_exit(interact_exit);
-
-MODULE_LICENSE("GPL");
diff -urN linux-2.4.10/drivers/char/joystick/lightning.c linux/drivers/char/joystick/lightning.c
--- linux-2.4.10/drivers/char/joystick/lightning.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/lightning.c Tue Sep 25 12:45:10 2001
@@ -1,9 +1,7 @@
/*
- * $Id: lightning.c,v 1.13 2001/04/26 10:24:46 vojtech Exp $
+ * $Id: lightning.c,v 1.18 2001/09/25 10:12:07 vojtech Exp $
*
* Copyright (c) 1998-2001 Vojtech Pavlik
- *
- * Sponsored by SuSE
*/
/*
@@ -26,8 +24,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <asm/io.h>
@@ -51,14 +49,18 @@
#define L4_BUSY 0x01
#define L4_TIMEOUT 80 /* 80 us */
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("PDPI Lightning 4 gamecard driver");
MODULE_LICENSE("GPL");
struct l4 {
struct gameport gameport;
unsigned char port;
+ char phys[32];
} *l4_port[8];
+char l4_name[] = "PDPI Lightning 4";
+
/*
* l4_wait_ready() waits for the L4 to become ready.
*/
@@ -247,12 +249,18 @@
l4 = l4_port[i * 4 + j] = l4_port[i * 4] + j;
l4->port = i * 4 + j;
+ sprintf(l4->phys, "isa%04x/gameport%d", L4_PORT, 4 * i + j);
+
gameport = &l4->gameport;
gameport->private = l4;
gameport->open = l4_open;
gameport->cooked_read = l4_cooked_read;
gameport->calibrate = l4_calibrate;
+ gameport->name = l4_name;
+ gameport->phys = l4->phys;
+ gameport->idbus = BUS_ISA;
+
if (!i && !j)
gameport->io = L4_PORT;
@@ -262,9 +270,7 @@
gameport_register_port(gameport);
}
- printk(KERN_INFO "gameport%d,%d,%d,%d: PDPI Lightning 4 %s card v%d.%d at %#x\n",
- l4_port[i * 4 + 0]->gameport.number, l4_port[i * 4 + 1]->gameport.number,
- l4_port[i * 4 + 2]->gameport.number, l4_port[i * 4 + 3]->gameport.number,
+ printk(KERN_INFO "gameport: PDPI Lightning 4 %s card v%d.%d at %#x\n",
i ? "secondary" : "primary", rev >> 4, rev, L4_PORT);
cards++;
diff -urN linux-2.4.10/drivers/char/joystick/magellan.c linux/drivers/char/joystick/magellan.c
--- linux-2.4.10/drivers/char/joystick/magellan.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/magellan.c Tue Sep 25 12:45:10 2001
@@ -1,9 +1,7 @@
/*
- * $Id: magellan.c,v 1.8 2000/05/31 13:17:12 vojtech Exp $
+ * $Id: magellan.c,v 1.15 2001/09/25 10:12:07 vojtech Exp $
*
- * Copyright (c) 1999-2000 Vojtech Pavlik
- *
- * Sponsored by SuSE
+ * Copyright (c) 1999-2001 Vojtech Pavlik
*/
/*
@@ -27,7 +25,7 @@
*
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/kernel.h>
@@ -37,15 +35,19 @@
#include <linux/serio.h>
#include <linux/init.h>
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Magellan and SpaceMouse 6dof controller driver");
+MODULE_LICENSE("GPL");
+
/*
* Definitions & global arrays.
*/
#define MAGELLAN_MAX_LENGTH 32
-static int magellan_buttons[] = { BTN_0, BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8};
-static int magellan_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ};
-static char *magellan_name = "LogiCad3D Magellan";
+static int magellan_buttons[] = { BTN_0, BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8 };
+static int magellan_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ };
+static char *magellan_name = "LogiCad3D Magellan / SpaceMouse";
/*
* Per-Magellan data.
@@ -55,6 +57,7 @@
struct input_dev dev;
int idx;
unsigned char data[MAGELLAN_MAX_LENGTH];
+ char phys[32];
};
/*
@@ -162,8 +165,11 @@
magellan->dev.absmax[t] = 360;
}
+ sprintf(magellan->phys, "%s/input0", serio->phys);
+
magellan->dev.private = magellan;
magellan->dev.name = magellan_name;
+ magellan->dev.phys = magellan->phys;
magellan->dev.idbus = BUS_RS232;
magellan->dev.idvendor = SERIO_MAGELLAN;
magellan->dev.idproduct = 0x0001;
@@ -178,7 +184,7 @@
input_register_device(&magellan->dev);
- printk(KERN_INFO "input%d: %s on serio%d\n", magellan->dev.number, magellan_name, serio->number);
+ printk(KERN_INFO "input: %s on %s\n", magellan_name, serio->phys);
}
/*
@@ -208,5 +214,3 @@
module_init(magellan_init);
module_exit(magellan_exit);
-
-MODULE_LICENSE("GPL");
diff -urN linux-2.4.10/drivers/char/joystick/ns558.c linux/drivers/char/joystick/ns558.c
--- linux-2.4.10/drivers/char/joystick/ns558.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/ns558.c Tue Sep 25 12:45:10 2001
@@ -1,10 +1,8 @@
/*
- * $Id: ns558.c,v 1.29 2001/04/24 07:48:56 vojtech Exp $
+ * $Id: ns558.c,v 1.39 2001/09/25 10:12:07 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
* Copyright (c) 1999 Brian Gerst
- *
- * Sponsored by SuSE
*/
/*
@@ -28,7 +26,7 @@
*
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <asm/io.h>
@@ -42,6 +40,7 @@
#include <linux/isapnp.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Classic gameport (ISA/PnP) driver");
MODULE_LICENSE("GPL");
#define NS558_ISA 1
@@ -56,6 +55,8 @@
struct pci_dev *dev;
struct ns558 *next;
struct gameport gameport;
+ char phys[32];
+ char name[32];
};
static struct ns558 *ns558;
@@ -141,12 +142,21 @@
port->type = NS558_ISA;
port->size = (1 << i);
port->gameport.io = io & (-1 << i);
+ port->gameport.phys = port->phys;
+ port->gameport.name = port->name;
+ port->gameport.idbus = BUS_ISA;
+ port->gameport.idvendor = 0x0000;
+ port->gameport.idproduct = 0x0000;
+ port->gameport.idversion = 0x0000;
+
+ sprintf(port->phys, "isa%04x/gameport0", io & (-1 << i));
+ sprintf(port->name, "NS558 ISA");
request_region(port->gameport.io, (1 << i), "ns558-isa");
gameport_register_port(&port->gameport);
- printk(KERN_INFO "gameport%d: NS558 ISA at %#x", port->gameport.number, port->gameport.io);
+ printk(KERN_INFO "gameport: NS558 ISA at %#x", port->gameport.io);
if (port->size > 1) printk(" size %d", port->size);
printk(" speed %d kHz\n", port->gameport.speed);
@@ -159,17 +169,33 @@
#ifdef NSS558_ISAPNP
+#define NS558_DEVICE(a,b,c,d)\
+ card_vendor: ISAPNP_ANY_ID, card_device: ISAPNP_ANY_ID,\
+ vendor: ISAPNP_VENDOR(a,b,c), device: ISAPNP_DEVICE(d)
+
static struct isapnp_device_id pnp_devids[] = {
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('@','P','@'), ISAPNP_DEVICE(0x0001), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('@','P','@'), ISAPNP_DEVICE(0x2001), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x7001), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x7002), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','S','C'), ISAPNP_DEVICE(0x0010), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','S','C'), ISAPNP_DEVICE(0x0110), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','S','C'), ISAPNP_DEVICE(0x0b35), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','S','C'), ISAPNP_DEVICE(0x0010), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','S','C'), ISAPNP_DEVICE(0x0110), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P','N','P'), ISAPNP_DEVICE(0xb02f), 0 },
+ { NS558_DEVICE('@','P','@',0x0001) }, /* ALS 100 */
+ { NS558_DEVICE('@','P','@',0x0020) }, /* ALS 200 */
+ { NS558_DEVICE('@','P','@',0x1001) }, /* ALS 100+ */
+ { NS558_DEVICE('@','P','@',0x2001) }, /* ALS 120 */
+ { NS558_DEVICE('A','S','B',0x16fd) }, /* AdLib NSC16 */
+ { NS558_DEVICE('A','Z','T',0x3001) }, /* AZT1008 */
+ { NS558_DEVICE('C','D','C',0x0001) }, /* Opl3-SAx */
+ { NS558_DEVICE('C','S','C',0x0001) }, /* CS4232 */
+ { NS558_DEVICE('C','S','C',0x000f) }, /* CS4236 */
+ { NS558_DEVICE('C','S','C',0x0101) }, /* CS4327 */
+ { NS558_DEVICE('C','T','L',0x7001) }, /* SB16 */
+ { NS558_DEVICE('C','T','L',0x7002) }, /* AWE64 */
+ { NS558_DEVICE('C','T','L',0x7005) }, /* Vibra16 */
+ { NS558_DEVICE('E','N','S',0x2020) }, /* SoundscapeVIVO */
+ { NS558_DEVICE('E','S','S',0x0001) }, /* ES1869 */
+ { NS558_DEVICE('E','S','S',0x0005) }, /* ES1878 */
+ { NS558_DEVICE('E','S','S',0x6880) }, /* ES688 */
+ { NS558_DEVICE('I','B','M',0x0012) }, /* CS4232 */
+ { NS558_DEVICE('O','P','T',0x0001) }, /* OPTi Audio16 */
+ { NS558_DEVICE('Y','M','H',0x0006) }, /* Opl3-SA */
+ { NS558_DEVICE('Y','M','H',0x0022) }, /* Opl3-SAx */
+ { NS558_DEVICE('P','N','P',0xb02f) }, /* Generic */
{ 0, },
};
@@ -207,13 +233,24 @@
port->next = next;
port->type = NS558_PNP;
- port->gameport.io = ioport;
port->size = iolen;
port->dev = dev;
+ port->gameport.io = ioport;
+ port->gameport.phys = port->phys;
+ port->gameport.name = port->name;
+ port->gameport.idbus = BUS_ISAPNP;
+ port->gameport.idvendor = dev->vendor;
+ port->gameport.idproduct = dev->device;
+ port->gameport.idversion = dev->version;
+
+ sprintf(port->phys, "isapnp%d.%d/gameport0", dev->number, dev->devfn);
+ sprintf(port->name, "%s" dev->name[0] ? dev->name : "NS558 PnP Gameport");
+
gameport_register_port(&port->gameport);
- printk(KERN_INFO "gameport%d: NS558 PnP at %#x", port->gameport.number, port->gameport.io);
+ printk(KERN_INFO "gameport: NS558 PnP at isapnp%d.%d io %#x",
+ dev->number, dev->devfn, port->gameport.io);
if (iolen > 1) printk(" size %d", iolen);
printk(" speed %d kHz\n", port->gameport.speed);
diff -urN linux-2.4.10/drivers/char/joystick/pcigame.c linux/drivers/char/joystick/pcigame.c
--- linux-2.4.10/drivers/char/joystick/pcigame.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/pcigame.c Tue Sep 25 12:45:10 2001
@@ -1,12 +1,10 @@
/*
- * $Id: pcigame.c,v 1.10 2001/04/26 10:24:46 vojtech Exp $
+ * $Id: pcigame.c,v 1.16 2001/09/25 10:12:07 vojtech Exp $
*
* Copyright (c) 2000-2001 Vojtech Pavlik
*
* Based on the work of:
* Raymond Ingles
- *
- * Sponsored by SuSE
*/
/*
@@ -29,8 +27,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <asm/io.h>
@@ -44,6 +42,10 @@
#include <linux/slab.h>
#include <linux/gameport.h>
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Trident 4DWave and Aureal Vortex gameport driver");
+MODULE_LICENSE("GPL");
+
#define PCI_VENDOR_ID_AUREAL 0x12eb
#define PCIGAME_DATA_WAIT 20 /* 20 ms */
@@ -72,6 +74,7 @@
struct pci_dev *dev;
unsigned char *base;
struct pcigame_data *data;
+ char phys[32];
};
static unsigned char pcigame_read(struct gameport *gameport)
@@ -131,8 +134,9 @@
pcigame->data = pcigame_data + id->driver_data;
-
pcigame->dev = dev;
+ sprintf(pcigame->phys, "pci%s/gameport0", dev->slot_name);
+
dev->driver_data = pcigame;
pcigame->gameport.private = pcigame;
@@ -143,6 +147,12 @@
pcigame->gameport.cooked_read = pcigame_cooked_read;
pcigame->gameport.open = pcigame_open;
+ pcigame->gameport.name = dev->name;
+ pcigame->gameport.phys = pcigame->phys;
+ pcigame->gameport.idbus = BUS_PCI;
+ pcigame->gameport.idvendor = dev->vendor;
+ pcigame->gameport.idproduct = dev->device;
+
for (i = 0; i < 6; i++)
if (~pci_resource_flags(dev, i) & IORESOURCE_IO)
break;
@@ -154,9 +164,8 @@
gameport_register_port(&pcigame->gameport);
- printk(KERN_INFO "gameport%d: %s at pci%02x:%02x.%x speed %d kHz\n",
- pcigame->gameport.number, dev->name, dev->bus->number,
- PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), pcigame->gameport.speed);
+ printk(KERN_INFO "gameport: %s at pci%s speed %d kHz\n",
+ dev->name, dev->slot_name, pcigame->gameport.speed);
return 0;
}
@@ -195,5 +204,3 @@
module_init(pcigame_init);
module_exit(pcigame_exit);
-
-MODULE_LICENSE("GPL");
diff -urN linux-2.4.10/drivers/char/joystick/serio.c linux/drivers/char/joystick/serio.c
--- linux-2.4.10/drivers/char/joystick/serio.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/serio.c Tue Sep 25 12:45:10 2001
@@ -1,9 +1,7 @@
/*
- * $Id: serio.c,v 1.5 2000/06/04 17:44:59 vojtech Exp $
+ * $Id: serio.c,v 1.14 2001/09/25 10:44:37 vojtech Exp $
*
- * Copyright (c) 1999-2000 Vojtech Pavlik
- *
- * Sponsored by SuSE
+ * Copyright (c) 1999-2001 Vojtech Pavlik
*/
/*
@@ -27,14 +25,16 @@
*
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/stddef.h>
#include <linux/module.h>
#include <linux/serio.h>
+#include <linux/errno.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Serio abstraction core");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(serio_register_port);
@@ -47,7 +47,6 @@
static struct serio *serio_list;
static struct serio_dev *serio_dev;
-static int serio_number;
static void serio_find_dev(struct serio *serio)
{
@@ -69,7 +68,6 @@
void serio_register_port(struct serio *serio)
{
- serio->number = serio_number++;
serio->next = serio_list;
serio_list = serio;
serio_find_dev(serio);
@@ -84,8 +82,6 @@
if (serio->dev && serio->dev->disconnect)
serio->dev->disconnect(serio);
-
- serio_number--;
}
void serio_register_device(struct serio_dev *dev)
diff -urN linux-2.4.10/drivers/char/joystick/serport.c linux/drivers/char/joystick/serport.c
--- linux-2.4.10/drivers/char/joystick/serport.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/serport.c Tue Sep 25 12:45:15 2001
@@ -1,9 +1,7 @@
/*
- * $Id: serport.c,v 1.7 2001/05/25 19:00:27 jdeneux Exp $
+ * $Id: serport_old.c,v 1.7 2001/09/25 10:12:07 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
- *
- * Sponsored by SuSE
*/
/*
@@ -28,7 +26,7 @@
*
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <asm/uaccess.h>
@@ -39,12 +37,19 @@
#include <linux/serio.h>
#include <linux/tty.h>
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Input device TTY line discipline");
+MODULE_LICENSE("GPL");
+
struct serport {
struct tty_struct *tty;
wait_queue_head_t wait;
struct serio serio;
+ char phys[32];
};
+char serport_name[] = "Serial port";
+
/*
* Callback functions from the serio code.
*/
@@ -75,6 +80,8 @@
static int serport_ldisc_open(struct tty_struct *tty)
{
struct serport *serport;
+ char ttyname[64];
+ int i;
MOD_INC_USE_COUNT;
@@ -85,9 +92,19 @@
memset(serport, 0, sizeof(struct serport));
+ set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
serport->tty = tty;
tty->disc_data = serport;
+ strcpy(ttyname, tty->driver.name);
+ for (i = 0; ttyname[i] != 0 && ttyname[i] != '/'; i++);
+ ttyname[i] = 0;
+
+ sprintf(serport->phys, "%s%d/serio0", ttyname, MINOR(tty->device) - tty->driver.minor_start);
+
+ serport->serio.name = serport_name;
+ serport->serio.phys = serport->phys;
+
serport->serio.type = SERIO_RS232;
serport->serio.write = serport_serio_write;
serport->serio.open = serport_serio_open;
@@ -156,7 +173,7 @@
serio_register_port(&serport->serio);
- printk(KERN_INFO "serio%d: Serial port %s\n", serport->serio.number, name);
+ printk(KERN_INFO "serio: Serial port %s\n", name);
add_wait_queue(&serport->wait, &wait);
current->state = TASK_INTERRUPTIBLE;
@@ -187,6 +204,14 @@
return -EINVAL;
}
+static void serport_ldisc_write_wakeup(struct tty_struct * tty)
+{
+ struct serport *sp = (struct serport *) tty->disc_data;
+
+ serio_dev_write_wakeup(&sp->serio);
+
+}
+
/*
* The line discipline structure.
*/
@@ -199,6 +224,7 @@
ioctl: serport_ldisc_ioctl,
receive_buf: serport_ldisc_receive,
receive_room: serport_ldisc_room,
+ write_wakeup: serport_ldisc_write_wakeup
};
/*
@@ -222,5 +248,3 @@
module_init(serport_init);
module_exit(serport_exit);
-
-MODULE_LICENSE("GPL");
diff -urN linux-2.4.10/drivers/char/joystick/sidewinder.c linux/drivers/char/joystick/sidewinder.c
--- linux-2.4.10/drivers/char/joystick/sidewinder.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/sidewinder.c Tue Sep 25 12:45:10 2001
@@ -1,9 +1,7 @@
/*
- * $Id: sidewinder.c,v 1.20 2001/05/19 08:14:54 vojtech Exp $
+ * $Id: sidewinder.c,v 1.28 2001/09/25 10:12:07 vojtech Exp $
*
* Copyright (c) 1998-2001 Vojtech Pavlik
- *
- * Sponsored by SuSE
*/
/*
@@ -26,8 +24,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/delay.h>
@@ -38,12 +36,16 @@
#include <linux/input.h>
#include <linux/gameport.h>
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Microsoft SideWinder joystick family driver");
+MODULE_LICENSE("GPL");
+
/*
* These are really magic values. Changing them can make a problem go away,
* as well as break everything.
*/
-#undef SW_DEBUG
+#define SW_DEBUG
#define SW_START 400 /* The time we wait for the first bit [400 us] */
#define SW_STROBE 45 /* Max time per bit [45 us] */
@@ -114,6 +116,7 @@
struct timer_list timer;
struct input_dev dev[4];
char name[64];
+ char phys[4][32];
int length;
int type;
int bits;
@@ -411,8 +414,8 @@
if (sw->type == SW_ID_3DP && sw->length == 66 && i != 66) { /* Broken packet, try to fix */
if (i == 64 && !sw_check(sw_get_bits(buf,0,64,1))) { /* Last init failed, 1 bit mode */
- printk(KERN_WARNING "sidewinder.c: Joystick in wrong mode on gameport%d"
- " - going to reinitialize.\n", sw->gameport->number);
+ printk(KERN_WARNING "sidewinder.c: Joystick in wrong mode on %s"
+ " - going to reinitialize.\n", sw->gameport->phys);
sw->fail = SW_FAIL; /* Reinitialize */
i = 128; /* Bogus value */
}
@@ -437,8 +440,8 @@
if (sw->type == SW_ID_3DP && sw->length == 66 /* Many packets OK */
&& sw->ok > SW_OK) {
- printk(KERN_INFO "sidewinder.c: No more trouble on gameport%d"
- " - enabling optimization again.\n", sw->gameport->number);
+ printk(KERN_INFO "sidewinder.c: No more trouble on %s"
+ " - enabling optimization again.\n", sw->gameport->phys);
sw->length = 22;
}
@@ -450,15 +453,15 @@
if (sw->type == SW_ID_3DP && sw->length == 22 && sw->fail > SW_BAD) { /* Consecutive bad packets */
- printk(KERN_INFO "sidewinder.c: Many bit errors on gameport%d"
- " - disabling optimization.\n", sw->gameport->number);
+ printk(KERN_INFO "sidewinder.c: Many bit errors on %s"
+ " - disabling optimization.\n", sw->gameport->phys);
sw->length = 66;
}
if (sw->fail < SW_FAIL) return -1; /* Not enough, don't reinitialize yet */
- printk(KERN_WARNING "sidewinder.c: Too many bit errors on gameport%d"
- " - reinitializing joystick.\n", sw->gameport->number);
+ printk(KERN_WARNING "sidewinder.c: Too many bit errors on %s"
+ " - reinitializing joystick.\n", sw->gameport->phys);
if (!i && sw->type == SW_ID_3DP) { /* 3D Pro can be in analog mode */
udelay(3 * SW_TIMEOUT);
@@ -582,8 +585,8 @@
if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
goto fail1;
- dbg("Init 0: Opened gameport %d, io %#x, speed %d",
- gameport->number, gameport->io, gameport->speed);
+ dbg("Init 0: Opened %s, io %#x, speed %d",
+ gameport->phys, gameport->io, gameport->speed);
i = sw_read_packet(gameport, buf, SW_LENGTH, 0); /* Read normal packet */
m |= sw_guess_mode(buf, i); /* Data packet (1-bit) can carry mode info [FSP] */
@@ -673,7 +676,7 @@
if (sw->type == -1) {
printk(KERN_WARNING "sidewinder.c: unknown joystick device detected "
- "on gameport%d, contact <vojtech@suse.cz>\n", gameport->number);
+ "on %s, contact <vojtech@ucw.cz>\n", gameport->phys);
sw_print_packet("ID", j * 3, idbuf, 3);
sw_print_packet("Data", i * m, buf, m);
goto fail2;
@@ -691,6 +694,7 @@
int bits, code;
sprintf(sw->name, "Microsoft SideWinder %s", sw_name[sw->type]);
+ sprintf(sw->phys[i], "%s/input%d", gameport->phys, i);
sw->dev[i].private = sw;
@@ -698,6 +702,7 @@
sw->dev[i].close = sw_close;
sw->dev[i].name = sw->name;
+ sw->dev[i].phys = sw->phys[i];
sw->dev[i].idbus = BUS_GAMEPORT;
sw->dev[i].idvendor = GAMEPORT_ID_VENDOR_MICROSOFT;
sw->dev[i].idproduct = sw->type;
@@ -719,8 +724,8 @@
set_bit(code, sw->dev[i].keybit);
input_register_device(sw->dev + i);
- printk(KERN_INFO "input%d: %s%s on gameport%d.%d [%d-bit id %d data %d]\n",
- sw->dev[i].number, sw->name, comment, gameport->number, i, m, l, k);
+ printk(KERN_INFO "input: %s%s on %s [%d-bit id %d data %d]\n",
+ sw->name, comment, gameport->phys, m, l, k);
}
return;
@@ -757,5 +762,3 @@
module_init(sw_init);
module_exit(sw_exit);
-
-MODULE_LICENSE("GPL");
diff -urN linux-2.4.10/drivers/char/joystick/spaceball.c linux/drivers/char/joystick/spaceball.c
--- linux-2.4.10/drivers/char/joystick/spaceball.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/spaceball.c Tue Sep 25 12:45:10 2001
@@ -1,17 +1,15 @@
/*
- * $Id: spaceball.c,v 1.8 2000/11/23 11:42:39 vojtech Exp $
+ * $Id: spaceball.c,v 1.16 2001/09/25 10:12:07 vojtech Exp $
*
- * Copyright (c) 1999-2000 Vojtech Pavlik
+ * Copyright (c) 1999-2001 Vojtech Pavlik
*
* Based on the work of:
* David Thompson
* Joseph Krahn
- *
- * Sponsored by SuSE
*/
/*
- * SpaceTec SpaceBall 4000 FLX driver for Linux
+ * SpaceTec SpaceBall 2003/3003/4000 FLX driver for Linux
*/
/*
@@ -30,8 +28,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/kernel.h>
@@ -41,13 +39,29 @@
#include <linux/input.h>
#include <linux/serio.h>
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("SpaceTec SpaceBall 2003/3003/4000 FLX driver");
+MODULE_LICENSE("GPL");
+
/*
* Constants.
*/
-#define JS_SBALL_MAX_LENGTH 128
+#define SPACEBALL_MAX_LENGTH 128
+#define SPACEBALL_MAX_ID 8
+
+#define SPACEBALL_1003 1
+#define SPACEBALL_2003B 3
+#define SPACEBALL_2003C 4
+#define SPACEBALL_3003C 7
+#define SPACEBALL_4000FLX 8
+#define SPACEBALL_4000FLX_L 9
+
static int spaceball_axes[] = { ABS_X, ABS_Z, ABS_Y, ABS_RX, ABS_RZ, ABS_RY };
-static char *spaceball_name = "SpaceTec SpaceBall 4000 FLX";
+static char *spaceball_names[] = {
+ "?", "SpaceTec SpaceBall 1003", "SpaceTec SpaceBall 2003", "SpaceTec SpaceBall 2003B",
+ "SpaceTec SpaceBall 2003C", "SpaceTec SpaceBall 3003", "SpaceTec SpaceBall SpaceController",
+ "SpaceTec SpaceBall 3003C", "SpaceTec SpaceBall 4000FLX", "SpaceTec SpaceBall 4000FLX Lefty" };
/*
* Per-Ball data.
@@ -58,7 +72,8 @@
struct serio *serio;
int idx;
int escape;
- unsigned char data[JS_SBALL_MAX_LENGTH];
+ unsigned char data[SPACEBALL_MAX_LENGTH];
+ char phys[32];
};
/*
@@ -74,35 +89,53 @@
if (spaceball->idx < 2) return;
- printk("%c %d\n", spaceball->data[0], spaceball->idx);
-
switch (spaceball->data[0]) {
- case '@': /* Reset packet */
- spaceball->data[spaceball->idx - 1] = 0;
- for (i = 1; i < spaceball->idx && spaceball->data[i] == ' '; i++);
- printk(KERN_INFO "input%d: %s [%s] on serio%d\n",
- spaceball->dev.number, spaceball_name, spaceball->data + i, spaceball->serio->number);
- break;
-
case 'D': /* Ball data */
if (spaceball->idx != 15) return;
- for (i = 0; i < 6; i++) {
+ for (i = 0; i < 6; i++)
input_report_abs(dev, spaceball_axes[i],
(__s16)((data[2 * i + 3] << 8) | data[2 * i + 2]));
- }
break;
- case '.': /* Button data, part2 */
+ case 'K': /* Button data */
if (spaceball->idx != 3) return;
- input_report_key(dev, BTN_0, data[2] & 1);
- input_report_key(dev, BTN_1, data[2] & 2);
+ input_report_key(dev, BTN_1, (data[2] & 0x01) || (data[2] & 0x20));
+ input_report_key(dev, BTN_2, data[2] & 0x02);
+ input_report_key(dev, BTN_3, data[2] & 0x04);
+ input_report_key(dev, BTN_4, data[2] & 0x08);
+ input_report_key(dev, BTN_5, data[1] & 0x01);
+ input_report_key(dev, BTN_6, data[1] & 0x02);
+ input_report_key(dev, BTN_7, data[1] & 0x04);
+ input_report_key(dev, BTN_8, data[1] & 0x10);
break;
- case '?': /* Error packet */
+ case '.': /* Advanced button data */
+ if (spaceball->idx != 3) return;
+ input_report_key(dev, BTN_1, data[2] & 0x01);
+ input_report_key(dev, BTN_2, data[2] & 0x02);
+ input_report_key(dev, BTN_3, data[2] & 0x04);
+ input_report_key(dev, BTN_4, data[2] & 0x08);
+ input_report_key(dev, BTN_5, data[2] & 0x10);
+ input_report_key(dev, BTN_6, data[2] & 0x20);
+ input_report_key(dev, BTN_7, data[2] & 0x80);
+ input_report_key(dev, BTN_8, data[1] & 0x01);
+ input_report_key(dev, BTN_9, data[1] & 0x02);
+ input_report_key(dev, BTN_A, data[1] & 0x04);
+ input_report_key(dev, BTN_B, data[1] & 0x08);
+ input_report_key(dev, BTN_C, data[1] & 0x10);
+ input_report_key(dev, BTN_MODE, data[1] & 0x20);
+ break;
+
+ case 'E': /* Device error */
spaceball->data[spaceball->idx - 1] = 0;
printk(KERN_ERR "spaceball: Device error. [%s]\n", spaceball->data + 1);
break;
+
+ case '?': /* Bad command packet */
+ spaceball->data[spaceball->idx - 1] = 0;
+ printk(KERN_ERR "spaceball: Bad command. [%s]\n", spaceball->data + 1);
+ break;
}
}
@@ -136,11 +169,9 @@
data &= 0x1f;
}
default:
- if (spaceball->escape) {
+ if (spaceball->escape)
spaceball->escape = 0;
- printk(KERN_WARNING "spaceball.c: Unknown escaped character: %#x (%c)\n", data, data);
- }
- if (spaceball->idx < JS_SBALL_MAX_LENGTH)
+ if (spaceball->idx < SPACEBALL_MAX_LENGTH)
spaceball->data[spaceball->idx++] = data;
return;
}
@@ -167,9 +198,12 @@
static void spaceball_connect(struct serio *serio, struct serio_dev *dev)
{
struct spaceball *spaceball;
- int i, t;
+ int i, t, id;
- if (serio->type != (SERIO_RS232 | SERIO_SPACEBALL))
+ if ((serio->type & ~SERIO_ID) != (SERIO_RS232 | SERIO_SPACEBALL))
+ return;
+
+ if ((id = (serio->type & SERIO_ID) >> 8) > SPACEBALL_MAX_ID)
return;
if (!(spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL)))
@@ -177,7 +211,18 @@
memset(spaceball, 0, sizeof(struct spaceball));
spaceball->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- spaceball->dev.keybit[LONG(BTN_0)] = BIT(BTN_0) | BIT(BTN_1);
+
+ switch (id) {
+ case SPACEBALL_4000FLX:
+ case SPACEBALL_4000FLX_L:
+ spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_9);
+ spaceball->dev.keybit[LONG(BTN_A)] |= BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_MODE);
+ default:
+ spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4)
+ | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7) | BIT(BTN_8);
+ case SPACEBALL_3003C:
+ spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_1) | BIT(BTN_8);
+ }
for (i = 0; i < 6; i++) {
t = spaceball_axes[i];
@@ -191,10 +236,13 @@
spaceball->serio = serio;
spaceball->dev.private = spaceball;
- spaceball->dev.name = spaceball_name;
+ sprintf(spaceball->phys, "%s/input0", serio->phys);
+
+ spaceball->dev.name = spaceball_names[id];
+ spaceball->dev.phys = spaceball->phys;
spaceball->dev.idbus = BUS_RS232;
spaceball->dev.idvendor = SERIO_SPACEBALL;
- spaceball->dev.idproduct = 0x0001;
+ spaceball->dev.idproduct = id;
spaceball->dev.idversion = 0x0100;
serio->private = spaceball;
@@ -205,6 +253,9 @@
}
input_register_device(&spaceball->dev);
+
+ printk(KERN_INFO "input: %s on serio%s\n",
+ spaceball_names[id], serio->phys);
}
/*
@@ -234,5 +285,3 @@
module_init(spaceball_init);
module_exit(spaceball_exit);
-
-MODULE_LICENSE("GPL");
diff -urN linux-2.4.10/drivers/char/joystick/spaceorb.c linux/drivers/char/joystick/spaceorb.c
--- linux-2.4.10/drivers/char/joystick/spaceorb.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/spaceorb.c Tue Sep 25 12:45:10 2001
@@ -1,12 +1,10 @@
/*
- * $Id: spaceorb.c,v 1.7 2000/05/29 11:19:51 vojtech Exp $
+ * $Id: spaceorb.c,v 1.14 2001/09/25 10:12:07 vojtech Exp $
*
- * Copyright (c) 1999-2000 Vojtech Pavlik
+ * Copyright (c) 1999-2001 Vojtech Pavlik
*
* Based on the work of:
* David Thompson
- *
- * Sponsored by SuSE
*/
/*
@@ -29,8 +27,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/kernel.h>
@@ -40,15 +38,19 @@
#include <linux/input.h>
#include <linux/serio.h>
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("SpaceTec SpaceOrb 360 and Avenger 6dof controller driver");
+MODULE_LICENSE("GPL");
+
/*
* Constants.
*/
#define SPACEORB_MAX_LENGTH 64
-static int spaceorb_buttons[] = { BTN_TL, BTN_TR, BTN_Y, BTN_X, BTN_B, BTN_A, BTN_MODE};
-static int spaceorb_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ};
-static char *spaceorb_name = "SpaceTec SpaceOrb 360";
+static int spaceorb_buttons[] = { BTN_TL, BTN_TR, BTN_Y, BTN_X, BTN_B, BTN_A };
+static int spaceorb_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ };
+static char *spaceorb_name = "SpaceTec SpaceOrb 360 / Avenger";
/*
* Per-Orb data.
@@ -59,6 +61,7 @@
struct serio *serio;
int idx;
unsigned char data[SPACEORB_MAX_LENGTH];
+ char phys[32];
};
static unsigned char spaceorb_xor[] = "SpaceWare";
@@ -88,8 +91,8 @@
case 'R': /* Reset packet */
spaceorb->data[spaceorb->idx - 1] = 0;
for (i = 1; i < spaceorb->idx && spaceorb->data[i] == ' '; i++);
- printk(KERN_INFO "input%d: %s [%s] on serio%d\n",
- spaceorb->dev.number, spaceorb_name, spaceorb->data + i, spaceorb->serio->number);
+ printk(KERN_INFO "input: %s [%s] on %s\n",
+ spaceorb_name, spaceorb->data + i, spaceorb->serio->phys);
break;
case 'D': /* Ball + button data */
@@ -103,7 +106,7 @@
axes[5] = ((data[9] & 0x3f) << 4) | (data[10] >> 3);
for (i = 0; i < 6; i++)
input_report_abs(dev, spaceorb_axes[i], axes[i] - ((axes[i] & 0x200) ? 1024 : 0));
- for (i = 0; i < 8; i++)
+ for (i = 0; i < 6; i++)
input_report_key(dev, spaceorb_buttons[i], (data[1] >> i) & 1);
break;
@@ -167,8 +170,8 @@
spaceorb->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- for (i = 0; i < 7; i++)
- set_bit(spaceorb_buttons[i], &spaceorb->dev.keybit);
+ for (i = 0; i < 6; i++)
+ set_bit(spaceorb_buttons[i], spaceorb->dev.keybit);
for (i = 0; i < 6; i++) {
t = spaceorb_axes[i];
@@ -180,7 +183,10 @@
spaceorb->serio = serio;
spaceorb->dev.private = spaceorb;
+ sprintf(spaceorb->phys, "%s/input0", serio->phys);
+
spaceorb->dev.name = spaceorb_name;
+ spaceorb->dev.phys = spaceorb->phys;
spaceorb->dev.idbus = BUS_RS232;
spaceorb->dev.idvendor = SERIO_SPACEORB;
spaceorb->dev.idproduct = 0x0001;
@@ -223,5 +229,3 @@
module_init(spaceorb_init);
module_exit(spaceorb_exit);
-
-MODULE_LICENSE("GPL");
diff -urN linux-2.4.10/drivers/char/joystick/stinger.c linux/drivers/char/joystick/stinger.c
--- linux-2.4.10/drivers/char/joystick/stinger.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/stinger.c Tue Sep 25 12:45:10 2001
@@ -1,10 +1,8 @@
/*
- * $Id: stinger.c,v 1.4 2001/05/23 09:25:02 vojtech Exp $
+ * $Id: stinger.c,v 1.9 2001/09/25 10:12:07 vojtech Exp $
*
* Copyright (c) 2000-2001 Vojtech Pavlik
* Copyright (c) 2000 Mark Fletcher
- *
- * Sponsored by SuSE
*/
/*
@@ -28,7 +26,7 @@
*
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/kernel.h>
@@ -38,6 +36,10 @@
#include <linux/serio.h>
#include <linux/init.h>
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Gravis Stinger gamepad driver");
+MODULE_LICENSE("GPL");
+
/*
* Constants.
*/
@@ -54,6 +56,7 @@
struct input_dev dev;
int idx;
unsigned char data[STINGER_MAX_LENGTH];
+ char phys[32];
};
/*
@@ -145,7 +148,10 @@
BIT(BTN_START) | BIT(BTN_SELECT);
stinger->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+ sprintf(stinger->phys, "%s/serio0", serio->phys);
+
stinger->dev.name = stinger_name;
+ stinger->dev.phys = stinger->phys;
stinger->dev.idbus = BUS_RS232;
stinger->dev.idvendor = SERIO_STINGER;
stinger->dev.idproduct = 0x0001;
@@ -168,7 +174,7 @@
input_register_device(&stinger->dev);
- printk(KERN_INFO "input%d: %s on serio%d\n", stinger->dev.number, stinger_name, serio->number);
+ printk(KERN_INFO "input: %s on %s\n", stinger_name, serio->phys);
}
/*
@@ -198,5 +204,3 @@
module_init(stinger_init);
module_exit(stinger_exit);
-
-MODULE_LICENSE("GPL");
diff -urN linux-2.4.10/drivers/char/joystick/tmdc.c linux/drivers/char/joystick/tmdc.c
--- linux-2.4.10/drivers/char/joystick/tmdc.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/tmdc.c Tue Sep 25 12:45:10 2001
@@ -1,13 +1,10 @@
/*
- * $Id: tmdc.c,v 1.23 2000/11/29 19:52:24 vojtech Exp $
+ * $Id: tmdc.c,v 1.30 2001/09/25 10:12:07 vojtech Exp $
*
- * Copyright (c) 1998-2000 Vojtech Pavlik
- *
- * Sponsored by SuSE
+ * Copyright (c) 1998-2001 Vojtech Pavlik
*
* Based on the work of:
* Trystan Larey-Williams
- *
*/
/*
@@ -30,8 +27,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/delay.h>
@@ -42,6 +39,10 @@
#include <linux/gameport.h>
#include <linux/input.h>
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("ThrustMaster DirectConnect joystick driver");
+MODULE_LICENSE("GPL");
+
#define TMDC_MAX_START 400 /* 400 us */
#define TMDC_MAX_STROBE 45 /* 45 us */
#define TMDC_MAX_LENGTH 13
@@ -94,6 +95,7 @@
struct timer_list timer;
struct input_dev dev[2];
char name[2][64];
+ char phys[2][32];
int mode[2];
signed char *abs[2];
short *btn[2];
@@ -172,6 +174,7 @@
if ((r = tmdc_read_packet(tmdc->gameport, data)) != tmdc->exists)
bad = 1;
+ else
for (j = 0; j < 2; j++)
if (r & (1 << j) & tmdc->exists) {
@@ -302,11 +305,14 @@
sprintf(tmdc->name[j], models[m].name, models[m].abs,
(data[j][TMDC_BYTE_DEF] & 0xf) << 3, tmdc->mode[j]);
+ sprintf(tmdc->phys[j], "%s/input%d", gameport->phys, j);
+
tmdc->dev[j].private = tmdc;
tmdc->dev[j].open = tmdc_open;
tmdc->dev[j].close = tmdc_close;
tmdc->dev[j].name = tmdc->name[j];
+ tmdc->dev[j].phys = tmdc->phys[j];
tmdc->dev[j].idbus = BUS_GAMEPORT;
tmdc->dev[j].idvendor = GAMEPORT_ID_VENDOR_THRUSTMASTER;
tmdc->dev[j].idproduct = models[m].id;
@@ -336,8 +342,7 @@
}
input_register_device(tmdc->dev + j);
- printk(KERN_INFO "input%d: %s on gameport%d.%d\n",
- tmdc->dev[j].number, tmdc->name[j], gameport->number, j);
+ printk(KERN_INFO "input: %s on %s\n", tmdc->name[j], gameport->phys);
}
return;
@@ -374,5 +379,3 @@
module_init(tmdc_init);
module_exit(tmdc_exit);
-
-MODULE_LICENSE("GPL");
diff -urN linux-2.4.10/drivers/char/joystick/turbografx.c linux/drivers/char/joystick/turbografx.c
--- linux-2.4.10/drivers/char/joystick/turbografx.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/turbografx.c Tue Sep 25 12:45:10 2001
@@ -1,12 +1,10 @@
/*
- * $Id: turbografx.c,v 1.8 2000/05/29 20:39:38 vojtech Exp $
+ * $Id: turbografx.c,v 1.13 2001/09/25 10:12:07 vojtech Exp $
*
- * Copyright (c) 1998-2000 Vojtech Pavlik
+ * Copyright (c) 1998-2001 Vojtech Pavlik
*
* Based on the work of:
* Steffen Schwenke
- *
- * Sponsored by SuSE
*/
/*
@@ -29,8 +27,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/kernel.h>
@@ -39,8 +37,10 @@
#include <linux/module.h>
#include <linux/init.h>
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("TurboGraFX parallel port interface driver");
MODULE_LICENSE("GPL");
+
MODULE_PARM(tgfx, "2-8i");
MODULE_PARM(tgfx_2, "2-8i");
MODULE_PARM(tgfx_3, "2-8i");
@@ -69,6 +69,7 @@
struct pardevice *pd;
struct timer_list timer;
struct input_dev dev[7];
+ char phys[7][32];
int sticks;
int used;
} *tgfx_base[3];
@@ -174,7 +175,10 @@
tgfx->dev[i].open = tgfx_open;
tgfx->dev[i].close = tgfx_close;
+ sprintf(tgfx->phys[i], "%s/input0", tgfx->pd->port->name);
+
tgfx->dev[i].name = tgfx_name;
+ tgfx->dev[i].phys = tgfx->phys[i];
tgfx->dev[i].idbus = BUS_PARPORT;
tgfx->dev[i].idvendor = 0x0003;
tgfx->dev[i].idproduct = config[i+1];
@@ -190,8 +194,8 @@
tgfx->dev[i].absmin[ABS_Y] = -1; tgfx->dev[i].absmax[ABS_Y] = 1;
input_register_device(tgfx->dev + i);
- printk(KERN_INFO "input%d: %d-button Multisystem joystick on %s\n",
- tgfx->dev[i].number, config[i+1], tgfx->pd->port->name);
+ printk(KERN_INFO "input: %d-button Multisystem joystick on %s\n",
+ config[i+1], tgfx->pd->port->name);
}
if (!tgfx->sticks) {
diff -urN linux-2.4.10/drivers/char/joystick/usbpath.h linux/drivers/char/joystick/usbpath.h
--- linux-2.4.10/drivers/char/joystick/usbpath.h Thu Jan 1 01:00:00 1970
+++ linux/drivers/char/joystick/usbpath.h Tue Sep 25 12:45:10 2001
@@ -0,0 +1,35 @@
+
+static int usb_make_path(struct usb_device *dev, char *buf, int maxlen)
+{
+ struct usb_device *pdev = dev->parent;
+ char *tmp, *port;
+ int i;
+
+ if (!(port = kmalloc(maxlen, GFP_KERNEL)))
+ return -1;
+ if (!(tmp = kmalloc(maxlen, GFP_KERNEL)))
+ return -1;
+
+ *port = 0;
+
+ while (pdev) {
+
+ for (i = 0; i < pdev->maxchild; i++)
+ if (pdev->children[i] == dev)
+ break;
+
+ if (pdev->children[i] != dev)
+ return -1;
+
+ strcpy(tmp, port);
+
+ sprintf(port, strlen(port) ? "%d.%s" : "%d", i + 1, tmp);
+
+ dev = pdev;
+ pdev = dev->parent;
+ }
+
+ sprintf(buf, "usb%d:%s", dev->bus->busnum, port);
+ return 0;
+}
+
diff -urN linux-2.4.10/drivers/char/joystick/warrior.c linux/drivers/char/joystick/warrior.c
--- linux-2.4.10/drivers/char/joystick/warrior.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/char/joystick/warrior.c Tue Sep 25 12:45:10 2001
@@ -1,9 +1,7 @@
/*
- * $Id: warrior.c,v 1.8 2000/05/31 13:17:12 vojtech Exp $
+ * $Id: warrior.c,v 1.13 2001/09/25 10:12:07 vojtech Exp $
*
- * Copyright (c) 1999-2000 Vojtech Pavlik
- *
- * Sponsored by SuSE
+ * Copyright (c) 1999-2001 Vojtech Pavlik
*/
/*
@@ -27,7 +25,7 @@
*
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/kernel.h>
@@ -37,6 +35,10 @@
#include <linux/serio.h>
#include <linux/init.h>
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Logitech WingMan Warrior joystick driver");
+MODULE_LICENSE("GPL");
+
/*
* Constants.
*/
@@ -53,6 +55,7 @@
struct input_dev dev;
int idx, len;
unsigned char data[WARRIOR_MAX_LENGTH];
+ char phys[32];
};
/*
@@ -149,7 +152,10 @@
warrior->dev.relbit[0] = BIT(REL_DIAL);
warrior->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y);
+ sprintf(warrior->phys, "%s/input0", serio->phys);
+
warrior->dev.name = warrior_name;
+ warrior->dev.phys = warrior->phys;
warrior->dev.idbus = BUS_RS232;
warrior->dev.idvendor = SERIO_WARRIOR;
warrior->dev.idproduct = 0x0001;
@@ -180,7 +186,7 @@
input_register_device(&warrior->dev);
- printk(KERN_INFO "input%d: Logitech WingMan Warrior on serio%d\n", warrior->dev.number, serio->number);
+ printk(KERN_INFO "input: Logitech WingMan Warrior on %s\n", serio->phys);
}
/*
@@ -210,5 +216,3 @@
module_init(warrior_init);
module_exit(warrior_exit);
-
-MODULE_LICENSE("GPL");
diff -urN linux-2.4.10/drivers/input/evdev.c linux/drivers/input/evdev.c
--- linux-2.4.10/drivers/input/evdev.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/input/evdev.c Tue Sep 25 12:45:02 2001
@@ -1,11 +1,9 @@
/*
- * $Id: evdev.c,v 1.27 2001/05/28 09:06:44 vojtech Exp $
+ * $Id: evdev.c,v 1.37 2001/09/25 10:44:37 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*
* Event char devices, giving access to raw input device events.
- *
- * Sponsored by SuSE
*/
/*
@@ -24,8 +22,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#define EVDEV_MINOR_BASE 64
@@ -39,10 +37,16 @@
#include <linux/input.h>
#include <linux/smp_lock.h>
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Input driver event char devices");
+MODULE_LICENSE("GPL");
+
struct evdev {
int exist;
int open;
+ int open_for_write;
int minor;
+ char name[16];
struct input_handle handle;
wait_queue_head_t wait;
devfs_handle_t devfs;
@@ -89,6 +93,11 @@
return retval < 0 ? retval : 0;
}
+static int evdev_flush(struct file * file)
+{
+ return input_flush_device(&((struct evdev_list*)file->private_data)->evdev->handle, file);
+}
+
static int evdev_release(struct inode * inode, struct file * file)
{
struct evdev_list *list = file->private_data;
@@ -122,10 +131,16 @@
{
struct evdev_list *list;
int i = MINOR(inode->i_rdev) - EVDEV_MINOR_BASE;
+ int accept_err;
if (i >= EVDEV_MINORS || !evdev_table[i])
return -ENODEV;
+ /* Ask the driver if he wishes to accept the open() */
+ if ((accept_err = input_accept_device(&(evdev_table[i]->handle), file))) {
+ return accept_err;
+ }
+
if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL)))
return -ENOMEM;
memset(list, 0, sizeof(struct evdev_list));
@@ -323,9 +338,10 @@
release: evdev_release,
ioctl: evdev_ioctl,
fasync: evdev_fasync,
+ flush: evdev_flush
};
-static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev)
+static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
{
struct evdev *evdev;
int minor;
@@ -344,16 +360,17 @@
evdev->minor = minor;
evdev_table[minor] = evdev;
+
+ sprintf(evdev->name, "event%d", minor);
evdev->handle.dev = dev;
+ evdev->handle.name = evdev->name;
evdev->handle.handler = handler;
evdev->handle.private = evdev;
- evdev->exist = 1;
-
evdev->devfs = input_register_minor("event%d", minor, EVDEV_MINOR_BASE);
-// printk(KERN_INFO "event%d: Event device for input%d\n", minor, dev->number);
+ evdev->exist = 1;
return &evdev->handle;
}
@@ -374,12 +391,21 @@
}
}
+static struct input_device_id evdev_ids[] = {
+ { driver_info: 1 }, /* Matches all devices */
+ { }, /* Terminating zero entry */
+};
+
+MODULE_DEVICE_TABLE(input, evdev_ids);
+
static struct input_handler evdev_handler = {
event: evdev_event,
connect: evdev_connect,
disconnect: evdev_disconnect,
fops: &evdev_fops,
minor: EVDEV_MINOR_BASE,
+ name: "evdev",
+ id_table: evdev_ids,
};
static int __init evdev_init(void)
@@ -396,5 +422,5 @@
module_init(evdev_init);
module_exit(evdev_exit);
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Event character device driver");
diff -urN linux-2.4.10/drivers/input/input.c linux/drivers/input/input.c
--- linux-2.4.10/drivers/input/input.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/input/input.c Tue Sep 25 12:45:02 2001
@@ -1,11 +1,9 @@
/*
- * $Id: input.c,v 1.20 2001/05/17 15:50:27 vojtech Exp $
+ * $Id: input.c,v 1.44 2001/09/25 10:12:07 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*
- * The input layer module itself
- *
- * Sponsored by SuSE
+ * The input core
*/
/*
@@ -24,8 +22,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/init.h>
@@ -34,9 +32,15 @@
#include <linux/input.h>
#include <linux/module.h>
#include <linux/random.h>
-
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("Input layer module");
+#include <linux/pm.h>
+#include <linux/proc_fs.h>
+#include <linux/kmod.h>
+#include <linux/interrupt.h>
+#include <linux/poll.h>
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Input core");
+MODULE_LICENSE("GPL");
EXPORT_SYMBOL(input_register_device);
EXPORT_SYMBOL(input_unregister_device);
@@ -46,6 +50,8 @@
EXPORT_SYMBOL(input_unregister_minor);
EXPORT_SYMBOL(input_open_device);
EXPORT_SYMBOL(input_close_device);
+EXPORT_SYMBOL(input_accept_device);
+EXPORT_SYMBOL(input_flush_device);
EXPORT_SYMBOL(input_event);
#define INPUT_MAJOR 13
@@ -55,20 +61,32 @@
static struct input_handler *input_handler;
static struct input_handler *input_table[8];
static devfs_handle_t input_devfs_handle;
-static int input_number;
-static long input_devices[NBITS(INPUT_DEVICES)];
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *proc_bus_input_dir;
+DECLARE_WAIT_QUEUE_HEAD(input_devices_poll_wait);
+static int input_devices_state;
+#endif
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
struct input_handle *handle = dev->handle;
/*
+ * Wake up the device if it is sleeping.
+ */
+ if (dev->pm_dev)
+ pm_access(dev->pm_dev);
+
+/*
* Filter non-events, and bad input values out.
*/
if (type > EV_MAX || !test_bit(type, dev->evbit))
return;
+ add_mouse_randomness((type << 4) ^ code ^ (code >> 4) ^ value);
+
switch (type) {
case EV_KEY:
@@ -183,16 +201,36 @@
mod_timer(&dev->timer, jiffies + dev->rep[REP_PERIOD]);
}
+int input_accept_device(struct input_handle *handle, struct file *file)
+{
+ if (handle->dev->accept)
+ return handle->dev->accept(handle->dev, file);
+
+ return 0;
+}
+
int input_open_device(struct input_handle *handle)
{
+ if (handle->dev->pm_dev)
+ pm_access(handle->dev->pm_dev);
handle->open++;
if (handle->dev->open)
return handle->dev->open(handle->dev);
return 0;
}
+int input_flush_device(struct input_handle* handle, struct file* file)
+{
+ if (handle->dev->flush)
+ return handle->dev->flush(handle->dev, file);
+
+ return 0;
+}
+
void input_close_device(struct input_handle *handle)
{
+ if (handle->dev->pm_dev)
+ pm_dev_idle(handle->dev->pm_dev);
if (handle->dev->close)
handle->dev->close(handle->dev);
handle->open--;
@@ -206,25 +244,197 @@
handle->handler->handle = handle;
}
+/**
+ * input_find_and_remove - Find and remove node
+ *
+ * @type: data type
+ * @initval: initial value
+ * @targ: node to find
+ * @next: next node in the list
+ *
+ * Searches the linked list for the target node @targ. If the node
+ * is found, it is removed from the list.
+ *
+ * If the node is not found, the end of the list will be hit,
+ * indicating that it wasn't in the list to begin with.
+ *
+ * Returns nothing.
+ */
+#define input_find_and_remove(type, initval, targ, next) \
+ do { \
+ type **ptr; \
+ for (ptr = &initval; *ptr; ptr = &((*ptr)->next)) \
+ if (*ptr == targ) break; \
+ if (*ptr) *ptr = (*ptr)->next; \
+ } while (0)
+
static void input_unlink_handle(struct input_handle *handle)
{
- struct input_handle **handleptr;
+ input_find_and_remove(struct input_handle, handle->dev->handle, handle, dnext);
+ input_find_and_remove(struct input_handle, handle->handler->handle, handle, hnext);
+}
+
+#define MATCH_BIT(bit, max) \
+ for (i = 0; i < NBITS(max); i++) \
+ if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \
+ break; \
+ if (i != NBITS(max)) \
+ continue;
+
+static struct input_device_id *input_match_device(struct input_device_id *id, struct input_dev *dev)
+{
+ int i;
+
+ for (; id->flags || id->driver_info; id++) {
+
+ if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
+ if (id->idbus != dev->idbus)
+ continue;
+
+ if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR)
+ if (id->idvendor != dev->idvendor)
+ continue;
+
+ if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT)
+ if (id->idproduct != dev->idproduct)
+ continue;
+
+ if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
+ if (id->idversion != dev->idversion)
+ continue;
+
+ MATCH_BIT(evbit, EV_MAX);
+ MATCH_BIT(keybit, KEY_MAX);
+ MATCH_BIT(relbit, REL_MAX);
+ MATCH_BIT(absbit, ABS_MAX);
+ MATCH_BIT(mscbit, MSC_MAX);
+ MATCH_BIT(ledbit, LED_MAX);
+ MATCH_BIT(sndbit, SND_MAX);
+ MATCH_BIT(ffbit, FF_MAX);
+
+ return id;
+ }
+
+ return NULL;
+}
+
+/*
+ * Input hotplugging interface - loading event handlers based on
+ * device bitfields.
+ */
+
+#ifdef CONFIG_HOTPLUG
+
+/*
+ * Input hotplugging invokes what /proc/sys/kernel/hotplug says
+ * (normally /sbin/hotplug) when input devices get added or removed.
+ *
+ * This invokes a user mode policy agent, typically helping to load driver
+ * or other modules, configure the device, and more. Drivers can provide
+ * a MODULE_DEVICE_TABLE to help with module loading subtasks.
+ *
+ */
+
+#define SPRINTF_BIT_A(bit, name, max) \
+ do { \
+ envp[i++] = scratch; \
+ scratch += sprintf(scratch, name); \
+ for (j = NBITS(max) - 1; j >= 0; j--) \
+ if (dev->bit[j]) break; \
+ for (; j >= 0; j--) \
+ scratch += sprintf(scratch, "%lx ", dev->bit[j]); \
+ scratch++; \
+ } while (0)
+
+#define SPRINTF_BIT_A2(bit, name, max, ev) \
+ do { \
+ if (test_bit(ev, dev->evbit)) \
+ SPRINTF_BIT_A(bit, name, max); \
+ } while (0)
+
+static void input_call_hotplug(char *verb, struct input_dev *dev)
+{
+ char *argv[3], **envp, *buf, *scratch;
+ int i = 0, j, value;
+
+ if (!hotplug_path[0]) {
+ printk(KERN_ERR "input.c: calling hotplug a hotplug agent defined\n");
+ return;
+ }
+ if (in_interrupt()) {
+ printk(KERN_ERR "input.c: calling hotplug from interrupt\n");
+ return;
+ }
+ if (!current->fs->root) {
+ printk(KERN_WARNING "input.c: calling hotplug without valid filesystem\n");
+ return;
+ }
+ if (!(envp = (char **) kmalloc(20 * sizeof(char *), GFP_KERNEL))) {
+ printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n");
+ return;
+ }
+ if (!(buf = kmalloc(1024, GFP_KERNEL))) {
+ kfree (envp);
+ printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n");
+ return;
+ }
+
+ argv[0] = hotplug_path;
+ argv[1] = "input";
+ argv[2] = 0;
+
+ envp[i++] = "HOME=/";
+ envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+
+ scratch = buf;
+
+ envp[i++] = scratch;
+ scratch += sprintf(scratch, "ACTION=%s", verb) + 1;
+
+ envp[i++] = scratch;
+ scratch += sprintf(scratch, "PRODUCT=%x/%x/%x/%x",
+ dev->idbus, dev->idvendor, dev->idproduct, dev->idversion) + 1;
+
+ if (dev->name) {
+ envp[i++] = scratch;
+ scratch += sprintf(scratch, "NAME=%s", dev->name) + 1;
+ }
+
+ if (dev->phys) {
+ envp[i++] = scratch;
+ scratch += sprintf(scratch, "PHYS=%s", dev->phys) + 1;
+ ]
+
+ SPRINTF_BIT_A(evbit, "EV=", EV_MAX);
+ SPRINTF_BIT_A2(keybit, "KEY=", KEY_MAX, EV_KEY);
+ SPRINTF_BIT_A2(relbit, "REL=", REL_MAX, EV_REL);
+ SPRINTF_BIT_A2(absbit, "ABS=", ABS_MAX, EV_ABS);
+ SPRINTF_BIT_A2(mscbit, "MSC=", MSC_MAX, EV_MSC);
+ SPRINTF_BIT_A2(ledbit, "LED=", LED_MAX, EV_LED);
+ SPRINTF_BIT_A2(sndbit, "SND=", SND_MAX, EV_SND);
+ SPRINTF_BIT_A2(ffbit, "FF=", FF_MAX, EV_FF);
+
+ envp[i++] = 0;
+
+ printk(KERN_DEBUG "input.c: calling %s %s [%s %s %s %s %s]\n",
+ argv[0], argv[1], envp[0], envp[1], envp[2], envp[3], envp[4]);
- handleptr = &handle->dev->handle;
- while (*handleptr && (*handleptr != handle))
- handleptr = &((*handleptr)->dnext);
- *handleptr = (*handleptr)->dnext;
-
- handleptr = &handle->handler->handle;
- while (*handleptr && (*handleptr != handle))
- handleptr = &((*handleptr)->hnext);
- *handleptr = (*handleptr)->hnext;
+ value = call_usermodehelper(argv [0], argv, envp);
+
+ kfree(buf);
+ kfree(envp);
+
+ if (value != 0)
+ printk(KERN_WARNING "input.c: hotplug returned %d\n", value);
}
+#endif
+
void input_register_device(struct input_dev *dev)
{
struct input_handler *handler = input_handler;
struct input_handle *handle;
+ struct input_device_id *id;
/*
* Initialize repeat timer to default values.
@@ -240,35 +450,51 @@
* Add the device.
*/
- if (input_number >= INPUT_DEVICES) {
- printk(KERN_WARNING "input: ran out of input device numbers!\n");
- dev->number = input_number;
- } else {
- dev->number = find_first_zero_bit(input_devices, INPUT_DEVICES);
- set_bit(dev->number, input_devices);
- }
-
dev->next = input_dev;
input_dev = dev;
- input_number++;
/*
* Notify handlers.
*/
while (handler) {
- if ((handle = handler->connect(handler, dev)))
- input_link_handle(handle);
+ if ((id = input_match_device(handler->id_table, dev)))
+ if ((handle = handler->connect(handler, dev, id)))
+ input_link_handle(handle);
handler = handler->next;
}
+
+/*
+ * Notify the hotplug agent.
+ */
+
+#ifdef CONFIG_HOTPLUG
+ input_call_hotplug("add", dev);
+#endif
+
+/*
+ * Notify /proc.
+ */
+
+#ifdef CONFIG_PROC_FS
+ input_devices_state++;
+ wake_up(&input_devices_poll_wait);
+#endif
}
void input_unregister_device(struct input_dev *dev)
{
struct input_handle *handle = dev->handle;
- struct input_dev **devptr = &input_dev;
struct input_handle *dnext;
+ if (!dev) return;
+
+/*
+ * Turn off power management for the device.
+ */
+ if (dev->pm_dev)
+ pm_unregister(dev->pm_dev);
+
/*
* Kill any pending repeat timers.
*/
@@ -287,23 +513,35 @@
}
/*
- * Remove the device.
+ * Notify the hotplug agent.
*/
- while (*devptr && (*devptr != dev))
- devptr = &((*devptr)->next);
- *devptr = (*devptr)->next;
+#ifdef CONFIG_HOTPLUG
+ input_call_hotplug("remove", dev);
+#endif
+
+/*
+ * Remove the device.
+ */
+ input_find_and_remove(struct input_dev, input_dev, dev, next);
- input_number--;
+/*
+ * Notify /proc.
+ */
- if (dev->number < INPUT_DEVICES)
- clear_bit(dev->number, input_devices);
+#ifdef CONFIG_PROC_FS
+ input_devices_state++;
+ wake_up(&input_devices_poll_wait);
+#endif
}
void input_register_handler(struct input_handler *handler)
{
struct input_dev *dev = input_dev;
struct input_handle *handle;
+ struct input_device_id *id;
+
+ if (!handler) return;
/*
* Add minors if needed.
@@ -324,15 +562,24 @@
*/
while (dev) {
- if ((handle = handler->connect(handler, dev)))
- input_link_handle(handle);
+ if ((id = input_match_device(handler->id_table, dev)))
+ if ((handle = handler->connect(handler, dev, id)))
+ input_link_handle(handle);
dev = dev->next;
}
+
+/*
+ * Notify /proc.
+ */
+
+#ifdef CONFIG_PROC_FS
+ input_devices_state++;
+ wake_up(&input_devices_poll_wait);
+#endif
}
void input_unregister_handler(struct input_handler *handler)
{
- struct input_handler **handlerptr = &input_handler;
struct input_handle *handle = handler->handle;
struct input_handle *hnext;
@@ -350,18 +597,23 @@
/*
* Remove it.
*/
-
- while (*handlerptr && (*handlerptr != handler))
- handlerptr = &((*handlerptr)->next);
-
- *handlerptr = (*handlerptr)->next;
+ input_find_and_remove(struct input_handler, input_handler, handler,
+ next);
/*
* Remove minors.
*/
-
if (handler->fops != NULL)
input_table[handler->minor >> 5] = NULL;
+
+/*
+ * Notify /proc.
+ */
+
+#ifdef CONFIG_PROC_FS
+ input_devices_state++;
+ wake_up(&input_devices_poll_wait);
+#endif
}
static int input_open_file(struct inode *inode, struct file *file)
@@ -415,18 +667,164 @@
devfs_unregister(handle);
}
+/*
+ * ProcFS interface for the input drivers.
+ */
+
+#ifdef CONFIG_PROC_FS
+
+#define SPRINTF_BIT_B(bit, name, max) \
+ do { \
+ len += sprintf(buf + len, "B: %s", name); \
+ for (i = NBITS(max) - 1; i >= 0; i--) \
+ if (dev->bit[i]) break; \
+ for (; i >= 0; i--) \
+ len += sprintf(buf + len, "%lx ", dev->bit[i]); \
+ len += sprintf(buf + len, "\n"); \
+ } while (0)
+
+#define SPRINTF_BIT_B2(bit, name, max, ev) \
+ do { \
+ if (test_bit(ev, dev->evbit)) \
+ SPRINTF_BIT_B(bit, name, max); \
+ } while (0)
+
+
+static unsigned int input_devices_poll(struct file *file, poll_table *wait)
+{
+ int state = input_devices_state;
+ poll_wait(file, &input_devices_poll_wait, wait);
+ if (state != input_devices_state)
+ return POLLIN | POLLRDNORM;
+ return 0;
+}
+
+static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
+{
+ struct input_dev *dev = input_dev;
+ struct input_handle *handle;
+
+ off_t at = 0;
+ int i, len, cnt = 0;
+
+ while (dev) {
+
+ len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
+ dev->idbus, dev->idvendor, dev->idproduct, dev->idversion);
+
+ len += sprintf(buf + len, "N: Name=\"%s\"\n", dev->name ? dev->name : "");
+ len += sprintf(buf + len, "P: Phys=%s\n", dev->phys ? dev->phys : "");
+ len += sprintf(buf + len, "D: Drivers=");
+
+ handle = dev->handle;
+
+ while (handle) {
+ len += sprintf(buf + len, "%s ", handle->name);
+ handle = handle->dnext;
+ }
+
+ len += sprintf(buf + len, "\n");
+
+ SPRINTF_BIT_B(evbit, "EV=", EV_MAX);
+ SPRINTF_BIT_B2(keybit, "KEY=", KEY_MAX, EV_KEY);
+ SPRINTF_BIT_B2(relbit, "REL=", REL_MAX, EV_REL);
+ SPRINTF_BIT_B2(absbit, "ABS=", ABS_MAX, EV_ABS);
+ SPRINTF_BIT_B2(mscbit, "MSC=", MSC_MAX, EV_MSC);
+ SPRINTF_BIT_B2(ledbit, "LED=", LED_MAX, EV_LED);
+ SPRINTF_BIT_B2(sndbit, "SND=", SND_MAX, EV_SND);
+ SPRINTF_BIT_B2(ffbit, "FF=", FF_MAX, EV_FF);
+
+ len += sprintf(buf + len, "\n");
+
+ at += len;
+
+ if (at >= pos) {
+ if (!*start) {
+ *start = buf + (pos - (at - len));
+ cnt = at - pos;
+ } else cnt += len;
+ buf += len;
+ if (cnt >= count)
+ break;
+ }
+
+ dev = dev->next;
+ }
+
+ if (!dev) *eof = 1;
+
+ return (count > cnt) ? cnt : count;
+}
+
+static int input_handlers_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
+{
+ struct input_handler *handler = input_handler;
+
+ off_t at = 0;
+ int len = 0, cnt = 0;
+ int i = 0;
+
+ while (handler) {
+
+ if (handler->fops)
+ len = sprintf(buf, "N: Number=%d Name=%s Minor=%d\n",
+ i++, handler->name, handler->minor);
+ else
+ len = sprintf(buf, "N: Number=%d Name=%s\n",
+ i++, handler->name);
+
+ at += len;
+
+ if (at >= pos) {
+ if (!*start) {
+ *start = buf + (pos - (at - len));
+ cnt = at - pos;
+ } else cnt += len;
+ buf += len;
+ if (cnt >= count)
+ break;
+ }
+
+ handler = handler->next;
+ }
+
+ if (!handler) *eof = 1;
+
+ return (count > cnt) ? cnt : count;
+}
+
+#endif
+
static int __init input_init(void)
{
+ struct proc_dir_entry *entry;
+
+#ifdef CONFIG_PROC_FS
+ proc_bus_input_dir = proc_mkdir("input", proc_bus);
+ proc_bus_input_dir->owner = THIS_MODULE;
+ entry = create_proc_read_entry("devices", 0, proc_bus_input_dir, input_devices_read, NULL);
+ entry->owner = THIS_MODULE;
+ entry->proc_fops->poll = input_devices_poll;
+ entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL);
+ entry->owner = THIS_MODULE;
+#endif
if (devfs_register_chrdev(INPUT_MAJOR, "input", &input_fops)) {
printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);
return -EBUSY;
}
+
input_devfs_handle = devfs_mk_dir(NULL, "input", NULL);
+
return 0;
}
static void __exit input_exit(void)
{
+#ifdef CONFIG_PROC_FS
+ remove_proc_entry("devices", proc_bus_input_dir);
+ remove_proc_entry("handlers", proc_bus_input_dir);
+ remove_proc_entry("input", proc_bus);
+#endif
devfs_unregister(input_devfs_handle);
if (devfs_unregister_chrdev(INPUT_MAJOR, "input"))
printk(KERN_ERR "input: can't unregister char major %d", INPUT_MAJOR);
diff -urN linux-2.4.10/drivers/input/joydev.c linux/drivers/input/joydev.c
--- linux-2.4.10/drivers/input/joydev.c Thu Apr 12 04:02:30 2001
+++ linux/drivers/input/joydev.c Tue Sep 25 12:45:02 2001
@@ -1,12 +1,10 @@
/*
- * $Id: joydev.c,v 1.19 2001/01/10 19:49:40 vojtech Exp $
+ * $Id: joydev.c,v 1.33 2001/09/25 10:44:37 vojtech Exp $
*
- * Copyright (c) 1999-2000 Vojtech Pavlik
+ * Copyright (c) 1999-2001 Vojtech Pavlik
* Copyright (c) 1999 Colin Van Dyke
*
* Joystick device driver for the input driver suite.
- *
- * Sponsored by SuSE and Intel
*/
/*
@@ -25,8 +23,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <asm/io.h>
@@ -46,14 +44,22 @@
#include <linux/init.h>
#include <linux/smp_lock.h>
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Joystick device interfaces");
+MODULE_SUPPORTED_DEVICE("input/js");
+MODULE_LICENSE("GPL");
+
#define JOYDEV_MINOR_BASE 0
#define JOYDEV_MINORS 32
#define JOYDEV_BUFFER_SIZE 64
+#define MSECS(t) (1000 * ((t) / HZ) + 1000 * ((t) % HZ) / HZ)
+
struct joydev {
int exist;
int open;
int minor;
+ char name[16];
struct input_handle handle;
wait_queue_head_t wait;
devfs_handle_t devfs;
@@ -82,10 +88,6 @@
static struct joydev *joydev_table[JOYDEV_MINORS];
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("Joystick device driver");
-MODULE_SUPPORTED_DEVICE("input/js");
-
static int joydev_correct(int value, struct js_corr *corr)
{
switch (corr->type) {
@@ -133,7 +135,7 @@
return;
}
- event.time = jiffies * (1000 / HZ);
+ event.time = MSECS(jiffies);
while (list) {
@@ -278,7 +280,7 @@
struct js_event event;
- event.time = jiffies * (1000/HZ);
+ event.time = MSECS(jiffies);
if (list->startup < joydev->nkey) {
event.type = JS_EVENT_BUTTON | JS_EVENT_INIT;
@@ -373,11 +375,11 @@
return copy_to_user((__u8 *) arg, joydev->abspam,
sizeof(__u8) * ABS_MAX) ? -EFAULT : 0;
case JSIOCSBTNMAP:
- if (copy_from_user((__u16 *) arg, joydev->absmap, sizeof(__u16) * (KEY_MAX - BTN_MISC)))
+ if (copy_from_user((__u16 *) arg, joydev->keypam, sizeof(__u16) * (KEY_MAX - BTN_MISC)))
return -EFAULT;
for (i = 0; i < KEY_MAX - BTN_MISC; i++); {
if (joydev->keypam[i] > KEY_MAX || joydev->keypam[i] < BTN_MISC) return -EINVAL;
- joydev->keymap[joydev->abspam[i - BTN_MISC]] = i;
+ joydev->keymap[joydev->keypam[i] - BTN_MISC] = i;
}
return 0;
case JSIOCGBTNMAP:
@@ -407,15 +409,13 @@
fasync: joydev_fasync,
};
-static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev)
+static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
{
struct joydev *joydev;
int i, j, minor;
- if (!(test_bit(EV_KEY, dev->evbit) && test_bit(EV_ABS, dev->evbit) &&
- (test_bit(ABS_X, dev->absbit) || test_bit(ABS_Y, dev->absbit)) &&
- (test_bit(BTN_TRIGGER, dev->keybit) || test_bit(BTN_A, dev->keybit)
- || test_bit(BTN_1, dev->keybit)))) return NULL;
+ if (test_bit(BTN_TOUCH, dev->keybit))
+ return NULL;
for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
if (minor == JOYDEV_MINORS) {
@@ -432,12 +432,13 @@
joydev->minor = minor;
joydev_table[minor] = joydev;
+ sprintf(joydev->name, "js%d", minor);
+
joydev->handle.dev = dev;
+ joydev->handle.name = joydev->name;
joydev->handle.handler = handler;
joydev->handle.private = joydev;
- joydev->exist = 1;
-
for (i = 0; i < ABS_MAX; i++)
if (test_bit(i, dev->absbit)) {
joydev->absmap[i] = joydev->nabs;
@@ -477,7 +478,7 @@
joydev->devfs = input_register_minor("js%d", minor, JOYDEV_MINOR_BASE);
-// printk(KERN_INFO "js%d: Joystick device for input%d\n", minor, dev->number);
+ joydev->exist = 1;
return &joydev->handle;
}
@@ -497,12 +498,35 @@
}
}
+static struct input_device_id joydev_ids[] = {
+ {
+ flags: INPUT_DEVICE_ID_MATCH_EVBIT,
+ evbit: { BIT(EV_KEY) | BIT(EV_ABS) },
+ absbit: { BIT(ABS_X) },
+ },
+ {
+ flags: INPUT_DEVICE_ID_MATCH_EVBIT,
+ evbit: { BIT(EV_KEY) | BIT(EV_ABS) },
+ absbit: { BIT(ABS_WHEEL) },
+ },
+ {
+ flags: INPUT_DEVICE_ID_MATCH_EVBIT,
+ evbit: { BIT(EV_KEY) | BIT(EV_ABS) },
+ absbit: { BIT(ABS_THROTTLE) },
+ },
+ { }, /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(input, joydev_ids);
+
static struct input_handler joydev_handler = {
event: joydev_event,
connect: joydev_connect,
disconnect: joydev_disconnect,
fops: &joydev_fops,
minor: JOYDEV_MINOR_BASE,
+ name: "joydev",
+ id_table: joydev_ids,
};
static int __init joydev_init(void)
diff -urN linux-2.4.10/drivers/input/keybdev.c linux/drivers/input/keybdev.c
--- linux-2.4.10/drivers/input/keybdev.c Tue Sep 18 23:10:43 2001
+++ linux/drivers/input/keybdev.c Tue Sep 25 12:45:02 2001
@@ -1,11 +1,9 @@
/*
- * $Id: keybdev.c,v 1.3 2000/05/28 17:31:36 vojtech Exp $
+ * $Id: keybdev.c,v 1.15 2001/09/25 10:44:37 vojtech Exp $
*
- * Copyright (c) 1999-2000 Vojtech Pavlik
+ * Copyright (c) 1999-2001 Vojtech Pavlik
*
- * Input driver to keyboard driver binding.
- *
- * Sponsored by SuSE
+ * Input core to console keyboard binding.
*/
/*
@@ -24,8 +22,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/config.h>
@@ -37,10 +35,16 @@
#include <linux/module.h>
#include <linux/kbd_kern.h>
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Input core to console keyboard binding");
+MODULE_LICENSE("GPL");
+
+char keybdev_name[] = "keyboard";
+
#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(__alpha__) || \
defined(__mips__) || defined(CONFIG_SPARC64) || defined(CONFIG_SUPERH) || \
defined(CONFIG_PPC) || defined(__mc68000__) || defined(__hppa__) || \
- defined(__arm__)
+ defined(__arm__) || defined(__x86_64__)
static int x86_sysrq_alt = 0;
#ifdef CONFIG_SPARC64
@@ -48,8 +52,6 @@
extern void batten_down_hatches(void);
#endif
-static int jp_kbd_109 = 1; /* Yes, .jp is the default. See 51142. */
-
static unsigned short x86_keycodes[256] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
@@ -62,7 +64,7 @@
360, 93, 94, 95, 98,376,100,101,357,316,354,304,289,102,351,355,
103,104,105,275,281,272,306,106,274,107,288,364,358,363,362,361,
291,108,381,290,287,292,279,305,280, 99,112,257,258,113,270,114,
- 118,117,125,374,379,259,260,261,262,263,264,265,266,267,268,269,
+ 118,117,125,374,379,115,112,125,121,123,264,265,266,267,268,269,
271,273,276,277,278,282,283,295,296,297,299,300,301,302,303,307,
308,310,313,314,315,317,318,319,320,321,322,323,324,325,326,330,
332,340,341,342,343,344,345,346,356,359,365,368,369,370,371,372 };
@@ -177,16 +179,14 @@
tasklet_schedule(&keyboard_tasklet);
}
-static struct input_handle *keybdev_connect(struct input_handler *handler, struct input_dev *dev)
+static struct input_handle *keybdev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
{
struct input_handle *handle;
int i;
- if (!test_bit(EV_KEY, dev->evbit))
- return NULL;
-
- for (i = KEY_RESERVED; i < BTN_MISC; i++)
- if (test_bit(i, dev->keybit)) break;
+ for (i = KEY_ESC; i < BTN_MISC; i++)
+ if (test_bit(i, dev->keybit))
+ break;
if (i == BTN_MISC)
return NULL;
@@ -196,41 +196,42 @@
memset(handle, 0, sizeof(struct input_handle));
handle->dev = dev;
+ handle->name = keybdev_name;
handle->handler = handler;
input_open_device(handle);
-// printk(KERN_INFO "keybdev.c: Adding keyboard: input%d\n", dev->number);
-
return handle;
}
static void keybdev_disconnect(struct input_handle *handle)
{
-// printk(KERN_INFO "keybdev.c: Removing keyboard: input%d\n", handle->dev->number);
input_close_device(handle);
kfree(handle);
}
+
+static struct input_device_id keybdev_ids[] = {
+ {
+ flags: INPUT_DEVICE_ID_MATCH_EVBIT,
+ evbit: { BIT(EV_KEY) },
+ },
+ { }, /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(input, keybdev_ids);
static struct input_handler keybdev_handler = {
event: keybdev_event,
connect: keybdev_connect,
disconnect: keybdev_disconnect,
+ name: "keybdev",
+ id_table: keybdev_ids,
};
static int __init keybdev_init(void)
{
input_register_handler(&keybdev_handler);
kbd_ledfunc = keybdev_ledfunc;
-
- if (jp_kbd_109) {
- x86_keycodes[0xb5] = 0x73; /* backslash, underscore */
- x86_keycodes[0xb6] = 0x70;
- x86_keycodes[0xb7] = 0x7d; /* Yen, pipe */
- x86_keycodes[0xb8] = 0x79;
- x86_keycodes[0xb9] = 0x7b;
- }
-
return 0;
}
@@ -243,6 +244,5 @@
module_init(keybdev_init);
module_exit(keybdev_exit);
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Input driver to keyboard driver binding");
-MODULE_PARM(jp_kbd_109, "i");
diff -urN linux-2.4.10/drivers/input/mousedev.c linux/drivers/input/mousedev.c
--- linux-2.4.10/drivers/input/mousedev.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/input/mousedev.c Tue Sep 25 12:45:02 2001
@@ -1,11 +1,9 @@
/*
- * $Id: mousedev.c,v 1.24 2000/11/15 10:57:45 vojtech Exp $
+ * $Id: mousedev.c,v 1.34 2001/09/25 10:12:07 vojtech Exp $
*
- * Copyright (c) 1999-2000 Vojtech Pavlik
+ * Copyright (c) 1999-2001 Vojtech Pavlik
*
- * Input driver to ImExPS/2 device driver module.
- *
- * Sponsored by SuSE
+ * Input driver to ExplorerPS/2 device driver module.
*/
/*
@@ -24,8 +22,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#define MOUSEDEV_MINOR_BASE 32
@@ -41,6 +39,10 @@
#include <linux/smp_lock.h>
#include <linux/random.h>
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Mouse (ExplorerPS/2) device interfaces");
+MODULE_LICENSE("GPL");
+
#ifndef CONFIG_INPUT_MOUSEDEV_SCREEN_X
#define CONFIG_INPUT_MOUSEDEV_SCREEN_X 1024
#endif
@@ -52,6 +54,7 @@
int exist;
int open;
int minor;
+ char name[16];
wait_queue_head_t wait;
struct mousedev_list *list;
struct input_handle handle;
@@ -89,8 +92,6 @@
struct mousedev_list *list;
int index, size;
- add_mouse_randomness((type << 4) ^ code ^ (code >> 4) ^ value);
-
while (*mousedev) {
list = (*mousedev)->list;
while (list) {
@@ -101,13 +102,23 @@
switch (code) {
case ABS_X:
size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X];
- list->dx += (value * xres - list->oldx) / size;
- list->oldx += list->dx * size;
+ if (size != 0) {
+ list->dx += (value * xres - list->oldx) / size;
+ list->oldx += list->dx * size;
+ } else {
+ list->dx += value - list->oldx;
+ list->oldx += list->dx;
+ }
break;
case ABS_Y:
size = handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y];
- list->dy -= (value * yres - list->oldy) / size;
- list->oldy -= list->dy * size;
+ if (size != 0) {
+ list->dy -= (value * yres - list->oldy) / size;
+ list->oldy -= list->dy * size;
+ } else {
+ list->dy -= value - list->oldy;
+ list->oldy -= list->dy;
+ }
break;
}
break;
@@ -403,19 +414,11 @@
fasync: mousedev_fasync,
};
-static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev)
+static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
{
struct mousedev *mousedev;
int minor = 0;
- if (!test_bit(EV_KEY, dev->evbit) ||
- (!test_bit(BTN_LEFT, dev->keybit) && !test_bit(BTN_TOUCH, dev->keybit)))
- return NULL;
-
- if ((!test_bit(EV_REL, dev->evbit) || !test_bit(REL_X, dev->relbit)) &&
- (!test_bit(EV_ABS, dev->evbit) || !test_bit(ABS_X, dev->absbit)))
- return NULL;
-
for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
if (minor == MOUSEDEV_MINORS) {
printk(KERN_ERR "mousedev: no more free mousedev devices\n");
@@ -427,11 +430,12 @@
memset(mousedev, 0, sizeof(struct mousedev));
init_waitqueue_head(&mousedev->wait);
- mousedev->exist = 1;
mousedev->minor = minor;
mousedev_table[minor] = mousedev;
+ sprintf(mousedev->name, "mouse%d", minor);
mousedev->handle.dev = dev;
+ mousedev->handle.name = mousedev->name;
mousedev->handle.handler = handler;
mousedev->handle.private = mousedev;
@@ -440,7 +444,7 @@
if (mousedev_mix.open)
input_open_device(&mousedev->handle);
-// printk(KERN_INFO "mouse%d: PS/2 mouse device for input%d\n", minor, dev->number);
+ mousedev->exist = 1;
return &mousedev->handle;
}
@@ -461,6 +465,26 @@
kfree(mousedev);
}
}
+
+static struct input_device_id mousedev_ids[] = {
+ {
+ flags: INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT,
+ evbit: { BIT(EV_KEY) | BIT(EV_REL) },
+ keybit: { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) },
+ relbit: { BIT(REL_X) | BIT(REL_Y) },
+ }, /* A mouse like device, at least one button, two relative axes */
+
+ {
+ flags: INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
+ evbit: { BIT(EV_KEY) | BIT(EV_ABS) },
+ keybit: { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
+ absbit: { BIT(ABS_X) | BIT(ABS_Y) },
+ }, /* A tablet like device, at least touch detection, two absolute axes */
+
+ { }, /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(input, mousedev_ids);
static struct input_handler mousedev_handler = {
event: mousedev_event,
@@ -468,6 +492,8 @@
disconnect: mousedev_disconnect,
fops: &mousedev_fops,
minor: MOUSEDEV_MINOR_BASE,
+ name: "mousedev",
+ id_table: mousedev_ids,
};
static int __init mousedev_init(void)
@@ -495,7 +521,7 @@
module_init(mousedev_init);
module_exit(mousedev_exit);
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Input driver to PS/2 or ImPS/2 device driver");
MODULE_PARM(xres, "i");
MODULE_PARM_DESC(xres, "Horizontal screen resolution");
diff -urN linux-2.4.10/drivers/usb/hid-core.c linux/drivers/usb/hid-core.c
--- linux-2.4.10/drivers/usb/hid-core.c Sun Sep 16 20:07:43 2001
+++ linux/drivers/usb/hid-core.c Tue Sep 25 12:45:05 2001
@@ -1,12 +1,10 @@
/*
- * $Id: hid-core.c,v 1.8 2001/05/23 12:02:18 vojtech Exp $
+ * $Id: hid-core.c,v 1.31 2001/09/25 10:12:07 vojtech Exp $
*
* Copyright (c) 1999 Andreas Gal
* Copyright (c) 2000-2001 Vojtech Pavlik
*
* USB HID support for Linux
- *
- * Sponsored by SuSE
*/
/*
@@ -25,8 +23,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/module.h>
@@ -45,6 +43,7 @@
#undef DEBUG_DATA
#include <linux/usb.h>
+#include "usbpath.h"
#include "hid.h"
#ifdef CONFIG_USB_HIDDEV
@@ -55,9 +54,10 @@
* Version Information
*/
-#define DRIVER_VERSION "v1.8"
-#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik <vojtech@suse.cz>"
-#define DRIVER_DESC "USB HID support drivers"
+#define DRIVER_VERSION "v1.31"
+#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik <vojtech@ucw.cz>"
+#define DRIVER_DESC "USB HID core driver"
+#define DRIVER_LICENSE "GPL"
static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick",
"Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"};
@@ -507,8 +507,6 @@
for (n = 0; n < report->maxfield; n++)
kfree(report->field[n]);
- if (report->data)
- kfree(report->data);
kfree(report);
}
@@ -537,60 +535,64 @@
* items, though they are not used yet.
*/
-static __u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
+static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
{
- if ((end - start) > 0) {
+ u8 b;
- __u8 b = *start++;
- item->type = (b >> 2) & 3;
- item->tag = (b >> 4) & 15;
+ if ((end - start) <= 0)
+ return NULL;
- if (item->tag == HID_ITEM_TAG_LONG) {
+ b = *start++;
- item->format = HID_ITEM_FORMAT_LONG;
+ item->type = (b >> 2) & 3;
+ item->tag = (b >> 4) & 15;
- if ((end - start) >= 2) {
+ if (item->tag == HID_ITEM_TAG_LONG) {
- item->size = *start++;
- item->tag = *start++;
+ item->format = HID_ITEM_FORMAT_LONG;
- if ((end - start) >= item->size) {
- item->data.longdata = start;
- start += item->size;
- return start;
- }
- }
- } else {
+ if ((end - start) < 2)
+ return NULL;
- item->format = HID_ITEM_FORMAT_SHORT;
- item->size = b & 3;
- switch (item->size) {
-
- case 0:
- return start;
-
- case 1:
- if ((end - start) >= 1) {
- item->data.u8 = *start++;
- return start;
- }
- break;
-
- case 2:
- if ((end - start) >= 2) {
- item->data.u16 = le16_to_cpu( get_unaligned(((__u16*)start)++));
- return start;
- }
-
- case 3:
- item->size++;
- if ((end - start) >= 4) {
- item->data.u32 = le32_to_cpu( get_unaligned(((__u32*)start)++));
- return start;
- }
- }
- }
+ item->size = *start++;
+ item->tag = *start++;
+
+ if ((end - start) < item->size)
+ return NULL;
+
+ item->data.longdata = start;
+ start += item->size;
+ return start;
+ }
+
+ item->format = HID_ITEM_FORMAT_SHORT;
+ item->size = b & 3;
+
+ switch (item->size) {
+
+ case 0:
+ return start;
+
+ case 1:
+ if ((end - start) < 1)
+ return NULL;
+ item->data.u8 = *start++;
+ return start;
+
+ case 2:
+ if ((end - start) < 2)
+ return NULL;
+ item->data.u16 = le16_to_cpu(get_unaligned(((__u16*)start)++));
+ return start;
+
+ case 3:
+ item->size++;
+ if ((end - start) < 4)
+ return NULL;
+ item->data.u32 = le32_to_cpu(get_unaligned(((__u32*)start)++));
+ return start;
}
+
return NULL;
}
@@ -637,12 +639,14 @@
end = start + size;
while ((start = fetch_item(start, end, &item)) != 0) {
+
if (item.format != HID_ITEM_FORMAT_SHORT) {
dbg("unexpected long global item");
hid_free_device(device);
kfree(parser);
return NULL;
}
+
if (dispatch_type[item.type](parser, &item)) {
dbg("item %u %u %u %u parsing failed\n",
item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
@@ -796,9 +800,12 @@
memcpy(field->value, value, count * sizeof(__s32));
}
-static int hid_input_report(int type, u8 *data, int len, struct hid_device *hid)
+static int hid_input_report(int type, struct urb *urb)
{
+ struct hid_device *hid = urb->context;
struct hid_report_enum *report_enum = hid->report_enum + type;
+ u8 *data = urb->transfer_buffer;
+ int len = urb->actual_length;
struct hid_report *report;
int n, size;
@@ -832,44 +839,13 @@
size = ((report->size - 1) >> 3) + 1;
if (len < size) {
-
- if (size <= 8) {
- dbg("report %d is too short, (%d < %d)", report->id, len, size);
- return -1;
- }
-
- /*
- * Some low-speed devices have large reports and maxpacketsize 8.
- * We buffer the data in that case and parse it when we got it all.
- * Works only for unnumbered reports. Doesn't make sense for numbered
- * reports anyway - then they don't need to be large.
- */
-
- if (!report->data)
- if (!(report->data = kmalloc(size, GFP_ATOMIC))) {
- dbg("couldn't allocate report buffer");
- return -1;
- }
-
- if (report->idx + len > size) {
- dbg("report data buffer overflow");
- report->idx = 0;
- return -1;
- }
-
- memcpy(report->data + report->idx, data, len);
- report->idx += len;
-
- if (report->idx < size)
- return 0;
-
- data = report->data;
+ dbg("report %d is too short, (%d < %d)", report->id, len, size);
+ return -1;
}
for (n = 0; n < report->maxfield; n++)
hid_input_field(hid, report->field[n], data);
- report->idx = 0;
return 0;
}
@@ -884,25 +860,7 @@
return;
}
- hid_input_report(HID_INPUT_REPORT, urb->transfer_buffer, urb->actual_length, urb->context);
-}
-
-/*
- * hid_read_report() reads in report values without waiting for an irq urb.
- */
-
-void hid_read_report(struct hid_device *hid, struct hid_report *report)
-{
- int len = ((report->size - 1) >> 3) + 1 + hid->report_enum[report->type].numbered;
- u8 data[len];
- int read;
-
- if ((read = usb_get_report(hid->dev, hid->ifnum, report->type + 1, report->id, data, len)) != len) {
- dbg("reading report type %d id %d failed len %d read %d", report->type + 1, report->id, len, read);
- return;
- }
-
- hid_input_report(report->type, data, len, hid);
+ hid_input_report(HID_INPUT_REPORT, urb);
}
/*
@@ -985,15 +943,31 @@
return -1;
}
-static int hid_submit_out(struct hid_device *hid)
+static int hid_submit_ctrl(struct hid_device *hid)
{
- hid->urbout.transfer_buffer_length = le16_to_cpup(&hid->out[hid->outtail].dr.length);
- hid->urbout.transfer_buffer = hid->out[hid->outtail].buffer;
- hid->urbout.setup_packet = (void *) &(hid->out[hid->outtail].dr);
- hid->urbout.dev = hid->dev;
+ struct hid_report *report;
+ unsigned char dir;
- if (usb_submit_urb(&hid->urbout)) {
- err("usb_submit_urb(out) failed");
+ report = hid->ctrl[hid->ctrltail].report;
+ dir = hid->ctrl[hid->ctrltail].dir;
+
+ if (!dir)
+ hid_output_report(report, hid->ctrlbuf);
+
+ hid->urbctrl.transfer_buffer_length = ((report->size - 1) >> 3) + 1 + ((report->id > 0) && dir);
+ hid->urbctrl.pipe = dir ? usb_rcvctrlpipe(hid->dev, 0) : usb_sndctrlpipe(hid->dev, 0);
+ hid->urbctrl.dev = hid->dev;
+
+ hid->dr.length = cpu_to_le16(hid->urbctrl.transfer_buffer_length);
+ hid->dr.requesttype = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir;
+ hid->dr.request = dir ? USB_REQ_GET_REPORT : USB_REQ_SET_REPORT;
+ hid->dr.index = cpu_to_le16(hid->ifnum);
+ hid->dr.value = ((report->type + 1) << 8) | report->id;
+
+ dbg("submitting ctrl urb");
+
+ if (usb_submit_urb(&hid->urbctrl)) {
+ err("usb_submit_urb(ctrl) failed");
return -1;
}
@@ -1007,26 +981,34 @@
if (urb->status)
warn("ctrl urb status %d received", urb->status);
- hid->outtail = (hid->outtail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
+ if (hid->ctrl[hid->ctrltail].dir)
+ hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb);
+
+ hid->ctrltail = (hid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
- if (hid->outhead != hid->outtail)
- hid_submit_out(hid);
+ if (hid->ctrlhead != hid->ctrltail) {
+ hid_submit_ctrl(hid);
+ return;
+ }
+
+ wake_up(&hid->wait);
}
-void hid_write_report(struct hid_device *hid, struct hid_report *report)
+void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
{
- hid_output_report(report, hid->out[hid->outhead].buffer);
+ int head;
- hid->out[hid->outhead].dr.value = cpu_to_le16(0x200 | report->id);
- hid->out[hid->outhead].dr.length = cpu_to_le16((report->size + 7) >> 3);
-
- hid->outhead = (hid->outhead + 1) & (HID_CONTROL_FIFO_SIZE - 1);
+ if ((head = (hid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == hid->ctrltail) {
+ warn("control queue full");
+ return;
+ }
- if (hid->outhead == hid->outtail)
- hid->outtail = (hid->outtail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
+ hid->ctrl[hid->ctrlhead].report = report;
+ hid->ctrl[hid->ctrlhead].dir = dir;
+ hid->ctrlhead = head;
- if (hid->urbout.status != -EINPROGRESS)
- hid_submit_out(hid);
+ if (hid->urbctrl.status != -EINPROGRESS)
+ hid_submit_ctrl(hid);
}
int hid_open(struct hid_device *hid)
@@ -1049,27 +1031,49 @@
}
/*
- * Initialize all readable reports
+ * Initialize all reports
*/
+
void hid_init_reports(struct hid_device *hid)
{
- int i;
- struct hid_report *report;
+ DECLARE_WAITQUEUE(wait, current);
struct hid_report_enum *report_enum;
+ struct hid_report *report;
struct list_head *list;
+ int len, timeout = 10*HZ;
- for (i = 0; i < HID_REPORT_TYPES; i++) {
- if (i == HID_FEATURE_REPORT || i == HID_INPUT_REPORT) {
- report_enum = hid->report_enum + i;
- list = report_enum->report_list.next;
- while (list != &report_enum->report_list) {
- report = (struct hid_report *) list;
- usb_set_idle(hid->dev, hid->ifnum, 0, report->id);
- hid_read_report(hid, report);
- list = list->next;
- }
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ add_wait_queue(&hid->wait, &wait);
+
+ report_enum = hid->report_enum + HID_INPUT_REPORT;
+ list = report_enum->report_list.next;
+ while (list != &report_enum->report_list) {
+ report = (struct hid_report *) list;
+ len = ((report->size - 1) >> 3) + 1 + report_enum->numbered;
+ if (len > hid->urb.transfer_buffer_length) {
+ hid->urb.transfer_buffer_length = len < 32 ? len : 32;
}
+ usb_set_idle(hid->dev, hid->ifnum, 0, report->id);
+ hid_submit_report(hid, report, USB_DIR_IN);
+ list = list->next;
}
+
+ report_enum = hid->report_enum + HID_FEATURE_REPORT;
+ list = report_enum->report_list.next;
+ while (list != &report_enum->report_list) {
+ report = (struct hid_report *) list;
+ hid_submit_report(hid, report, USB_DIR_IN);
+ list = list->next;
+ }
+
+ while (timeout && (hid->ctrlhead != hid->ctrltail))
+ timeout = schedule_timeout(timeout);
+
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&hid->wait, &wait);
+
+ if (!timeout)
+ dbg("timeout waiting for ctrl queue to clear");
}
#define USB_VENDOR_ID_WACOM 0x056a
@@ -1141,7 +1145,7 @@
for (n = 0; n < interface->bNumEndpoints; n++) {
struct usb_endpoint_descriptor *endpoint = &interface->endpoint[n];
- int pipe, maxp;
+ int pipe;
if ((endpoint->bmAttributes & 3) != 3) /* Not an interrupt endpoint */
continue;
@@ -1150,9 +1154,8 @@
continue;
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
- maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
- FILL_INT_URB(&hid->urb, dev, pipe, hid->buffer, maxp > 32 ? 32 : maxp, hid_irq, hid, endpoint->bInterval);
+ FILL_INT_URB(&hid->urb, dev, pipe, hid->buffer, 0, hid_irq, hid, endpoint->bInterval);
break;
}
@@ -1163,43 +1166,34 @@
return NULL;
}
+ init_waitqueue_head(&hid->wait);
+
hid->version = hdesc->bcdHID;
hid->country = hdesc->bCountryCode;
hid->dev = dev;
hid->ifnum = interface->bInterfaceNumber;
- for (n = 0; n < HID_CONTROL_FIFO_SIZE; n++) {
- hid->out[n].dr.requesttype = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
- hid->out[n].dr.request = USB_REQ_SET_REPORT;
- hid->out[n].dr.index = cpu_to_le16(hid->ifnum);
- }
-
hid->name[0] = 0;
- if (!(buf = kmalloc(63, GFP_KERNEL)))
+ if (!(buf = kmalloc(64, GFP_KERNEL)))
return NULL;
- if (usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0) {
+ if (usb_string(dev, dev->descriptor.iManufacturer, buf, 64) > 0) {
strcat(hid->name, buf);
- if (usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0)
+ if (usb_string(dev, dev->descriptor.iProduct, buf, 64) > 0)
sprintf(hid->name, "%s %s", hid->name, buf);
} else
sprintf(hid->name, "%04x:%04x", dev->descriptor.idVendor, dev->descriptor.idProduct);
- kfree(buf);
+ usb_make_path(dev, buf, 63);
+ sprintf(hid->phys, "%s/input%d", buf, ifnum);
- FILL_CONTROL_URB(&hid->urbout, dev, usb_sndctrlpipe(dev, 0),
- (void*) &hid->out[0].dr, hid->out[0].buffer, 1, hid_ctrl, hid);
+ if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0)
+ hid->uniq[0] = 0;
-/*
- * Some devices don't like this and crash. I don't know of any devices
- * needing this, so it is disabled for now.
- */
+ kfree(buf);
-#if 0
- if (interface->bInterfaceSubClass == 1)
- usb_set_protocol(dev, hid->ifnum, 1);
-#endif
+ FILL_CONTROL_URB(&hid->urbctrl, dev, 0, (void*) &hid->dr, hid->ctrlbuf, 1, hid_ctrl, hid);
return hid;
}
@@ -1208,6 +1202,7 @@
const struct usb_device_id *id)
{
struct hid_device *hid;
+ char path[64];
int i;
char *c;
@@ -1228,7 +1223,7 @@
printk(KERN_INFO);
if (hid->claimed & HID_CLAIMED_INPUT)
- printk("input%d", hid->input.number);
+ printk("input");
if (hid->claimed == (HID_CLAIMED_INPUT | HID_CLAIMED_HIDDEV))
printk(",");
if (hid->claimed & HID_CLAIMED_HIDDEV)
@@ -1241,9 +1236,10 @@
break;
}
- printk(": USB HID v%x.%02x %s [%s] on usb%d:%d.%d\n",
- hid->version >> 8, hid->version & 0xff, c, hid->name,
- dev->bus->busnum, dev->devnum, ifnum);
+ usb_make_path(dev, path, 63);
+
+ printk(": USB HID v%x.%02x %s [%s] on %s\n",
+ hid->version >> 8, hid->version & 0xff, c, hid->name, path);
return hid;
}
@@ -1265,8 +1261,7 @@
}
static struct usb_device_id hid_usb_ids [] = {
- { match_flags: USB_DEVICE_ID_MATCH_INT_CLASS,
- bInterfaceClass: USB_INTERFACE_CLASS_HID },
+ { bInterfaceClass: USB_INTERFACE_CLASS_HID },
{ } /* Terminating entry */
};
@@ -1285,8 +1280,7 @@
hiddev_init();
#endif
usb_register(&hid_driver);
- info(DRIVER_VERSION " " DRIVER_AUTHOR);
- info(DRIVER_DESC);
+ info(DRIVER_VERSION ":" DRIVER_DESC);
return 0;
}
@@ -1302,6 +1296,6 @@
module_init(hid_init);
module_exit(hid_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
diff -urN linux-2.4.10/drivers/usb/hid-debug.h linux/drivers/usb/hid-debug.h
--- linux-2.4.10/drivers/usb/hid-debug.h Thu Sep 13 00:34:06 2001
+++ linux/drivers/usb/hid-debug.h Tue Sep 25 12:45:05 2001
@@ -1,12 +1,10 @@
/*
- * $Id: hid-debug.h,v 1.3 2001/05/10 15:56:07 vojtech Exp $
+ * $Id: hid-debug.h,v 1.8 2001/09/25 09:37:57 vojtech Exp $
*
* (c) 1999 Andreas Gal <gal@cs.uni-magdeburg.de>
- * (c) 2000-2001 Vojtech Pavlik <vojtech@suse.cz>
+ * (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz>
*
* Some debug stuff for the HID parser.
- *
- * Sponsored by SuSE
*/
/*
@@ -25,8 +23,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
struct hid_usage_entry {
diff -urN linux-2.4.10/drivers/usb/hid-input.c linux/drivers/usb/hid-input.c
--- linux-2.4.10/drivers/usb/hid-input.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/usb/hid-input.c Tue Sep 25 12:45:05 2001
@@ -1,11 +1,9 @@
/*
- * $Id: hid-input.c,v 1.5 2001/05/23 09:25:02 vojtech Exp $
+ * $Id: hid-input.c,v 1.16 2001/09/25 10:12:07 vojtech Exp $
*
* Copyright (c) 2000-2001 Vojtech Pavlik
*
- * USB HID to Linux Input mapping module
- *
- * Sponsored by SuSE
+ * USB HID to Linux Input mapping
*/
/*
@@ -24,13 +22,12 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/input.h>
#include <linux/usb.h>
@@ -67,6 +64,7 @@
{
struct input_dev *input = &device->input;
int max;
+ int is_abs = 0;
unsigned long *bit;
switch (usage->hid & HID_USAGE_PAGE) {
@@ -197,6 +195,7 @@
case HID_UP_CONSUMER: /* USB HUT v1.1, pages 56-62 */
+ set_bit(EV_REP, input->evbit);
switch (usage->hid & HID_USAGE) {
case 0x000: usage->code = 0; break;
case 0x034: usage->code = KEY_SLEEP; break;
@@ -204,14 +203,21 @@
case 0x08a: usage->code = KEY_WWW; break;
case 0x095: usage->code = KEY_HELP; break;
+ case 0x0b0: usage->code = KEY_PLAY; break;
+ case 0x0b1: usage->code = KEY_PAUSE; break;
+ case 0x0b2: usage->code = KEY_RECORD; break;
+ case 0x0b3: usage->code = KEY_FASTFORWARD; break;
case 0x0b4: usage->code = KEY_REWIND; break;
case 0x0b5: usage->code = KEY_NEXTSONG; break;
case 0x0b6: usage->code = KEY_PREVIOUSSONG; break;
case 0x0b7: usage->code = KEY_STOPCD; break;
case 0x0b8: usage->code = KEY_EJECTCD; break;
case 0x0cd: usage->code = KEY_PLAYPAUSE; break;
-
+ case 0x0e0: is_abs = 1;
+ usage->code = ABS_VOLUME;
+ break;
case 0x0e2: usage->code = KEY_MUTE; break;
+ case 0x0e5: usage->code = KEY_BASSBOOST; break;
case 0x0e9: usage->code = KEY_VOLUMEUP; break;
case 0x0ea: usage->code = KEY_VOLUMEDOWN; break;
@@ -219,7 +225,6 @@
case 0x18a: usage->code = KEY_MAIL; break;
case 0x192: usage->code = KEY_CALC; break;
case 0x194: usage->code = KEY_FILE; break;
-
case 0x21a: usage->code = KEY_UNDO; break;
case 0x21b: usage->code = KEY_COPY; break;
case 0x21c: usage->code = KEY_CUT; break;
@@ -234,6 +239,34 @@
case 0x22a: usage->code = KEY_BOOKMARKS; break;
default: usage->code = KEY_UNKNOWN; break;
+ }
+
+ if (is_abs) {
+ usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX;
+ } else {
+ usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
+ }
+ break;
+
+ case HID_UP_HPVENDOR: /* Reported on a Dutch layout HP5308 */
+
+ set_bit(EV_REP, input->evbit);
+ switch (usage->hid & HID_USAGE) {
+ case 0x021: usage->code = KEY_PRINT; break;
+ case 0x070: usage->code = KEY_HP; break;
+ case 0x071: usage->code = KEY_CAMERA; break;
+ case 0x072: usage->code = KEY_SOUND; break;
+ case 0x073: usage->code = KEY_QUESTION; break;
+
+ case 0x080: usage->code = KEY_EMAIL; break;
+ case 0x081: usage->code = KEY_CHAT; break;
+ case 0x082: usage->code = KEY_SEARCH; break;
+ case 0x083: usage->code = KEY_CONNECT; break;
+ case 0x084: usage->code = KEY_FINANCE; break;
+ case 0x085: usage->code = KEY_SPORT; break;
+ case 0x086: usage->code = KEY_SHOP; break;
+
+ default: usage->code = KEY_UNKNOWN; break;
}
@@ -352,7 +385,7 @@
}
hid_set_field(field, offset, value);
- hid_write_report(hid, field->report);
+ hid_submit_report(hid, field->report, USB_DIR_OUT);
return 0;
}
@@ -396,6 +429,8 @@
hid->input.close = hidinput_close;
hid->input.name = hid->name;
+ hid->input.phys = hid->phys;
+ hid->input.uniq = hid->uniq;
hid->input.idbus = BUS_USB;
hid->input.idvendor = dev->descriptor.idVendor;
hid->input.idproduct = dev->descriptor.idProduct;
diff -urN linux-2.4.10/drivers/usb/hid.h linux/drivers/usb/hid.h
--- linux-2.4.10/drivers/usb/hid.h Thu Sep 13 00:34:06 2001
+++ linux/drivers/usb/hid.h Tue Sep 25 12:55:48 2001
@@ -2,12 +2,10 @@
#define __HID_H
/*
- * $Id: hid.h,v 1.10 2001/05/10 15:56:07 vojtech Exp $
+ * $Id: hid.h,v 1.22 2001/09/25 09:37:57 vojtech Exp $
*
* Copyright (c) 1999 Andreas Gal
* Copyright (c) 2000-2001 Vojtech Pavlik
- *
- * Sponsored by SuSE
*/
/*
@@ -26,8 +24,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/types.h>
@@ -161,6 +159,7 @@
#define HID_UP_CONSUMER 0x000c0000
#define HID_UP_DIGITIZER 0x000d0000
#define HID_UP_PID 0x000f0000
+#define HID_UP_HPVENDOR 0xff7f0000
#define HID_USAGE 0x0000ffff
@@ -267,8 +266,6 @@
struct hid_field *field[HID_MAX_FIELDS]; /* fields of the report */
unsigned maxfield; /* maximum valid field index */
unsigned size; /* size of the report (bits) */
- unsigned idx; /* where we're in data */
- unsigned char *data; /* data for multi-packet reports */
struct hid_device *device; /* associated device */
};
@@ -281,11 +278,11 @@
#define HID_REPORT_TYPES 3
#define HID_BUFFER_SIZE 32
-#define HID_CONTROL_FIFO_SIZE 8
+#define HID_CONTROL_FIFO_SIZE 64
struct hid_control_fifo {
- devrequest dr;
- char buffer[HID_BUFFER_SIZE];
+ unsigned char dir;
+ struct hid_report *report;
};
#define HID_CLAIMED_INPUT 1
@@ -306,9 +303,11 @@
struct urb urb; /* USB URB structure */
char buffer[HID_BUFFER_SIZE]; /* Rx buffer */
- struct urb urbout; /* Output URB */
- struct hid_control_fifo out[HID_CONTROL_FIFO_SIZE]; /* Transmit buffer */
- unsigned char outhead, outtail; /* Tx buffer head & tail */
+ struct urb urbctrl; /* Control URB */
+ devrequest dr; /* Control devrquest struct */
+ struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE]; /* Control fifo */
+ unsigned char ctrlhead, ctrltail; /* Control fifo head & tail */
+ char ctrlbuf[HID_BUFFER_SIZE]; /* Control buffer */
unsigned claimed; /* Claimed by hidinput, hiddev? */
unsigned quirks; /* Various quirks the device can pull on us */
@@ -317,8 +316,12 @@
void *hiddev; /* The hiddev structure */
int minor; /* Hiddev minor number */
+ wait_queue_head_t wait; /* For sleeping */
+
int open; /* is the device open by anyone? */
char name[128]; /* Device name */
+ char phys[64]; /* Device physical location */
+ char uniq[64]; /* Device unique identifier (serial #) */
};
#define HID_GLOBAL_STACK_SIZE 4
@@ -362,12 +365,13 @@
#endif
-#define IS_INPUT_APPLICATION(a) ((a >= 0x00010000) && (a <= 0x00010008))
+/* Applications from HID Usage Tables 4/8/99 Version 1.1 */
+/* We ignore a few input applications that are not widely used */
+#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || ( a == 0x00010080) || ( a == 0x000c0001))
int hid_open(struct hid_device *);
void hid_close(struct hid_device *);
int hid_find_field(struct hid_device *, unsigned int, unsigned int, struct hid_field **);
int hid_set_field(struct hid_field *, unsigned, __s32);
-void hid_write_report(struct hid_device *, struct hid_report *);
-void hid_read_report(struct hid_device *, struct hid_report *);
+void hid_submit_report(struct hid_device *, struct hid_report *, unsigned char dir);
void hid_init_reports(struct hid_device *hid);
diff -urN linux-2.4.10/drivers/usb/hiddev.c linux/drivers/usb/hiddev.c
--- linux-2.4.10/drivers/usb/hiddev.c Thu Sep 13 00:34:06 2001
+++ linux/drivers/usb/hiddev.c Tue Sep 25 12:45:05 2001
@@ -402,7 +402,7 @@
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
return -EINVAL;
- hid_read_report(hid, report);
+ hid_submit_report(hid, report, USB_DIR_IN);
return 0;
@@ -416,7 +416,7 @@
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
return -EINVAL;
- hid_write_report(hid, report);
+ hid_submit_report(hid, report, USB_DIR_OUT);
return 0;
diff -urN linux-2.4.10/drivers/usb/usbkbd.c linux/drivers/usb/usbkbd.c
--- linux-2.4.10/drivers/usb/usbkbd.c Fri Sep 14 23:04:07 2001
+++ linux/drivers/usb/usbkbd.c Tue Sep 25 12:45:05 2001
@@ -1,11 +1,9 @@
/*
- * $Id: usbkbd.c,v 1.20 2001/04/26 08:34:49 vojtech Exp $
+ * $Id: usbkbd.c,v 1.26 2001/09/25 10:12:07 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*
* USB HIDBP Keyboard support
- *
- * Sponsored by SuSE
*/
/*
@@ -24,8 +22,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/kernel.h>
@@ -34,17 +32,19 @@
#include <linux/input.h>
#include <linux/init.h>
#include <linux/usb.h>
+#include "usbpath.h"
/*
* Version Information
*/
#define DRIVER_VERSION ""
-#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@suse.cz>"
+#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
#define DRIVER_DESC "USB HID Boot Protocol keyboard driver"
+#define DRIVER_LICENSE "GPL"
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
static unsigned char usb_kbd_keycode[256] = {
0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
@@ -74,6 +74,7 @@
devrequest dr;
unsigned char leds, newleds;
char name[128];
+ char phys[64];
int open;
};
@@ -178,6 +179,7 @@
struct usb_endpoint_descriptor *endpoint;
struct usb_kbd *kbd;
int i, pipe, maxp;
+ char path[64];
char *buf;
iface = &dev->actconfig->interface[ifnum];
@@ -221,7 +223,11 @@
kbd->dr.index = interface->bInterfaceNumber;
kbd->dr.length = 1;
+ usb_make_path(dev, path, 64);
+ sprintf(kbd->phys, "%s/input0", path);
+
kbd->dev.name = kbd->name;
+ kbd->dev.phys = kbd->phys;
kbd->dev.idbus = BUS_USB;
kbd->dev.idvendor = dev->descriptor.idVendor;
kbd->dev.idproduct = dev->descriptor.idProduct;
@@ -250,8 +256,7 @@
input_register_device(&kbd->dev);
- printk(KERN_INFO "input%d: %s on usb%d:%d.%d\n",
- kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum);
+ printk(KERN_INFO "input: %s on %s\n", kbd->name, path);
return kbd;
}
diff -urN linux-2.4.10/drivers/usb/usbmouse.c linux/drivers/usb/usbmouse.c
--- linux-2.4.10/drivers/usb/usbmouse.c Fri Sep 14 23:04:07 2001
+++ linux/drivers/usb/usbmouse.c Tue Sep 25 12:45:05 2001
@@ -1,11 +1,9 @@
/*
- * $Id: usbmouse.c,v 1.6 2000/08/14 21:05:26 vojtech Exp $
+ * $Id: usbmouse.c,v 1.14 2001/09/25 10:12:07 vojtech Exp $
*
- * Copyright (c) 1999-2000 Vojtech Pavlik
+ * Copyright (c) 1999-2001 Vojtech Pavlik
*
* USB HIDBP Mouse support
- *
- * Sponsored by SuSE
*/
/*
@@ -24,8 +22,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/kernel.h>
@@ -34,21 +32,24 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb.h>
+#include "usbpath.h"
/*
* Version Information
*/
#define DRIVER_VERSION "v1.6"
-#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@suse.cz>"
+#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
#define DRIVER_DESC "USB HID Boot Protocol mouse driver"
+#define DRIVER_LICENSE "GPL"
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
struct usb_mouse {
signed char data[8];
char name[128];
+ char phys[64];
struct usb_device *usbdev;
struct input_dev dev;
struct urb irq;
@@ -104,6 +105,7 @@
struct usb_endpoint_descriptor *endpoint;
struct usb_mouse *mouse;
int pipe, maxp;
+ char path[64];
char *buf;
iface = &dev->actconfig->interface[ifnum];
@@ -135,7 +137,11 @@
mouse->dev.open = usb_mouse_open;
mouse->dev.close = usb_mouse_close;
+ usb_make_path(dev, path, 64);
+ sprintf(mouse->phys, "%s/input0", path);
+
mouse->dev.name = mouse->name;
+ mouse->dev.phys = mouse->phys;
mouse->dev.idbus = BUS_USB;
mouse->dev.idvendor = dev->descriptor.idVendor;
mouse->dev.idproduct = dev->descriptor.idProduct;
@@ -164,8 +170,7 @@
input_register_device(&mouse->dev);
- printk(KERN_INFO "input%d: %s on usb%d:%d.%d\n",
- mouse->dev.number, mouse->name, dev->bus->busnum, dev->devnum, ifnum);
+ printk(KERN_INFO "input: %s on %s\n", mouse->name, path);
return mouse;
}
diff -urN linux-2.4.10/drivers/usb/usbpath.h linux/drivers/usb/usbpath.h
--- linux-2.4.10/drivers/usb/usbpath.h Thu Jan 1 01:00:00 1970
+++ linux/drivers/usb/usbpath.h Tue Sep 25 12:45:05 2001
@@ -0,0 +1,35 @@
+
+static int usb_make_path(struct usb_device *dev, char *buf, int maxlen)
+{
+ struct usb_device *pdev = dev->parent;
+ char *tmp, *port;
+ int i;
+
+ if (!(port = kmalloc(maxlen, GFP_KERNEL)))
+ return -1;
+ if (!(tmp = kmalloc(maxlen, GFP_KERNEL)))
+ return -1;
+
+ *port = 0;
+
+ while (pdev) {
+
+ for (i = 0; i < pdev->maxchild; i++)
+ if (pdev->children[i] == dev)
+ break;
+
+ if (pdev->children[i] != dev)
+ return -1;
+
+ strcpy(tmp, port);
+
+ sprintf(port, strlen(port) ? "%d.%s" : "%d", i + 1, tmp);
+
+ dev = pdev;
+ pdev = dev->parent;
+ }
+
+ sprintf(buf, "usb%d:%s", dev->bus->busnum, port);
+ return 0;
+}
+
diff -urN linux-2.4.10/drivers/usb/wacom.c linux/drivers/usb/wacom.c
--- linux-2.4.10/drivers/usb/wacom.c Tue Sep 18 07:52:35 2001
+++ linux/drivers/usb/wacom.c Tue Sep 25 12:45:05 2001
@@ -1,7 +1,7 @@
/*
- * $Id: wacom.c,v 1.22 2001/04/26 11:26:09 vojtech Exp $
+ * $Id: wacom.c,v 1.28 2001/09/25 10:12:07 vojtech Exp $
*
- * Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.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>
@@ -11,8 +11,6 @@
*
* USB Wacom Graphire and Wacom Intuos tablet support
*
- * Sponsored by SuSE
- *
* ChangeLog:
* v0.1 (vp) - Initial release
* v0.2 (aba) - Support for all buttons / combinations
@@ -57,8 +55,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/kernel.h>
@@ -67,17 +65,19 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb.h>
+#include "usbpath.h"
/*
* Version Information
*/
#define DRIVER_VERSION "v1.21"
-#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@suse.cz>"
+#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
+#define DRIVER_LICENSE "GPL"
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
#define USB_VENDOR_ID_WACOM 0x056a
@@ -106,6 +106,7 @@
int open;
int x, y;
__u32 serial[2];
+ char phys[32];
};
static void wacom_pl_irq(struct urb *urb)
@@ -354,6 +355,7 @@
{
struct usb_endpoint_descriptor *endpoint;
struct wacom *wacom;
+ char path[64];
if (!(wacom = kmalloc(sizeof(struct wacom), GFP_KERNEL))) return NULL;
memset(wacom, 0, sizeof(struct wacom));
@@ -388,7 +390,11 @@
wacom->dev.open = wacom_open;
wacom->dev.close = wacom_close;
+ usb_make_path(dev, path, 64);
+ sprintf(wacom->phys, "%s/input0", path);
+
wacom->dev.name = wacom->features->name;
+ wacom->dev.phys = wacom->phys;
wacom->dev.idbus = BUS_USB;
wacom->dev.idvendor = dev->descriptor.idVendor;
wacom->dev.idproduct = dev->descriptor.idProduct;
@@ -402,8 +408,7 @@
input_register_device(&wacom->dev);
- printk(KERN_INFO "input%d: %s on usb%d:%d.%d\n",
- wacom->dev.number, wacom->features->name, dev->bus->busnum, dev->devnum, ifnum);
+ printk(KERN_INFO "input: %s on %s\n", wacom->features->name, path);
return wacom;
}
diff -urN linux-2.4.10/include/linux/gameport.h linux/include/linux/gameport.h
--- linux-2.4.10/include/linux/gameport.h Sun Sep 23 19:33:46 2001
+++ linux/include/linux/gameport.h Tue Sep 25 12:53:06 2001
@@ -2,11 +2,9 @@
#define _GAMEPORT_H
/*
- * $Id: gameport.h,v 1.11 2001/04/26 10:24:46 vojtech Exp $
+ * $Id: gameport.h,v 1.18 2001/09/25 10:49:40 vojtech Exp $
*
- * Copyright (c) 1999-2000 Vojtech Pavlik
- *
- * Sponsored by SuSE
+ * Copyright (c) 1999-2001 Vojtech Pavlik
*/
/*
@@ -26,20 +24,24 @@
*
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
-#include <linux/sched.h>
-#include <linux/delay.h>
#include <asm/io.h>
+#include <linux/input.h>
struct gameport;
struct gameport {
void *private;
+ char *name;
+ char *phys;
- int number;
+ unsigned short idbus;
+ unsigned short idvendor;
+ unsigned short idproduct;
+ unsigned short idversion;
int io;
int speed;
@@ -59,6 +61,7 @@
struct gameport_dev {
void *private;
+ char *name;
void (*connect)(struct gameport *, struct gameport_dev *dev);
void (*disconnect)(struct gameport *);
@@ -70,7 +73,7 @@
void gameport_close(struct gameport *gameport);
void gameport_rescan(struct gameport *gameport);
-#if defined(CONFIG_INPUT_GAMEPORT) || defined(CONFIG_INPUT_GAMEPORT_MODULE)
+#ifdef CONFIG_INPUT_GAMEPORT
void gameport_register_port(struct gameport *gameport);
void gameport_unregister_port(struct gameport *gameport);
#else
@@ -94,6 +97,7 @@
#define GAMEPORT_ID_VENDOR_MICROSOFT 0x0007
#define GAMEPORT_ID_VENDOR_THRUSTMASTER 0x0008
#define GAMEPORT_ID_VENDOR_GRAVIS 0x0009
+#define GAMEPORT_ID_VENDOR_GUILLEMOT 0x000a
static __inline__ void gameport_trigger(struct gameport *gameport)
{
diff -urN linux-2.4.10/include/linux/input.h linux/include/linux/input.h
--- linux-2.4.10/include/linux/input.h Thu Sep 13 00:34:06 2001
+++ linux/include/linux/input.h Tue Sep 25 12:52:06 2001
@@ -2,11 +2,9 @@
#define _INPUT_H
/*
- * $Id: input.h,v 1.34 2001/05/28 09:06:44 vojtech Exp $
+ * $Id: input.h,v 1.51 2001/09/25 10:49:40 vojtech Exp $
*
- * Copyright (c) 1999-2000 Vojtech Pavlik
- *
- * Sponsored by SuSE
+ * Copyright (c) 1999-2001 Vojtech Pavlik
*/
/*
@@ -17,7 +15,7 @@
*
* 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
+ * 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
@@ -25,8 +23,8 @@
* 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
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#ifdef __KERNEL__
@@ -73,8 +71,6 @@
#define EVIOCSFF _IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ff_effect)) /* send a force effect to a force feedback device */
#define EVIOCRMFF _IOW('E', 0x81, int) /* Erase a force effect */
-#define EVIOCSGAIN _IOW('E', 0x82, unsigned short) /* Set overall gain */
-#define EVIOCSAUTOCENTER _IOW('E', 0x83, unsigned short) /* Enable or disable auto-centering */
#define EVIOCGEFFECTS _IOR('E', 0x84, int) /* Report number of effects playable at the same time */
/*
@@ -90,6 +86,8 @@
#define EV_SND 0x12
#define EV_REP 0x14
#define EV_FF 0x15
+#define EV_PWR 0x16
+#define EV_FF_STATUS 0x17
#define EV_MAX 0x1f
/*
@@ -304,8 +302,23 @@
#define KEY_PROG4 203
#define KEY_SUSPEND 205
#define KEY_CLOSE 206
+#define KEY_PLAY 207
+#define KEY_FASTFORWARD 208
+#define KEY_BASSBOOST 209
+#define KEY_PRINT 210
+#define KEY_HP 211
+#define KEY_CAMERA 212
+#define KEY_SOUND 213
+#define KEY_QUESTION 214
+#define KEY_EMAIL 215
+#define KEY_CHAT 216
+#define KEY_SEARCH 217
+#define KEY_CONNECT 218
+#define KEY_FINANCE 219
+#define KEY_SPORT 220
+#define KEY_SHOP 221
-#define KEY_UNKNOWN 220
+#define KEY_UNKNOWN 240
#define BTN_MISC 0x100
#define BTN_0 0x100
@@ -415,8 +428,9 @@
#define ABS_DISTANCE 0x19
#define ABS_TILT_X 0x1a
#define ABS_TILT_Y 0x1b
-#define ABS_MISC 0x1c
-#define ABS_MAX 0x1f
+#define ABS_VOLUME 0x20
+#define ABS_MISC 0x28
+#define ABS_MAX 0x3f
/*
* Misc events
@@ -480,25 +494,32 @@
#define BUS_I2C 0x18
/*
+ * Values describing the status of an effect
+ */
+#define FF_STATUS_STOPPED 0x00
+#define FF_STATUS_PLAYING 0x01
+#define FF_STATUS_MAX 0x01
+
+/*
* Structures used in ioctls to upload effects to a device
* The first structures are not passed directly by using ioctls.
* They are sub-structures of the actually sent structure (called ff_effect)
*/
struct ff_replay {
- __u16 length; /* Duration of an effect */
+ __u16 length; /* Duration of an effect in ms. All other times are also expressed in ms */
__u16 delay; /* Time to wait before to start playing an effect */
};
struct ff_trigger {
__u16 button; /* Number of button triggering an effect */
- __u16 interval; /* Time to wait before an effect can be re-triggered */
+ __u16 interval; /* Time to wait before an effect can be re-triggered (ms) */
};
struct ff_shape {
- __u16 attack_length; /* Duration of attack */
+ __u16 attack_length; /* Duration of attack (ms) */
__s16 attack_level; /* Level at beginning of attack */
- __u16 fade_length; /* Duration of fade */
+ __u16 fade_length; /* Duration of fade (ms) */
__s16 fade_level; /* Level at end of fade */
};
@@ -519,7 +540,7 @@
__u16 direction;
__s16 right_saturation; /* Max level when joystick is on the right */
- __s16 left_saturation; /* Max level when joystick in on the left */
+ __s16 left_saturation; /* Max level when joystick in on the left */
__s16 right_coeff; /* Indicates how fast the force grows when the
joystick moves to the right */
@@ -533,7 +554,7 @@
/* FF_PERIODIC */
struct ff_periodic_effect {
__u16 waveform; /* Kind of wave (sine, square...) */
- __u16 period;
+ __u16 period; /* in ms */
__s16 magnitude; /* Peak value */
__s16 offset; /* Mean value of wave (roughly) */
__u16 phase; /* 'Horizontal' shift */
@@ -549,7 +570,8 @@
struct ff_effect {
__u16 type;
/* Following field denotes the unique id assigned to an effect.
- * It is set by the driver.
+ * If user sets if to -1, a new effect is created, and its id is returned in the same field
+ * Else, the user sets it to the effect id it wants to update.
*/
__s16 id;
@@ -564,7 +586,7 @@
};
/*
- * Buttons that can trigger effects. Use for example FF_BTN(BTN_TRIGGER) to
+ * Buttons that can trigger effects. Use for example FF_BTN(BTN_TRIGGER) to
* access the bitmap.
*/
@@ -625,8 +647,9 @@
void *private;
- int number;
char *name;
+ char *phys;
+ char *uniq;
unsigned short idbus;
unsigned short idvendor;
unsigned short idproduct;
@@ -649,6 +672,9 @@
unsigned int repeat_key;
struct timer_list timer;
+ struct pm_dev *pm_dev;
+ int state;
+
int abs[ABS_MAX + 1];
int rep[REP_MAX + 1];
@@ -661,8 +687,12 @@
int absfuzz[ABS_MAX + 1];
int absflat[ABS_MAX + 1];
+ int only_one_writer;
+
int (*open)(struct input_dev *dev);
void (*close)(struct input_dev *dev);
+ int (*accept)(struct input_dev *dev, struct file *file);
+ int (*flush)(struct input_dev *dev, struct file *file);
int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
int (*upload_effect)(struct input_dev *dev, struct ff_effect *effect);
int (*erase_effect)(struct input_dev *dev, int effect_id);
@@ -671,16 +701,63 @@
struct input_dev *next;
};
+/*
+ * Structure for hotplug & device<->driver matching.
+ */
+
+#define INPUT_DEVICE_ID_MATCH_BUS 1
+#define INPUT_DEVICE_ID_MATCH_VENDOR 2
+#define INPUT_DEVICE_ID_MATCH_PRODUCT 4
+#define INPUT_DEVICE_ID_MATCH_VERSION 8
+
+#define INPUT_DEVICE_ID_MATCH_EVBIT 0x010
+#define INPUT_DEVICE_ID_MATCH_KEYBIT 0x020
+#define INPUT_DEVICE_ID_MATCH_RELBIT 0x040
+#define INPUT_DEVICE_ID_MATCH_ABSBIT 0x080
+#define INPUT_DEVICE_ID_MATCH_MSCIT 0x100
+#define INPUT_DEVICE_ID_MATCH_LEDBIT 0x200
+#define INPUT_DEVICE_ID_MATCH_SNDBIT 0x400
+#define INPUT_DEVICE_ID_MATCH_FFBIT 0x800
+
+#define INPUT_DEVICE_ID_MATCH_DEVICE\
+ (INPUT_DEVICE_ID_MATCH_BUS | INPUT_DEVICE_ID_MATCH_VENDOR | INPUT_DEVICE_ID_MATCH_PRODUCT)
+#define INPUT_DEVICE_ID_MATCH_DEVICE_AND_VERSION\
+ (INPUT_DEVICE_ID_MATCH_DEVICE | INPUT_DEVICE_ID_MATCH_VERSION)
+
+struct input_device_id {
+
+ unsigned long flags;
+
+ unsigned short idbus;
+ unsigned short idvendor;
+ unsigned short idproduct;
+ unsigned short idversion;
+
+ unsigned long evbit[NBITS(EV_MAX)];
+ unsigned long keybit[NBITS(KEY_MAX)];
+ unsigned long relbit[NBITS(REL_MAX)];
+ unsigned long absbit[NBITS(ABS_MAX)];
+ unsigned long mscbit[NBITS(MSC_MAX)];
+ unsigned long ledbit[NBITS(LED_MAX)];
+ unsigned long sndbit[NBITS(SND_MAX)];
+ unsigned long ffbit[NBITS(FF_MAX)];
+
+ unsigned long driver_info;
+};
+
struct input_handler {
void *private;
void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
- struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev);
+ struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id);
void (*disconnect)(struct input_handle *handle);
struct file_operations *fops;
int minor;
+ char *name;
+
+ struct input_device_id *id_table;
struct input_handle *handle;
struct input_handler *next;
@@ -691,6 +768,7 @@
void *private;
int open;
+ char *name;
struct input_dev *dev;
struct input_handler *handler;
@@ -708,6 +786,9 @@
int input_open_device(struct input_handle *);
void input_close_device(struct input_handle *);
+int input_accept_device(struct input_handle *handle, struct file *file);
+int input_flush_device(struct input_handle* handle, struct file* file);
+
devfs_handle_t input_register_minor(char *name, int minor, int minor_base);
void input_unregister_minor(devfs_handle_t handle);
@@ -716,6 +797,8 @@
#define input_report_key(a,b,c) input_event(a, EV_KEY, b, !!(c))
#define input_report_rel(a,b,c) input_event(a, EV_REL, b, c)
#define input_report_abs(a,b,c) input_event(a, EV_ABS, b, c)
+#define input_report_ff(a,b,c) input_event(a, EV_FF, b, c)
+#define input_report_ff_status(a,b,c) input_event(a, EV_FF_STATUS, b, c)
#endif
#endif
diff -urN linux-2.4.10/include/linux/serio.h linux/include/linux/serio.h
--- linux-2.4.10/include/linux/serio.h Sun Aug 12 20:13:59 2001
+++ linux/include/linux/serio.h Tue Sep 25 12:50:14 2001
@@ -2,31 +2,29 @@
#define _SERIO_H
/*
- * $Id: serio.h,v 1.11 2001/05/29 02:58:50 jsimmons Exp $
+ * $Id: serio.h,v 1.20 2001/09/25 10:49:40 vojtech Exp $
*
- * Copyright (C) 1999 Vojtech Pavlik
- *
- * Sponsored by SuSE
+ * Copyright (C) 1999-2001 Vojtech Pavlik
*/
/*
* 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@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
/*
@@ -42,23 +40,30 @@
void *private;
void *driver;
+ char *name;
+ char *phys;
+
+ unsigned short idbus;
+ unsigned short idvendor;
+ unsigned short idproduct;
+ unsigned short idversion;
unsigned long type;
- int number;
int (*write)(struct serio *, unsigned char);
int (*open)(struct serio *);
void (*close)(struct serio *);
struct serio_dev *dev;
-
struct serio *next;
};
struct serio_dev {
void *private;
+ char *name;
+ void (*write_wakeup)(struct serio *);
void (*interrupt)(struct serio *, unsigned char, unsigned int);
void (*connect)(struct serio *, struct serio_dev *dev);
void (*disconnect)(struct serio *);
@@ -80,6 +85,13 @@
return serio->write(serio, data);
}
+static __inline__ void serio_dev_write_wakeup(struct serio *serio)
+{
+ if (serio->dev && serio->dev->write_wakeup) {
+ serio->dev->write_wakeup(serio);
+ }
+}
+
#define SERIO_TIMEOUT 1
#define SERIO_PARITY 2
@@ -108,6 +120,8 @@
#define SERIO_STOWAWAY 0x20
#define SERIO_H3600 0x21
#define SERIO_PS2SER 0x22
+#define SERIO_TWIDKBD 0x23
+#define SERIO_TWIDJOY 0x24
#define SERIO_ID 0xff00UL
#define SERIO_EXTRA 0xff0000UL
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: Hotplugging for the input subsystem
2001-09-28 13:07 Hotplugging for the input subsystem Vojtech Pavlik
@ 2001-09-28 16:29 ` David Brownell
2001-09-28 18:09 ` Vojtech Pavlik
1 sibling, 0 replies; 3+ messages in thread
From: David Brownell @ 2001-09-28 16:29 UTC (permalink / raw)
To: linux-hotplug
> For a long time there was the problem that while upon inserting an USB
> keyboard the HID driver was auto-loaded OK, the mousedev, joydev, etc
> drivers were not.
>
> This patch implements (among other things) hotplugging for the input
> subsystem.
Great to see this patch! Did you submit this to Linus, or are you
waiting for feedback first? And what version of modutils knows
how to emit records for "struct input_device_id" (or is there one?)
via MODULE_DEVICE_TABLE?
> I can provide some docs if it isn't obvious how it works.
I provided skeletal docs on the website, mostly just grubbed from
the invocation of the hotplug agent.
http://linux-hotplug.sourceforge.net/?selected=input
Real explanations of all those bit parameters would be good to have,
from anyone who knows the input subsystem. There's too much
"see the kernel source" there for my taste ... :)
> It'd be nice if someone could add support for this to the hotplug tools.
Yes indeed ... volunteers?
- Dave
_______________________________________________
Linux-hotplug-devel mailing list http://linux-hotplug.sourceforge.net
Linux-hotplug-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: Hotplugging for the input subsystem
2001-09-28 13:07 Hotplugging for the input subsystem Vojtech Pavlik
2001-09-28 16:29 ` David Brownell
@ 2001-09-28 18:09 ` Vojtech Pavlik
1 sibling, 0 replies; 3+ messages in thread
From: Vojtech Pavlik @ 2001-09-28 18:09 UTC (permalink / raw)
To: linux-hotplug
On Fri, Sep 28, 2001 at 09:29:36AM -0700, David Brownell wrote:
> > For a long time there was the problem that while upon inserting an USB
> > keyboard the HID driver was auto-loaded OK, the mousedev, joydev, etc
> > drivers were not.
> >
> > This patch implements (among other things) hotplugging for the input
> > subsystem.
>
> Great to see this patch! Did you submit this to Linus, or are you
> waiting for feedback first?
I'd like feedback first, yes.
> And what version of modutils knows
> how to emit records for "struct input_device_id" (or is there one?)
> via MODULE_DEVICE_TABLE?
None at all yet. I just started with the kernelside part of the whole
puzzle. This has to be implemented.
> > I can provide some docs if it isn't obvious how it works.
>
> I provided skeletal docs on the website, mostly just grubbed from
> the invocation of the hotplug agent.
>
> http://linux-hotplug.sourceforge.net/?selected=input
>
> Real explanations of all those bit parameters would be good to have,
> from anyone who knows the input subsystem. There's too much
> "see the kernel source" there for my taste ... :)
Ok.:
ACTION: "add" or "remove", adding or removing the device
PRODUCT: idbus/idvendor/idproduct/idversion. Idbus is defined in
input.h, the rest is in bus specific includes, ie for PCI
idvendor and idproduct are from pci_ids.h.
NAME: The name of the device, as a string. Can be anything.
PHYS: Physical path of the device. This is defined to be constant if the
device is plugged to the same port in the system and unique for all
connected devices. It has the form: busX.X/busX.X/busX.X ...,
where bus is bus type, X.X is bus address, typically slot or
port, entries are slash delimited. Examples:
pci00:07.2/usb0:2.3/input0
USB device (mouse, keyboard ...) connected to port #3 of
an USB hub connected to port #2, USB bus 0 of USB controller
located in PCI slot 7 function 2.
isa0201/gameport0/input0
Joystick connected to a gameport on an ISA card at
i/o address 0x201
amimouse/input0
Mouse of the Amiga
UNIQ: Unique device ID. If non-empty, and present, then this is a string that
is unique for each device with the idbus/idvendor/idproduct/idversion
combination. Typically a serial number. Not all devices have
this.
EV, KEY, REL, ABS, MSC, LED, FF: Bitfields describing the device
features, buttons, axes, etc. Encoded as arrays of hex longs
without any leading zeros.
> > It'd be nice if someone could add support for this to the hotplug tools.
>
> Yes indeed ... volunteers?
I can do it myself, if noone will take it, but I'd prefer on working on
hotplug support for gameport and serio ...
--
Vojtech Pavlik
SuSE Labs
_______________________________________________
Linux-hotplug-devel mailing list http://linux-hotplug.sourceforge.net
Linux-hotplug-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2001-09-28 18:09 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-09-28 13:07 Hotplugging for the input subsystem Vojtech Pavlik
2001-09-28 16:29 ` David Brownell
2001-09-28 18:09 ` Vojtech Pavlik
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).