linux/drivers/input/mouse/vsxxxaa.c
<<
>>
Prefs
   1/*
   2 * Driver for   DEC VSXXX-AA mouse (hockey-puck mouse, ball or two rollers)
   3 *              DEC VSXXX-GA mouse (rectangular mouse, with ball)
   4 *              DEC VSXXX-AB tablet (digitizer with hair cross or stylus)
   5 *
   6 * Copyright (C) 2003-2004 by Jan-Benedict Glaw <jbglaw@lug-owl.de>
   7 *
   8 * The packet format was initially taken from a patch to GPM which is (C) 2001
   9 * by   Karsten Merker <merker@linuxtag.org>
  10 * and  Maciej W. Rozycki <macro@ds2.pg.gda.pl>
  11 * Later on, I had access to the device's documentation (referenced below).
  12 */
  13
  14/*
  15 * This program is free software; you can redistribute it and/or modify
  16 * it under the terms of the GNU General Public License as published by
  17 * the Free Software Foundation; either version 2 of the License, or
  18 * (at your option) any later version.
  19 *
  20 * This program is distributed in the hope that it will be useful,
  21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23 * GNU General Public License for more details.
  24 *
  25 * You should have received a copy of the GNU General Public License
  26 * along with this program; if not, write to the Free Software
  27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  28 */
  29
  30/*
  31 * Building an adaptor to DE9 / DB25 RS232
  32 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  33 *
  34 * DISCLAIMER: Use this description AT YOUR OWN RISK! I'll not pay for
  35 * anything if you break your mouse, your computer or whatever!
  36 *
  37 * In theory, this mouse is a simple RS232 device. In practice, it has got
  38 * a quite uncommon plug and the requirement to additionally get a power
  39 * supply at +5V and -12V.
  40 *
  41 * If you look at the socket/jack (_not_ at the plug), we use this pin
  42 * numbering:
  43 *    _______
  44 *   / 7 6 5 \
  45 *  | 4 --- 3 |
  46 *   \  2 1  /
  47 *    -------
  48 *
  49 *      DEC socket      DE9     DB25    Note
  50 *      1 (GND)         5       7       -
  51 *      2 (RxD)         2       3       -
  52 *      3 (TxD)         3       2       -
  53 *      4 (-12V)        -       -       Somewhere from the PSU. At ATX, it's
  54 *                                      the thin blue wire at pin 12 of the
  55 *                                      ATX power connector. Only required for
  56 *                                      VSXXX-AA/-GA mice.
  57 *      5 (+5V)         -       -       PSU (red wires of ATX power connector
  58 *                                      on pin 4, 6, 19 or 20) or HDD power
  59 *                                      connector (also red wire).
  60 *      6 (+12V)        -       -       HDD power connector, yellow wire. Only
  61 *                                      required for VSXXX-AB digitizer.
  62 *      7 (dev. avail.) -       -       The mouse shorts this one to pin 1.
  63 *                                      This way, the host computer can detect
  64 *                                      the mouse. To use it with the adaptor,
  65 *                                      simply don't connect this pin.
  66 *
  67 * So to get a working adaptor, you need to connect the mouse with three
  68 * wires to a RS232 port and two or three additional wires for +5V, +12V and
  69 * -12V to the PSU.
  70 *
  71 * Flow specification for the link is 4800, 8o1.
  72 *
  73 * The mice and tablet are described in "VCB02 Video Subsystem - Technical
  74 * Manual", DEC EK-104AA-TM-001. You'll find it at MANX, a search engine
  75 * specific for DEC documentation. Try
  76 * http://www.vt100.net/manx/details?pn=EK-104AA-TM-001;id=21;cp=1
  77 */
  78
  79#include <linux/delay.h>
  80#include <linux/module.h>
  81#include <linux/slab.h>
  82#include <linux/interrupt.h>
  83#include <linux/input.h>
  84#include <linux/serio.h>
  85#include <linux/init.h>
  86
  87#define DRIVER_DESC "Driver for DEC VSXXX-AA and -GA mice and VSXXX-AB tablet"
  88
  89MODULE_AUTHOR ("Jan-Benedict Glaw <jbglaw@lug-owl.de>");
  90MODULE_DESCRIPTION (DRIVER_DESC);
  91MODULE_LICENSE ("GPL");
  92
  93#undef VSXXXAA_DEBUG
  94#ifdef VSXXXAA_DEBUG
  95#define DBG(x...) printk (x)
  96#else
  97#define DBG(x...) do {} while (0)
  98#endif
  99
 100#define VSXXXAA_INTRO_MASK      0x80
 101#define VSXXXAA_INTRO_HEAD      0x80
 102#define IS_HDR_BYTE(x)          (((x) & VSXXXAA_INTRO_MASK)     \
 103                                        == VSXXXAA_INTRO_HEAD)
 104
 105#define VSXXXAA_PACKET_MASK     0xe0
 106#define VSXXXAA_PACKET_REL      0x80
 107#define VSXXXAA_PACKET_ABS      0xc0
 108#define VSXXXAA_PACKET_POR      0xa0
 109#define MATCH_PACKET_TYPE(data, type)   (((data) & VSXXXAA_PACKET_MASK) == (type))
 110
 111
 112
 113struct vsxxxaa {
 114        struct input_dev *dev;
 115        struct serio *serio;
 116#define BUFLEN 15 /* At least 5 is needed for a full tablet packet */
 117        unsigned char buf[BUFLEN];
 118        unsigned char count;
 119        unsigned char version;
 120        unsigned char country;
 121        unsigned char type;
 122        char name[64];
 123        char phys[32];
 124};
 125
 126static void
 127vsxxxaa_drop_bytes (struct vsxxxaa *mouse, int num)
 128{
 129        if (num >= mouse->count)
 130                mouse->count = 0;
 131        else {
 132                memmove (mouse->buf, mouse->buf + num - 1, BUFLEN - num);
 133                mouse->count -= num;
 134        }
 135}
 136
 137static void
 138vsxxxaa_queue_byte (struct vsxxxaa *mouse, unsigned char byte)
 139{
 140        if (mouse->count == BUFLEN) {
 141                printk (KERN_ERR "%s on %s: Dropping a byte of full buffer.\n",
 142                                mouse->name, mouse->phys);
 143                vsxxxaa_drop_bytes (mouse, 1);
 144        }
 145        DBG (KERN_INFO "Queueing byte 0x%02x\n", byte);
 146
 147        mouse->buf[mouse->count++] = byte;
 148}
 149
 150static void
 151vsxxxaa_detection_done (struct vsxxxaa *mouse)
 152{
 153        switch (mouse->type) {
 154                case 0x02:
 155                        strlcpy (mouse->name, "DEC VSXXX-AA/-GA mouse",
 156                                 sizeof (mouse->name));
 157                        break;
 158
 159                case 0x04:
 160                        strlcpy (mouse->name, "DEC VSXXX-AB digitizer",
 161                                 sizeof (mouse->name));
 162                        break;
 163
 164                default:
 165                        snprintf (mouse->name, sizeof (mouse->name),
 166                                  "unknown DEC pointer device (type = 0x%02x)",
 167                                  mouse->type);
 168                        break;
 169        }
 170
 171        printk (KERN_INFO
 172                "Found %s version 0x%02x from country 0x%02x on port %s\n",
 173                mouse->name, mouse->version, mouse->country, mouse->phys);
 174}
 175
 176/*
 177 * Returns number of bytes to be dropped, 0 if packet is okay.
 178 */
 179static int
 180vsxxxaa_check_packet (struct vsxxxaa *mouse, int packet_len)
 181{
 182        int i;
 183
 184        /* First byte must be a header byte */
 185        if (!IS_HDR_BYTE (mouse->buf[0])) {
 186                DBG ("vsck: len=%d, 1st=0x%02x\n", packet_len, mouse->buf[0]);
 187                return 1;
 188        }
 189
 190        /* Check all following bytes */
 191        if (packet_len > 1) {
 192                for (i = 1; i < packet_len; i++) {
 193                        if (IS_HDR_BYTE (mouse->buf[i])) {
 194                                printk (KERN_ERR "Need to drop %d bytes "
 195                                                "of a broken packet.\n",
 196                                                i - 1);
 197                                DBG (KERN_INFO "check: len=%d, b[%d]=0x%02x\n",
 198                                                packet_len, i, mouse->buf[i]);
 199                                return i - 1;
 200                        }
 201                }
 202        }
 203
 204        return 0;
 205}
 206
 207static __inline__ int
 208vsxxxaa_smells_like_packet (struct vsxxxaa *mouse, unsigned char type, size_t len)
 209{
 210        return (mouse->count >= len) && MATCH_PACKET_TYPE (mouse->buf[0], type);
 211}
 212
 213static void
 214vsxxxaa_handle_REL_packet (struct vsxxxaa *mouse)
 215{
 216        struct input_dev *dev = mouse->dev;
 217        unsigned char *buf = mouse->buf;
 218        int left, middle, right;
 219        int dx, dy;
 220
 221        /*
 222         * Check for normal stream packets. This is three bytes,
 223         * with the first byte's 3 MSB set to 100.
 224         *
 225         * [0]: 1       0       0       SignX   SignY   Left    Middle  Right
 226         * [1]: 0       dx      dx      dx      dx      dx      dx      dx
 227         * [2]: 0       dy      dy      dy      dy      dy      dy      dy
 228         */
 229
 230        /*
 231         * Low 7 bit of byte 1 are abs(dx), bit 7 is
 232         * 0, bit 4 of byte 0 is direction.
 233         */
 234        dx = buf[1] & 0x7f;
 235        dx *= ((buf[0] >> 4) & 0x01)? 1: -1;
 236
 237        /*
 238         * Low 7 bit of byte 2 are abs(dy), bit 7 is
 239         * 0, bit 3 of byte 0 is direction.
 240         */
 241        dy = buf[2] & 0x7f;
 242        dy *= ((buf[0] >> 3) & 0x01)? -1: 1;
 243
 244        /*
 245         * Get button state. It's the low three bits
 246         * (for three buttons) of byte 0.
 247         */
 248        left    = (buf[0] & 0x04)? 1: 0;
 249        middle  = (buf[0] & 0x02)? 1: 0;
 250        right   = (buf[0] & 0x01)? 1: 0;
 251
 252        vsxxxaa_drop_bytes (mouse, 3);
 253
 254        DBG (KERN_INFO "%s on %s: dx=%d, dy=%d, buttons=%s%s%s\n",
 255                        mouse->name, mouse->phys, dx, dy,
 256                        left? "L": "l", middle? "M": "m", right? "R": "r");
 257
 258        /*
 259         * Report what we've found so far...
 260         */
 261        input_report_key (dev, BTN_LEFT, left);
 262        input_report_key (dev, BTN_MIDDLE, middle);
 263        input_report_key (dev, BTN_RIGHT, right);
 264        input_report_key (dev, BTN_TOUCH, 0);
 265        input_report_rel (dev, REL_X, dx);
 266        input_report_rel (dev, REL_Y, dy);
 267        input_sync (dev);
 268}
 269
 270static void
 271vsxxxaa_handle_ABS_packet (struct vsxxxaa *mouse)
 272{
 273        struct input_dev *dev = mouse->dev;
 274        unsigned char *buf = mouse->buf;
 275        int left, middle, right, touch;
 276        int x, y;
 277
 278        /*
 279         * Tablet position / button packet
 280         *
 281         * [0]: 1       1       0       B4      B3      B2      B1      Pr
 282         * [1]: 0       0       X5      X4      X3      X2      X1      X0
 283         * [2]: 0       0       X11     X10     X9      X8      X7      X6
 284         * [3]: 0       0       Y5      Y4      Y3      Y2      Y1      Y0
 285         * [4]: 0       0       Y11     Y10     Y9      Y8      Y7      Y6
 286         */
 287
 288        /*
 289         * Get X/Y position. Y axis needs to be inverted since VSXXX-AB
 290         * counts down->top while monitor counts top->bottom.
 291         */
 292        x = ((buf[2] & 0x3f) << 6) | (buf[1] & 0x3f);
 293        y = ((buf[4] & 0x3f) << 6) | (buf[3] & 0x3f);
 294        y = 1023 - y;
 295
 296        /*
 297         * Get button state. It's bits <4..1> of byte 0.
 298         */
 299        left    = (buf[0] & 0x02)? 1: 0;
 300        middle  = (buf[0] & 0x04)? 1: 0;
 301        right   = (buf[0] & 0x08)? 1: 0;
 302        touch   = (buf[0] & 0x10)? 1: 0;
 303
 304        vsxxxaa_drop_bytes (mouse, 5);
 305
 306        DBG (KERN_INFO "%s on %s: x=%d, y=%d, buttons=%s%s%s%s\n",
 307                        mouse->name, mouse->phys, x, y,
 308                        left? "L": "l", middle? "M": "m",
 309                        right? "R": "r", touch? "T": "t");
 310
 311        /*
 312         * Report what we've found so far...
 313         */
 314        input_report_key (dev, BTN_LEFT, left);
 315        input_report_key (dev, BTN_MIDDLE, middle);
 316        input_report_key (dev, BTN_RIGHT, right);
 317        input_report_key (dev, BTN_TOUCH, touch);
 318        input_report_abs (dev, ABS_X, x);
 319        input_report_abs (dev, ABS_Y, y);
 320        input_sync (dev);
 321}
 322
 323static void
 324vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse)
 325{
 326        struct input_dev *dev = mouse->dev;
 327        unsigned char *buf = mouse->buf;
 328        int left, middle, right;
 329        unsigned char error;
 330
 331        /*
 332         * Check for Power-On-Reset packets. These are sent out
 333         * after plugging the mouse in, or when explicitly
 334         * requested by sending 'T'.
 335         *
 336         * [0]: 1       0       1       0       R3      R2      R1      R0
 337         * [1]: 0       M2      M1      M0      D3      D2      D1      D0
 338         * [2]: 0       E6      E5      E4      E3      E2      E1      E0
 339         * [3]: 0       0       0       0       0       Left    Middle  Right
 340         *
 341         * M: manufacturer location code
 342         * R: revision code
 343         * E: Error code. If it's in the range of 0x00..0x1f, only some
 344         *    minor problem occured. Errors >= 0x20 are considered bad
 345         *    and the device may not work properly...
 346         * D: <0010> == mouse, <0100> == tablet
 347         */
 348
 349        mouse->version = buf[0] & 0x0f;
 350        mouse->country = (buf[1] >> 4) & 0x07;
 351        mouse->type = buf[1] & 0x0f;
 352        error = buf[2] & 0x7f;
 353
 354        /*
 355         * Get button state. It's the low three bits
 356         * (for three buttons) of byte 0. Maybe even the bit <3>
 357         * has some meaning if a tablet is attached.
 358         */
 359        left    = (buf[0] & 0x04)? 1: 0;
 360        middle  = (buf[0] & 0x02)? 1: 0;
 361        right   = (buf[0] & 0x01)? 1: 0;
 362
 363        vsxxxaa_drop_bytes (mouse, 4);
 364        vsxxxaa_detection_done (mouse);
 365
 366        if (error <= 0x1f) {
 367                /* No (serious) error. Report buttons */
 368                input_report_key (dev, BTN_LEFT, left);
 369                input_report_key (dev, BTN_MIDDLE, middle);
 370                input_report_key (dev, BTN_RIGHT, right);
 371                input_report_key (dev, BTN_TOUCH, 0);
 372                input_sync (dev);
 373
 374                if (error != 0)
 375                        printk (KERN_INFO "Your %s on %s reports error=0x%02x\n",
 376                                        mouse->name, mouse->phys, error);
 377
 378        }
 379
 380        /*
 381         * If the mouse was hot-plugged, we need to force differential mode
 382         * now... However, give it a second to recover from it's reset.
 383         */
 384        printk (KERN_NOTICE "%s on %s: Forceing standard packet format, "
 385                        "incremental streaming mode and 72 samples/sec\n",
 386                        mouse->name, mouse->phys);
 387        serio_write (mouse->serio, 'S');        /* Standard format */
 388        mdelay (50);
 389        serio_write (mouse->serio, 'R');        /* Incremental */
 390        mdelay (50);
 391        serio_write (mouse->serio, 'L');        /* 72 samples/sec */
 392}
 393
 394static void
 395vsxxxaa_parse_buffer (struct vsxxxaa *mouse)
 396{
 397        unsigned char *buf = mouse->buf;
 398        int stray_bytes;
 399
 400        /*
 401         * Parse buffer to death...
 402         */
 403        do {
 404                /*
 405                 * Out of sync? Throw away what we don't understand. Each
 406                 * packet starts with a byte whose bit 7 is set. Unhandled
 407                 * packets (ie. which we don't know about or simply b0rk3d
 408                 * data...) will get shifted out of the buffer after some
 409                 * activity on the mouse.
 410                 */
 411                while (mouse->count > 0 && !IS_HDR_BYTE(buf[0])) {
 412                        printk (KERN_ERR "%s on %s: Dropping a byte to regain "
 413                                        "sync with mouse data stream...\n",
 414                                        mouse->name, mouse->phys);
 415                        vsxxxaa_drop_bytes (mouse, 1);
 416                }
 417
 418                /*
 419                 * Check for packets we know about.
 420                 */
 421
 422                if (vsxxxaa_smells_like_packet (mouse, VSXXXAA_PACKET_REL, 3)) {
 423                        /* Check for broken packet */
 424                        stray_bytes = vsxxxaa_check_packet (mouse, 3);
 425                        if (stray_bytes > 0) {
 426                                printk (KERN_ERR "Dropping %d bytes now...\n",
 427                                                stray_bytes);
 428                                vsxxxaa_drop_bytes (mouse, stray_bytes);
 429                                continue;
 430                        }
 431
 432                        vsxxxaa_handle_REL_packet (mouse);
 433                        continue; /* More to parse? */
 434                }
 435
 436                if (vsxxxaa_smells_like_packet (mouse, VSXXXAA_PACKET_ABS, 5)) {
 437                        /* Check for broken packet */
 438                        stray_bytes = vsxxxaa_check_packet (mouse, 5);
 439                        if (stray_bytes > 0) {
 440                                printk (KERN_ERR "Dropping %d bytes now...\n",
 441                                                stray_bytes);
 442                                vsxxxaa_drop_bytes (mouse, stray_bytes);
 443                                continue;
 444                        }
 445
 446                        vsxxxaa_handle_ABS_packet (mouse);
 447                        continue; /* More to parse? */
 448                }
 449
 450                if (vsxxxaa_smells_like_packet (mouse, VSXXXAA_PACKET_POR, 4)) {
 451                        /* Check for broken packet */
 452                        stray_bytes = vsxxxaa_check_packet (mouse, 4);
 453                        if (stray_bytes > 0) {
 454                                printk (KERN_ERR "Dropping %d bytes now...\n",
 455                                                stray_bytes);
 456                                vsxxxaa_drop_bytes (mouse, stray_bytes);
 457                                continue;
 458                        }
 459
 460                        vsxxxaa_handle_POR_packet (mouse);
 461                        continue; /* More to parse? */
 462                }
 463
 464                break; /* No REL, ABS or POR packet found */
 465        } while (1);
 466}
 467
 468static irqreturn_t
 469vsxxxaa_interrupt (struct serio *serio, unsigned char data, unsigned int flags)
 470{
 471        struct vsxxxaa *mouse = serio_get_drvdata (serio);
 472
 473        vsxxxaa_queue_byte (mouse, data);
 474        vsxxxaa_parse_buffer (mouse);
 475
 476        return IRQ_HANDLED;
 477}
 478
 479static void
 480vsxxxaa_disconnect (struct serio *serio)
 481{
 482        struct vsxxxaa *mouse = serio_get_drvdata (serio);
 483
 484        serio_close (serio);
 485        serio_set_drvdata (serio, NULL);
 486        input_unregister_device (mouse->dev);
 487        kfree (mouse);
 488}
 489
 490static int
 491vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
 492{
 493        struct vsxxxaa *mouse;
 494        struct input_dev *input_dev;
 495        int err = -ENOMEM;
 496
 497        mouse = kzalloc (sizeof (struct vsxxxaa), GFP_KERNEL);
 498        input_dev = input_allocate_device ();
 499        if (!mouse || !input_dev)
 500                goto fail1;
 501
 502        mouse->dev = input_dev;
 503        mouse->serio = serio;
 504        strlcat (mouse->name, "DEC VSXXX-AA/-GA mouse or VSXXX-AB digitizer",
 505                 sizeof (mouse->name));
 506        snprintf (mouse->phys, sizeof (mouse->phys), "%s/input0", serio->phys);
 507
 508        input_dev->name = mouse->name;
 509        input_dev->phys = mouse->phys;
 510        input_dev->id.bustype = BUS_RS232;
 511        input_dev->dev.parent = &serio->dev;
 512
 513        set_bit (EV_KEY, input_dev->evbit);             /* We have buttons */
 514        set_bit (EV_REL, input_dev->evbit);
 515        set_bit (EV_ABS, input_dev->evbit);
 516        set_bit (BTN_LEFT, input_dev->keybit);          /* We have 3 buttons */
 517        set_bit (BTN_MIDDLE, input_dev->keybit);
 518        set_bit (BTN_RIGHT, input_dev->keybit);
 519        set_bit (BTN_TOUCH, input_dev->keybit);         /* ...and Tablet */
 520        set_bit (REL_X, input_dev->relbit);
 521        set_bit (REL_Y, input_dev->relbit);
 522        input_set_abs_params (input_dev, ABS_X, 0, 1023, 0, 0);
 523        input_set_abs_params (input_dev, ABS_Y, 0, 1023, 0, 0);
 524
 525        serio_set_drvdata (serio, mouse);
 526
 527        err = serio_open (serio, drv);
 528        if (err)
 529                goto fail2;
 530
 531        /*
 532         * Request selftest. Standard packet format and differential
 533         * mode will be requested after the device ID'ed successfully.
 534         */
 535        serio_write (serio, 'T'); /* Test */
 536
 537        err = input_register_device (input_dev);
 538        if (err)
 539                goto fail3;
 540
 541        return 0;
 542
 543 fail3: serio_close (serio);
 544 fail2: serio_set_drvdata (serio, NULL);
 545 fail1: input_free_device (input_dev);
 546        kfree (mouse);
 547        return err;
 548}
 549
 550static struct serio_device_id vsxxaa_serio_ids[] = {
 551        {
 552                .type   = SERIO_RS232,
 553                .proto  = SERIO_VSXXXAA,
 554                .id     = SERIO_ANY,
 555                .extra  = SERIO_ANY,
 556        },
 557        { 0 }
 558};
 559
 560MODULE_DEVICE_TABLE(serio, vsxxaa_serio_ids);
 561
 562static struct serio_driver vsxxxaa_drv = {
 563        .driver         = {
 564                .name   = "vsxxxaa",
 565        },
 566        .description    = DRIVER_DESC,
 567        .id_table       = vsxxaa_serio_ids,
 568        .connect        = vsxxxaa_connect,
 569        .interrupt      = vsxxxaa_interrupt,
 570        .disconnect     = vsxxxaa_disconnect,
 571};
 572
 573static int __init
 574vsxxxaa_init (void)
 575{
 576        return serio_register_driver(&vsxxxaa_drv);
 577}
 578
 579static void __exit
 580vsxxxaa_exit (void)
 581{
 582        serio_unregister_driver(&vsxxxaa_drv);
 583}
 584
 585module_init (vsxxxaa_init);
 586module_exit (vsxxxaa_exit);
 587
 588