/*
- * 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/serio.h>
#include <linux/init.h>
-#define DRIVER_DESC "Serial DEC VSXXX-AA/GA mouse / DEC tablet driver"
+#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 (DRIVER_DESC);
#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");
+ sprintf (mouse->name, "DEC VSXXX-AA/-GA mouse");
break;
case 0x04:
break;
default:
- sprintf (mouse->name, "unknown DEC pointer device");
+ sprintf (mouse->name, "unknown DEC pointer device "
+ "(type = 0x%02x)", mouse->type);
break;
}
static void
vsxxxaa_handle_REL_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
{
- struct input_dev *dev = &mouse->dev;
+ struct input_dev *dev = mouse->dev;
unsigned char *buf = mouse->buf;
int left, middle, right;
int dx, dy;
static void
vsxxxaa_handle_ABS_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
{
- 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;
static void
vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
{
- 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 */
+ /* No (serious) error. Report buttons */
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);
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'); /* Incremental */
mdelay (50);
- mouse->serio->write (mouse->serio, 'R');
+ mouse->serio->write (mouse->serio, 'L'); /* 72 samples/sec */
}
static void
vsxxxaa_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
struct pt_regs *regs)
{
- struct vsxxxaa *mouse = serio->private;
+ struct vsxxxaa *mouse = serio_get_drvdata (serio);
vsxxxaa_queue_byte (mouse, data);
vsxxxaa_parse_buffer (mouse, regs);
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
+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 = kzalloc (sizeof (struct vsxxxaa), GFP_KERNEL);
+ input_dev = input_allocate_device ();
+ if (!mouse || !input_dev)
+ goto fail;
+
+ mouse->dev = input_dev;
mouse->serio = serio;
+ sprintf (mouse->name, "DEC VSXXX-AA/-GA mouse or VSXXX-AB digitizer");
+ sprintf (mouse->phys, "%s/input0", serio->phys);
- if (serio_open (serio, drv)) {
- kfree (mouse);
- return;
- }
+ 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 fail;
/*
* 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);
+ input_register_device (input_dev);
- printk (KERN_INFO "input: %s on %s\n", mouse->name, mouse->phys);
+ return 0;
+
+ fail: serio_set_drvdata (serio, NULL);
+ input_free_device (input_dev);
+ kfree (mouse);
+ return err;
}
+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_driver(&vsxxxaa_drv);
return 0;
}
-void __exit
+static void __exit
vsxxxaa_exit (void)
{
serio_unregister_driver(&vsxxxaa_drv);