fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / input / mouse / vsxxxaa.c
index c26d907..c3d64fc 100644 (file)
@@ -1,11 +1,14 @@
 /*
- * DEC VSXXX-AA and VSXXX-GA mouse driver.
+ * Driver for  DEC VSXXX-AA mouse (hockey-puck mouse, ball or two rollers)
+ *             DEC VSXXX-GA mouse (rectangular mouse, with ball)
+ *             DEC VSXXX-AB tablet (digitizer with hair cross or stylus)
  *
  * Copyright (C) 2003-2004 by Jan-Benedict Glaw <jbglaw@lug-owl.de>
  *
- * The packet format was taken from a patch to GPM which is (C) 2001
+ * The packet format was initially taken from a patch to GPM which is (C) 2001
  * by  Karsten Merker <merker@linuxtag.org>
  * and Maciej W. Rozycki <macro@ds2.pg.gda.pl>
+ * Later on, I had access to the device's documentation (referenced below).
  */
 
 /*
@@ -25,7 +28,7 @@
  */
 
 /*
- * Building an adaptor to DB9 / DB25 RS232
+ * Building an adaptor to DE9 / DB25 RS232
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
  * DISCLAIMER: Use this description AT YOUR OWN RISK! I'll not pay for
@@ -42,8 +45,8 @@
  *  | 4 --- 3 |
  *   \  2 1  /
  *    -------
- * 
- *     DEC socket      DB9     DB25    Note
+ *
+ *     DEC socket      DE9     DB25    Note
  *     1 (GND)         5       7       -
  *     2 (RxD)         2       3       -
  *     3 (TxD)         3       2       -
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/input.h>
-#include <linux/config.h>
 #include <linux/serio.h>
 #include <linux/init.h>
 
+#define DRIVER_DESC "Driver for DEC VSXXX-AA and -GA mice and VSXXX-AB tablet"
+
 MODULE_AUTHOR ("Jan-Benedict Glaw <jbglaw@lug-owl.de>");
-MODULE_DESCRIPTION ("Serial DEC VSXXX-AA/GA mouse / DEC tablet driver");
+MODULE_DESCRIPTION (DRIVER_DESC);
 MODULE_LICENSE ("GPL");
 
 #undef VSXXXAA_DEBUG
@@ -102,12 +106,12 @@ MODULE_LICENSE ("GPL");
 #define VSXXXAA_PACKET_REL     0x80
 #define VSXXXAA_PACKET_ABS     0xc0
 #define VSXXXAA_PACKET_POR     0xa0
-#define MATCH_PACKET_TYPE(data, type)  (((data) & VSXXXAA_PACKET_MASK) == type)
+#define MATCH_PACKET_TYPE(data, type)  (((data) & VSXXXAA_PACKET_MASK) == (type))
 
 
 
 struct vsxxxaa {
-       struct input_dev dev;
+       struct input_dev *dev;
        struct serio *serio;
 #define BUFLEN 15 /* At least 5 is needed for a full tablet packet */
        unsigned char buf[BUFLEN];
@@ -148,21 +152,25 @@ vsxxxaa_detection_done (struct vsxxxaa *mouse)
 {
        switch (mouse->type) {
                case 0x02:
-                       sprintf (mouse->name, "DEC VSXXX-AA/GA mouse");
+                       strlcpy (mouse->name, "DEC VSXXX-AA/-GA mouse",
+                                sizeof (mouse->name));
                        break;
 
                case 0x04:
-                       sprintf (mouse->name, "DEC VSXXX-AB digitizer");
+                       strlcpy (mouse->name, "DEC VSXXX-AB digitizer",
+                                sizeof (mouse->name));
                        break;
 
                default:
-                       sprintf (mouse->name, "unknown DEC pointer device");
+                       snprintf (mouse->name, sizeof (mouse->name),
+                                 "unknown DEC pointer device (type = 0x%02x)",
+                                 mouse->type);
                        break;
        }
 
-       printk (KERN_INFO "Found %s version 0x%02x from country 0x%02x "
-                       "on port %s\n", mouse->name, mouse->version,
-                       mouse->country, mouse->phys);
+       printk (KERN_INFO
+               "Found %s version 0x%02x from country 0x%02x on port %s\n",
+               mouse->name, mouse->version, mouse->country, mouse->phys);
 }
 
 /*
@@ -203,9 +211,9 @@ vsxxxaa_smells_like_packet (struct vsxxxaa *mouse, unsigned char type, size_t le
 }
 
 static void
-vsxxxaa_handle_REL_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
+vsxxxaa_handle_REL_packet (struct vsxxxaa *mouse)
 {
-       struct input_dev *dev = &mouse->dev;
+       struct input_dev *dev = mouse->dev;
        unsigned char *buf = mouse->buf;
        int left, middle, right;
        int dx, dy;
@@ -250,7 +258,6 @@ vsxxxaa_handle_REL_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
        /*
         * Report what we've found so far...
         */
