Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / input / joystick / guillemot.c
index cfe8c6b..6e2c721 100644 (file)
 #include <linux/init.h>
 #include <linux/gameport.h>
 #include <linux/input.h>
+#include <linux/jiffies.h>
+
+#define DRIVER_DESC    "Guillemot Digital joystick driver"
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Guillemot Digital joystick driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 #define GUILLEMOT_MAX_START    600     /* 600 us */
 #define GUILLEMOT_MAX_STROBE   60      /* 60 us */
 #define GUILLEMOT_MAX_LENGTH   17      /* 17 bytes */
-#define GUILLEMOT_REFRESH_TIME HZ/50   /* 20 ms */
 
 static short guillemot_abs_pad[] =
        { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, -1 };
@@ -66,9 +68,7 @@ struct guillemot_type {
 
 struct guillemot {
        struct gameport *gameport;
-       struct input_dev dev;
-       struct timer_list timer;
-       int used;
+       struct input_dev *dev;
        int bads;
        int reads;
        struct guillemot_type *type;
@@ -118,13 +118,13 @@ static int guillemot_read_packet(struct gameport *gameport, u8 *data)
 }
 
 /*
- * guillemot_timer() reads and analyzes Guillemot joystick data.
+ * guillemot_poll() reads and analyzes Guillemot joystick data.
  */
 
-static void guillemot_timer(unsigned long private)
+static void guillemot_poll(struct gameport *gameport)
 {
-       struct guillemot *guillemot = (struct guillemot *) private;
-       struct input_dev *dev = &guillemot->dev;
+       struct guillemot *guillemot = gameport_get_drvdata(gameport);
+       struct input_dev *dev = guillemot->dev;
        u8 data[GUILLEMOT_MAX_LENGTH];
        int i;
 
@@ -148,8 +148,6 @@ static void guillemot_timer(unsigned long private)
        }
 
        input_sync(dev);
-
-       mod_timer(&guillemot->timer, jiffies + GUILLEMOT_REFRESH_TIME);
 }
 
 /*
@@ -159,8 +157,8 @@ static void guillemot_timer(unsigned long private)
 static int guillemot_open(struct input_dev *dev)
 {
        struct guillemot *guillemot = dev->private;
-       if (!guillemot->used++)
-               mod_timer(&guillemot->timer, jiffies + GUILLEMOT_REFRESH_TIME);
+
+       gameport_start_polling(guillemot->gameport);
        return 0;
 }
 
@@ -171,38 +169,44 @@ static int guillemot_open(struct input_dev *dev)
 static void guillemot_close(struct input_dev *dev)
 {
        struct guillemot *guillemot = dev->private;
-       if (!--guillemot->used)
-               del_timer(&guillemot->timer);
+
+       gameport_stop_polling(guillemot->gameport);
 }
 
 /*
  * guillemot_connect() probes for Guillemot joysticks.
  */
 
