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, int 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
 183static int synaptics_query_hardware(struct psmouse *psmouse)
 184{
 185        if (synaptics_identify(psmouse))
 186                return -1;
 187        if (synaptics_model_id(psmouse))
 188                return -1;
 189        if (synaptics_capability(psmouse))
 190                return -1;
 191
 192        return 0;
 193}
 194
 195static int synaptics_set_absolute_mode(struct psmouse *psmouse)
 196{
 197        struct synaptics_data *priv = psmouse->private;
 198
 199        priv->mode = SYN_BIT_ABSOLUTE_MODE;
 200        if (SYN_ID_MAJOR(priv->identity) >= 4)
 201                priv->mode |= SYN_BIT_DISABLE_GESTURE;
 202        if (SYN_CAP_EXTENDED(priv->capabilities))
 203                priv->mode |= SYN_BIT_W_MODE;
 204
 205        if (synaptics_mode_cmd(psmouse, priv->mode))
 206                return -1;
 207
 208        return 0;
 209}
 210
 211static void synaptics_set_rate(struct psmouse *psmouse, unsigned int rate)
 212{
 213        struct synaptics_data *priv = psmouse->private;
 214
 215        if (rate >= 80) {
 216                priv->mode |= SYN_BIT_HIGH_RATE;
 217                psmouse->rate = 80;
 218        } else {
 219                priv->mode &= ~SYN_BIT_HIGH_RATE;
 220                psmouse->rate = 40;
 221        }
 222
 223        synaptics_mode_cmd(psmouse, priv->mode);
 224}
 225
 226/*****************************************************************************
 227 *      Synaptics pass-through PS/2 port support
 228 ****************************************************************************/
 229static int synaptics_pt_write(struct serio *serio, unsigned char c)
 230{
 231        struct psmouse *parent = serio_get_drvdata(serio->parent);
 232        char rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */
 233
 234        if (psmouse_sliced_command(parent, c))
 235                return -1;
 236        if (ps2_command(&parent->ps2dev, &rate_param, PSMOUSE_CMD_SETRATE))
 237                return -1;
 238        return 0;
 239}
 240
 241static inline int synaptics_is_pt_packet(unsigned char *buf)
 242{
 243        return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4;
 244}
 245
 246static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet)
 247{
 248        struct psmouse *child = serio_get_drvdata(ptport);
 249
 250        if (child && child->state == PSMOUSE_ACTIVATED) {
 251                serio_interrupt(ptport, packet[1], 0);
 252                serio_interrupt(ptport, packet[4], 0);
 253                serio_interrupt(ptport, packet[5], 0);
 254                if (child->pktsize == 4)
 255                        serio_interrupt(ptport, packet[2], 0);
 256        } else
 257                serio_interrupt(ptport, packet[1], 0);
 258}
 259
 260static void synaptics_pt_activate(struct psmouse *psmouse)
 261{
 262        struct serio *ptport = psmouse->ps2dev.serio->child;
 263        struct psmouse *child = serio_get_drvdata(ptport);
 264        struct synaptics_data *priv = psmouse->private;
 265
 266        /* adjust the touchpad to child's choice of protocol */
 267        if (child) {
 268                if (child->pktsize == 4)
 269                        priv->mode |= SYN_BIT_FOUR_BYTE_CLIENT;
 270                else
 271                        priv->mode &= ~SYN_BIT_FOUR_BYTE_CLIENT;
 272
 273                if (synaptics_mode_cmd(psmouse, priv->mode))
 274                        printk(KERN_INFO "synaptics: failed to switch guest protocol\n");
 275        }
 276}
 277
 278static void synaptics_pt_create(struct psmouse *psmouse)
 279{
 280        struct serio *serio;
 281
 282        serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
 283        if (!serio) {
 284                printk(KERN_ERR "synaptics: not enough memory to allocate pass-through port\n");
 285                return;
 286        }
 287
 288        serio->id.type = SERIO_PS_PSTHRU;
 289        strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name));
 290        strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name));
 291        serio->write = synaptics_pt_write;
 292        serio->parent = psmouse->ps2dev.serio;
 293
 294        psmouse->pt_activate = synaptics_pt_activate;
 295
 296        printk(KERN_INFO "serio: %s port at %s\n", serio->name, psmouse->phys);
 297        serio_register_port(serio);
 298}
 299
 300/*****************************************************************************
 301 *      Functions to interpret the absolute mode packets
 302 ****************************************************************************/
 303
 304static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data *priv, struct synaptics_hw_state *hw)
 305{
 306        memset(hw, 0, sizeof(struct synaptics_hw_state));
 307
 308        if (SYN_MODEL_NEWABS(priv->model_id)) {
 309                hw->x = (((buf[3] & 0x10) << 8) |
 310                         ((buf[1] & 0x0f) << 8) |
 311                         buf[4]);
 312                hw->y = (((buf[3] & 0x20) << 7) |
 313                         ((buf[1] & 0xf0) << 4) |
 314                         buf[5]);
 315
 316                hw->z = buf[2];
 317                hw->w = (((buf[0] & 0x30) >> 2) |
 318                         ((buf[0] & 0x04) >> 1) |
 319                         ((buf[3] & 0x04) >> 2));
 320
 321                hw->left  = (buf[0] & 0x01) ? 1 : 0;
 322                hw->right = (buf[0] & 0x02) ? 1 : 0;
 323
 324                if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) {
 325                        hw->middle = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
 326                        if (hw->w == 2)
 327                                hw->scroll = (signed char)(buf[1]);
 328                }
 329
 330                if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
 331                        hw->up   = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
 332                        hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
 333                }
 334
 335                if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) &&
 336                    ((buf[0] ^ buf[3]) & 0x02)) {
 337                        switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) {
 338                        default:
 339                                /*
 340                                 * if nExtBtn is greater than 8 it should be
 341                                 * considered invalid and treated as 0
 342                                 */
 343                                break;
 344                        case 8:
 345                                hw->ext_buttons |= ((buf[5] & 0x08)) ? 0x80 : 0;
 346                                hw->ext_buttons |= ((buf[4] & 0x08)) ? 0x40 : 0;
 347                        case 6:
 348                                hw->ext_buttons |= ((buf[5] & 0x04)) ? 0x20 : 0;
 349                                hw->ext_buttons |= ((buf[4] & 0x04)) ? 0x10 : 0;
 350                        case 4:
 351                                hw->ext_buttons |= ((buf[5] & 0x02)) ? 0x08 : 0;
 352                                hw->ext_buttons |= ((buf[4] & 0x02)) ? 0x04 : 0;
 353                        case 2:
 354                                hw->ext_buttons |= ((buf[5] & 0x01)) ? 0x02 : 0;
 355                                hw->ext_buttons |= ((buf[4] & 0x01)) ? 0x01 : 0;
 356                        }
 357                }
 358        } else {
 359                hw->x = (((buf[1] & 0x1f) << 8) | buf[2]);
 360                hw->y = (((buf[4] & 0x1f) << 8) | buf[5]);
 361
 362                hw->z = (((buf[0] & 0x30) << 2) | (buf[3] & 0x3F));
 363                hw->w = (((buf[1] & 0x80) >> 4) | ((buf[0] & 0x04) >> 1));
 364
 365                hw->left  = (buf[0] & 0x01) ? 1 : 0;
 366                hw->right = (buf[0] & 0x02) ? 1 : 0;
 367        }
 368}
 369
 370/*
 371 *  called for each full received packet from the touchpad
 372 */
 373static void synaptics_process_packet(struct psmouse *psmouse)
 374{
 375        struct input_dev *dev = psmouse->dev;
 376        struct synaptics_data *priv = psmouse->private;
 377        struct synaptics_hw_state hw;
 378        int num_fingers;
 379        int finger_width;
 380        int i;
 381
 382        synaptics_parse_hw_state(psmouse->packet, priv, &hw);
 383
 384        if (hw.scroll) {
 385                priv->scroll += hw.scroll;
 386
 387                while (priv->scroll >= 4) {
 388                        input_report_key(dev, BTN_BACK, !hw.down);
 389                        input_sync(dev);
 390                        input_report_key(dev, BTN_BACK, hw.down);
 391                        input_sync(dev);
 392                        priv->scroll -= 4;
 393                }
 394                while (priv->scroll <= -4) {
 395                        input_report_key(dev, BTN_FORWARD, !hw.up);
 396                        input_sync(dev);
 397                        input_report_key(dev, BTN_FORWARD, hw.up);
 398                        input_sync(dev);
 399                        priv->scroll += 4;
 400                }
 401                return;
 402        }
 403
 404        if (hw.z > 0) {
 405                num_fingers = 1;
 406                finger_width = 5;
 407                if (SYN_CAP_EXTENDED(priv->capabilities)) {
 408                        switch (hw.w) {
 409                        case 0 ... 1:
 410                                if (SYN_CAP_MULTIFINGER(priv->capabilities))
 411                                        num_fingers = hw.w + 2;
 412                                break;
 413                        case 2:
 414                                if (SYN_MODEL_PEN(priv->model_id))
 415                                        ;   /* Nothing, treat a pen as a single finger */
 416                                break;
 417                        case 4 ... 15:
 418                                if (SYN_CAP_PALMDETECT(priv->capabilities))
 419                                        finger_width = hw.w;
 420                                break;
 421                        }
 422                }
 423        } else {
 424                num_fingers = 0;
 425                finger_width = 0;
 426        }
 427
 428        /* Post events
 429         * BTN_TOUCH has to be first as mousedev relies on it when doing
 430         * absolute -> relative conversion
 431         */
 432        if (hw.z > 30) input_report_key(dev, BTN_TOUCH, 1);
 433        if (hw.z < 25) input_report_key(dev, BTN_TOUCH, 0);
 434
 435        if (hw.z > 0) {
 436                input_report_abs(dev, ABS_X, hw.x);
 437                input_report_abs(dev, ABS_Y, YMAX_NOMINAL + YMIN_NOMINAL - hw.y);
 438        }
 439        input_report_abs(dev, ABS_PRESSURE, hw.z);
 440
 441        input_report_abs(dev, ABS_TOOL_WIDTH, finger_width);
 442        input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1);
 443        input_report_key(dev, BTN_LEFT, hw.left);
 444        input_report_key(dev, BTN_RIGHT, hw.right);
 445
 446        if (SYN_CAP_MULTIFINGER(priv->capabilities)) {
 447                input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2);
 448                input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3);
 449        }
 450
 451        if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
 452                input_report_key(dev, BTN_MIDDLE, hw.middle);
 453
 454        if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
 455                input_report_key(dev, BTN_FORWARD, hw.up);
 456                input_report_key(dev, BTN_BACK, hw.down);
 457        }
 458
 459        for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
 460                input_report_key(dev, BTN_0 + i, hw.ext_buttons & (1 << i));
 461
 462        input_sync(dev);
 463}
 464
 465static int synaptics_validate_byte(unsigned char packet[], int idx, unsigned char pkt_type)
 466{
 467        static const unsigned char newabs_mask[]        = { 0xC8, 0x00, 0x00, 0xC8, 0x00 };
 468        static const unsigned char newabs_rel_mask[]    = { 0xC0, 0x00, 0x00, 0xC0, 0x00 };
 469        static const unsigned char newabs_rslt[]        = { 0x80, 0x00, 0x00, 0xC0, 0x00 };
 470        static const unsigned char oldabs_mask[]        = { 0xC0, 0x60, 0x00, 0xC0, 0x60 };
 471        static const unsigned char oldabs_rslt[]        = { 0xC0, 0x00, 0x00, 0x80, 0x00 };
 472
 473        if (idx < 0 || idx > 4)
 474                return 0;
 475
 476        switch (pkt_type) {
 477                case SYN_NEWABS:
 478                case SYN_NEWABS_RELAXED:
 479                        return (packet[idx] & newabs_rel_mask[idx]) == newabs_rslt[idx];
 480
 481                case SYN_NEWABS_STRICT:
 482                        return (packet[idx] & newabs_mask[idx]) == newabs_rslt[idx];
 483
 484                case SYN_OLDABS:
 485                        return (packet[idx] & oldabs_mask[idx]) == oldabs_rslt[idx];
 486
 487                default:
 488                        printk(KERN_ERR "synaptics: unknown packet type %d\n", pkt_type);
 489                        return 0;
 490        }
 491}
 492
 493static unsigned char synaptics_detect_pkt_type(struct psmouse *psmouse)
 494{
 495        int i;
 496
 497        for (i = 0; i < 5; i++)
 498                if (!synaptics_validate_byte(psmouse->packet, i, SYN_NEWABS_STRICT)) {
 499                        printk(KERN_INFO "synaptics: using relaxed packet validation\n");
 500                        return SYN_NEWABS_RELAXED;
 501                }
 502
 503        return SYN_NEWABS_STRICT;
 504}
 505
 506static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse)
 507{
 508        struct synaptics_data *priv = psmouse->private;
 509
 510        if (psmouse->pktcnt >= 6) { /* Full packet received */
 511                if (unlikely(priv->pkt_type == SYN_NEWABS))
 512                        priv->pkt_type = synaptics_detect_pkt_type(psmouse);
 513
 514                if (SYN_CAP_PASS_THROUGH(priv->capabilities) && synaptics_is_pt_packet(psmouse->packet)) {
 515                        if (psmouse->ps2dev.serio->child)
 516                                synaptics_pass_pt_packet(psmouse->ps2dev.serio->child, psmouse->packet);
 517                } else
 518                        synaptics_process_packet(psmouse);
 519
 520                return PSMOUSE_FULL_PACKET;
 521        }
 522
 523        return synaptics_validate_byte(psmouse->packet, psmouse->pktcnt - 1, priv->pkt_type) ?
 524                PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
 525}
 526
 527/*****************************************************************************
 528 *      Driver initialization/cleanup functions
 529 ****************************************************************************/
 530static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
 531{
 532        int i;
 533
 534        set_bit(EV_ABS, dev->evbit);
 535        input_set_abs_params(dev, ABS_X, XMIN_NOMINAL, XMAX_NOMINAL, 0, 0);
 536        input_set_abs_params(dev, ABS_Y, YMIN_NOMINAL, YMAX_NOMINAL, 0, 0);
 537        input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
 538        set_bit(ABS_TOOL_WIDTH, dev->absbit);
 539
 540        set_bit(EV_KEY, dev->evbit);
 541        set_bit(BTN_TOUCH, dev->keybit);
 542        set_bit(BTN_TOOL_FINGER, dev->keybit);
 543        set_bit(BTN_LEFT, dev->keybit);
 544        set_bit(BTN_RIGHT, dev->keybit);
 545
 546        if (SYN_CAP_MULTIFINGER(priv->capabilities)) {
 547                set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
 548                set_bit(BTN_TOOL_TRIPLETAP, dev->keybit);
 549        }
 550
 551        if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
 552                set_bit(BTN_MIDDLE, dev->keybit);
 553
 554        if (SYN_CAP_FOUR_BUTTON(priv->capabilities) ||
 555            SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) {
 556                set_bit(BTN_FORWARD, dev->keybit);
 557                set_bit(BTN_BACK, dev->keybit);
 558        }
 559
 560        for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
 561                set_bit(BTN_0 + i, dev->keybit);
 562
 563        clear_bit(EV_REL, dev->evbit);
 564        clear_bit(REL_X, dev->relbit);
 565        clear_bit(REL_Y, dev->relbit);
 566}
 567
 568static void synaptics_disconnect(struct psmouse *psmouse)
 569{
 570        synaptics_reset(psmouse);
 571        kfree(psmouse->private);
 572        psmouse->private = NULL;
 573}
 574
 575static int synaptics_reconnect(struct psmouse *psmouse)
 576{
 577        struct synaptics_data *priv = psmouse->private;
 578        struct synaptics_data old_priv = *priv;
 579
 580        psmouse_reset(psmouse);
 581
 582        if (synaptics_detect(psmouse, 0))
 583                return -1;
 584
 585        if (synaptics_query_hardware(psmouse)) {
 586                printk(KERN_ERR "Unable to query Synaptics hardware.\n");
 587                return -1;
 588        }
 589
 590        if (old_priv.identity != priv->identity ||
 591            old_priv.model_id != priv->model_id ||
 592            old_priv.capabilities != priv->capabilities ||
 593            old_priv.ext_cap != priv->ext_cap)
 594                return -1;
 595
 596        if (synaptics_set_absolute_mode(psmouse)) {
 597                printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
 598                return -1;
 599        }
 600
 601        return 0;
 602}
 603
 604#if defined(__i386__)
 605#include <linux/dmi.h>
 606static const struct dmi_system_id toshiba_dmi_table[] = {
 607        {
 608                .ident = "Toshiba Satellite",
 609                .matches = {
 610                        DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
 611                        DMI_MATCH(DMI_PRODUCT_NAME, "Satellite"),
 612                },
 613        },
 614        {
 615                .ident = "Toshiba Dynabook",
 616                .matches = {
 617                        DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
 618                        DMI_MATCH(DMI_PRODUCT_NAME, "dynabook"),
 619                },
 620        },
 621        {
 622                .ident = "Toshiba Portege M300",
 623                .matches = {
 624                        DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
 625                        DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M300"),
 626                },
 627        },
 628        { }
 629};
 630#endif
 631
 632int synaptics_init(struct psmouse *psmouse)
 633{
 634        struct synaptics_data *priv;
 635
 636        psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL);
 637        if (!priv)
 638                return -1;
 639
 640        psmouse_reset(psmouse);
 641
 642        if (synaptics_query_hardware(psmouse)) {
 643                printk(KERN_ERR "Unable to query Synaptics hardware.\n");
 644                goto init_fail;
 645        }
 646
 647        if (synaptics_set_absolute_mode(psmouse)) {
 648                printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
 649                goto init_fail;
 650        }
 651
 652        priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS;
 653
 654        printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx\n",
 655                SYN_ID_MODEL(priv->identity),
 656                SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
 657                priv->model_id, priv->capabilities, priv->ext_cap);
 658
 659        set_input_params(psmouse->dev, priv);
 660
 661        /*
 662         * Encode touchpad model so that it can be used to set
 663         * input device->id.version and be visible to userspace.
 664         * Because version is __u16 we have to drop something.
 665         * Hardware info bits seem to be good candidates as they
 666         * are documented to be for Synaptics corp. internal use.
 667         */
 668        psmouse->model = ((priv->model_id & 0x00ff0000) >> 8) |
 669                          (priv->model_id & 0x000000ff);
 670
 671        psmouse->protocol_handler = synaptics_process_byte;
 672        psmouse->set_rate = synaptics_set_rate;
 673        psmouse->disconnect = synaptics_disconnect;
 674        psmouse->reconnect = synaptics_reconnect;
 675        psmouse->cleanup = synaptics_reset;
 676        psmouse->pktsize = 6;
 677        /* Synaptics can usually stay in sync without extra help */
 678        psmouse->resync_time = 0;
 679
 680        if (SYN_CAP_PASS_THROUGH(priv->capabilities))
 681                synaptics_pt_create(psmouse);
 682
 683#if defined(__i386__)
 684        /*
 685         * Toshiba's KBC seems to have trouble handling data from
 686         * Synaptics as full rate, switch to lower rate which is roughly
 687         * thye same as rate of standard PS/2 mouse.
 688         */
 689        if (psmouse->rate >= 80 && dmi_check_system(toshiba_dmi_table)) {
 690                printk(KERN_INFO "synaptics: Toshiba %s detected, limiting rate to 40pps.\n",
 691                        dmi_get_system_info(DMI_PRODUCT_NAME));
 692                psmouse->rate = 40;
 693        }
 694#endif
 695
 696        return 0;
 697
 698 init_fail:
 699        kfree(priv);
 700        return -1;
 701}
 702
 703#else /* CONFIG_MOUSE_PS2_SYNAPTICS */
 704
 705int synaptics_init(struct psmouse *psmouse)
 706{
 707        return -ENOSYS;
 708}
 709
 710#endif /* CONFIG_MOUSE_PS2_SYNAPTICS */
 711
 712