-       input_regs (dev, regs);
        input_report_key (dev, BTN_LEFT, left);
        input_report_key (dev, BTN_MIDDLE, middle);
        input_report_key (dev, BTN_RIGHT, right);
@@ -261,9 +268,9 @@ vsxxxaa_handle_REL_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
 }
 
 static void
-vsxxxaa_handle_ABS_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
+vsxxxaa_handle_ABS_packet (struct vsxxxaa *mouse)
 {
-       struct input_dev *dev = &mouse->dev;
+       struct input_dev *dev = mouse->dev;
        unsigned char *buf = mouse->buf;
        int left, middle, right, touch;
        int x, y;
@@ -304,7 +311,6 @@ vsxxxaa_handle_ABS_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
        /*
         * Report what we've found so far...
         */
-       input_regs (dev, regs);
        input_report_key (dev, BTN_LEFT, left);
        input_report_key (dev, BTN_MIDDLE, middle);
        input_report_key (dev, BTN_RIGHT, right);
@@ -315,9 +321,9 @@ vsxxxaa_handle_ABS_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
 }
 
 static void
-vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
+vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse)
 {
-       struct input_dev *dev = &mouse->dev;
+       struct input_dev *dev = mouse->dev;
        unsigned char *buf = mouse->buf;
        int left, middle, right;
        unsigned char error;
@@ -334,13 +340,10 @@ vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
         *
         * M: manufacturer location code
         * R: revision code
-        * E: Error code. I'm not sure about these, but gpm's sources,
-        *    which support this mouse, too, tell about them:
-        *      E = [0x00 .. 0x1f]: no error, byte #3 is button state
-        *      E = 0x3d: button error, byte #3 tells which one.
-        *      E = <else>: other error
+        * E: Error code. If it's in the range of 0x00..0x1f, only some
+        *    minor problem occured. Errors >= 0x20 are considered bad
+        *    and the device may not work properly...
         * D: <0010> == mouse, <0100> == tablet
-        *
         */
 
        mouse->version = buf[0] & 0x0f;
@@ -361,32 +364,35 @@ vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
        vsxxxaa_detection_done (mouse);
 
        if (error <= 0x1f) {
-               /* No error. Report buttons */
-               input_regs (dev, regs);
+               /* No (serious) error. Report buttons */
                input_report_key (dev, BTN_LEFT, left);
                input_report_key (dev, BTN_MIDDLE, middle);
                input_report_key (dev, BTN_RIGHT, right);
                input_report_key (dev, BTN_TOUCH, 0);
                input_sync (dev);
-       } else {
-               printk (KERN_ERR "Your %s on %s reports an undefined error, "
-                               "please check it...\n", mouse->name,
-                               mouse->phys);
+
+               if (error != 0)
+                       printk (KERN_INFO "Your %s on %s reports error=0x%02x\n",
+                                       mouse->name, mouse->phys, error);
+
        }
 
        /*
         * If the mouse was hot-plugged, we need to force differential mode
         * now... However, give it a second to recover from it's reset.
         */
-       printk (KERN_NOTICE "%s on %s: Forceing standard packet format and "
-                       "streaming mode\n", mouse->name, mouse->phys);
-       mouse->serio->write (mouse->serio, 'S');
+       printk (KERN_NOTICE "%s on %s: Forceing standard packet format, "
+                       "incremental streaming mode and 72 samples/sec\n",
+                       mouse->name, mouse->phys);
+       mouse->serio->write (mouse->serio, 'S');        /* Standard format */
        mdelay (50);
-       mouse->serio->write (mouse->serio, 'R');
+       mouse->serio->write (mouse->serio, 'R');        /* Incremental */
+       mdelay (50);
+       mouse->serio->write (mouse->serio, 'L');        /* 72 samples/sec */
 }
 
 static void
