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