X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Finput%2Fjoystick%2Fanalog.c;h=7ef68456d7d65c3cddc339a9018c828de48b3dcd;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=3e83968a9bd8cf5c1fbbf62fc635781e93c0ea64;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 3e83968a9..7ef68456d 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c @@ -28,7 +28,6 @@ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ -#include #include #include #include @@ -38,10 +37,13 @@ #include #include #include +#include #include +#define DRIVER_DESC "Analog joystick and gamepad driver" + MODULE_AUTHOR("Vojtech Pavlik "); -MODULE_DESCRIPTION("Analog joystick and gamepad driver"); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); /* @@ -53,7 +55,7 @@ MODULE_LICENSE("GPL"); static char *js[ANALOG_PORTS]; static int js_nargs; static int analog_options[ANALOG_PORTS]; -module_param_array_named(map, js, charp, js_nargs, 0); +module_param_array_named(map, js, charp, &js_nargs, 0); MODULE_PARM_DESC(map, "Describes analog joysticks type/capabilities"); __obsolete_setup("js="); @@ -88,7 +90,6 @@ __obsolete_setup("js="); #define ANALOG_MAX_TIME 3 /* 3 ms */ #define ANALOG_LOOP_TIME 2000 /* 2 * loop */ -#define ANALOG_REFRESH_TIME HZ/100 /* 10 ms */ #define ANALOG_SAITEK_DELAY 200 /* 200 us */ #define ANALOG_SAITEK_TIME 2000 /* 2000 us */ #define ANALOG_AXIS_TIME 2 /* 2 * refresh */ @@ -110,7 +111,7 @@ static short analog_joy_btn[] = { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN static unsigned char analog_chf[] = { 0xf, 0x0, 0x1, 0x9, 0x2, 0x4, 0xc, 0x8, 0x3, 0x5, 0xb, 0x7, 0xd, 0xe, 0xa, 0x6 }; struct analog { - struct input_dev dev; + struct input_dev *dev; int mask; short *buttons; char name[ANALOG_MAX_NAME_LENGTH]; @@ -119,7 +120,6 @@ struct analog { struct analog_port { struct gameport *gameport; - struct timer_list timer; struct analog analog[2]; unsigned char mask; char saitek; @@ -132,7 +132,6 @@ struct analog_port { int axes[4]; int buttons; int initial[4]; - int used; int axtime; }; @@ -141,12 +140,14 @@ struct analog_port { */ #ifdef __i386__ + +#include + #define GET_TIME(x) do { if (cpu_has_tsc) rdtscl(x); else x = get_time_pit(); } while (0) #define DELTA(x,y) (cpu_has_tsc ? ((y) - (x)) : ((x) - (y) + ((x) < (y) ? CLOCK_TICK_RATE / HZ : 0))) #define TIME_NAME (cpu_has_tsc?"TSC":"PIT") static unsigned int get_time_pit(void) { - extern spinlock_t i8253_lock; unsigned long flags; unsigned int count; @@ -158,11 +159,11 @@ static unsigned int get_time_pit(void) return count; } -#elif __x86_64__ +#elif defined(__x86_64__) #define GET_TIME(x) rdtscl(x) #define DELTA(x,y) ((y)-(x)) #define TIME_NAME "TSC" -#elif __alpha__ +#elif defined(__alpha__) #define GET_TIME(x) do { x = get_cycles(); } while (0) #define DELTA(x,y) ((y)-(x)) #define TIME_NAME "PCC" @@ -181,7 +182,7 @@ static unsigned long analog_faketime = 0; static void analog_decode(struct analog *analog, int *axes, int *initial, int buttons) { - struct input_dev *dev = &analog->dev; + struct input_dev *dev = analog->dev; int i, j; if (analog->mask & ANALOG_HAT_FCS) @@ -305,12 +306,12 @@ static int analog_button_read(struct analog_port *port, char saitek, char chf) } /* - * analog_timer() repeatedly polls the Analog joysticks. + * analog_poll() repeatedly polls the Analog joysticks. */ -static void analog_timer(unsigned long data) +static void analog_poll(struct gameport *gameport) { - struct analog_port *port = (void *) data; + struct analog_port *port = gameport_get_drvdata(gameport); int i; char saitek = !!(port->analog[0].mask & ANALOG_SAITEK); @@ -336,8 +337,6 @@ static void analog_timer(unsigned long data) for (i = 0; i < 2; i++) if (port->analog[i].mask) analog_decode(port->analog + i, port->axes, port->initial, port->buttons); - - mod_timer(&port->timer, jiffies + ANALOG_REFRESH_TIME); } /* @@ -347,8 +346,8 @@ static void analog_timer(unsigned long data) static int analog_open(struct input_dev *dev) { struct analog_port *port = dev->private; - if (!port->used++) - mod_timer(&port->timer, jiffies + ANALOG_REFRESH_TIME); + + gameport_start_polling(port->gameport); return 0; } @@ -359,8 +358,8 @@ static int analog_open(struct input_dev *dev) static void analog_close(struct input_dev *dev) { struct analog_port *port = dev->private; - if (!--port->used) - del_timer(&port->timer); + + gameport_stop_polling(port->gameport); } /* @@ -379,7 +378,7 @@ static void analog_calibrate_timer(struct analog_port *port) #ifdef FAKE_TIME analog_faketime += 830; #endif - udelay(1000); + mdelay(1); GET_TIME(t2); GET_TIME(t3); local_irq_restore(flags); @@ -408,48 +407,55 @@ static void analog_calibrate_timer(struct analog_port *port) static void analog_name(struct analog *analog) { - sprintf(analog->name, "Analog %d-axis %d-button", - hweight8(analog->mask & ANALOG_AXES_STD), - hweight8(analog->mask & ANALOG_BTNS_STD) + !!(analog->mask & ANALOG_BTNS_CHF) * 2 + - hweight16(analog->mask & ANALOG_BTNS_GAMEPAD) + !!(analog->mask & ANALOG_HBTN_CHF) * 4); + snprintf(analog->name, sizeof(analog->name), "Analog %d-axis %d-button", + hweight8(analog->mask & ANALOG_AXES_STD), + hweight8(analog->mask & ANALOG_BTNS_STD) + !!(analog->mask & ANALOG_BTNS_CHF) * 2 + + hweight16(analog->mask & ANALOG_BTNS_GAMEPAD) + !!(analog->mask & ANALOG_HBTN_CHF) * 4); if (analog->mask & ANALOG_HATS_ALL) - sprintf(analog->name, "%s %d-hat", - analog->name, hweight16(analog->mask & ANALOG_HATS_ALL)); + snprintf(analog->name, sizeof(analog->name), "%s %d-hat", + analog->name, hweight16(analog->mask & ANALOG_HATS_ALL)); if (analog->mask & ANALOG_HAT_FCS) - strcat(analog->name, " FCS"); + strlcat(analog->name, " FCS", sizeof(analog->name)); if (analog->mask & ANALOG_ANY_CHF) - strcat(analog->name, (analog->mask & ANALOG_SAITEK) ? " Saitek" : " CHF"); + strlcat(analog->name, (analog->mask & ANALOG_SAITEK) ? " Saitek" : " CHF", + sizeof(analog->name)); - strcat(analog->name, (analog->mask & ANALOG_GAMEPAD) ? " gamepad": " joystick"); + strlcat(analog->name, (analog->mask & ANALOG_GAMEPAD) ? " gamepad": " joystick", + sizeof(analog->name)); } /* * analog_init_device() */ -static void analog_init_device(struct analog_port *port, struct analog *analog, int index) +static int analog_init_device(struct analog_port *port, struct analog *analog, int index) { + struct input_dev *input_dev; int i, j, t, v, w, x, y, z; + int error; analog_name(analog); - sprintf(analog->phys, "%s/input%d", port->gameport->phys, index); + snprintf(analog->phys, sizeof(analog->phys), + "%s/input%d", port->gameport->phys, index); analog->buttons = (analog->mask & ANALOG_GAMEPAD) ? analog_pad_btn : analog_joy_btn; - init_input_dev(&analog->dev); + analog->dev = input_dev = input_allocate_device(); + if (!input_dev) + return -ENOMEM; - analog->dev.name = analog->name; - analog->dev.phys = analog->phys; - analog->dev.id.bustype = BUS_GAMEPORT; - analog->dev.id.vendor = GAMEPORT_ID_VENDOR_ANALOG; - analog->dev.id.product = analog->mask >> 4; - analog->dev.id.version = 0x0100; + input_dev->name = analog->name; + input_dev->phys = analog->phys; + input_dev->id.bustype = BUS_GAMEPORT; + input_dev->id.vendor = GAMEPORT_ID_VENDOR_ANALOG; + input_dev->id.product = analog->mask >> 4; + input_dev->id.version = 0x0100; - analog->dev.open = analog_open; - analog->dev.close = analog_close; - analog->dev.private = port; - analog->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + input_dev->open = analog_open; + input_dev->close = analog_close; + input_dev->private = port; + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); for (i = j = 0; i < 4; i++) if (analog->mask & (1 << i)) { @@ -462,8 +468,6 @@ static void analog_init_device(struct analog_port *port, struct analog *analog, v = (x >> 3); w = (x >> 3); - set_bit(t, analog->dev.absbit); - if ((i == 2 || i == 3) && (j == 2 || j == 3) && (z > (y >> 3))) x = y; @@ -473,11 +477,7 @@ static void analog_init_device(struct analog_port *port, struct analog *analog, w = (x >> 4); } - analog->dev.absmax[t] = (x << 1) - v; - analog->dev.absmin[t] = v; - analog->dev.absfuzz[t] = port->fuzz; - analog->dev.absflat[t] = w; - + input_set_abs_params(input_dev, t, v, (x << 1) - v, port->fuzz, w); j++; } @@ -485,41 +485,34 @@ static void analog_init_device(struct analog_port *port, struct analog *analog, if (analog->mask & analog_exts[i]) for (x = 0; x < 2; x++) { t = analog_hats[j++]; - set_bit(t, analog->dev.absbit); - analog->dev.absmax[t] = 1; - analog->dev.absmin[t] = -1; + input_set_abs_params(input_dev, t, -1, 1, 0, 0); } for (i = j = 0; i < 4; i++) if (analog->mask & (0x10 << i)) - set_bit(analog->buttons[j++], analog->dev.keybit); + set_bit(analog->buttons[j++], input_dev->keybit); if (analog->mask & ANALOG_BTNS_CHF) for (i = 0; i < 2; i++) - set_bit(analog->buttons[j++], analog->dev.keybit); + set_bit(analog->buttons[j++], input_dev->keybit); if (analog->mask & ANALOG_HBTN_CHF) for (i = 0; i < 4; i++) - set_bit(analog->buttons[j++], analog->dev.keybit); + set_bit(analog->buttons[j++], input_dev->keybit); for (i = 0; i < 4; i++) if (analog->mask & (ANALOG_BTN_TL << i)) - set_bit(analog_pads[i], analog->dev.keybit); + set_bit(analog_pads[i], input_dev->keybit); analog_decode(analog, port->axes, port->initial, port->buttons); - input_register_device(&analog->dev); - - printk(KERN_INFO "input: %s at %s", analog->name, port->gameport->phys); + error = input_register_device(analog->dev); + if (error) { + input_free_device(analog->dev); + return error; + } - if (port->cooked) - printk(" [ADC port]\n"); - else - printk(" [%s timer, %d %sHz clock, %d ns res]\n", TIME_NAME, - port->speed > 10000 ? (port->speed + 800) / 1000 : port->speed, - port->speed > 10000 ? "M" : "k", - port->speed > 10000 ? (port->loop * 1000) / (port->speed / 1000) - : (port->loop * 1000000) / port->speed); + return 0; } /* @@ -587,17 +580,15 @@ static int analog_init_masks(struct analog_port *port) return -!(analog[0].mask || analog[1].mask); } -static int analog_init_port(struct gameport *gameport, struct gameport_dev *dev, struct analog_port *port) +static int analog_init_port(struct gameport *gameport, struct gameport_driver *drv, struct analog_port *port) { int i, t, u, v; - gameport->private = port; port->gameport = gameport; - init_timer(&port->timer); - port->timer.data = (long) port; - port->timer.function = analog_timer; - if (!gameport_open(gameport, dev, GAMEPORT_MODE_RAW)) { + gameport_set_drvdata(gameport, port); + + if (!gameport_open(gameport, drv, GAMEPORT_MODE_RAW)) { analog_calibrate_timer(port); @@ -608,7 +599,8 @@ static int analog_init_port(struct gameport *gameport, struct gameport_dev *dev, port->fuzz = (port->speed * ANALOG_FUZZ_MAGIC) / port->loop / 1000 + ANALOG_FUZZ_BITS; for (i = 0; i < ANALOG_INIT_RETRIES; i++) { - if (!analog_cooked_read(port)) break; + if (!analog_cooked_read(port)) + break; msleep(ANALOG_MAX_TIME); } @@ -617,11 +609,13 @@ static int analog_init_port(struct gameport *gameport, struct gameport_dev *dev, msleep(ANALOG_MAX_TIME); t = gameport_time(gameport, ANALOG_MAX_TIME * 1000); gameport_trigger(gameport); - while ((gameport_read(port->gameport) & port->mask) && (u < t)) u++; + while ((gameport_read(port->gameport) & port->mask) && (u < t)) + u++; udelay(ANALOG_SAITEK_DELAY); t = gameport_time(gameport, ANALOG_SAITEK_TIME); gameport_trigger(gameport); - while ((gameport_read(port->gameport) & port->mask) && (v < t)) v++; + while ((gameport_read(port->gameport) & port->mask) && (v < t)) + v++; if (v < (u >> 1)) { /* FIXME - more than one port */ analog_options[0] |= /* FIXME - more than one port */ @@ -632,59 +626,71 @@ static int analog_init_port(struct gameport *gameport, struct gameport_dev *dev, gameport_close(gameport); } - if (!gameport_open(gameport, dev, GAMEPORT_MODE_COOKED)) { + if (!gameport_open(gameport, drv, GAMEPORT_MODE_COOKED)) { for (i = 0; i < ANALOG_INIT_RETRIES; i++) if (!gameport_cooked_read(gameport, port->axes, &port->buttons)) break; for (i = 0; i < 4; i++) - if (port->axes[i] != -1) port->mask |= 1 << i; + if (port->axes[i] != -1) + port->mask |= 1 << i; port->fuzz = gameport->fuzz; port->cooked = 1; return 0; } - if (!gameport_open(gameport, dev, GAMEPORT_MODE_RAW)) - return 0; - - return -1; + return gameport_open(gameport, drv, GAMEPORT_MODE_RAW); } -static void analog_connect(struct gameport *gameport, struct gameport_dev *dev) +static int analog_connect(struct gameport *gameport, struct gameport_driver *drv) { struct analog_port *port; int i; + int err; - if (!(port = kmalloc(sizeof(struct analog_port), GFP_KERNEL))) - return; - memset(port, 0, sizeof(struct analog_port)); + if (!(port = kzalloc(sizeof(struct analog_port), GFP_KERNEL))) + return - ENOMEM; - if (analog_init_port(gameport, dev, port)) { - kfree(port); - return; - } + err = analog_init_port(gameport, drv, port); + if (err) + goto fail1; - if (analog_init_masks(port)) { - gameport_close(gameport); - kfree(port); - return; - } + err = analog_init_masks(port); + if (err) + goto fail2; + + gameport_set_poll_handler(gameport, analog_poll); + gameport_set_poll_interval(gameport, 10); for (i = 0; i < 2; i++) + if (port->analog[i].mask) { + err = analog_init_device(port, port->analog + i, i); + if (err) + goto fail3; + } + + return 0; + + fail3: while (--i >= 0) if (port->analog[i].mask) - analog_init_device(port, port->analog + i, i); + input_unregister_device(port->analog[i].dev); + fail2: gameport_close(gameport); + fail1: gameport_set_drvdata(gameport, NULL); + kfree(port); + return err; } static void analog_disconnect(struct gameport *gameport) { + struct analog_port *port = gameport_get_drvdata(gameport); int i; - struct analog_port *port = gameport->private; for (i = 0; i < 2; i++) if (port->analog[i].mask) - input_unregister_device(&port->analog[i].dev); + input_unregister_device(port->analog[i].dev); gameport_close(gameport); + gameport_set_drvdata(gameport, NULL); 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->phys); @@ -696,7 +702,7 @@ struct analog_types { int value; }; -struct analog_types analog_types[] = { +static struct analog_types analog_types[] = { { "none", 0x00000000 }, { "auto", 0x000000ff }, { "2btn", 0x0000003f }, @@ -741,21 +747,26 @@ static void analog_parse_options(void) * The gameport device structure. */ -static struct gameport_dev analog_dev = { - .connect = analog_connect, - .disconnect = analog_disconnect, +static struct gameport_driver analog_drv = { + .driver = { + .name = "analog", + }, + .description = DRIVER_DESC, + .connect = analog_connect, + .disconnect = analog_disconnect, }; -int __init analog_init(void) +static int __init analog_init(void) { analog_parse_options(); - gameport_register_device(&analog_dev); + gameport_register_driver(&analog_drv); + return 0; } -void __exit analog_exit(void) +static void __exit analog_exit(void) { - gameport_unregister_device(&analog_dev); + gameport_unregister_driver(&analog_drv); } module_init(analog_init);