-static void guillemot_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int guillemot_connect(struct gameport *gameport, struct gameport_driver *drv)
 {
        struct guillemot *guillemot;
+       struct input_dev *input_dev;
        u8 data[GUILLEMOT_MAX_LENGTH];
        int i, t;
+       int err;
 
-       if (!(guillemot = kmalloc(sizeof(struct guillemot), GFP_KERNEL)))
-               return;
-       memset(guillemot, 0, sizeof(struct guillemot));
-
-       gameport->private = guillemot;
+       guillemot = kzalloc(sizeof(struct guillemot), GFP_KERNEL);
+       input_dev = input_allocate_device();
+       if (!guillemot || !input_dev) {
+               err = -ENOMEM;
+               goto fail1;
+       }
 
        guillemot->gameport = gameport;
-       init_timer(&guillemot->timer);
-       guillemot->timer.data = (long) guillemot;
-       guillemot->timer.function = guillemot_timer;
+       guillemot->dev = input_dev;
 
-       if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+       gameport_set_drvdata(gameport, guillemot);
+
+       err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+       if (err)
                goto fail1;
 
        i = guillemot_read_packet(gameport, data);
 
-       if (i != GUILLEMOT_MAX_LENGTH * 8 || data[0] != 0x55 || data[16] != 0xaa)
+       if (i != GUILLEMOT_MAX_LENGTH * 8 || data[0] != 0x55 || data[16] != 0xaa) {
+               err = -ENODEV;
                goto fail2;
+       }
 
        for (i = 0; guillemot_type[i].name; i++)
                if (guillemot_type[i].id == data[11])
@@ -211,75 +215,80 @@ static void guillemot_connect(struct gameport *gameport, struct gameport_dev *de
        if (!guillemot_type[i].name) {
                printk(KERN_WARNING "guillemot.c: Unknown joystick on %s. [ %02x%02x:%04x, ver %d.%02d ]\n",
                        gameport->phys, data[12], data[13], data[11], data[14], data[15]);
+               err = -ENODEV;
                goto fail2;
        }
 
-       sprintf(guillemot->phys, "%s/input0", gameport->phys);
+       gameport_set_poll_handler(gameport, guillemot_poll);
+       gameport_set_poll_interval(gameport, 20);
 
+       sprintf(guillemot->phys, "%s/input0", gameport->phys);
        guillemot->type = guillemot_type + i;
 
-       guillemot->dev.private = guillemot;
-       guillemot->dev.open = guillemot_open;
-       guillemot->dev.close = guillemot_close;
+       input_dev->name = guillemot_type[i].name;
+       input_dev->phys = guillemot->phys;
+       input_dev->id.bustype = BUS_GAMEPORT;
+       input_dev->id.vendor = GAMEPORT_ID_VENDOR_GUILLEMOT;
+       input_dev->id.product = guillemot_type[i].id;
+       input_dev->id.version = (int)data[14] << 8 | data[15];
+       input_dev->cdev.dev = &gameport->dev;
+       input_dev->private = guillemot;
 
-       guillemot->dev.name = guillemot_type[i].name;
-       guillemot->dev.phys = guillemot->phys;
-       guillemot->dev.id.bustype = BUS_GAMEPORT;
-       guillemot->dev.id.vendor = GAMEPORT_ID_VENDOR_GUILLEMOT;
-       guillemot->dev.id.product = guillemot_type[i].id;
-       guillemot->dev.id.version = (int)data[14] << 8 | data[15];
+       input_dev->open = guillemot_open;
+       input_dev->close = guillemot_close;
 
-       guillemot->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+       input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
-       for (i = 0; (t = guillemot->type->abs[i]) >= 0; i++) {
-               set_bit(t, guillemot->dev.absbit);
-               guillemot->dev.absmin[t] = 0;
-               guillemot->dev.absmax[t] = 255;
-       }
+       for (i = 0; (t = guillemot->type->abs[i]) >= 0; i++)
+               input_set_abs_params(input_dev, t, 0, 255, 0, 0);
 
-       if (guillemot->type->hat)
-               for (i = 0; i < 2; i++) {
-                       t = ABS_HAT0X + i;
-                       set_bit(t, guillemot->dev.absbit);
-                       guillemot->dev.absmin[t] = -1;
-                       guillemot->dev.absmax[t] = 1;
-               }
+       if (guillemot->type->hat) {
+               input_set_abs_params(input_dev, ABS_HAT0X, -1, 1, 0, 0);
+               input_set_abs_params(input_dev, ABS_HAT0Y, -1, 1, 0, 0);
+       }
 
        for (i = 0; (t = guillemot->type->btn[i]) >= 0; i++)
-               set_bit(t, guillemot->dev.keybit);
+               set_bit(t, input_dev->keybit);
 
-       input_register_device(&guillemot->dev);
-       printk(KERN_INFO "input: %s ver %d.%02d on %s\n",
-               guillemot->type->name, data[14], data[15], gameport->phys);
+       input_register_device(guillemot->dev);
+
+       return 0;
 
-       return;
 fail2: gameport_close(gameport);
-fail1:  kfree(guillemot);
+fail1:  gameport_set_drvdata(gameport, NULL);
+       input_free_device(input_dev);
+       kfree(guillemot);
+       return err;
 }
 
 static void guillemot_disconnect(struct gameport *gameport)
 {
-       struct guillemot *guillemot = gameport->private;
+       struct guillemot *guillemot = gameport_get_drvdata(gameport);
+
        printk(KERN_INFO "guillemot.c: Failed %d reads out of %d on %s\n", guillemot->reads, guillemot->bads, guillemot->phys);
-       input_unregister_device(&guillemot->dev);
+       input_unregister_device(guillemot->dev);
        gameport_close(gameport);
        kfree(guillemot);
 }
 
-static struct gameport_dev guillemot_dev = {
-       .connect =      guillemot_connect,
-       .disconnect =   guillemot_disconnect,
+static struct gameport_driver guillemot_drv = {
+       .driver         = {
+               .name   = "guillemot",
+       },
+       .description    = DRIVER_DESC,
+       .connect        = guillemot_connect,
+       .disconnect     = guillemot_disconnect,
 };
 
-int __init guillemot_init(void)
+static int __init guillemot_init(void)
 {
-       gameport_register_device(&guillemot_dev);
+       gameport_register_driver(&guillemot_drv);
        return 0;
 }
 
-void __exit guillemot_exit(void)
+static void __exit guillemot_exit(void)
 {
-       gameport_unregister_device(&guillemot_dev);
+       gameport_unregister_driver(&guillemot_drv);
 }
 
 module_init(guillemot_init);