linux/drivers/input/mouse/synaptics.c
<<
>>
Prefs
   1/*
   2 * Synaptics TouchPad PS/2 mouse driver
   3 *
   4 *   2003 Dmitry Torokhov <dtor@mail.ru>
   5 *     Added support for pass-through port. Special thanks to Peter Berg Larsen
   6 *     for explaining various Synaptics quirks.
   7 *
   8 *   2003 Peter Osterlund <petero2@telia.com>
   9 *     Ported to 2.5 input device infrastructure.
  10 *
  11 *   Copyright (C) 2001 Stefan Gmeiner <riddlebox@freesurf.ch>
  12 *     start merging tpconfig and gpm code to a xfree-input module
  13 *     adding some changes and extensions (ex. 3rd and 4th button)
  14 *
  15 *   Copyright (c) 1997 C. Scott Ananian <cananian@alumni.priceton.edu>
  16 *   Copyright (c) 1998-2000 Bruce Kalk <kall@compass.com>
  17 *     code for the special synaptics commands (from the tpconfig-source)
  18 *
  19 * This program is free software; you can redistribute it and/or modify it
  20 * under the terms of the GNU General Public License version 2 as published by
  21 * the Free Software Foundation.
  22 *
  23 * Trademarks are the property of their respective owners.
  24 */
  25
  26#include <linux/module.h>
  27#include <linux/input.h>
  28#include <linux/serio.h>
  29#include <linux/libps2.h>
  30#include "psmouse.h"
  31#include "synaptics.h"
  32
  33/*
  34 * The x/y limits are taken from the Synaptics TouchPad interfacing Guide,
  35 * section 2.3.2, which says that they should be valid regardless of the
  36 * actual size of the sensor.
  37 */
  38#define XMIN_NOMINAL 1472
  39#define XMAX_NOMINAL 5472
  40#define YMIN_NOMINAL 1408
  41#define YMAX_NOMINAL 4448
  42
  43
  44/*****************************************************************************
  45 *      Stuff we need even when we do not want native Synaptics support
  46 ****************************************************************************/
  47
  48/*
  49 * Set the synaptics touchpad mode byte by special commands
  50 */
  51static int synaptics_mode_cmd(struct psmouse *psmouse, unsigned char mode)
  52{
  53        unsigned char param[1];
  54
  55        if (psmouse_sliced_command(psmouse, mode))
  56                return -1;
  57        param[0] = SYN_PS_SET_MODE2;
  58        if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_SETRATE))
  59                return -1;
  60        return 0;
  61}
  62
  63int synaptics_detect(struct psmouse *psmouse, bool set_properties)
  64{
  65        struct ps2dev *ps2dev = &psmouse->ps2dev;
  66        unsigned char param[4];
  67
  68        param[0] = 0;
  69
  70        ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
  71        ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
  72        ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
  73        ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
  74        ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
  75
  76        if (param[1] != 0x47)
  77                return -ENODEV;
  78
  79        if (set_properties) {
  80                psmouse->vendor = "Synaptics";
  81                psmouse->name = "TouchPad";
  82        }
  83
  84        return 0;
  85}
  86
  87void synaptics_reset(struct psmouse *psmouse)
  88{
  89        /* reset touchpad back to relative mode, gestures enabled */
  90        synaptics_mode_cmd(psmouse, 0);
  91}
  92
  93#ifdef CONFIG_MOUSE_PS2_SYNAPTICS
  94
  95/*****************************************************************************
  96 *      Synaptics communications functions
  97 ****************************************************************************/
  98
  99/*
 100 * Send a command to the synpatics touchpad by special commands
 101 */
 102static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, unsigned char *param)
 103{
 104        if (psmouse_sliced_command(psmouse, c))
 105                return -1;
 106        if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO))
 107                return -1;
 108        return 0;
 109}
 110
 111/*
 112 * Read the model-id bytes from the touchpad
 113 * see also SYN_MODEL_* macros
 114 */
 115static int synaptics_model_id(struct psmouse *psmouse)
 116{
 117        struct synaptics_data *priv = psmouse->private;
 118        unsigned char mi[3];
 119
 120        if (synaptics_send_cmd(psmouse, SYN_QUE_MODEL, mi))
 121                return -1;
 122        priv->model_id = (mi[0]<<16) | (mi[1]<<8) | mi[2];
 123        return 0;
 124}
 125
 126/*
 127 * Read the capability-bits from the touchpad
 128 * see also the SYN_CAP_* macros
 129 */
 130static int synaptics_capability(struct psmouse *psmouse)
 131{
 132        struct synaptics_data *priv = psmouse->private;
 133        unsigned char cap[3];
 134
 135        if (synaptics_send_cmd(psmouse, SYN_QUE_CAPABILITIES, cap))
 136                return -1;
 137        priv->capabilities = (cap[0] << 16) | (cap[1] << 8) | cap[2];
 138        priv->ext_cap = 0;
 139        if (!SYN_CAP_VALID(priv->capabilities))
 140                return -1;
 141
 142        /*
 143         * Unless capExtended is set the rest of the flags should be ignored
 144         */
 145        if (!SYN_CAP_EXTENDED(priv->capabilities))
 146                priv->capabilities = 0;
 147
 148        if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) {
 149                if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) {
 150                        printk(KERN_ERR "Synaptics claims to have extended capabilities,"
 151                               " but I'm not able to read them.");
 152                } else {
 153                        priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2];
 154
 155                        /*
 156                         * if nExtBtn is greater than 8 it should be considered
 157                         * invalid and treated as 0
 158                         */
 159                        if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) > 8)
 160                                priv->ext_cap &= 0xff0fff;
 161                }
 162        }
 163        return 0;
 164}
 165
 166/*
 167 * Identify Touchpad
 168 * See also the SYN_ID_* macros
 169 */
 170static int synaptics_identify(struct psmouse *psmouse)
 171{
 172        struct synaptics_data *priv = psmouse->private;
 173        unsigned char id[3];
 174
 175        if (synaptics_send_cmd(psmouse, SYN_QUE_IDENTIFY, id))
 176                return -1;
 177        priv->identity = (id[0]<<16) | (id[1]<<8) | id[2];
 178        if (SYN_ID_IS_SYNAPTICS(priv->identity))
 179                return 0;
 180        return -1;
 181}
 182
 183/*
 184 * Read touchpad resolution
 185 * Resolution is left zero if touchpad does not support the query
 186 */
 187static int synaptics_resolution(struct psmouse *psmouse)
 188{
 189        struct synaptics_data *priv = psmouse->private;
 190        unsigned char res[3];
 191
 192        if (SYN_ID_MAJOR(priv->identity) < 4)
 193                return 0;
 194
 195        if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, res))
 196                return 0;
 197
 198        if ((res[0] != 0) && (res[1] & 0x80) && (res[2] != 0)) {
 199                priv->x_res = res[0]; /* x resolution in units/mm */
 200                priv->y_res = res[2]; /* y resolution in units/mm */
 201        }
 202
 203        return 0;
 204}
 205
 206static int synaptics_query_hardware(struct psmouse *psmouse)
 207{
 208        if (synaptics_identify(psmouse))
 209                return -1;
 210        if (synaptics_model_id(psmouse))
 211                return -1;
 212        if (synaptics_capability(psmouse))
 213                return -1;
 214        if (synaptics_resolution(psmouse))
 215                return -1;
 216
 217        return 0;
 218}
 219
 220static int synaptics_set_absolute_mode(struct psmouse *psmouse)
 221{
 222        struct synaptics_data *priv = psmouse->private;
 223
 224        priv->mode = SYN_BIT_ABSOLUTE_MODE;
 225        if (SYN_ID_MAJOR(priv->identity) >= 4)
 226                priv->mode |= SYN_BIT_DISABLE_GESTURE;
 227        if (SYN_CAP_EXTENDED(priv->capabilities))
 228                priv->mode |= SYN_BIT_W_MODE;
 229
 230        if (synaptics_mode_cmd(psmouse, priv->mode))
 231                return -1;
 232
 233        return 0;
 234}
 235
 236static void synaptics_set_rate(struct psmouse *psmouse, unsigned int rate)
 237{
 238        struct synaptics_data *priv = psmouse->private;
 239
 240        if (rate >= 80) {
 241                priv->mode |= SYN_BIT_HIGH_RATE;
 242                psmouse->rate = 80;
 243        } else {
 244                priv->mode &= ~SYN_BIT_HIGH_RATE;
 245                psmouse->rate = 40;
 246        }
 247
 248        synaptics_mode_cmd(psmouse, priv->mode);
 249}
 250
 251/*****************************************************************************
 252 *      Synaptics pass-through PS/2 port support
 253 ****************************************************************************/
 254static int synaptics_pt_write(struct serio *serio, unsigned char c)
 255{
 256        struct psmouse *parent = serio_get_drvdata(serio->parent);
 257        char rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */
 258
 259        if (psmouse_sliced_command(parent, c))
 260                return -1;
 261        if (ps2_command(&parent->ps2dev, &rate_param, PSMOUSE_CMD_SETRATE))
 262                return -1;
 263        return 0;
 264}
 265
 266static inline int synaptics_is_pt_packet(unsigned char *buf)
 267{
 268        return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4;
 269}
 270
 271static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet)
 272{
 273        struct psmouse *child = serio_get_drvdata(ptport);
 274
 275        if (child && child->state == PSMOUSE_ACTIVATED) {
 276                serio_interrupt(ptport, packet[1], 0);
 277                serio_interrupt(ptport, packet[4], 0);
 278                serio_interrupt(ptport, packet[5], 0);
 279                if (child->pktsize == 4)
 280                        serio_interrupt(ptport, packet[2], 0);
 281        } else
 282                serio_interrupt(ptport, packet[1], 0);
 283}
 284
 285static void synaptics_pt_activate(struct psmouse *psmouse)
 286{
 287        struct serio *ptport = psmouse->ps2dev.serio->child;
 288        struct psmouse *child = serio_get_drvdata(ptport);
 289        struct synaptics_data *priv = psmouse->private;
 290
 291        /* adjust the touchpad to child's choice of protocol */
 292        if (child) {
 293                if (child->pktsize == 4)
 294                        priv->mode |= SYN_BIT_FOUR_BYTE_CLIENT;
 295                else
 296                        priv->mode &= ~SYN_BIT_FOUR_BYTE_CLIENT;
 297
 298                if (synaptics_mode_cmd(psmouse, priv->mode))
 299                        printk(KERN_INFO "synaptics: failed to switch guest protocol\n");
 300        }
 301}
 302
 303static void synaptics_pt_create(struct psmouse *psmouse)
 304{
 305        struct serio *serio;
 306
 307        serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
 308        if (!serio) {
 309                printk(KERN_ERR "synaptics: not enough memory to allocate pass-through port\n");
 310                return;
 311        }
 312
 313        serio->id.type = SERIO_PS_PSTHRU;
 314        strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name));
 315        strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name));
 316        serio->write = synaptics_pt_write;
 317        serio->parent = psmouse->ps2dev.serio;
 318
 319        psmouse->pt_activate = synaptics_pt_activate;
 320
 321        printk(KERN_INFO "serio: %s port at %s\n", serio->name, psmouse->phys);
 322        serio_register_port(serio);
 323}
 324
 325/*****************************************************************************
 326 *      Functions to interpret the absolute mode packets
 327 ****************************************************************************/
 328
 329static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data *priv, struct synaptics_hw_state *hw)
 330{
 331        memset(hw, 0, sizeof(struct synaptics_hw_state));
 332
 333        if (SYN_MODEL_NEWABS(priv->model_id)) {
 334                hw->x = (((buf[3] & 0x10) << 8) |
 335                         ((buf[1] & 0x0f) << 8) |
 336                         buf[4]);
 337                hw->y = (((buf[3] & 0x20) << 7) |
 338                         ((buf[1] & 0xf0) << 4) |
 339                         buf[5]);
 340
 341                hw->z = buf[2];
 342                hw->w = (((buf[0] & 0x30) >> 2) |
 343                         ((buf[0] & 0x04) >> 1) |
 344                         ((buf[3] & 0x04) >> 2));
 345
 346                hw->left  = (buf[0] & 0x01) ? 1 : 0;
 347                hw->right = (buf[0] & 0x02) ? 1 : 0;
 348
 349                if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) {
 350                        hw->middle = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
 351                        if (hw->w == 2)
 352                                hw->scroll = (signed char)(buf[1]);
 353                }
 354
 355                if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
 356                        hw->up   = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
 357                        hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
 358                }
 359
 360                if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) &&
 361                    ((buf[0] ^ buf[3]) & 0x02)) {
 362                        switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) {
 363                        default:
 364                                /*
 365                                 * if nExtBtn is greater than 8 it should be
 366                                 * considered invalid and treated as 0
 367                                 */
 368                                break;
 369                        case 8:
 370                                hw->ext_buttons |= ((buf[5] & 0x08)) ? 0x80 : 0;
 371                                hw->ext_buttons |= ((buf[4] & 0x08)) ? 0x40 : 0;
 372                        case 6:
 373                                hw->ext_buttons |= ((buf[5] & 0x04)) ? 0x20 : 0;
 374                                hw->ext_buttons |= ((buf[4] & 0x04)) ? 0x10 : 0;
 375                        case 4:
 376                                hw->ext_buttons |= ((buf[5] & 0x02)) ? 0x08 : 0;
 377                                hw->ext_buttons |= ((buf[4] & 0x02)) ? 0x04 : 0;
 378                        case 2:
 379                                hw->ext_buttons |= ((buf[5] & 0x01)) ? 0x02 : 0;
 380                                hw->ext_buttons |= ((buf[4] & 0x01)) ? 0x01 : 0;
 381                        }
 382                }
 383        } else {
 384                hw->x = (((buf[1] & 0x1f) << 8) | buf[2]);
 385                hw->y = (((buf[4] & 0x1f) << 8) | buf[5]);
 386
 387                hw->z = (((buf[0] & 0x30) << 2) | (buf[3] & 0x3F));
 388                hw->w = (((buf[1] & 0x80) >> 4) | ((buf[0] & 0x04) >> 1));
 389
 390                hw->left  = (buf[0] & 0x01) ? 1 : 0;
 391                hw->right = (buf[0] & 0x02) ? 1 : 0;
 392        }
 393}
 394
 395/*
 396 *  called for each full received packet from the touchpad
 397 */
 398static void synaptics_process_packet(struct psmouse *psmouse)
 399{
 400        struct input_dev *dev = psmouse->dev;
 401        struct synaptics_data *priv = psmouse->private;
 402        struct synaptics_hw_state hw;
 403        int num_fingers;
 404        int finger_width;
 405        int i;
 406
 407        synaptics_parse_hw_state(psmouse->packet, priv, &hw);
 408
 409        if (hw.scroll) {
 410                priv->scroll += hw.scroll;
 411
 412                while (priv->scroll >= 4) {
 413                        input_report_key(dev, BTN_BACK, !hw.down);
 414                        input_sync(dev);
 415                        input_report_key(dev, BTN_BACK, hw.down);
 416                        input_sync(dev);
 417                        priv->scroll -= 4;
 418                }
 419                while (priv->scroll <= -4) {
 420                        input_report_key(dev, BTN_FORWARD, !hw.up);
 421                        input_sync(dev);
 422                        input_report_key(dev, BTN_FORWARD, hw.up);
 423                        input_sync(dev);
 424                        priv->scroll += 4;
 425                }
 426                return;
 427        }
 428
 429        if (hw.z > 0) {
 430                num_fingers = 1;
 431                finger_width = 5;
 432                if (SYN_CAP_EXTENDED(priv->capabilities)) {
 433                        switch (hw.w) {
 434                        case 0 ... 1:
 435                                if (SYN_CAP_MULTIFINGER(priv->capabilities))
 436                                        num_fingers = hw.w + 2;
 437                                break;
 438                        case 2:
 439                                if (SYN_MODEL_PEN(priv->model_id))
 440                                        ;   /* Nothing, treat a pen as a single finger */
 441                                break;
 442                        case 4 ... 15:
 443                                if (SYN_CAP_PALMDETECT(priv->capabilities))
 444                                        finger_width = hw.w;
 445                                break;
 446                        }
 447                }
 448        } else {
 449                num_fingers = 0;
 450                finger_width = 0;
 451        }
 452
 453        /* Post events
 454         * BTN_TOUCH has to be first as mousedev relies on it when doing
 455         * absolute -> relative conversion
 456         */
 457        if (hw.z > 30) input_report_key(dev, BTN_TOUCH, 1);
 458        if (hw.z < 25) input_report_key(dev, BTN_TOUCH, 0);
 459
 460        if (hw.z > 0) {
 461                input_report_abs(dev, ABS_X, hw.x);
 462                input_report_abs(dev, ABS_Y, YMAX_NOMINAL + YMIN_NOMINAL - hw.y);
 463        }
 464        input_report_abs(dev, ABS_PRESSURE, hw.z);
 465
 466        input_report_abs(dev, ABS_TOOL_WIDTH, finger_width);
 467        input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1);
 468        input_report_key(dev, BTN_LEFT, hw.left);
 469        input_report_key(dev, BTN_RIGHT, hw.right);
 470
 471        if (SYN_CAP_MULTIFINGER(priv->capabilities)) {
 472                input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2);
 473                input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3);
 474        }
 475
 476        if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
 477                input_report_key(dev, BTN_MIDDLE, hw.middle);
 478
 479        if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
 480                input_report_key(dev, BTN_FORWARD, hw.up);
 481                input_report_key(dev, BTN_BACK, hw.down);
 482        }
 483
 484        for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
 485                input_report_key(dev, BTN_0 + i, hw.ext_buttons & (1 << i));
 486
 487        input_sync(dev);
 488}
 489
 490static int synaptics_validate_byte(unsigned char packet[], int idx, unsigned char pkt_type)
 491{
 492        static const unsigned char newabs_mask[]        = { 0xC8, 0x00, 0x00, 0xC8, 0x00 };
 493        static const unsigned char newabs_rel_mask[]    = { 0xC0, 0x00, 0x00, 0xC0, 0x00 };
 494        static const unsigned char newabs_rslt[]        = { 0x80, 0x00, 0x00, 0xC0, 0x00 };
 495        static const unsigned char oldabs_mask[]        = { 0xC0, 0x60, 0x00, 0xC0, 0x60 };
 496        static const unsigned char oldabs_rslt[]        = { 0xC0, 0x00, 0x00, 0x80, 0x00 };
 497
 498        if (idx < 0 || idx > 4)
 499                return 0;
 500
 501        switch (pkt_type) {
 502                case SYN_NEWABS:
 503                case SYN_NEWABS_RELAXED:
 504                        return (packet[idx] & newabs_rel_mask[idx]) == newabs_rslt[idx];
 505
 506                case SYN_NEWABS_STRICT:
 507                        return (packet[idx] & newabs_mask[idx]) == newabs_rslt[idx];
 508
 509                case SYN_OLDABS:
 510                        return (packet[idx] & oldabs_mask[idx]) == oldabs_rslt[idx];
 511
 512                default:
 513                        printk(KERN_ERR "synaptics: unknown packet type %d\n", pkt_type);
 514                        return 0;
 515        }
 516}
 517
 518static unsigned char synaptics_detect_pkt_type(struct psmouse *psmouse)
 519{
 520        int i;
 521
 522        for (i = 0; i < 5; i++)
 523                if (!synaptics_validate_byte(psmouse->packet, i, SYN_NEWABS_STRICT)) {
 524                        printk(KERN_INFO "synaptics: using relaxed packet validation\n");
 525                        return SYN_NEWABS_RELAXED;
 526                }
 527
 528        return SYN_NEWABS_STRICT;
 529}
 530
 531static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse)
 532{
 533        struct synaptics_data *priv = psmouse->private;
 534
 535        if (psmouse->pktcnt >= 6) { /* Full packet received */
 536                if (unlikely(priv->pkt_type == SYN_NEWABS))
 537                        priv->pkt_type = synaptics_detect_pkt_type(psmouse);
 538
 539                if (SYN_CAP_PASS_THROUGH(priv->capabilities) && synaptics_is_pt_packet(psmouse->packet)) {
 540                        if (psmouse->ps2dev.serio->child)
 541                                synaptics_pass_pt_packet(psmouse->ps2dev.serio->child, psmouse->packet);
 542                } else
 543                        synaptics_process_packet(psmouse);
 544
 545                return PSMOUSE_FULL_PACKET;
 546        }
 547
 548        return synaptics_validate_byte(psmouse->packet, psmouse->pktcnt - 1, priv->pkt_type) ?
 549                PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
 550}
 551
 552/*****************************************************************************
 553 *      Driver initialization/cleanup functions
 554 ****************************************************************************/
 555static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
 556{
 557        int i;
 558
 559        __set_bit(EV_ABS, dev->evbit);
 560        input_set_abs_params(dev, ABS_X, XMIN_NOMINAL, XMAX_NOMINAL, 0, 0);
 561        input_set_abs_params(dev, ABS_Y, YMIN_NOMINAL, YMAX_NOMINAL, 0, 0);
 562        input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
 563        __set_bit(ABS_TOOL_WIDTH, dev->absbit);
 564
 565        __set_bit(EV_KEY, dev->evbit);
 566        __set_bit(BTN_TOUCH, dev->keybit);
 567        __set_bit(BTN_TOOL_FINGER, dev->keybit);
 568        __set_bit(BTN_LEFT, dev->keybit);
 569        __set_bit(BTN_RIGHT, dev->keybit);
 570
 571        if (SYN_CAP_MULTIFINGER(priv->capabilities)) {
 572                __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
 573                __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit);
 574        }
 575
 576        if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
 577                __set_bit(BTN_MIDDLE, dev->keybit);
 578
 579        if (SYN_CAP_FOUR_BUTTON(priv->capabilities) ||
 580            SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) {
 581                __set_bit(BTN_FORWARD, dev->keybit);
 582                __set_bit(BTN_BACK, dev->keybit);
 583        }
 584
 585        for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
 586                __set_bit(BTN_0 + i, dev->keybit);
 587
 588        __clear_bit(EV_REL, dev->evbit);
 589        __clear_bit(REL_X, dev->relbit);
 590        __clear_bit(REL_Y, dev->relbit);
 591
 592        dev->absres[ABS_X] = priv->x_res;
 593        dev->absres[ABS_Y] = priv->y_res;
 594}
 595
 596static void synaptics_disconnect(struct psmouse *psmouse)
 597{
 598        synaptics_reset(psmouse);
 599        kfree(psmouse->private);
 600        psmouse->private = NULL;
 601}
 602
 603static int synaptics_reconnect(struct psmouse *psmouse)
 604{
 605        struct synaptics_data *priv = psmouse->private;
 606        struct synaptics_data old_priv = *priv;
 607
 608        psmouse_reset(psmouse);
 609
 610        if (synaptics_detect(psmouse, 0))
 611                return -1;
 612
 613        if (synaptics_query_hardware(psmouse)) {
 614                printk(KERN_ERR "Unable to query Synaptics hardware.\n");
 615                return -1;
 616        }
 617
 618        if (old_priv.identity != priv->identity ||
 619            old_priv.model_id != priv->model_id ||
 620            old_priv.capabilities != priv->capabilities ||
 621            old_priv.ext_cap != priv->ext_cap)
 622                return -1;
 623
 624        if (synaptics_set_absolute_mode(psmouse)) {
 625                printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
 626                return -1;
 627        }
 628
 629        return 0;
 630}
 631
 632#if defined(__i386__)
 633#include <linux/dmi.h>
 634static const struct dmi_system_id toshiba_dmi_table[] = {
 635        {
 636                .ident = "Toshiba Satellite",
 637                .matches = {
 638                        DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
 639                        DMI_MATCH(DMI_PRODUCT_NAME, "Satellite"),
 640                },
 641        },
 642        {
 643                .ident = "Toshiba Dynabook",
 644                .matches = {
 645                        DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
 646                        DMI_MATCH(DMI_PRODUCT_NAME, "dynabook"),
 647                },
 648        },
 649        {
 650                .ident = "Toshiba Portege M300",
 651                .matches = {
 652                        DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
 653                        DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M300"),
 654                },
 655
 656        },
 657        {
 658                .ident = "Toshiba Portege M300",
 659                .matches = {
 660                        DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
 661                        DMI_MATCH(DMI_PRODUCT_NAME, "Portable PC"),
 662                        DMI_MATCH(DMI_PRODUCT_VERSION, "Version 1.0"),
 663                },
 664
 665        },
 666        { }
 667};
 668#endif
 669
 670int synaptics_init(struct psmouse *psmouse)
 671{
 672        struct synaptics_data *priv;
 673
 674        psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL);
 675        if (!priv)
 676                return -1;
 677
 678        psmouse_reset(psmouse);
 679
 680        if (synaptics_query_hardware(psmouse)) {
 681                printk(KERN_ERR "Unable to query Synaptics hardware.\n");
 682                goto init_fail;
 683        }
 684
 685        if (synaptics_set_absolute_mode(psmouse)) {
 686                printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
 687                goto init_fail;
 688        }
 689
 690        priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS;
 691
 692        printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx\n",
 693                SYN_ID_MODEL(priv->identity),
 694                SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
 695                priv->model_id, priv->capabilities, priv->ext_cap);
 696
 697        set_input_params(psmouse->dev, priv);
 698
 699        /*
 700         * Encode touchpad model so that it can be used to set
 701         * input device->id.version and be visible to userspace.
 702         * Because version is __u16 we have to drop something.
 703         * Hardware info bits seem to be good candidates as they
 704         * are documented to be for Synaptics corp. internal use.
 705         */
 706        psmouse->model = ((priv->model_id & 0x00ff0000) >> 8) |
 707                          (priv->model_id & 0x000000ff);
 708
 709        psmouse->protocol_handler = synaptics_process_byte;
 710        psmouse->set_rate = synaptics_set_rate;
 711        psmouse->disconnect = synaptics_disconnect;
 712        psmouse->reconnect = synaptics_reconnect;
 713        psmouse->cleanup = synaptics_reset;
 714        psmouse->pktsize = 6;
 715        /* Synaptics can usually stay in sync without extra help */
 716        psmouse->resync_time = 0;
 717
 718        if (SYN_CAP_PASS_THROUGH(priv->capabilities))
 719                synaptics_pt_create(psmouse);
 720
 721#if defined(__i386__)
 722        /*
 723         * Toshiba's KBC seems to have trouble handling data from
 724         * Synaptics as full rate, switch to lower rate which is roughly
 725         * thye same as rate of standard PS/2 mouse.
 726         */
 727        if (psmouse->rate >= 80 && dmi_check_system(toshiba_dmi_table)) {
 728                printk(KERN_INFO "synaptics: Toshiba %s detected, limiting rate to 40pps.\n",
 729                        dmi_get_system_info(DMI_PRODUCT_NAME));
 730                psmouse->rate = 40;
 731        }
 732#endif
 733
 734        return 0;
 735
 736 init_fail:
 737        kfree(priv);
 738        return -1;
 739}
 740
 741#else /* CONFIG_MOUSE_PS2_SYNAPTICS */
 742
 743int synaptics_init(struct psmouse *psmouse)
 744{
 745        return -ENOSYS;
 746}
 747
 748#endif /* CONFIG_MOUSE_PS2_SYNAPTICS */
 749
 750