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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -37,6 +35,10 @@ #include #include +MODULE_AUTHOR("Vojtech Pavlik "); +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 \n", gameport->number, a3d->mode); + "(%s, id=%d), contact \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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -39,6 +37,10 @@ #include #include +MODULE_AUTHOR("Vojtech Pavlik "); +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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -40,13 +38,15 @@ #include #include -MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_AUTHOR("Vojtech Pavlik "); +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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -41,8 +39,8 @@ #include #include -MODULE_AUTHOR("Vojtech Pavlik "); -MODULE_DESCRIPTION("Analog joystick and gamepad driver for Linux"); +MODULE_AUTHOR("Vojtech Pavlik "); +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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -37,6 +35,10 @@ #include #include +MODULE_AUTHOR("Vojtech Pavlik "); +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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -40,8 +38,10 @@ #include #include -MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_AUTHOR("Vojtech Pavlik "); +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 , 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 @@ -41,6 +39,7 @@ #include MODULE_AUTHOR("Vojtech Pavlik "); +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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -41,8 +39,10 @@ #include #include -MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_AUTHOR("Vojtech Pavlik "); +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 .\n", psx); + " please report to .\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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -40,7 +38,8 @@ #include #include -MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_AUTHOR("Vojtech Pavlik "); +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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -38,6 +36,10 @@ #include #include +MODULE_AUTHOR("Vojtech Pavlik "); +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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -37,6 +35,10 @@ #include #include +MODULE_AUTHOR("Vojtech Pavlik "); +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 + * Copyright (c) 2000-2001 Vojtech Pavlik * Copyright (c) 2001 Johann Deneux * * 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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -38,6 +36,10 @@ #include #include #include +#include +#include + +#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 -MODULE_AUTHOR("Vojtech Pavlik , Johann Deneux "); +MODULE_AUTHOR("Vojtech Pavlik , Johann Deneux "); 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; idev.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; jprivate; + int i; + + /* Erase all effects this process owns */ + for (i=0; iff_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<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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -41,6 +39,10 @@ #include #include +MODULE_AUTHOR("Vojtech Pavlik "); +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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -51,14 +49,18 @@ #define L4_BUSY 0x01 #define L4_TIMEOUT 80 /* 80 us */ -MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_AUTHOR("Vojtech Pavlik "); +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 , 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 @@ -37,15 +35,19 @@ #include #include +MODULE_AUTHOR("Vojtech Pavlik "); +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 , 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 @@ -42,6 +40,7 @@ #include MODULE_AUTHOR("Vojtech Pavlik "); +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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -44,6 +42,10 @@ #include #include +MODULE_AUTHOR("Vojtech Pavlik "); +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 , 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 #include #include +#include MODULE_AUTHOR("Vojtech Pavlik "); +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 , 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 @@ -39,12 +37,19 @@ #include #include +MODULE_AUTHOR("Vojtech Pavlik "); +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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -38,12 +36,16 @@ #include #include +MODULE_AUTHOR("Vojtech Pavlik "); +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 \n", gameport->number); + "on %s, contact \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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -41,13 +39,29 @@ #include #include +MODULE_AUTHOR("Vojtech Pavlik "); +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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -40,15 +38,19 @@ #include #include +MODULE_AUTHOR("Vojtech Pavlik "); +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 , 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 @@ -38,6 +36,10 @@ #include #include +MODULE_AUTHOR("Vojtech Pavlik "); +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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -42,6 +39,10 @@ #include #include +MODULE_AUTHOR("Vojtech Pavlik "); +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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -39,8 +37,10 @@ #include #include -MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_AUTHOR("Vojtech Pavlik "); +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 , 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 @@ -37,6 +35,10 @@ #include #include +MODULE_AUTHOR("Vojtech Pavlik "); +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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #define EVDEV_MINOR_BASE 64 @@ -39,10 +37,16 @@ #include #include +MODULE_AUTHOR("Vojtech Pavlik "); +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 "); +MODULE_AUTHOR("Vojtech Pavlik "); 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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -34,9 +32,15 @@ #include #include #include - -MODULE_AUTHOR("Vojtech Pavlik "); -MODULE_DESCRIPTION("Input layer module"); +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Vojtech Pavlik "); +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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -46,14 +44,22 @@ #include #include +MODULE_AUTHOR("Vojtech Pavlik "); +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 "); -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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -37,10 +35,16 @@ #include #include +MODULE_AUTHOR("Vojtech Pavlik "); +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 "); +MODULE_AUTHOR("Vojtech Pavlik "); 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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #define MOUSEDEV_MINOR_BASE 32 @@ -41,6 +39,10 @@ #include #include +MODULE_AUTHOR("Vojtech Pavlik "); +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 "); +MODULE_AUTHOR("Vojtech Pavlik "); 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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -45,6 +43,7 @@ #undef DEBUG_DATA #include +#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 " -#define DRIVER_DESC "USB HID support drivers" +#define DRIVER_VERSION "v1.31" +#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik " +#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 - * (c) 2000-2001 Vojtech Pavlik + * (c) 2000-2001 Vojtech Pavlik * * 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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , 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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include #include -#include #include #include #include @@ -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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -34,17 +32,19 @@ #include #include #include +#include "usbpath.h" /* * Version Information */ #define DRIVER_VERSION "" -#define DRIVER_AUTHOR "Vojtech Pavlik " +#define DRIVER_AUTHOR "Vojtech Pavlik " #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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -34,21 +32,24 @@ #include #include #include +#include "usbpath.h" /* * Version Information */ #define DRIVER_VERSION "v1.6" -#define DRIVER_AUTHOR "Vojtech Pavlik " +#define DRIVER_AUTHOR "Vojtech Pavlik " #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 + * Copyright (c) 2000-2001 Vojtech Pavlik * Copyright (c) 2000 Andreas Bach Aaen * Copyright (c) 2000 Clifford Wolf * Copyright (c) 2000 Sam Mosel @@ -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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include @@ -67,17 +65,19 @@ #include #include #include +#include "usbpath.h" /* * Version Information */ #define DRIVER_VERSION "v1.21" -#define DRIVER_AUTHOR "Vojtech Pavlik " +#define DRIVER_AUTHOR "Vojtech Pavlik " #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 , 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 -#include #include +#include 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 , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + * e-mail - mail your message to , 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 , 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