linux/drivers/input/mouse/hgpk.c
<<
>>
Prefs
   1/*
   2 * OLPC HGPK (XO-1) touchpad PS/2 mouse driver
   3 *
   4 * Copyright (c) 2006-2008 One Laptop Per Child
   5 * Authors:
   6 *   Zephaniah E. Hull
   7 *   Andres Salomon <dilinger@debian.org>
   8 *
   9 * This driver is partly based on the ALPS driver, which is:
  10 *
  11 * Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au>
  12 * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com>
  13 * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru>
  14 * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
  15 *
  16 * This program is free software; you can redistribute it and/or modify
  17 * it under the terms of the GNU General Public License version 2 as
  18 * published by the Free Software Foundation.
  19 */
  20
  21/*
  22 * The spec from ALPS is available from
  23 * <http://wiki.laptop.org/go/Touch_Pad/Tablet>.  It refers to this
  24 * device as HGPK (Hybrid GS, PT, and Keymatrix).
  25 *
  26 * The earliest versions of the device had simultaneous reporting; that
  27 * was removed.  After that, the device used the Advanced Mode GS/PT streaming
  28 * stuff.  That turned out to be too buggy to support, so we've finally
  29 * switched to Mouse Mode (which utilizes only the center 1/3 of the touchpad).
  30 */
  31
  32#define DEBUG
  33#include <linux/input.h>
  34#include <linux/serio.h>
  35#include <linux/libps2.h>
  36#include <linux/delay.h>
  37#include <asm/olpc.h>
  38
  39#include "psmouse.h"
  40#include "hgpk.h"
  41
  42static int tpdebug;
  43module_param(tpdebug, int, 0644);
  44MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG.");
  45
  46static int recalib_delta = 100;
  47module_param(recalib_delta, int, 0644);
  48MODULE_PARM_DESC(recalib_delta,
  49        "packets containing a delta this large will cause a recalibration.");
  50
  51static int jumpy_delay = 1000;
  52module_param(jumpy_delay, int, 0644);
  53MODULE_PARM_DESC(jumpy_delay,
  54        "delay (ms) before recal after jumpiness detected");
  55
  56static int spew_delay = 1000;
  57module_param(spew_delay, int, 0644);
  58MODULE_PARM_DESC(spew_delay,
  59        "delay (ms) before recal after packet spew detected");
  60
  61static int recal_guard_time = 2000;
  62module_param(recal_guard_time, int, 0644);
  63MODULE_PARM_DESC(recal_guard_time,
  64        "interval (ms) during which recal will be restarted if packet received");
  65
  66static int post_interrupt_delay = 1000;
  67module_param(post_interrupt_delay, int, 0644);
  68MODULE_PARM_DESC(post_interrupt_delay,
  69        "delay (ms) before recal after recal interrupt detected");
  70
  71static int autorecal = 1;
  72module_param(autorecal, int, 0644);
  73MODULE_PARM_DESC(autorecal, "enable recalibration in the driver");
  74
  75/*
  76 * When the touchpad gets ultra-sensitive, one can keep their finger 1/2"
  77 * above the pad and still have it send packets.  This causes a jump cursor
  78 * when one places their finger on the pad.  We can probably detect the
  79 * jump as we see a large deltas (>= 100px).  In mouse mode, I've been
  80 * unable to even come close to 100px deltas during normal usage, so I think
  81 * this threshold is safe.  If a large delta occurs, trigger a recalibration.
  82 */
  83static void hgpk_jumpy_hack(struct psmouse *psmouse, int x, int y)
  84{
  85        struct hgpk_data *priv = psmouse->private;
  86
  87        if (abs(x) > recalib_delta || abs(y) > recalib_delta) {
  88                hgpk_err(psmouse, ">%dpx jump detected (%d,%d)\n",
  89                                recalib_delta, x, y);
  90                /* My car gets forty rods to the hogshead and that's the
  91                 * way I likes it! */
  92                psmouse_queue_work(psmouse, &priv->recalib_wq,
  93                                msecs_to_jiffies(jumpy_delay));
  94        }
  95}
  96
  97/*
  98 * We have no idea why this particular hardware bug occurs.  The touchpad
  99 * will randomly start spewing packets without anything touching the
 100 * pad.  This wouldn't necessarily be bad, but it's indicative of a
 101 * severely miscalibrated pad; attempting to use the touchpad while it's
 102 * spewing means the cursor will jump all over the place, and act "drunk".
 103 *
 104 * The packets that are spewed tend to all have deltas between -2 and 2, and
 105 * the cursor will move around without really going very far.  It will
 106 * tend to end up in the same location; if we tally up the changes over
 107 * 100 packets, we end up w/ a final delta of close to 0.  This happens
 108 * pretty regularly when the touchpad is spewing, and is pretty hard to
 109 * manually trigger (at least for *my* fingers).  So, it makes a perfect
 110 * scheme for detecting spews.
 111 */
 112static void hgpk_spewing_hack(struct psmouse *psmouse,
 113                              int l, int r, int x, int y)
 114{
 115        struct hgpk_data *priv = psmouse->private;
 116
 117        /* ignore button press packets; many in a row could trigger
 118         * a false-positive! */
 119        if (l || r)
 120                return;
 121
 122        priv->x_tally += x;
 123        priv->y_tally += y;
 124
 125        if (++priv->count > 100) {
 126                if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) {
 127                        hgpk_dbg(psmouse, "packet spew detected (%d,%d)\n",
 128                                 priv->x_tally, priv->y_tally);
 129                        psmouse_queue_work(psmouse, &priv->recalib_wq,
 130                                           msecs_to_jiffies(spew_delay));
 131                }
 132                /* reset every 100 packets */
 133                priv->count = 0;
 134                priv->x_tally = 0;
 135                priv->y_tally = 0;
 136        }
 137}
 138
 139/*
 140 * HGPK Mouse Mode format (standard mouse format, sans middle button)
 141 *
 142 * byte 0:      y-over  x-over  y-neg   x-neg   1       0       swr     swl
 143 * byte 1:      x7      x6      x5      x4      x3      x2      x1      x0
 144 * byte 2:      y7      y6      y5      y4      y3      y2      y1      y0
 145 *
 146 * swr/swl are the left/right buttons.
 147 * x-neg/y-neg are the x and y delta negative bits
 148 * x-over/y-over are the x and y overflow bits
 149 */
 150static int hgpk_validate_byte(unsigned char *packet)
 151{
 152        return (packet[0] & 0x0C) != 0x08;
 153}
 154
 155static void hgpk_process_packet(struct psmouse *psmouse)
 156{
 157        struct input_dev *dev = psmouse->dev;
 158        unsigned char *packet = psmouse->packet;
 159        int x, y, left, right;
 160
 161        left = packet[0] & 1;
 162        right = (packet[0] >> 1) & 1;
 163
 164        x = packet[1] - ((packet[0] << 4) & 0x100);
 165        y = ((packet[0] << 3) & 0x100) - packet[2];
 166
 167        hgpk_jumpy_hack(psmouse, x, y);
 168        hgpk_spewing_hack(psmouse, left, right, x, y);
 169
 170        if (tpdebug)
 171                hgpk_dbg(psmouse, "l=%d r=%d x=%d y=%d\n", left, right, x, y);
 172
 173        input_report_key(dev, BTN_LEFT, left);
 174        input_report_key(dev, BTN_RIGHT, right);
 175
 176        input_report_rel(dev, REL_X, x);
 177        input_report_rel(dev, REL_Y, y);
 178
 179        input_sync(dev);
 180}
 181
 182static psmouse_ret_t hgpk_process_byte(struct psmouse *psmouse)
 183{
 184        struct hgpk_data *priv = psmouse->private;
 185
 186        if (hgpk_validate_byte(psmouse->packet)) {
 187                hgpk_dbg(psmouse, "%s: (%d) %02x %02x %02x\n",
 188                                __func__, psmouse->pktcnt, psmouse->packet[0],
 189                                psmouse->packet[1], psmouse->packet[2]);
 190                return PSMOUSE_BAD_DATA;
 191        }
 192
 193        if (psmouse->pktcnt >= psmouse->pktsize) {
 194                hgpk_process_packet(psmouse);
 195                return PSMOUSE_FULL_PACKET;
 196        }
 197
 198        if (priv->recalib_window) {
 199                if (time_before(jiffies, priv->recalib_window)) {
 200                        /*
 201                         * ugh, got a packet inside our recalibration
 202                         * window, schedule another recalibration.
 203                         */
 204                        hgpk_dbg(psmouse,
 205                                 "packet inside calibration window, "
 206                                 "queueing another recalibration\n");
 207                        psmouse_queue_work(psmouse, &priv->recalib_wq,
 208                                        msecs_to_jiffies(post_interrupt_delay));
 209                }
 210                priv->recalib_window = 0;
 211        }
 212
 213        return PSMOUSE_GOOD_DATA;
 214}
 215
 216static int hgpk_force_recalibrate(struct psmouse *psmouse)
 217{
 218        struct ps2dev *ps2dev = &psmouse->ps2dev;
 219        struct hgpk_data *priv = psmouse->private;
 220
 221        /* C-series touchpads added the recalibrate command */
 222        if (psmouse->model < HGPK_MODEL_C)
 223                return 0;
 224
 225        /* we don't want to race with the irq handler, nor with resyncs */
 226        psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
 227
 228        /* start by resetting the device */
 229        psmouse_reset(psmouse);
 230
 231        /* send the recalibrate request */
 232        if (ps2_command(ps2dev, NULL, 0xf5) ||
 233            ps2_command(ps2dev, NULL, 0xf5) ||
 234            ps2_command(ps2dev, NULL, 0xe6) ||
 235            ps2_command(ps2dev, NULL, 0xf5)) {
 236                return -1;
 237        }
 238
 239        /* according to ALPS, 150mS is required for recalibration */
 240        msleep(150);
 241
 242        /* XXX: If a finger is down during this delay, recalibration will
 243         * detect capacitance incorrectly.  This is a hardware bug, and
 244         * we don't have a good way to deal with it.  The 2s window stuff
 245         * (below) is our best option for now.
 246         */
 247
 248        if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE))
 249                return -1;
 250
 251        psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
 252
 253        /* After we recalibrate, we shouldn't get any packets for 2s.  If
 254         * we do, it's likely that someone's finger was on the touchpad.
 255         * If someone's finger *was* on the touchpad, it's probably
 256         * miscalibrated.  So, we should schedule another recalibration
 257         */
 258        priv->recalib_window = jiffies +  msecs_to_jiffies(recal_guard_time);
 259
 260        return 0;
 261}
 262
 263/*
 264 * This kills power to the touchpad; according to ALPS, current consumption
 265 * goes down to 50uA after running this.  To turn power back on, we drive
 266 * MS-DAT low.
 267 */
 268static int hgpk_toggle_power(struct psmouse *psmouse, int enable)
 269{
 270        struct ps2dev *ps2dev = &psmouse->ps2dev;
 271        int timeo;
 272
 273        /* Added on D-series touchpads */
 274        if (psmouse->model < HGPK_MODEL_D)
 275                return 0;
 276
 277        if (enable) {
 278                psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
 279
 280                /*
 281                 * Sending a byte will drive MS-DAT low; this will wake up
 282                 * the controller.  Once we get an ACK back from it, it
 283                 * means we can continue with the touchpad re-init.  ALPS
 284                 * tells us that 1s should be long enough, so set that as
 285                 * the upper bound.
 286                 */
 287                for (timeo = 20; timeo > 0; timeo--) {
 288                        if (!ps2_sendbyte(&psmouse->ps2dev,
 289                                        PSMOUSE_CMD_DISABLE, 20))
 290                                break;
 291                        msleep(50);
 292                }
 293
 294                psmouse_reset(psmouse);
 295
 296                /* should be all set, enable the touchpad */
 297                ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE);
 298                psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
 299
 300        } else {
 301                hgpk_dbg(psmouse, "Powering off touchpad.\n");
 302                psmouse_set_state(psmouse, PSMOUSE_IGNORE);
 303
 304                if (ps2_command(ps2dev, NULL, 0xec) ||
 305                    ps2_command(ps2dev, NULL, 0xec) ||
 306                    ps2_command(ps2dev, NULL, 0xea)) {
 307                        return -1;
 308                }
 309
 310                /* probably won't see an ACK, the touchpad will be off */
 311                ps2_sendbyte(&psmouse->ps2dev, 0xec, 20);
 312        }
 313
 314        return 0;
 315}
 316
 317static int hgpk_poll(struct psmouse *psmouse)
 318{
 319        /* We can't poll, so always return failure. */
 320        return -1;
 321}
 322
 323static int hgpk_reconnect(struct psmouse *psmouse)
 324{
 325        /* During suspend/resume the ps2 rails remain powered.  We don't want
 326         * to do a reset because it's flush data out of buffers; however,
 327         * earlier prototypes (B1) had some brokenness that required a reset. */
 328        if (olpc_board_at_least(olpc_board(0xb2)))
 329                if (psmouse->ps2dev.serio->dev.power.power_state.event !=
 330                                PM_EVENT_ON)
 331                        return 0;
 332
 333        psmouse_reset(psmouse);
 334
 335        return 0;
 336}
 337
 338static ssize_t hgpk_show_powered(struct psmouse *psmouse, void *data, char *buf)
 339{
 340        struct hgpk_data *priv = psmouse->private;
 341
 342        return sprintf(buf, "%d\n", priv->powered);
 343}
 344
 345static ssize_t hgpk_set_powered(struct psmouse *psmouse, void *data,
 346                                const char *buf, size_t count)
 347{
 348        struct hgpk_data *priv = psmouse->private;
 349        unsigned long value;
 350        int err;
 351
 352        err = strict_strtoul(buf, 10, &value);
 353        if (err || value > 1)
 354                return -EINVAL;
 355
 356        if (value != priv->powered) {
 357                /*
 358                 * hgpk_toggle_power will deal w/ state so
 359                 * we're not racing w/ irq
 360                 */
 361                err = hgpk_toggle_power(psmouse, value);
 362                if (!err)
 363                        priv->powered = value;
 364        }
 365
 366        return err ? err : count;
 367}
 368
 369__PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL,
 370                      hgpk_show_powered, hgpk_set_powered, false);
 371
 372static ssize_t hgpk_trigger_recal_show(struct psmouse *psmouse,
 373                void *data, char *buf)
 374{
 375        return -EINVAL;
 376}
 377
 378static ssize_t hgpk_trigger_recal(struct psmouse *psmouse, void *data,
 379                                const char *buf, size_t count)
 380{
 381        struct hgpk_data *priv = psmouse->private;
 382        unsigned long value;
 383        int err;
 384
 385        err = strict_strtoul(buf, 10, &value);
 386        if (err || value != 1)
 387                return -EINVAL;
 388
 389        /*
 390         * We queue work instead of doing recalibration right here
 391         * to avoid adding locking to to hgpk_force_recalibrate()
 392         * since workqueue provides serialization.
 393         */
 394        psmouse_queue_work(psmouse, &priv->recalib_wq, 0);
 395        return count;
 396}
 397
 398__PSMOUSE_DEFINE_ATTR(recalibrate, S_IWUSR | S_IRUGO, NULL,
 399                      hgpk_trigger_recal_show, hgpk_trigger_recal, false);
 400
 401static void hgpk_disconnect(struct psmouse *psmouse)
 402{
 403        struct hgpk_data *priv = psmouse->private;
 404
 405        device_remove_file(&psmouse->ps2dev.serio->dev,
 406                           &psmouse_attr_powered.dattr);
 407
 408        if (psmouse->model >= HGPK_MODEL_C)
 409                device_remove_file(&psmouse->ps2dev.serio->dev,
 410                                   &psmouse_attr_recalibrate.dattr);
 411
 412        psmouse_reset(psmouse);
 413        kfree(priv);
 414}
 415
 416static void hgpk_recalib_work(struct work_struct *work)
 417{
 418        struct delayed_work *w = to_delayed_work(work);
 419        struct hgpk_data *priv = container_of(w, struct hgpk_data, recalib_wq);
 420        struct psmouse *psmouse = priv->psmouse;
 421
 422        hgpk_dbg(psmouse, "recalibrating touchpad..\n");
 423
 424        if (hgpk_force_recalibrate(psmouse))
 425                hgpk_err(psmouse, "recalibration failed!\n");
 426}
 427
 428static int hgpk_register(struct psmouse *psmouse)
 429{
 430        struct input_dev *dev = psmouse->dev;
 431        int err;
 432
 433        /* unset the things that psmouse-base sets which we don't have */
 434        __clear_bit(BTN_MIDDLE, dev->keybit);
 435
 436        /* set the things we do have */
 437        __set_bit(EV_KEY, dev->evbit);
 438        __set_bit(EV_REL, dev->evbit);
 439
 440        __set_bit(REL_X, dev->relbit);
 441        __set_bit(REL_Y, dev->relbit);
 442
 443        __set_bit(BTN_LEFT, dev->keybit);
 444        __set_bit(BTN_RIGHT, dev->keybit);
 445
 446        /* register handlers */
 447        psmouse->protocol_handler = hgpk_process_byte;
 448        psmouse->poll = hgpk_poll;
 449        psmouse->disconnect = hgpk_disconnect;
 450        psmouse->reconnect = hgpk_reconnect;
 451        psmouse->pktsize = 3;
 452
 453        /* Disable the idle resync. */
 454        psmouse->resync_time = 0;
 455        /* Reset after a lot of bad bytes. */
 456        psmouse->resetafter = 1024;
 457
 458        err = device_create_file(&psmouse->ps2dev.serio->dev,
 459                                 &psmouse_attr_powered.dattr);
 460        if (err) {
 461                hgpk_err(psmouse, "Failed creating 'powered' sysfs node\n");
 462                return err;
 463        }
 464
 465        /* C-series touchpads added the recalibrate command */
 466        if (psmouse->model >= HGPK_MODEL_C) {
 467                err = device_create_file(&psmouse->ps2dev.serio->dev,
 468                                         &psmouse_attr_recalibrate.dattr);
 469                if (err) {
 470                        hgpk_err(psmouse,
 471                                "Failed creating 'recalibrate' sysfs node\n");
 472                        device_remove_file(&psmouse->ps2dev.serio->dev,
 473                                        &psmouse_attr_powered.dattr);
 474                        return err;
 475                }
 476        }
 477
 478        return 0;
 479}
 480
 481int hgpk_init(struct psmouse *psmouse)
 482{
 483        struct hgpk_data *priv;
 484        int err = -ENOMEM;
 485
 486        priv = kzalloc(sizeof(struct hgpk_data), GFP_KERNEL);
 487        if (!priv)
 488                goto alloc_fail;
 489
 490        psmouse->private = priv;
 491        priv->psmouse = psmouse;
 492        priv->powered = true;
 493        INIT_DELAYED_WORK(&priv->recalib_wq, hgpk_recalib_work);
 494
 495        err = psmouse_reset(psmouse);
 496        if (err)
 497                goto init_fail;
 498
 499        err = hgpk_register(psmouse);
 500        if (err)
 501                goto init_fail;
 502
 503        return 0;
 504
 505init_fail:
 506        kfree(priv);
 507alloc_fail:
 508        return err;
 509}
 510
 511static enum hgpk_model_t hgpk_get_model(struct psmouse *psmouse)
 512{
 513        struct ps2dev *ps2dev = &psmouse->ps2dev;
 514        unsigned char param[3];
 515
 516        /* E7, E7, E7, E9 gets us a 3 byte identifier */
 517        if (ps2_command(ps2dev,  NULL, PSMOUSE_CMD_SETSCALE21) ||
 518            ps2_command(ps2dev,  NULL, PSMOUSE_CMD_SETSCALE21) ||
 519            ps2_command(ps2dev,  NULL, PSMOUSE_CMD_SETSCALE21) ||
 520            ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) {
 521                return -EIO;
 522        }
 523
 524        hgpk_dbg(psmouse, "ID: %02x %02x %02x\n", param[0], param[1], param[2]);
 525
 526        /* HGPK signature: 0x67, 0x00, 0x<model> */
 527        if (param[0] != 0x67 || param[1] != 0x00)
 528                return -ENODEV;
 529
 530        hgpk_info(psmouse, "OLPC touchpad revision 0x%x\n", param[2]);
 531
 532        return param[2];
 533}
 534
 535int hgpk_detect(struct psmouse *psmouse, bool set_properties)
 536{
 537        int version;
 538
 539        version = hgpk_get_model(psmouse);
 540        if (version < 0)
 541                return version;
 542
 543        if (set_properties) {
 544                psmouse->vendor = "ALPS";
 545                psmouse->name = "HGPK";
 546                psmouse->model = version;
 547        }
 548
 549        return 0;
 550}
 551