X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Finput%2Fjoystick%2Fadi.c;h=704bf70f1db739b7860b0a3b4c67b10e867c06ab;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=da70b5dea625f16ccd263f47da7d3ff792a11e05;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c index da70b5dea..704bf70f1 100644 --- a/drivers/input/joystick/adi.c +++ b/drivers/input/joystick/adi.c @@ -1,7 +1,5 @@ /* - * $Id: adi.c,v 1.23 2002/01/22 20:26:17 vojtech Exp $ - * - * Copyright (c) 1998-2001 Vojtech Pavlik + * Copyright (c) 1998-2005 Vojtech Pavlik */ /* @@ -36,9 +34,12 @@ #include #include #include +#include + +#define DRIVER_DESC "Logitech ADI joystick family driver" MODULE_AUTHOR("Vojtech Pavlik "); -MODULE_DESCRIPTION("Logitech ADI joystick family driver"); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); /* @@ -47,7 +48,6 @@ MODULE_LICENSE("GPL"); #define ADI_MAX_START 200 /* Trigger to packet timeout [200us] */ #define ADI_MAX_STROBE 40 /* Single bit timeout [40us] */ -#define ADI_REFRESH_TIME HZ/50 /* How often to poll the joystick [20 ms] */ #define ADI_INIT_DELAY 10 /* Delay after init packet [10ms] */ #define ADI_DATA_DELAY 4 /* Delay after data packet [4ms] */ @@ -55,9 +55,9 @@ MODULE_LICENSE("GPL"); #define ADI_MIN_LENGTH 8 #define ADI_MIN_LEN_LENGTH 10 #define ADI_MIN_ID_LENGTH 66 -#define ADI_MAX_NAME_LENGTH 48 +#define ADI_MAX_NAME_LENGTH 64 #define ADI_MAX_CNAME_LENGTH 16 -#define ADI_MAX_PHYS_LENGTH 32 +#define ADI_MAX_PHYS_LENGTH 64 #define ADI_FLAG_HAT 0x04 #define ADI_FLAG_10BIT 0x08 @@ -83,7 +83,7 @@ static char adi_cm2_abs[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ }; static char adi_wmf_abs[] = { ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y }; static short adi_wmgpe_key[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE, BTN_SELECT }; -static short adi_wmi_key[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_EXTRA }; +static short adi_wmi_key[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_EXTRA }; static short adi_wmed3d_key[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2 }; static short adi_cm2_key[] = { BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8 }; @@ -107,7 +107,7 @@ static struct { */ struct adi { - struct input_dev dev; + struct input_dev *dev; int length; int ret; int idx; @@ -127,11 +127,9 @@ struct adi { struct adi_port { struct gameport *gameport; - struct timer_list timer; struct adi adi[2]; int bad; int reads; - int used; }; /* @@ -186,7 +184,7 @@ static void adi_move_bits(struct adi_port *port, int length) int i; struct adi *adi = port->adi; - adi[0].idx = adi[1].idx = 0; + adi[0].idx = adi[1].idx = 0; if (adi[0].ret <= 0 || adi[1].ret <= 0) return; if (adi[0].data[0] & 0x20 || ~adi[1].data[0] & 0x20) return; @@ -218,7 +216,7 @@ static inline int adi_get_bits(struct adi *adi, int count) static int adi_decode(struct adi *adi) { - struct input_dev *dev = &adi->dev; + struct input_dev *dev = adi->dev; char *abs = adi->abs; short *key = adi->key; int i, t; @@ -275,15 +273,15 @@ static int adi_read(struct adi_port *port) } /* - * adi_timer() repeatedly polls the Logitech joysticks. + * adi_poll() repeatedly polls the Logitech joysticks. */ -static void adi_timer(unsigned long data) +static void adi_poll(struct gameport *gameport) { - struct adi_port *port = (void *) data; + struct adi_port *port = gameport_get_drvdata(gameport); + port->bad -= adi_read(port); port->reads++; - mod_timer(&port->timer, jiffies + ADI_REFRESH_TIME); } /* @@ -293,8 +291,8 @@ static void adi_timer(unsigned long data) static int adi_open(struct input_dev *dev) { struct adi_port *port = dev->private; - if (!port->used++) - mod_timer(&port->timer, jiffies + ADI_REFRESH_TIME); + + gameport_start_polling(port->gameport); return 0; } @@ -305,8 +303,8 @@ static int adi_open(struct input_dev *dev) static void adi_close(struct input_dev *dev) { struct adi_port *port = dev->private; - if (!--port->used) - del_timer(&port->timer); + + gameport_stop_polling(port->gameport); } /* @@ -316,13 +314,17 @@ static void adi_close(struct input_dev *dev) static void adi_init_digital(struct gameport *gameport) { - int seq[] = { 3, -2, -3, 10, -6, -11, -7, -9, 11, 0 }; + int seq[] = { 4, -2, -3, 10, -6, -11, -7, -9, 11, 0 }; int i; for (i = 0; seq[i]; i++) { gameport_trigger(gameport); - if (seq[i] > 0) msleep(seq[i]); - if (seq[i] < 0) mdelay(-seq[i]); + if (seq[i] > 0) + msleep(seq[i]); + if (seq[i] < 0) { + mdelay(-seq[i]); + udelay(-seq[i]*14); /* It looks like mdelay() is off by approx 1.4% */ + } } } @@ -397,77 +399,69 @@ static void adi_id_decode(struct adi *adi, struct adi_port *port) } } -static void adi_init_input(struct adi *adi, struct adi_port *port, int half) +static int adi_init_input(struct adi *adi, struct adi_port *port, int half) { - int i, t; + struct input_dev *input_dev; char buf[ADI_MAX_NAME_LENGTH]; + int i, t; - if (!adi->length) return; - - init_input_dev(&adi->dev); + adi->dev = input_dev = input_allocate_device(); + if (!input_dev) + return -ENOMEM; t = adi->id < ADI_ID_MAX ? adi->id : ADI_ID_MAX; - sprintf(buf, adi_names[t], adi->id); - sprintf(adi->name, "Logitech %s", buf); - sprintf(adi->phys, "%s/input%d", port->gameport->phys, half); + snprintf(buf, ADI_MAX_PHYS_LENGTH, adi_names[t], adi->id); + snprintf(adi->name, ADI_MAX_NAME_LENGTH, "Logitech %s [%s]", buf, adi->cname); + snprintf(adi->phys, ADI_MAX_PHYS_LENGTH, "%s/input%d", port->gameport->phys, half); adi->abs = adi_abs[t]; adi->key = adi_key[t]; - adi->dev.open = adi_open; - adi->dev.close = adi_close; + input_dev->name = adi->name; + input_dev->phys = adi->phys; + input_dev->id.bustype = BUS_GAMEPORT; + input_dev->id.vendor = GAMEPORT_ID_VENDOR_LOGITECH; + input_dev->id.product = adi->id; + input_dev->id.version = 0x0100; + input_dev->cdev.dev = &port->gameport->dev; + input_dev->private = port; - adi->dev.name = adi->name; - adi->dev.phys = adi->phys; - adi->dev.id.bustype = BUS_GAMEPORT; - adi->dev.id.vendor = GAMEPORT_ID_VENDOR_LOGITECH; - adi->dev.id.product = adi->id; - adi->dev.id.version = 0x0100; + input_dev->open = adi_open; + input_dev->close = adi_close; - adi->dev.private = port; - adi->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++) - set_bit(adi->abs[i], adi->dev.absbit); + set_bit(adi->abs[i], input_dev->absbit); for (i = 0; i < adi->buttons; i++) - set_bit(adi->key[i], adi->dev.keybit); + set_bit(adi->key[i], input_dev->keybit); + + return 0; } static void adi_init_center(struct adi *adi) { int i, t, x; - if (!adi->length) return; + if (!adi->length) + return; for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++) { t = adi->abs[i]; - x = adi->dev.abs[t]; - - if (t == ABS_THROTTLE || t == ABS_RUDDER || adi->id == ADI_ID_WGPE) { - if (i < adi->axes10) x = 512; else x = 128; - } - - if (i < adi->axes10) { - adi->dev.absmax[t] = x * 2 - 64; - adi->dev.absmin[t] = 64; - adi->dev.absfuzz[t] = 2; - adi->dev.absflat[t] = 16; - continue; - } + x = adi->dev->abs[t]; - if (i < adi->axes10 + adi->axes8) { - adi->dev.absmax[t] = x * 2 - 48; - adi->dev.absmin[t] = 48; - adi->dev.absfuzz[t] = 1; - adi->dev.absflat[t] = 16; - continue; - } + if (t == ABS_THROTTLE || t == ABS_RUDDER || adi->id == ADI_ID_WGPE) + x = i < adi->axes10 ? 512 : 128; - adi->dev.absmax[t] = 1; - adi->dev.absmin[t] = -1; + if (i < adi->axes10) + input_set_abs_params(adi->dev, t, 64, x * 2 - 64, 2, 16); + else if (i < adi->axes10 + adi->axes8) + input_set_abs_params(adi->dev, t, 48, x * 2 - 48, 1, 16); + else + input_set_abs_params(adi->dev, t, -1, 1, 0, 0); } } @@ -475,26 +469,23 @@ static void adi_init_center(struct adi *adi) * adi_connect() probes for Logitech ADI joysticks. */ -static void adi_connect(struct gameport *gameport, struct gameport_dev *dev) +static int adi_connect(struct gameport *gameport, struct gameport_driver *drv) { struct adi_port *port; int i; + int err; - if (!(port = kmalloc(sizeof(struct adi_port), GFP_KERNEL))) - return; - memset(port, 0, sizeof(struct adi_port)); - - gameport->private = port; + port = kzalloc(sizeof(struct adi_port), GFP_KERNEL); + if (!port) + return -ENOMEM; port->gameport = gameport; - init_timer(&port->timer); - port->timer.data = (long) port; - port->timer.function = adi_timer; - if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW)) { - kfree(port); - return; - } + gameport_set_drvdata(gameport, port); + + err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW); + if (err) + goto fail1; adi_init_digital(gameport); adi_read_packet(port); @@ -504,15 +495,23 @@ static void adi_connect(struct gameport *gameport, struct gameport_dev *dev) for (i = 0; i < 2; i++) { adi_id_decode(port->adi + i, port); - adi_init_input(port->adi + i, port, i); + + if (!port->adi[i].length) + continue; + + err = adi_init_input(port->adi + i, port, i); + if (err) + goto fail2; } if (!port->adi[0].length && !port->adi[1].length) { - gameport_close(gameport); - kfree(port); - return; + err = -ENODEV; + goto fail2; } + gameport_set_poll_handler(gameport, adi_poll); + gameport_set_poll_interval(gameport, 20); + msleep(ADI_INIT_DELAY); if (adi_read(port)) { msleep(ADI_DATA_DELAY); @@ -522,21 +521,30 @@ static void adi_connect(struct gameport *gameport, struct gameport_dev *dev) for (i = 0; i < 2; i++) if (port->adi[i].length > 0) { adi_init_center(port->adi + i); - input_register_device(&port->adi[i].dev); - printk(KERN_INFO "input: %s [%s] on %s\n", - port->adi[i].name, port->adi[i].cname, gameport->phys); + input_register_device(port->adi[i].dev); } + + return 0; + + fail2: for (i = 0; i < 2; i++) + if (port->adi[i].dev) + input_free_device(port->adi[i].dev); + gameport_close(gameport); + fail1: gameport_set_drvdata(gameport, NULL); + kfree(port); + return err; } static void adi_disconnect(struct gameport *gameport) { int i; + struct adi_port *port = gameport_get_drvdata(gameport); - struct adi_port *port = gameport->private; for (i = 0; i < 2; i++) if (port->adi[i].length > 0) - input_unregister_device(&port->adi[i].dev); + input_unregister_device(port->adi[i].dev); gameport_close(gameport); + gameport_set_drvdata(gameport, NULL); kfree(port); } @@ -544,20 +552,24 @@ static void adi_disconnect(struct gameport *gameport) * The gameport device structure. */ -static struct gameport_dev adi_dev = { - .connect = adi_connect, - .disconnect = adi_disconnect, +static struct gameport_driver adi_drv = { + .driver = { + .name = "adi", + }, + .description = DRIVER_DESC, + .connect = adi_connect, + .disconnect = adi_disconnect, }; -int __init adi_init(void) +static int __init adi_init(void) { - gameport_register_device(&adi_dev); + gameport_register_driver(&adi_drv); return 0; } -void __exit adi_exit(void) +static void __exit adi_exit(void) { - gameport_unregister_device(&adi_dev); + gameport_unregister_driver(&adi_drv); } module_init(adi_init);