-vsxxxaa_parse_buffer (struct vsxxxaa *mouse, struct pt_regs *regs)
+vsxxxaa_parse_buffer (struct vsxxxaa *mouse)
 {
        unsigned char *buf = mouse->buf;
        int stray_bytes;
@@ -423,7 +429,7 @@ vsxxxaa_parse_buffer (struct vsxxxaa *mouse, struct pt_regs *regs)
                                continue;
                        }
 
-                       vsxxxaa_handle_REL_packet (mouse, regs);
+                       vsxxxaa_handle_REL_packet (mouse);
                        continue; /* More to parse? */
                }
 
@@ -437,7 +443,7 @@ vsxxxaa_parse_buffer (struct vsxxxaa *mouse, struct pt_regs *regs)
                                continue;
                        }
 
-                       vsxxxaa_handle_ABS_packet (mouse, regs);
+                       vsxxxaa_handle_ABS_packet (mouse);
                        continue; /* More to parse? */
                }
 
@@ -451,7 +457,7 @@ vsxxxaa_parse_buffer (struct vsxxxaa *mouse, struct pt_regs *regs)
                                continue;
                        }
 
-                       vsxxxaa_handle_POR_packet (mouse, regs);
+                       vsxxxaa_handle_POR_packet (mouse);
                        continue; /* More to parse? */
                }
 
@@ -460,13 +466,12 @@ vsxxxaa_parse_buffer (struct vsxxxaa *mouse, struct pt_regs *regs)
 }
 
 static irqreturn_t
-vsxxxaa_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
-               struct pt_regs *regs)
+vsxxxaa_interrupt (struct serio *serio, unsigned char data, unsigned int flags)
 {
-       struct vsxxxaa *mouse = serio->private;
+       struct vsxxxaa *mouse = serio_get_drvdata (serio);
 
        vsxxxaa_queue_byte (mouse, data);
-       vsxxxaa_parse_buffer (mouse, regs);
+       vsxxxaa_parse_buffer (mouse);
 
        return IRQ_HANDLED;
 }
@@ -474,89 +479,108 @@ vsxxxaa_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
 static void
 vsxxxaa_disconnect (struct serio *serio)
 {
-       struct vsxxxaa *mouse = serio->private;
+       struct vsxxxaa *mouse = serio_get_drvdata (serio);
 
-       input_unregister_device (&mouse->dev);
        serio_close (serio);
+       serio_set_drvdata (serio, NULL);
+       input_unregister_device (mouse->dev);
        kfree (mouse);
 }
 
