X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Finput%2Fjoystick%2Fspaceball.c;h=d6f8db8ec3fd34aacc743156d5a9ae91c2170af4;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=4e288b58c9b2df28b73032c96cac57f7e6ab4675;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c index 4e288b58c..d6f8db8ec 100644 --- a/drivers/input/joystick/spaceball.c +++ b/drivers/input/joystick/spaceball.c @@ -4,8 +4,8 @@ * Copyright (c) 1999-2001 Vojtech Pavlik * * Based on the work of: - * David Thompson - * Joseph Krahn + * David Thompson + * Joseph Krahn */ /* @@ -15,18 +15,18 @@ /* * 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, Simunkova 1594, Prague 8, 182 00 Czech Republic @@ -39,8 +39,10 @@ #include #include +#define DRIVER_DESC "SpaceTec SpaceBall 2003/3003/4000 FLX driver" + MODULE_AUTHOR("Vojtech Pavlik "); -MODULE_DESCRIPTION("SpaceTec SpaceBall 2003/3003/4000 FLX driver"); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); /* @@ -59,8 +61,8 @@ MODULE_LICENSE("GPL"); static int spaceball_axes[] = { ABS_X, ABS_Z, ABS_Y, ABS_RX, ABS_RZ, ABS_RY }; static char *spaceball_names[] = { - "?", "SpaceTec SpaceBall 1003", "SpaceTec SpaceBall 2003", "SpaceTec SpaceBall 2003B", - "SpaceTec SpaceBall 2003C", "SpaceTec SpaceBall 3003", "SpaceTec SpaceBall SpaceController", + "?", "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" }; /* @@ -68,8 +70,7 @@ static char *spaceball_names[] = { */ struct spaceball { - struct input_dev dev; - struct serio *serio; + struct input_dev *dev; int idx; int escape; unsigned char data[SPACEBALL_MAX_LENGTH]; @@ -83,7 +84,7 @@ struct spaceball { static void spaceball_process_packet(struct spaceball* spaceball, struct pt_regs *regs) { - struct input_dev *dev = &spaceball->dev; + struct input_dev *dev = spaceball->dev; unsigned char *data = spaceball->data; int i; @@ -96,7 +97,7 @@ static void spaceball_process_packet(struct spaceball* spaceball, struct pt_regs case 'D': /* Ball data */ if (spaceball->idx != 15) return; for (i = 0; i < 6; i++) - input_report_abs(dev, spaceball_axes[i], + input_report_abs(dev, spaceball_axes[i], (__s16)((data[2 * i + 3] << 8) | data[2 * i + 2])); break; @@ -152,7 +153,7 @@ static void spaceball_process_packet(struct spaceball* spaceball, struct pt_regs static irqreturn_t spaceball_interrupt(struct serio *serio, unsigned char data, unsigned int flags, struct pt_regs *regs) { - struct spaceball *spaceball = serio->private; + struct spaceball *spaceball = serio_get_drvdata(serio); switch (data) { case 0xd: @@ -189,105 +190,121 @@ static irqreturn_t spaceball_interrupt(struct serio *serio, static void spaceball_disconnect(struct serio *serio) { - struct spaceball* spaceball = serio->private; - input_unregister_device(&spaceball->dev); + struct spaceball* spaceball = serio_get_drvdata(serio); + serio_close(serio); + serio_set_drvdata(serio, NULL); + input_unregister_device(spaceball->dev); kfree(spaceball); } /* * spaceball_connect() is the routine that is called when someone adds a - * new serio device. It looks for the Magellan, and if found, registers - * it as an input device. + * new serio device that supports Spaceball protocol and registers it as + * an input device. */ -static void spaceball_connect(struct serio *serio, struct serio_dev *dev) +static int spaceball_connect(struct serio *serio, struct serio_driver *drv) { struct spaceball *spaceball; - int i, t, id; + struct input_dev *input_dev; + int err = -ENOMEM; + int i, id; + + if ((id = serio->id.id) > SPACEBALL_MAX_ID) + return -ENODEV; - if ((serio->type & ~SERIO_ID) != (SERIO_RS232 | SERIO_SPACEBALL)) - return; + spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!spaceball || !input_dev) + goto fail; - if ((id = (serio->type & SERIO_ID) >> 8) > SPACEBALL_MAX_ID) - return; + spaceball->dev = input_dev; + sprintf(spaceball->phys, "%s/input0", serio->phys); - if (!(spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL))) - return; - memset(spaceball, 0, sizeof(struct spaceball)); + input_dev->name = spaceball_names[id]; + input_dev->phys = spaceball->phys; + input_dev->id.bustype = BUS_RS232; + input_dev->id.vendor = SERIO_SPACEBALL; + input_dev->id.product = id; + input_dev->id.version = 0x0100; + input_dev->cdev.dev = &serio->dev; + input_dev->private = spaceball; - spaceball->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); 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); + input_dev->keybit[LONG(BTN_0)] |= BIT(BTN_9); + input_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) + input_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); + input_dev->keybit[LONG(BTN_0)] |= BIT(BTN_1) | BIT(BTN_8); } - for (i = 0; i < 6; i++) { - t = spaceball_axes[i]; - set_bit(t, spaceball->dev.absbit); - spaceball->dev.absmin[t] = i < 3 ? -8000 : -1600; - spaceball->dev.absmax[t] = i < 3 ? 8000 : 1600; - spaceball->dev.absflat[t] = i < 3 ? 40 : 8; - spaceball->dev.absfuzz[t] = i < 3 ? 8 : 2; + for (i = 0; i < 3; i++) { + input_set_abs_params(input_dev, ABS_X + i, -8000, 8000, 8, 40); + input_set_abs_params(input_dev, ABS_RX + i, -1600, 1600, 2, 8); } - spaceball->serio = serio; - spaceball->dev.private = spaceball; + serio_set_drvdata(serio, spaceball); - sprintf(spaceball->phys, "%s/input0", serio->phys); - - init_input_dev(&spaceball->dev); - spaceball->dev.name = spaceball_names[id]; - spaceball->dev.phys = spaceball->phys; - spaceball->dev.id.bustype = BUS_RS232; - spaceball->dev.id.vendor = SERIO_SPACEBALL; - spaceball->dev.id.product = id; - spaceball->dev.id.version = 0x0100; - - serio->private = spaceball; - - if (serio_open(serio, dev)) { - kfree(spaceball); - return; - } + err = serio_open(serio, drv); + if (err) + goto fail; - input_register_device(&spaceball->dev); + input_register_device(spaceball->dev); + return 0; - printk(KERN_INFO "input: %s on serio%s\n", - spaceball_names[id], serio->phys); + fail: serio_set_drvdata(serio, NULL); + input_free_device(input_dev); + kfree(spaceball); + return err; } /* - * The serio device structure. + * The serio driver structure. */ -static struct serio_dev spaceball_dev = { - .interrupt = spaceball_interrupt, - .connect = spaceball_connect, - .disconnect = spaceball_disconnect, +static struct serio_device_id spaceball_serio_ids[] = { + { + .type = SERIO_RS232, + .proto = SERIO_SPACEBALL, + .id = SERIO_ANY, + .extra = SERIO_ANY, + }, + { 0 } +}; + +MODULE_DEVICE_TABLE(serio, spaceball_serio_ids); + +static struct serio_driver spaceball_drv = { + .driver = { + .name = "spaceball", + }, + .description = DRIVER_DESC, + .id_table = spaceball_serio_ids, + .interrupt = spaceball_interrupt, + .connect = spaceball_connect, + .disconnect = spaceball_disconnect, }; /* * The functions for inserting/removing us as a module. */ -int __init spaceball_init(void) +static int __init spaceball_init(void) { - serio_register_device(&spaceball_dev); + serio_register_driver(&spaceball_drv); return 0; } -void __exit spaceball_exit(void) +static void __exit spaceball_exit(void) { - serio_unregister_device(&spaceball_dev); + serio_unregister_driver(&spaceball_drv); } module_init(spaceball_init);