/*
- * 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).
*/
/*
*/
/*
- * 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
* | 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
#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];
{
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);
}
/*
}
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;
/*
* 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);
}
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;
/*
* 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);
}
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;
*
* 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;
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;
continue;
}
- vsxxxaa_handle_REL_packet (mouse, regs);
+ vsxxxaa_handle_REL_packet (mouse);
continue; /* More to parse? */
}
continue;
}
- vsxxxaa_handle_ABS_packet (mouse, regs);
+ vsxxxaa_handle_ABS_packet (mouse);
continue; /* More to parse? */
}
continue;
}
- vsxxxaa_handle_POR_packet (mouse, regs);
+ vsxxxaa_handle_POR_packet (mouse);
continue; /* More to parse? */
}
}
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;
}
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);