-static void
-vsxxxaa_connect (struct serio *serio, struct serio_dev *dev)
+static int
+vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
 {
        struct vsxxxaa *mouse;
+       struct input_dev *input_dev;
+       int err = -ENOMEM;
 
-       if ((serio->type & SERIO_TYPE) != SERIO_RS232)
-               return;
-       if ((serio->type & SERIO_PROTO) != SERIO_VSXXXAA)
-               return;
-
-       if (!(mouse = kmalloc (sizeof (struct vsxxxaa), GFP_KERNEL)))
-               return;
-
-       memset (mouse, 0, sizeof (struct vsxxxaa));
-
-       init_input_dev (&mouse->dev);
-       set_bit (EV_KEY, mouse->dev.evbit);             /* We have buttons */
-       set_bit (EV_REL, mouse->dev.evbit);
-       set_bit (EV_ABS, mouse->dev.evbit);
-       set_bit (BTN_LEFT, mouse->dev.keybit);          /* We have 3 buttons */
-       set_bit (BTN_MIDDLE, mouse->dev.keybit);
-       set_bit (BTN_RIGHT, mouse->dev.keybit);
-       set_bit (BTN_TOUCH, mouse->dev.keybit);         /* ...and Tablet */
-       set_bit (REL_X, mouse->dev.relbit);
-       set_bit (REL_Y, mouse->dev.relbit);
-       set_bit (ABS_X, mouse->dev.absbit);
-       set_bit (ABS_Y, mouse->dev.absbit);
-
-       mouse->dev.absmin[ABS_X] = 0;
-       mouse->dev.absmax[ABS_X] = 1023;
-       mouse->dev.absmin[ABS_Y] = 0;
-       mouse->dev.absmax[ABS_Y] = 1023;
-
-       mouse->dev.private = mouse;
-       serio->private = mouse;
-
-       sprintf (mouse->name, "DEC VSXXX-AA/GA mouse or VSXXX-AB digitizer");
-       sprintf (mouse->phys, "%s/input0", serio->phys);
-       mouse->dev.name = mouse->name;
-       mouse->dev.phys = mouse->phys;
-       mouse->dev.id.bustype = BUS_RS232;
-       mouse->serio = serio;
+       mouse = kzalloc (sizeof (struct vsxxxaa), GFP_KERNEL);
+       input_dev = input_allocate_device ();
+       if (!mouse || !input_dev)
+               goto fail1;
 
-       if (serio_open (serio, dev)) {
-               kfree (mouse);
-               return;
-       }
+       mouse->dev = input_dev;
+       mouse->serio = serio;
+       strlcat (mouse->name, "DEC VSXXX-AA/-GA mouse or VSXXX-AB digitizer",
+                sizeof (mouse->name));
+       snprintf (mouse->phys, sizeof (mouse->phys), "%s/input0", serio->phys);
+
+       input_dev->name = mouse->name;
+       input_dev->phys = mouse->phys;
+       input_dev->id.bustype = BUS_RS232;
+       input_dev->cdev.dev = &serio->dev;
+       input_dev->private = mouse;
+
+       set_bit (EV_KEY, input_dev->evbit);             /* We have buttons */
+       set_bit (EV_REL, input_dev->evbit);
+       set_bit (EV_ABS, input_dev->evbit);
+       set_bit (BTN_LEFT, input_dev->keybit);          /* We have 3 buttons */
+       set_bit (BTN_MIDDLE, input_dev->keybit);
+       set_bit (BTN_RIGHT, input_dev->keybit);
+       set_bit (BTN_TOUCH, input_dev->keybit);         /* ...and Tablet */
+       set_bit (REL_X, input_dev->relbit);
+       set_bit (REL_Y, input_dev->relbit);
+       input_set_abs_params (input_dev, ABS_X, 0, 1023, 0, 0);
+       input_set_abs_params (input_dev, ABS_Y, 0, 1023, 0, 0);
+
+       serio_set_drvdata (serio, mouse);
+
+       err = serio_open (serio, drv);
+       if (err)
+               goto fail2;
 
        /*
         * Request selftest. Standard packet format and differential
         * mode will be requested after the device ID'ed successfully.
         */
-       mouse->serio->write (mouse->serio, 'T'); /* Test */
+       serio->write (serio, 'T'); /* Test */
 
-       input_register_device (&mouse->dev);
+       err = input_register_device (input_dev);
+       if (err)
+               goto fail3;
+
+       return 0;
 
-       printk (KERN_INFO "input: %s on %s\n", mouse->name, mouse->phys);
+ fail3:        serio_close (serio);
+ fail2:        serio_set_drvdata (serio, NULL);
+ fail1:        input_free_device (input_dev);
+       kfree (mouse);
+       return err;
 }
 
-static struct serio_dev vsxxxaa_dev = {
-       .connect = vsxxxaa_connect,
-       .interrupt = vsxxxaa_interrupt,
-       .disconnect = vsxxxaa_disconnect,
+static struct serio_device_id vsxxaa_serio_ids[] = {
+       {
+               .type   = SERIO_RS232,
+               .proto  = SERIO_VSXXXAA,
+               .id     = SERIO_ANY,
+               .extra  = SERIO_ANY,
+       },
+       { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, vsxxaa_serio_ids);
+
+static struct serio_driver vsxxxaa_drv = {
+       .driver         = {
+               .name   = "vsxxxaa",
+       },
+       .description    = DRIVER_DESC,
+       .id_table       = vsxxaa_serio_ids,
+       .connect        = vsxxxaa_connect,
+       .interrupt      = vsxxxaa_interrupt,
+       .disconnect     = vsxxxaa_disconnect,
 };
 
-int __init
+static int __init
 vsxxxaa_init (void)
 {
-       serio_register_device (&vsxxxaa_dev);
-       return 0;
+       return serio_register_driver(&vsxxxaa_drv);
 }
 
-void __exit
+static void __exit
 vsxxxaa_exit (void)
 {
-       serio_unregister_device (&vsxxxaa_dev);
+       serio_unregister_driver(&vsxxxaa_drv);
 }
 
 module_init (vsxxxaa_init);