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