Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Driver for   DEC VSXXX-AA mouse (hockey-puck mouse, ball or two rollers)
0004  *      DEC VSXXX-GA mouse (rectangular mouse, with ball)
0005  *      DEC VSXXX-AB tablet (digitizer with hair cross or stylus)
0006  *
0007  * Copyright (C) 2003-2004 by Jan-Benedict Glaw <jbglaw@lug-owl.de>
0008  *
0009  * The packet format was initially taken from a patch to GPM which is (C) 2001
0010  * by   Karsten Merker <merker@linuxtag.org>
0011  * and  Maciej W. Rozycki <macro@ds2.pg.gda.pl>
0012  * Later on, I had access to the device's documentation (referenced below).
0013  */
0014 
0015 /*
0016  */
0017 
0018 /*
0019  * Building an adaptor to DE9 / DB25 RS232
0020  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0021  *
0022  * DISCLAIMER: Use this description AT YOUR OWN RISK! I'll not pay for
0023  * anything if you break your mouse, your computer or whatever!
0024  *
0025  * In theory, this mouse is a simple RS232 device. In practice, it has got
0026  * a quite uncommon plug and the requirement to additionally get a power
0027  * supply at +5V and -12V.
0028  *
0029  * If you look at the socket/jack (_not_ at the plug), we use this pin
0030  * numbering:
0031  *    _______
0032  *   / 7 6 5 \
0033  *  | 4 --- 3 |
0034  *   \  2 1  /
0035  *    -------
0036  *
0037  *  DEC socket  DE9 DB25    Note
0038  *  1 (GND)     5   7   -
0039  *  2 (RxD)     2   3   -
0040  *  3 (TxD)     3   2   -
0041  *  4 (-12V)    -   -   Somewhere from the PSU. At ATX, it's
0042  *                  the thin blue wire at pin 12 of the
0043  *                  ATX power connector. Only required for
0044  *                  VSXXX-AA/-GA mice.
0045  *  5 (+5V)     -   -   PSU (red wires of ATX power connector
0046  *                  on pin 4, 6, 19 or 20) or HDD power
0047  *                  connector (also red wire).
0048  *  6 (+12V)    -   -   HDD power connector, yellow wire. Only
0049  *                  required for VSXXX-AB digitizer.
0050  *  7 (dev. avail.) -   -   The mouse shorts this one to pin 1.
0051  *                  This way, the host computer can detect
0052  *                  the mouse. To use it with the adaptor,
0053  *                  simply don't connect this pin.
0054  *
0055  * So to get a working adaptor, you need to connect the mouse with three
0056  * wires to a RS232 port and two or three additional wires for +5V, +12V and
0057  * -12V to the PSU.
0058  *
0059  * Flow specification for the link is 4800, 8o1.
0060  *
0061  * The mice and tablet are described in "VCB02 Video Subsystem - Technical
0062  * Manual", DEC EK-104AA-TM-001. You'll find it at MANX, a search engine
0063  * specific for DEC documentation. Try
0064  * http://www.vt100.net/manx/details?pn=EK-104AA-TM-001;id=21;cp=1
0065  */
0066 
0067 #include <linux/delay.h>
0068 #include <linux/module.h>
0069 #include <linux/slab.h>
0070 #include <linux/interrupt.h>
0071 #include <linux/input.h>
0072 #include <linux/serio.h>
0073 
0074 #define DRIVER_DESC "Driver for DEC VSXXX-AA and -GA mice and VSXXX-AB tablet"
0075 
0076 MODULE_AUTHOR("Jan-Benedict Glaw <jbglaw@lug-owl.de>");
0077 MODULE_DESCRIPTION(DRIVER_DESC);
0078 MODULE_LICENSE("GPL");
0079 
0080 #undef VSXXXAA_DEBUG
0081 #ifdef VSXXXAA_DEBUG
0082 #define DBG(x...) printk(x)
0083 #else
0084 #define DBG(x...) do {} while (0)
0085 #endif
0086 
0087 #define VSXXXAA_INTRO_MASK  0x80
0088 #define VSXXXAA_INTRO_HEAD  0x80
0089 #define IS_HDR_BYTE(x)          \
0090     (((x) & VSXXXAA_INTRO_MASK) == VSXXXAA_INTRO_HEAD)
0091 
0092 #define VSXXXAA_PACKET_MASK 0xe0
0093 #define VSXXXAA_PACKET_REL  0x80
0094 #define VSXXXAA_PACKET_ABS  0xc0
0095 #define VSXXXAA_PACKET_POR  0xa0
0096 #define MATCH_PACKET_TYPE(data, type)   \
0097     (((data) & VSXXXAA_PACKET_MASK) == (type))
0098 
0099 
0100 
0101 struct vsxxxaa {
0102     struct input_dev *dev;
0103     struct serio *serio;
0104 #define BUFLEN 15 /* At least 5 is needed for a full tablet packet */
0105     unsigned char buf[BUFLEN];
0106     unsigned char count;
0107     unsigned char version;
0108     unsigned char country;
0109     unsigned char type;
0110     char name[64];
0111     char phys[32];
0112 };
0113 
0114 static void vsxxxaa_drop_bytes(struct vsxxxaa *mouse, int num)
0115 {
0116     if (num >= mouse->count) {
0117         mouse->count = 0;
0118     } else {
0119         memmove(mouse->buf, mouse->buf + num, BUFLEN - num);
0120         mouse->count -= num;
0121     }
0122 }
0123 
0124 static void vsxxxaa_queue_byte(struct vsxxxaa *mouse, unsigned char byte)
0125 {
0126     if (mouse->count == BUFLEN) {
0127         printk(KERN_ERR "%s on %s: Dropping a byte of full buffer.\n",
0128             mouse->name, mouse->phys);
0129         vsxxxaa_drop_bytes(mouse, 1);
0130     }
0131 
0132     DBG(KERN_INFO "Queueing byte 0x%02x\n", byte);
0133 
0134     mouse->buf[mouse->count++] = byte;
0135 }
0136 
0137 static void vsxxxaa_detection_done(struct vsxxxaa *mouse)
0138 {
0139     switch (mouse->type) {
0140     case 0x02:
0141         strlcpy(mouse->name, "DEC VSXXX-AA/-GA mouse",
0142             sizeof(mouse->name));
0143         break;
0144 
0145     case 0x04:
0146         strlcpy(mouse->name, "DEC VSXXX-AB digitizer",
0147             sizeof(mouse->name));
0148         break;
0149 
0150     default:
0151         snprintf(mouse->name, sizeof(mouse->name),
0152              "unknown DEC pointer device (type = 0x%02x)",
0153              mouse->type);
0154         break;
0155     }
0156 
0157     printk(KERN_INFO
0158         "Found %s version 0x%02x from country 0x%02x on port %s\n",
0159         mouse->name, mouse->version, mouse->country, mouse->phys);
0160 }
0161 
0162 /*
0163  * Returns number of bytes to be dropped, 0 if packet is okay.
0164  */
0165 static int vsxxxaa_check_packet(struct vsxxxaa *mouse, int packet_len)
0166 {
0167     int i;
0168 
0169     /* First byte must be a header byte */
0170     if (!IS_HDR_BYTE(mouse->buf[0])) {
0171         DBG("vsck: len=%d, 1st=0x%02x\n", packet_len, mouse->buf[0]);
0172         return 1;
0173     }
0174 
0175     /* Check all following bytes */
0176     for (i = 1; i < packet_len; i++) {
0177         if (IS_HDR_BYTE(mouse->buf[i])) {
0178             printk(KERN_ERR
0179                 "Need to drop %d bytes of a broken packet.\n",
0180                 i - 1);
0181             DBG(KERN_INFO "check: len=%d, b[%d]=0x%02x\n",
0182                 packet_len, i, mouse->buf[i]);
0183             return i - 1;
0184         }
0185     }
0186 
0187     return 0;
0188 }
0189 
0190 static inline int vsxxxaa_smells_like_packet(struct vsxxxaa *mouse,
0191                          unsigned char type, size_t len)
0192 {
0193     return mouse->count >= len && MATCH_PACKET_TYPE(mouse->buf[0], type);
0194 }
0195 
0196 static void vsxxxaa_handle_REL_packet(struct vsxxxaa *mouse)
0197 {
0198     struct input_dev *dev = mouse->dev;
0199     unsigned char *buf = mouse->buf;
0200     int left, middle, right;
0201     int dx, dy;
0202 
0203     /*
0204      * Check for normal stream packets. This is three bytes,
0205      * with the first byte's 3 MSB set to 100.
0206      *
0207      * [0]: 1   0   0   SignX   SignY   Left    Middle  Right
0208      * [1]: 0   dx  dx  dx  dx  dx  dx  dx
0209      * [2]: 0   dy  dy  dy  dy  dy  dy  dy
0210      */
0211 
0212     /*
0213      * Low 7 bit of byte 1 are abs(dx), bit 7 is
0214      * 0, bit 4 of byte 0 is direction.
0215      */
0216     dx = buf[1] & 0x7f;
0217     dx *= ((buf[0] >> 4) & 0x01) ? 1 : -1;
0218 
0219     /*
0220      * Low 7 bit of byte 2 are abs(dy), bit 7 is
0221      * 0, bit 3 of byte 0 is direction.
0222      */
0223     dy = buf[2] & 0x7f;
0224     dy *= ((buf[0] >> 3) & 0x01) ? -1 : 1;
0225 
0226     /*
0227      * Get button state. It's the low three bits
0228      * (for three buttons) of byte 0.
0229      */
0230     left    = buf[0] & 0x04;
0231     middle  = buf[0] & 0x02;
0232     right   = buf[0] & 0x01;
0233 
0234     vsxxxaa_drop_bytes(mouse, 3);
0235 
0236     DBG(KERN_INFO "%s on %s: dx=%d, dy=%d, buttons=%s%s%s\n",
0237         mouse->name, mouse->phys, dx, dy,
0238         left ? "L" : "l", middle ? "M" : "m", right ? "R" : "r");
0239 
0240     /*
0241      * Report what we've found so far...
0242      */
0243     input_report_key(dev, BTN_LEFT, left);
0244     input_report_key(dev, BTN_MIDDLE, middle);
0245     input_report_key(dev, BTN_RIGHT, right);
0246     input_report_key(dev, BTN_TOUCH, 0);
0247     input_report_rel(dev, REL_X, dx);
0248     input_report_rel(dev, REL_Y, dy);
0249     input_sync(dev);
0250 }
0251 
0252 static void vsxxxaa_handle_ABS_packet(struct vsxxxaa *mouse)
0253 {
0254     struct input_dev *dev = mouse->dev;
0255     unsigned char *buf = mouse->buf;
0256     int left, middle, right, touch;
0257     int x, y;
0258 
0259     /*
0260      * Tablet position / button packet
0261      *
0262      * [0]: 1   1   0   B4  B3  B2  B1  Pr
0263      * [1]: 0   0   X5  X4  X3  X2  X1  X0
0264      * [2]: 0   0   X11 X10 X9  X8  X7  X6
0265      * [3]: 0   0   Y5  Y4  Y3  Y2  Y1  Y0
0266      * [4]: 0   0   Y11 Y10 Y9  Y8  Y7  Y6
0267      */
0268 
0269     /*
0270      * Get X/Y position. Y axis needs to be inverted since VSXXX-AB
0271      * counts down->top while monitor counts top->bottom.
0272      */
0273     x = ((buf[2] & 0x3f) << 6) | (buf[1] & 0x3f);
0274     y = ((buf[4] & 0x3f) << 6) | (buf[3] & 0x3f);
0275     y = 1023 - y;
0276 
0277     /*
0278      * Get button state. It's bits <4..1> of byte 0.
0279      */
0280     left    = buf[0] & 0x02;
0281     middle  = buf[0] & 0x04;
0282     right   = buf[0] & 0x08;
0283     touch   = buf[0] & 0x10;
0284 
0285     vsxxxaa_drop_bytes(mouse, 5);
0286 
0287     DBG(KERN_INFO "%s on %s: x=%d, y=%d, buttons=%s%s%s%s\n",
0288         mouse->name, mouse->phys, x, y,
0289         left ? "L" : "l", middle ? "M" : "m",
0290         right ? "R" : "r", touch ? "T" : "t");
0291 
0292     /*
0293      * Report what we've found so far...
0294      */
0295     input_report_key(dev, BTN_LEFT, left);
0296     input_report_key(dev, BTN_MIDDLE, middle);
0297     input_report_key(dev, BTN_RIGHT, right);
0298     input_report_key(dev, BTN_TOUCH, touch);
0299     input_report_abs(dev, ABS_X, x);
0300     input_report_abs(dev, ABS_Y, y);
0301     input_sync(dev);
0302 }
0303 
0304 static void vsxxxaa_handle_POR_packet(struct vsxxxaa *mouse)
0305 {
0306     struct input_dev *dev = mouse->dev;
0307     unsigned char *buf = mouse->buf;
0308     int left, middle, right;
0309     unsigned char error;
0310 
0311     /*
0312      * Check for Power-On-Reset packets. These are sent out
0313      * after plugging the mouse in, or when explicitly
0314      * requested by sending 'T'.
0315      *
0316      * [0]: 1   0   1   0   R3  R2  R1  R0
0317      * [1]: 0   M2  M1  M0  D3  D2  D1  D0
0318      * [2]: 0   E6  E5  E4  E3  E2  E1  E0
0319      * [3]: 0   0   0   0   0   Left    Middle  Right
0320      *
0321      * M: manufacturer location code
0322      * R: revision code
0323      * E: Error code. If it's in the range of 0x00..0x1f, only some
0324      *    minor problem occurred. Errors >= 0x20 are considered bad
0325      *    and the device may not work properly...
0326      * D: <0010> == mouse, <0100> == tablet
0327      */
0328 
0329     mouse->version = buf[0] & 0x0f;
0330     mouse->country = (buf[1] >> 4) & 0x07;
0331     mouse->type = buf[1] & 0x0f;
0332     error = buf[2] & 0x7f;
0333 
0334     /*
0335      * Get button state. It's the low three bits
0336      * (for three buttons) of byte 0. Maybe even the bit <3>
0337      * has some meaning if a tablet is attached.
0338      */
0339     left    = buf[0] & 0x04;
0340     middle  = buf[0] & 0x02;
0341     right   = buf[0] & 0x01;
0342 
0343     vsxxxaa_drop_bytes(mouse, 4);
0344     vsxxxaa_detection_done(mouse);
0345 
0346     if (error <= 0x1f) {
0347         /* No (serious) error. Report buttons */
0348         input_report_key(dev, BTN_LEFT, left);
0349         input_report_key(dev, BTN_MIDDLE, middle);
0350         input_report_key(dev, BTN_RIGHT, right);
0351         input_report_key(dev, BTN_TOUCH, 0);
0352         input_sync(dev);
0353 
0354         if (error != 0)
0355             printk(KERN_INFO "Your %s on %s reports error=0x%02x\n",
0356                 mouse->name, mouse->phys, error);
0357 
0358     }
0359 
0360     /*
0361      * If the mouse was hot-plugged, we need to force differential mode
0362      * now... However, give it a second to recover from it's reset.
0363      */
0364     printk(KERN_NOTICE
0365         "%s on %s: Forcing standard packet format, "
0366         "incremental streaming mode and 72 samples/sec\n",
0367         mouse->name, mouse->phys);
0368     serio_write(mouse->serio, 'S'); /* Standard format */
0369     mdelay(50);
0370     serio_write(mouse->serio, 'R'); /* Incremental */
0371     mdelay(50);
0372     serio_write(mouse->serio, 'L'); /* 72 samples/sec */
0373 }
0374 
0375 static void vsxxxaa_parse_buffer(struct vsxxxaa *mouse)
0376 {
0377     unsigned char *buf = mouse->buf;
0378     int stray_bytes;
0379 
0380     /*
0381      * Parse buffer to death...
0382      */
0383     do {
0384         /*
0385          * Out of sync? Throw away what we don't understand. Each
0386          * packet starts with a byte whose bit 7 is set. Unhandled
0387          * packets (ie. which we don't know about or simply b0rk3d
0388          * data...) will get shifted out of the buffer after some
0389          * activity on the mouse.
0390          */
0391         while (mouse->count > 0 && !IS_HDR_BYTE(buf[0])) {
0392             printk(KERN_ERR "%s on %s: Dropping a byte to regain "
0393                 "sync with mouse data stream...\n",
0394                 mouse->name, mouse->phys);
0395             vsxxxaa_drop_bytes(mouse, 1);
0396         }
0397 
0398         /*
0399          * Check for packets we know about.
0400          */
0401 
0402         if (vsxxxaa_smells_like_packet(mouse, VSXXXAA_PACKET_REL, 3)) {
0403             /* Check for broken packet */
0404             stray_bytes = vsxxxaa_check_packet(mouse, 3);
0405             if (!stray_bytes)
0406                 vsxxxaa_handle_REL_packet(mouse);
0407 
0408         } else if (vsxxxaa_smells_like_packet(mouse,
0409                               VSXXXAA_PACKET_ABS, 5)) {
0410             /* Check for broken packet */
0411             stray_bytes = vsxxxaa_check_packet(mouse, 5);
0412             if (!stray_bytes)
0413                 vsxxxaa_handle_ABS_packet(mouse);
0414 
0415         } else if (vsxxxaa_smells_like_packet(mouse,
0416                               VSXXXAA_PACKET_POR, 4)) {
0417             /* Check for broken packet */
0418             stray_bytes = vsxxxaa_check_packet(mouse, 4);
0419             if (!stray_bytes)
0420                 vsxxxaa_handle_POR_packet(mouse);
0421 
0422         } else {
0423             break; /* No REL, ABS or POR packet found */
0424         }
0425 
0426         if (stray_bytes > 0) {
0427             printk(KERN_ERR "Dropping %d bytes now...\n",
0428                 stray_bytes);
0429             vsxxxaa_drop_bytes(mouse, stray_bytes);
0430         }
0431 
0432     } while (1);
0433 }
0434 
0435 static irqreturn_t vsxxxaa_interrupt(struct serio *serio,
0436                      unsigned char data, unsigned int flags)
0437 {
0438     struct vsxxxaa *mouse = serio_get_drvdata(serio);
0439 
0440     vsxxxaa_queue_byte(mouse, data);
0441     vsxxxaa_parse_buffer(mouse);
0442 
0443     return IRQ_HANDLED;
0444 }
0445 
0446 static void vsxxxaa_disconnect(struct serio *serio)
0447 {
0448     struct vsxxxaa *mouse = serio_get_drvdata(serio);
0449 
0450     serio_close(serio);
0451     serio_set_drvdata(serio, NULL);
0452     input_unregister_device(mouse->dev);
0453     kfree(mouse);
0454 }
0455 
0456 static int vsxxxaa_connect(struct serio *serio, struct serio_driver *drv)
0457 {
0458     struct vsxxxaa *mouse;
0459     struct input_dev *input_dev;
0460     int err = -ENOMEM;
0461 
0462     mouse = kzalloc(sizeof(struct vsxxxaa), GFP_KERNEL);
0463     input_dev = input_allocate_device();
0464     if (!mouse || !input_dev)
0465         goto fail1;
0466 
0467     mouse->dev = input_dev;
0468     mouse->serio = serio;
0469     strlcat(mouse->name, "DEC VSXXX-AA/-GA mouse or VSXXX-AB digitizer",
0470          sizeof(mouse->name));
0471     snprintf(mouse->phys, sizeof(mouse->phys), "%s/input0", serio->phys);
0472 
0473     input_dev->name = mouse->name;
0474     input_dev->phys = mouse->phys;
0475     input_dev->id.bustype = BUS_RS232;
0476     input_dev->dev.parent = &serio->dev;
0477 
0478     __set_bit(EV_KEY, input_dev->evbit);        /* We have buttons */
0479     __set_bit(EV_REL, input_dev->evbit);
0480     __set_bit(EV_ABS, input_dev->evbit);
0481     __set_bit(BTN_LEFT, input_dev->keybit);     /* We have 3 buttons */
0482     __set_bit(BTN_MIDDLE, input_dev->keybit);
0483     __set_bit(BTN_RIGHT, input_dev->keybit);
0484     __set_bit(BTN_TOUCH, input_dev->keybit);    /* ...and Tablet */
0485     __set_bit(REL_X, input_dev->relbit);
0486     __set_bit(REL_Y, input_dev->relbit);
0487     input_set_abs_params(input_dev, ABS_X, 0, 1023, 0, 0);
0488     input_set_abs_params(input_dev, ABS_Y, 0, 1023, 0, 0);
0489 
0490     serio_set_drvdata(serio, mouse);
0491 
0492     err = serio_open(serio, drv);
0493     if (err)
0494         goto fail2;
0495 
0496     /*
0497      * Request selftest. Standard packet format and differential
0498      * mode will be requested after the device ID'ed successfully.
0499      */
0500     serio_write(serio, 'T'); /* Test */
0501 
0502     err = input_register_device(input_dev);
0503     if (err)
0504         goto fail3;
0505 
0506     return 0;
0507 
0508  fail3: serio_close(serio);
0509  fail2: serio_set_drvdata(serio, NULL);
0510  fail1: input_free_device(input_dev);
0511     kfree(mouse);
0512     return err;
0513 }
0514 
0515 static struct serio_device_id vsxxaa_serio_ids[] = {
0516     {
0517         .type   = SERIO_RS232,
0518         .proto  = SERIO_VSXXXAA,
0519         .id = SERIO_ANY,
0520         .extra  = SERIO_ANY,
0521     },
0522     { 0 }
0523 };
0524 
0525 MODULE_DEVICE_TABLE(serio, vsxxaa_serio_ids);
0526 
0527 static struct serio_driver vsxxxaa_drv = {
0528     .driver     = {
0529         .name   = "vsxxxaa",
0530     },
0531     .description    = DRIVER_DESC,
0532     .id_table   = vsxxaa_serio_ids,
0533     .connect    = vsxxxaa_connect,
0534     .interrupt  = vsxxxaa_interrupt,
0535     .disconnect = vsxxxaa_disconnect,
0536 };
0537 
0538 module_serio_driver(vsxxxaa_drv);