LCOV - code coverage report
Current view: top level - drivers/input/mouse - synaptics.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 545 0.0 %
Date: 2014-02-18 Functions: 0 46 0.0 %
Branches: 0 403 0.0 %

           Branch data     Line data    Source code
       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/delay.h>
      28                 :            : #include <linux/dmi.h>
      29                 :            : #include <linux/input/mt.h>
      30                 :            : #include <linux/serio.h>
      31                 :            : #include <linux/libps2.h>
      32                 :            : #include <linux/slab.h>
      33                 :            : #include "psmouse.h"
      34                 :            : #include "synaptics.h"
      35                 :            : 
      36                 :            : /*
      37                 :            :  * The x/y limits are taken from the Synaptics TouchPad interfacing Guide,
      38                 :            :  * section 2.3.2, which says that they should be valid regardless of the
      39                 :            :  * actual size of the sensor.
      40                 :            :  * Note that newer firmware allows querying device for maximum useable
      41                 :            :  * coordinates.
      42                 :            :  */
      43                 :            : #define XMIN 0
      44                 :            : #define XMAX 6143
      45                 :            : #define YMIN 0
      46                 :            : #define YMAX 6143
      47                 :            : #define XMIN_NOMINAL 1472
      48                 :            : #define XMAX_NOMINAL 5472
      49                 :            : #define YMIN_NOMINAL 1408
      50                 :            : #define YMAX_NOMINAL 4448
      51                 :            : 
      52                 :            : /* Size in bits of absolute position values reported by the hardware */
      53                 :            : #define ABS_POS_BITS 13
      54                 :            : 
      55                 :            : /*
      56                 :            :  * These values should represent the absolute maximum value that will
      57                 :            :  * be reported for a positive position value. Some Synaptics firmware
      58                 :            :  * uses this value to indicate a finger near the edge of the touchpad
      59                 :            :  * whose precise position cannot be determined.
      60                 :            :  *
      61                 :            :  * At least one touchpad is known to report positions in excess of this
      62                 :            :  * value which are actually negative values truncated to the 13-bit
      63                 :            :  * reporting range. These values have never been observed to be lower
      64                 :            :  * than 8184 (i.e. -8), so we treat all values greater than 8176 as
      65                 :            :  * negative and any other value as positive.
      66                 :            :  */
      67                 :            : #define X_MAX_POSITIVE 8176
      68                 :            : #define Y_MAX_POSITIVE 8176
      69                 :            : 
      70                 :            : /*****************************************************************************
      71                 :            :  *      Stuff we need even when we do not want native Synaptics support
      72                 :            :  ****************************************************************************/
      73                 :            : 
      74                 :            : /*
      75                 :            :  * Set the synaptics touchpad mode byte by special commands
      76                 :            :  */
      77                 :          0 : static int synaptics_mode_cmd(struct psmouse *psmouse, unsigned char mode)
      78                 :            : {
      79                 :            :         unsigned char param[1];
      80                 :            : 
      81         [ #  # ]:          0 :         if (psmouse_sliced_command(psmouse, mode))
      82                 :            :                 return -1;
      83                 :          0 :         param[0] = SYN_PS_SET_MODE2;
      84         [ #  # ]:          0 :         if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_SETRATE))
      85                 :            :                 return -1;
      86                 :          0 :         return 0;
      87                 :            : }
      88                 :            : 
      89                 :          0 : int synaptics_detect(struct psmouse *psmouse, bool set_properties)
      90                 :            : {
      91                 :          0 :         struct ps2dev *ps2dev = &psmouse->ps2dev;
      92                 :            :         unsigned char param[4];
      93                 :            : 
      94                 :          0 :         param[0] = 0;
      95                 :            : 
      96                 :          0 :         ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
      97                 :          0 :         ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
      98                 :          0 :         ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
      99                 :          0 :         ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
     100                 :          0 :         ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
     101                 :            : 
     102         [ #  # ]:          0 :         if (param[1] != 0x47)
     103                 :            :                 return -ENODEV;
     104                 :            : 
     105         [ #  # ]:          0 :         if (set_properties) {
     106                 :          0 :                 psmouse->vendor = "Synaptics";
     107                 :          0 :                 psmouse->name = "TouchPad";
     108                 :            :         }
     109                 :            : 
     110                 :            :         return 0;
     111                 :            : }
     112                 :            : 
     113                 :          0 : void synaptics_reset(struct psmouse *psmouse)
     114                 :            : {
     115                 :            :         /* reset touchpad back to relative mode, gestures enabled */
     116                 :          0 :         synaptics_mode_cmd(psmouse, 0);
     117                 :          0 : }
     118                 :            : 
     119                 :            : #ifdef CONFIG_MOUSE_PS2_SYNAPTICS
     120                 :            : 
     121                 :            : /*****************************************************************************
     122                 :            :  *      Synaptics communications functions
     123                 :            :  ****************************************************************************/
     124                 :            : 
     125                 :            : /*
     126                 :            :  * Synaptics touchpads report the y coordinate from bottom to top, which is
     127                 :            :  * opposite from what userspace expects.
     128                 :            :  * This function is used to invert y before reporting.
     129                 :            :  */
     130                 :            : static int synaptics_invert_y(int y)
     131                 :            : {
     132                 :          0 :         return YMAX_NOMINAL + YMIN_NOMINAL - y;
     133                 :            : }
     134                 :            : 
     135                 :            : /*
     136                 :            :  * Send a command to the synpatics touchpad by special commands
     137                 :            :  */
     138                 :          0 : static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, unsigned char *param)
     139                 :            : {
     140         [ #  # ]:          0 :         if (psmouse_sliced_command(psmouse, c))
     141                 :            :                 return -1;
     142         [ #  # ]:          0 :         if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO))
     143                 :            :                 return -1;
     144                 :          0 :         return 0;
     145                 :            : }
     146                 :            : 
     147                 :            : /*
     148                 :            :  * Read the model-id bytes from the touchpad
     149                 :            :  * see also SYN_MODEL_* macros
     150                 :            :  */
     151                 :          0 : static int synaptics_model_id(struct psmouse *psmouse)
     152                 :            : {
     153                 :          0 :         struct synaptics_data *priv = psmouse->private;
     154                 :            :         unsigned char mi[3];
     155                 :            : 
     156         [ #  # ]:          0 :         if (synaptics_send_cmd(psmouse, SYN_QUE_MODEL, mi))
     157                 :            :                 return -1;
     158                 :          0 :         priv->model_id = (mi[0]<<16) | (mi[1]<<8) | mi[2];
     159                 :          0 :         return 0;
     160                 :            : }
     161                 :            : 
     162                 :            : /*
     163                 :            :  * Read the board id from the touchpad
     164                 :            :  * The board id is encoded in the "QUERY MODES" response
     165                 :            :  */
     166                 :          0 : static int synaptics_board_id(struct psmouse *psmouse)
     167                 :            : {
     168                 :          0 :         struct synaptics_data *priv = psmouse->private;
     169                 :            :         unsigned char bid[3];
     170                 :            : 
     171         [ #  # ]:          0 :         if (synaptics_send_cmd(psmouse, SYN_QUE_MODES, bid))
     172                 :            :                 return -1;
     173                 :          0 :         priv->board_id = ((bid[0] & 0xfc) << 6) | bid[1];
     174                 :          0 :         return 0;
     175                 :            : }
     176                 :            : 
     177                 :            : /*
     178                 :            :  * Read the firmware id from the touchpad
     179                 :            :  */
     180                 :          0 : static int synaptics_firmware_id(struct psmouse *psmouse)
     181                 :            : {
     182                 :          0 :         struct synaptics_data *priv = psmouse->private;
     183                 :            :         unsigned char fwid[3];
     184                 :            : 
     185         [ #  # ]:          0 :         if (synaptics_send_cmd(psmouse, SYN_QUE_FIRMWARE_ID, fwid))
     186                 :            :                 return -1;
     187                 :          0 :         priv->firmware_id = (fwid[0] << 16) | (fwid[1] << 8) | fwid[2];
     188                 :          0 :         return 0;
     189                 :            : }
     190                 :            : 
     191                 :            : /*
     192                 :            :  * Read the capability-bits from the touchpad
     193                 :            :  * see also the SYN_CAP_* macros
     194                 :            :  */
     195                 :          0 : static int synaptics_capability(struct psmouse *psmouse)
     196                 :            : {
     197                 :          0 :         struct synaptics_data *priv = psmouse->private;
     198                 :            :         unsigned char cap[3];
     199                 :            : 
     200         [ #  # ]:          0 :         if (synaptics_send_cmd(psmouse, SYN_QUE_CAPABILITIES, cap))
     201                 :            :                 return -1;
     202                 :          0 :         priv->capabilities = (cap[0] << 16) | (cap[1] << 8) | cap[2];
     203                 :          0 :         priv->ext_cap = priv->ext_cap_0c = 0;
     204                 :            : 
     205                 :            :         /*
     206                 :            :          * Older firmwares had submodel ID fixed to 0x47
     207                 :            :          */
     208 [ #  # ][ #  # ]:          0 :         if (SYN_ID_FULL(priv->identity) < 0x705 &&
     209                 :          0 :             SYN_CAP_SUBMODEL_ID(priv->capabilities) != 0x47) {
     210                 :            :                 return -1;
     211                 :            :         }
     212                 :            : 
     213                 :            :         /*
     214                 :            :          * Unless capExtended is set the rest of the flags should be ignored
     215                 :            :          */
     216         [ #  # ]:          0 :         if (!SYN_CAP_EXTENDED(priv->capabilities))
     217                 :          0 :                 priv->capabilities = 0;
     218                 :            : 
     219         [ #  # ]:          0 :         if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) {
     220         [ #  # ]:          0 :                 if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) {
     221                 :          0 :                         psmouse_warn(psmouse,
     222                 :            :                                      "device claims to have extended capabilities, but I'm not able to read them.\n");
     223                 :            :                 } else {
     224                 :          0 :                         priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2];
     225                 :            : 
     226                 :            :                         /*
     227                 :            :                          * if nExtBtn is greater than 8 it should be considered
     228                 :            :                          * invalid and treated as 0
     229                 :            :                          */
     230         [ #  # ]:          0 :                         if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) > 8)
     231                 :          0 :                                 priv->ext_cap &= 0xff0fff;
     232                 :            :                 }
     233                 :            :         }
     234                 :            : 
     235         [ #  # ]:          0 :         if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 4) {
     236         [ #  # ]:          0 :                 if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB_0C, cap)) {
     237                 :          0 :                         psmouse_warn(psmouse,
     238                 :            :                                      "device claims to have extended capability 0x0c, but I'm not able to read it.\n");
     239                 :            :                 } else {
     240                 :          0 :                         priv->ext_cap_0c = (cap[0] << 16) | (cap[1] << 8) | cap[2];
     241                 :            :                 }
     242                 :            :         }
     243                 :            : 
     244                 :            :         return 0;
     245                 :            : }
     246                 :            : 
     247                 :            : /*
     248                 :            :  * Identify Touchpad
     249                 :            :  * See also the SYN_ID_* macros
     250                 :            :  */
     251                 :          0 : static int synaptics_identify(struct psmouse *psmouse)
     252                 :            : {
     253                 :          0 :         struct synaptics_data *priv = psmouse->private;
     254                 :            :         unsigned char id[3];
     255                 :            : 
     256         [ #  # ]:          0 :         if (synaptics_send_cmd(psmouse, SYN_QUE_IDENTIFY, id))
     257                 :            :                 return -1;
     258                 :          0 :         priv->identity = (id[0]<<16) | (id[1]<<8) | id[2];
     259         [ #  # ]:          0 :         if (SYN_ID_IS_SYNAPTICS(priv->identity))
     260                 :            :                 return 0;
     261                 :          0 :         return -1;
     262                 :            : }
     263                 :            : 
     264                 :            : /*
     265                 :            :  * Read touchpad resolution and maximum reported coordinates
     266                 :            :  * Resolution is left zero if touchpad does not support the query
     267                 :            :  */
     268                 :          0 : static int synaptics_resolution(struct psmouse *psmouse)
     269                 :            : {
     270                 :          0 :         struct synaptics_data *priv = psmouse->private;
     271                 :            :         unsigned char resp[3];
     272                 :            : 
     273         [ #  # ]:          0 :         if (SYN_ID_MAJOR(priv->identity) < 4)
     274                 :            :                 return 0;
     275                 :            : 
     276         [ #  # ]:          0 :         if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, resp) == 0) {
     277 [ #  # ][ #  # ]:          0 :                 if (resp[0] != 0 && (resp[1] & 0x80) && resp[2] != 0) {
                 [ #  # ]
     278                 :          0 :                         priv->x_res = resp[0]; /* x resolution in units/mm */
     279                 :          0 :                         priv->y_res = resp[2]; /* y resolution in units/mm */
     280                 :            :                 }
     281                 :            :         }
     282                 :            : 
     283 [ #  # ][ #  # ]:          0 :         if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 &&
     284                 :          0 :             SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) {
     285         [ #  # ]:          0 :                 if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) {
     286                 :          0 :                         psmouse_warn(psmouse,
     287                 :            :                                      "device claims to have max coordinates query, but I'm not able to read it.\n");
     288                 :            :                 } else {
     289                 :          0 :                         priv->x_max = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
     290                 :          0 :                         priv->y_max = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
     291                 :            :                 }
     292                 :            :         }
     293                 :            : 
     294 [ #  # ][ #  # ]:          0 :         if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 &&
     295                 :          0 :             SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c)) {
     296         [ #  # ]:          0 :                 if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MIN_COORDS, resp)) {
     297                 :          0 :                         psmouse_warn(psmouse,
     298                 :            :                                      "device claims to have min coordinates query, but I'm not able to read it.\n");
     299                 :            :                 } else {
     300                 :          0 :                         priv->x_min = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
     301                 :          0 :                         priv->y_min = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
     302                 :            :                 }
     303                 :            :         }
     304                 :            : 
     305                 :            :         return 0;
     306                 :            : }
     307                 :            : 
     308                 :          0 : static int synaptics_query_hardware(struct psmouse *psmouse)
     309                 :            : {
     310         [ #  # ]:          0 :         if (synaptics_identify(psmouse))
     311                 :            :                 return -1;
     312         [ #  # ]:          0 :         if (synaptics_model_id(psmouse))
     313                 :            :                 return -1;
     314         [ #  # ]:          0 :         if (synaptics_firmware_id(psmouse))
     315                 :            :                 return -1;
     316         [ #  # ]:          0 :         if (synaptics_board_id(psmouse))
     317                 :            :                 return -1;
     318         [ #  # ]:          0 :         if (synaptics_capability(psmouse))
     319                 :            :                 return -1;
     320         [ #  # ]:          0 :         if (synaptics_resolution(psmouse))
     321                 :            :                 return -1;
     322                 :            : 
     323                 :          0 :         return 0;
     324                 :            : }
     325                 :            : 
     326                 :          0 : static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse)
     327                 :            : {
     328                 :            :         static unsigned char param = 0xc8;
     329                 :          0 :         struct synaptics_data *priv = psmouse->private;
     330                 :            : 
     331         [ #  # ]:          0 :         if (!(SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
     332                 :            :               SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)))
     333                 :            :                 return 0;
     334                 :            : 
     335         [ #  # ]:          0 :         if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL))
     336                 :            :                 return -1;
     337                 :            : 
     338         [ #  # ]:          0 :         if (ps2_command(&psmouse->ps2dev, &param, PSMOUSE_CMD_SETRATE))
     339                 :            :                 return -1;
     340                 :            : 
     341                 :            :         /* Advanced gesture mode also sends multi finger data */
     342                 :          0 :         priv->capabilities |= BIT(1);
     343                 :            : 
     344                 :          0 :         return 0;
     345                 :            : }
     346                 :            : 
     347                 :          0 : static int synaptics_set_mode(struct psmouse *psmouse)
     348                 :            : {
     349                 :          0 :         struct synaptics_data *priv = psmouse->private;
     350                 :            : 
     351                 :          0 :         priv->mode = 0;
     352         [ #  # ]:          0 :         if (priv->absolute_mode)
     353                 :          0 :                 priv->mode |= SYN_BIT_ABSOLUTE_MODE;
     354         [ #  # ]:          0 :         if (priv->disable_gesture)
     355                 :          0 :                 priv->mode |= SYN_BIT_DISABLE_GESTURE;
     356         [ #  # ]:          0 :         if (psmouse->rate >= 80)
     357                 :          0 :                 priv->mode |= SYN_BIT_HIGH_RATE;
     358         [ #  # ]:          0 :         if (SYN_CAP_EXTENDED(priv->capabilities))
     359                 :          0 :                 priv->mode |= SYN_BIT_W_MODE;
     360                 :            : 
     361         [ #  # ]:          0 :         if (synaptics_mode_cmd(psmouse, priv->mode))
     362                 :            :                 return -1;
     363                 :            : 
     364   [ #  #  #  # ]:          0 :         if (priv->absolute_mode &&
     365                 :          0 :             synaptics_set_advanced_gesture_mode(psmouse)) {
     366                 :          0 :                 psmouse_err(psmouse, "Advanced gesture mode init failed.\n");
     367                 :          0 :                 return -1;
     368                 :            :         }
     369                 :            : 
     370                 :            :         return 0;
     371                 :            : }
     372                 :            : 
     373                 :          0 : static void synaptics_set_rate(struct psmouse *psmouse, unsigned int rate)
     374                 :            : {
     375                 :          0 :         struct synaptics_data *priv = psmouse->private;
     376                 :            : 
     377         [ #  # ]:          0 :         if (rate >= 80) {
     378                 :          0 :                 priv->mode |= SYN_BIT_HIGH_RATE;
     379                 :          0 :                 psmouse->rate = 80;
     380                 :            :         } else {
     381                 :          0 :                 priv->mode &= ~SYN_BIT_HIGH_RATE;
     382                 :          0 :                 psmouse->rate = 40;
     383                 :            :         }
     384                 :            : 
     385                 :          0 :         synaptics_mode_cmd(psmouse, priv->mode);
     386                 :          0 : }
     387                 :            : 
     388                 :            : /*****************************************************************************
     389                 :            :  *      Synaptics pass-through PS/2 port support
     390                 :            :  ****************************************************************************/
     391                 :          0 : static int synaptics_pt_write(struct serio *serio, unsigned char c)
     392                 :            : {
     393                 :          0 :         struct psmouse *parent = serio_get_drvdata(serio->parent);
     394                 :          0 :         char rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */
     395                 :            : 
     396         [ #  # ]:          0 :         if (psmouse_sliced_command(parent, c))
     397                 :            :                 return -1;
     398         [ #  # ]:          0 :         if (ps2_command(&parent->ps2dev, &rate_param, PSMOUSE_CMD_SETRATE))
     399                 :            :                 return -1;
     400                 :          0 :         return 0;
     401                 :            : }
     402                 :            : 
     403                 :          0 : static int synaptics_pt_start(struct serio *serio)
     404                 :            : {
     405                 :          0 :         struct psmouse *parent = serio_get_drvdata(serio->parent);
     406                 :          0 :         struct synaptics_data *priv = parent->private;
     407                 :            : 
     408                 :          0 :         serio_pause_rx(parent->ps2dev.serio);
     409                 :          0 :         priv->pt_port = serio;
     410                 :          0 :         serio_continue_rx(parent->ps2dev.serio);
     411                 :            : 
     412                 :          0 :         return 0;
     413                 :            : }
     414                 :            : 
     415                 :          0 : static void synaptics_pt_stop(struct serio *serio)
     416                 :            : {
     417                 :          0 :         struct psmouse *parent = serio_get_drvdata(serio->parent);
     418                 :          0 :         struct synaptics_data *priv = parent->private;
     419                 :            : 
     420                 :          0 :         serio_pause_rx(parent->ps2dev.serio);
     421                 :          0 :         priv->pt_port = NULL;
     422                 :          0 :         serio_continue_rx(parent->ps2dev.serio);
     423                 :          0 : }
     424                 :            : 
     425                 :            : static int synaptics_is_pt_packet(unsigned char *buf)
     426                 :            : {
     427 [ #  # ][ #  # ]:          0 :         return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4;
     428                 :            : }
     429                 :            : 
     430                 :          0 : static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet)
     431                 :            : {
     432                 :            :         struct psmouse *child = serio_get_drvdata(ptport);
     433                 :            : 
     434 [ #  # ][ #  # ]:          0 :         if (child && child->state == PSMOUSE_ACTIVATED) {
     435                 :          0 :                 serio_interrupt(ptport, packet[1], 0);
     436                 :          0 :                 serio_interrupt(ptport, packet[4], 0);
     437                 :          0 :                 serio_interrupt(ptport, packet[5], 0);
     438         [ #  # ]:          0 :                 if (child->pktsize == 4)
     439                 :          0 :                         serio_interrupt(ptport, packet[2], 0);
     440                 :            :         } else
     441                 :          0 :                 serio_interrupt(ptport, packet[1], 0);
     442                 :          0 : }
     443                 :            : 
     444                 :          0 : static void synaptics_pt_activate(struct psmouse *psmouse)
     445                 :            : {
     446                 :          0 :         struct synaptics_data *priv = psmouse->private;
     447                 :          0 :         struct psmouse *child = serio_get_drvdata(priv->pt_port);
     448                 :            : 
     449                 :            :         /* adjust the touchpad to child's choice of protocol */
     450         [ #  # ]:          0 :         if (child) {
     451         [ #  # ]:          0 :                 if (child->pktsize == 4)
     452                 :          0 :                         priv->mode |= SYN_BIT_FOUR_BYTE_CLIENT;
     453                 :            :                 else
     454                 :          0 :                         priv->mode &= ~SYN_BIT_FOUR_BYTE_CLIENT;
     455                 :            : 
     456         [ #  # ]:          0 :                 if (synaptics_mode_cmd(psmouse, priv->mode))
     457                 :          0 :                         psmouse_warn(psmouse,
     458                 :            :                                      "failed to switch guest protocol\n");
     459                 :            :         }
     460                 :          0 : }
     461                 :            : 
     462                 :          0 : static void synaptics_pt_create(struct psmouse *psmouse)
     463                 :            : {
     464                 :            :         struct serio *serio;
     465                 :            : 
     466                 :            :         serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
     467         [ #  # ]:          0 :         if (!serio) {
     468                 :          0 :                 psmouse_err(psmouse,
     469                 :            :                             "not enough memory for pass-through port\n");
     470                 :          0 :                 return;
     471                 :            :         }
     472                 :            : 
     473                 :          0 :         serio->id.type = SERIO_PS_PSTHRU;
     474                 :          0 :         strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name));
     475                 :          0 :         strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name));
     476                 :          0 :         serio->write = synaptics_pt_write;
     477                 :          0 :         serio->start = synaptics_pt_start;
     478                 :          0 :         serio->stop = synaptics_pt_stop;
     479                 :          0 :         serio->parent = psmouse->ps2dev.serio;
     480                 :            : 
     481                 :          0 :         psmouse->pt_activate = synaptics_pt_activate;
     482                 :            : 
     483                 :          0 :         psmouse_info(psmouse, "serio: %s port at %s\n",
     484                 :            :                      serio->name, psmouse->phys);
     485                 :          0 :         serio_register_port(serio);
     486                 :            : }
     487                 :            : 
     488                 :            : /*****************************************************************************
     489                 :            :  *      Functions to interpret the absolute mode packets
     490                 :            :  ****************************************************************************/
     491                 :            : 
     492                 :            : static void synaptics_mt_state_set(struct synaptics_mt_state *state, int count,
     493                 :            :                                    int sgm, int agm)
     494                 :            : {
     495                 :          0 :         state->count = count;
     496                 :          0 :         state->sgm = sgm;
     497                 :          0 :         state->agm = agm;
     498                 :            : }
     499                 :            : 
     500                 :          0 : static void synaptics_parse_agm(const unsigned char buf[],
     501                 :            :                                 struct synaptics_data *priv,
     502                 :            :                                 struct synaptics_hw_state *hw)
     503                 :            : {
     504                 :            :         struct synaptics_hw_state *agm = &priv->agm;
     505                 :            :         int agm_packet_type;
     506                 :            : 
     507                 :          0 :         agm_packet_type = (buf[5] & 0x30) >> 4;
     508      [ #  #  # ]:          0 :         switch (agm_packet_type) {
     509                 :            :         case 1:
     510                 :            :                 /* Gesture packet: (x, y, z) half resolution */
     511                 :          0 :                 agm->w = hw->w;
     512                 :          0 :                 agm->x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1;
     513                 :          0 :                 agm->y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1;
     514                 :          0 :                 agm->z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1;
     515                 :            :                 break;
     516                 :            : 
     517                 :            :         case 2:
     518                 :            :                 /* AGM-CONTACT packet: (count, sgm, agm) */
     519                 :          0 :                 synaptics_mt_state_set(&agm->mt_state, buf[1], buf[2], buf[4]);
     520                 :            :                 break;
     521                 :            : 
     522                 :            :         default:
     523                 :            :                 break;
     524                 :            :         }
     525                 :            : 
     526                 :            :         /* Record that at least one AGM has been received since last SGM */
     527                 :          0 :         priv->agm_pending = true;
     528                 :          0 : }
     529                 :            : 
     530                 :          0 : static int synaptics_parse_hw_state(const unsigned char buf[],
     531                 :            :                                     struct synaptics_data *priv,
     532                 :            :                                     struct synaptics_hw_state *hw)
     533                 :            : {
     534                 :          0 :         memset(hw, 0, sizeof(struct synaptics_hw_state));
     535                 :            : 
     536         [ #  # ]:          0 :         if (SYN_MODEL_NEWABS(priv->model_id)) {
     537                 :          0 :                 hw->w = (((buf[0] & 0x30) >> 2) |
     538                 :          0 :                          ((buf[0] & 0x04) >> 1) |
     539                 :          0 :                          ((buf[3] & 0x04) >> 2));
     540                 :            : 
     541                 :          0 :                 hw->left  = (buf[0] & 0x01) ? 1 : 0;
     542                 :          0 :                 hw->right = (buf[0] & 0x02) ? 1 : 0;
     543                 :            : 
     544         [ #  # ]:          0 :                 if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
     545                 :            :                         /*
     546                 :            :                          * Clickpad's button is transmitted as middle button,
     547                 :            :                          * however, since it is primary button, we will report
     548                 :            :                          * it as BTN_LEFT.
     549                 :            :                          */
     550                 :          0 :                         hw->left = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
     551                 :            : 
     552         [ #  # ]:          0 :                 } else if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) {
     553                 :          0 :                         hw->middle = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
     554         [ #  # ]:          0 :                         if (hw->w == 2)
     555                 :          0 :                                 hw->scroll = (signed char)(buf[1]);
     556                 :            :                 }
     557                 :            : 
     558         [ #  # ]:          0 :                 if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
     559                 :          0 :                         hw->up   = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
     560                 :          0 :                         hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
     561                 :            :                 }
     562                 :            : 
     563         [ #  # ]:          0 :                 if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
     564         [ #  # ]:          0 :                         SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) &&
     565                 :            :                     hw->w == 2) {
     566                 :          0 :                         synaptics_parse_agm(buf, priv, hw);
     567                 :          0 :                         return 1;
     568                 :            :                 }
     569                 :            : 
     570                 :          0 :                 hw->x = (((buf[3] & 0x10) << 8) |
     571                 :          0 :                          ((buf[1] & 0x0f) << 8) |
     572                 :          0 :                          buf[4]);
     573                 :          0 :                 hw->y = (((buf[3] & 0x20) << 7) |
     574                 :          0 :                          ((buf[1] & 0xf0) << 4) |
     575                 :          0 :                          buf[5]);
     576                 :          0 :                 hw->z = buf[2];
     577                 :            : 
     578 [ #  # ][ #  # ]:          0 :                 if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) &&
     579                 :          0 :                     ((buf[0] ^ buf[3]) & 0x02)) {
     580   [ #  #  #  #  :          0 :                         switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) {
                      # ]
     581                 :            :                         default:
     582                 :            :                                 /*
     583                 :            :                                  * if nExtBtn is greater than 8 it should be
     584                 :            :                                  * considered invalid and treated as 0
     585                 :            :                                  */
     586                 :            :                                 break;
     587                 :            :                         case 8:
     588         [ #  # ]:          0 :                                 hw->ext_buttons |= ((buf[5] & 0x08)) ? 0x80 : 0;
     589         [ #  # ]:          0 :                                 hw->ext_buttons |= ((buf[4] & 0x08)) ? 0x40 : 0;
     590                 :            :                         case 6:
     591         [ #  # ]:          0 :                                 hw->ext_buttons |= ((buf[5] & 0x04)) ? 0x20 : 0;
     592         [ #  # ]:          0 :                                 hw->ext_buttons |= ((buf[4] & 0x04)) ? 0x10 : 0;
     593                 :            :                         case 4:
     594         [ #  # ]:          0 :                                 hw->ext_buttons |= ((buf[5] & 0x02)) ? 0x08 : 0;
     595         [ #  # ]:          0 :                                 hw->ext_buttons |= ((buf[4] & 0x02)) ? 0x04 : 0;
     596                 :            :                         case 2:
     597         [ #  # ]:          0 :                                 hw->ext_buttons |= ((buf[5] & 0x01)) ? 0x02 : 0;
     598                 :          0 :                                 hw->ext_buttons |= ((buf[4] & 0x01)) ? 0x01 : 0;
     599                 :            :                         }
     600                 :            :                 }
     601                 :            :         } else {
     602                 :          0 :                 hw->x = (((buf[1] & 0x1f) << 8) | buf[2]);
     603                 :          0 :                 hw->y = (((buf[4] & 0x1f) << 8) | buf[5]);
     604                 :            : 
     605                 :          0 :                 hw->z = (((buf[0] & 0x30) << 2) | (buf[3] & 0x3F));
     606                 :          0 :                 hw->w = (((buf[1] & 0x80) >> 4) | ((buf[0] & 0x04) >> 1));
     607                 :            : 
     608                 :          0 :                 hw->left  = (buf[0] & 0x01) ? 1 : 0;
     609                 :          0 :                 hw->right = (buf[0] & 0x02) ? 1 : 0;
     610                 :            :         }
     611                 :            : 
     612                 :            :         /*
     613                 :            :          * Convert wrap-around values to negative. (X|Y)_MAX_POSITIVE
     614                 :            :          * is used by some firmware to indicate a finger at the edge of
     615                 :            :          * the touchpad whose precise position cannot be determined, so
     616                 :            :          * convert these values to the maximum axis value.
     617                 :            :          */
     618         [ #  # ]:          0 :         if (hw->x > X_MAX_POSITIVE)
     619                 :          0 :                 hw->x -= 1 << ABS_POS_BITS;
     620         [ #  # ]:          0 :         else if (hw->x == X_MAX_POSITIVE)
     621                 :          0 :                 hw->x = XMAX;
     622                 :            : 
     623         [ #  # ]:          0 :         if (hw->y > Y_MAX_POSITIVE)
     624                 :          0 :                 hw->y -= 1 << ABS_POS_BITS;
     625         [ #  # ]:          0 :         else if (hw->y == Y_MAX_POSITIVE)
     626                 :          0 :                 hw->y = YMAX;
     627                 :            : 
     628                 :            :         return 0;
     629                 :            : }
     630                 :            : 
     631                 :          0 : static void synaptics_report_semi_mt_slot(struct input_dev *dev, int slot,
     632                 :            :                                           bool active, int x, int y)
     633                 :            : {
     634                 :            :         input_mt_slot(dev, slot);
     635                 :          0 :         input_mt_report_slot_state(dev, MT_TOOL_FINGER, active);
     636         [ #  # ]:          0 :         if (active) {
     637                 :            :                 input_report_abs(dev, ABS_MT_POSITION_X, x);
     638                 :            :                 input_report_abs(dev, ABS_MT_POSITION_Y, synaptics_invert_y(y));
     639                 :            :         }
     640                 :          0 : }
     641                 :            : 
     642                 :          0 : static void synaptics_report_semi_mt_data(struct input_dev *dev,
     643                 :            :                                           const struct synaptics_hw_state *a,
     644                 :            :                                           const struct synaptics_hw_state *b,
     645                 :            :                                           int num_fingers)
     646                 :            : {
     647         [ #  # ]:          0 :         if (num_fingers >= 2) {
     648                 :          0 :                 synaptics_report_semi_mt_slot(dev, 0, true, min(a->x, b->x),
     649                 :          0 :                                               min(a->y, b->y));
     650                 :          0 :                 synaptics_report_semi_mt_slot(dev, 1, true, max(a->x, b->x),
     651                 :          0 :                                               max(a->y, b->y));
     652         [ #  # ]:          0 :         } else if (num_fingers == 1) {
     653                 :          0 :                 synaptics_report_semi_mt_slot(dev, 0, true, a->x, a->y);
     654                 :          0 :                 synaptics_report_semi_mt_slot(dev, 1, false, 0, 0);
     655                 :            :         } else {
     656                 :          0 :                 synaptics_report_semi_mt_slot(dev, 0, false, 0, 0);
     657                 :          0 :                 synaptics_report_semi_mt_slot(dev, 1, false, 0, 0);
     658                 :            :         }
     659                 :          0 : }
     660                 :            : 
     661                 :          0 : static void synaptics_report_buttons(struct psmouse *psmouse,
     662                 :            :                                      const struct synaptics_hw_state *hw)
     663                 :            : {
     664                 :          0 :         struct input_dev *dev = psmouse->dev;
     665                 :          0 :         struct synaptics_data *priv = psmouse->private;
     666                 :            :         int i;
     667                 :            : 
     668                 :          0 :         input_report_key(dev, BTN_LEFT, hw->left);
     669                 :          0 :         input_report_key(dev, BTN_RIGHT, hw->right);
     670                 :            : 
     671         [ #  # ]:          0 :         if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
     672                 :          0 :                 input_report_key(dev, BTN_MIDDLE, hw->middle);
     673                 :            : 
     674         [ #  # ]:          0 :         if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
     675                 :          0 :                 input_report_key(dev, BTN_FORWARD, hw->up);
     676                 :          0 :                 input_report_key(dev, BTN_BACK, hw->down);
     677                 :            :         }
     678                 :            : 
     679         [ #  # ]:          0 :         for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
     680                 :          0 :                 input_report_key(dev, BTN_0 + i, hw->ext_buttons & (1 << i));
     681                 :          0 : }
     682                 :            : 
     683                 :          0 : static void synaptics_report_slot(struct input_dev *dev, int slot,
     684                 :            :                                   const struct synaptics_hw_state *hw)
     685                 :            : {
     686                 :            :         input_mt_slot(dev, slot);
     687                 :          0 :         input_mt_report_slot_state(dev, MT_TOOL_FINGER, (hw != NULL));
     688         [ #  # ]:          0 :         if (!hw)
     689                 :          0 :                 return;
     690                 :            : 
     691                 :          0 :         input_report_abs(dev, ABS_MT_POSITION_X, hw->x);
     692                 :          0 :         input_report_abs(dev, ABS_MT_POSITION_Y, synaptics_invert_y(hw->y));
     693                 :          0 :         input_report_abs(dev, ABS_MT_PRESSURE, hw->z);
     694                 :            : }
     695                 :            : 
     696                 :          0 : static void synaptics_report_mt_data(struct psmouse *psmouse,
     697                 :            :                                      struct synaptics_mt_state *mt_state,
     698                 :            :                                      const struct synaptics_hw_state *sgm)
     699                 :            : {
     700                 :          0 :         struct input_dev *dev = psmouse->dev;
     701                 :          0 :         struct synaptics_data *priv = psmouse->private;
     702                 :          0 :         struct synaptics_hw_state *agm = &priv->agm;
     703                 :            :         struct synaptics_mt_state *old = &priv->mt_state;
     704                 :            : 
     705      [ #  #  # ]:          0 :         switch (mt_state->count) {
     706                 :            :         case 0:
     707                 :          0 :                 synaptics_report_slot(dev, 0, NULL);
     708                 :          0 :                 synaptics_report_slot(dev, 1, NULL);
     709                 :          0 :                 break;
     710                 :            :         case 1:
     711         [ #  # ]:          0 :                 if (mt_state->sgm == -1) {
     712                 :          0 :                         synaptics_report_slot(dev, 0, NULL);
     713                 :          0 :                         synaptics_report_slot(dev, 1, NULL);
     714         [ #  # ]:          0 :                 } else if (mt_state->sgm == 0) {
     715                 :          0 :                         synaptics_report_slot(dev, 0, sgm);
     716                 :          0 :                         synaptics_report_slot(dev, 1, NULL);
     717                 :            :                 } else {
     718                 :          0 :                         synaptics_report_slot(dev, 0, NULL);
     719                 :          0 :                         synaptics_report_slot(dev, 1, sgm);
     720                 :            :                 }
     721                 :            :                 break;
     722                 :            :         default:
     723                 :            :                 /*
     724                 :            :                  * If the finger slot contained in SGM is valid, and either
     725                 :            :                  * hasn't changed, or is new, or the old SGM has now moved to
     726                 :            :                  * AGM, then report SGM in MTB slot 0.
     727                 :            :                  * Otherwise, empty MTB slot 0.
     728                 :            :                  */
     729 [ #  # ][ #  # ]:          0 :                 if (mt_state->sgm != -1 &&
     730         [ #  # ]:          0 :                     (mt_state->sgm == old->sgm ||
     731         [ #  # ]:          0 :                      old->sgm == -1 || mt_state->agm == old->sgm))
     732                 :          0 :                         synaptics_report_slot(dev, 0, sgm);
     733                 :            :                 else
     734                 :          0 :                         synaptics_report_slot(dev, 0, NULL);
     735                 :            : 
     736                 :            :                 /*
     737                 :            :                  * If the finger slot contained in AGM is valid, and either
     738                 :            :                  * hasn't changed, or is new, then report AGM in MTB slot 1.
     739                 :            :                  * Otherwise, empty MTB slot 1.
     740                 :            :                  *
     741                 :            :                  * However, in the case where the AGM is new, make sure that
     742                 :            :                  * that it is either the same as the old SGM, or there was no
     743                 :            :                  * SGM.
     744                 :            :                  *
     745                 :            :                  * Otherwise, if the SGM was just 1, and the new AGM is 2, then
     746                 :            :                  * the new AGM will keep the old SGM's tracking ID, which can
     747                 :            :                  * cause apparent drumroll.  This happens if in the following
     748                 :            :                  * valid finger sequence:
     749                 :            :                  *
     750                 :            :                  *  Action                 SGM  AGM (MTB slot:Contact)
     751                 :            :                  *  1. Touch contact 0    (0:0)
     752                 :            :                  *  2. Touch contact 1    (0:0, 1:1)
     753                 :            :                  *  3. Lift  contact 0    (1:1)
     754                 :            :                  *  4. Touch contacts 2,3 (0:2, 1:3)
     755                 :            :                  *
     756                 :            :                  * In step 4, contact 3, in AGM must not be given the same
     757                 :            :                  * tracking ID as contact 1 had in step 3.  To avoid this,
     758                 :            :                  * the first agm with contact 3 is dropped and slot 1 is
     759                 :            :                  * invalidated (tracking ID = -1).
     760                 :            :                  */
     761 [ #  # ][ #  # ]:          0 :                 if (mt_state->agm != -1 &&
     762         [ #  # ]:          0 :                     (mt_state->agm == old->agm ||
     763         [ #  # ]:          0 :                      (old->agm == -1 &&
     764         [ #  # ]:          0 :                       (old->sgm == -1 || mt_state->agm == old->sgm))))
     765                 :          0 :                         synaptics_report_slot(dev, 1, agm);
     766                 :            :                 else
     767                 :          0 :                         synaptics_report_slot(dev, 1, NULL);
     768                 :            :                 break;
     769                 :            :         }
     770                 :            : 
     771                 :            :         /* Don't use active slot count to generate BTN_TOOL events. */
     772                 :          0 :         input_mt_report_pointer_emulation(dev, false);
     773                 :            : 
     774                 :            :         /* Send the number of fingers reported by touchpad itself. */
     775                 :          0 :         input_mt_report_finger_count(dev, mt_state->count);
     776                 :            : 
     777                 :          0 :         synaptics_report_buttons(psmouse, sgm);
     778                 :            : 
     779                 :            :         input_sync(dev);
     780                 :          0 : }
     781                 :            : 
     782                 :            : /* Handle case where mt_state->count = 0 */
     783                 :            : static void synaptics_image_sensor_0f(struct synaptics_data *priv,
     784                 :            :                                       struct synaptics_mt_state *mt_state)
     785                 :            : {
     786                 :            :         synaptics_mt_state_set(mt_state, 0, -1, -1);
     787                 :          0 :         priv->mt_state_lost = false;
     788                 :            : }
     789                 :            : 
     790                 :            : /* Handle case where mt_state->count = 1 */
     791                 :          0 : static void synaptics_image_sensor_1f(struct synaptics_data *priv,
     792                 :            :                                       struct synaptics_mt_state *mt_state)
     793                 :            : {
     794                 :            :         struct synaptics_hw_state *agm = &priv->agm;
     795                 :            :         struct synaptics_mt_state *old = &priv->mt_state;
     796                 :            : 
     797                 :            :         /*
     798                 :            :          * If the last AGM was (0,0,0), and there is only one finger left,
     799                 :            :          * then we absolutely know that SGM contains slot 0, and all other
     800                 :            :          * fingers have been removed.
     801                 :            :          */
     802 [ #  # ][ #  # ]:          0 :         if (priv->agm_pending && agm->z == 0) {
     803                 :            :                 synaptics_mt_state_set(mt_state, 1, 0, -1);
     804                 :          0 :                 priv->mt_state_lost = false;
     805                 :          0 :                 return;
     806                 :            :         }
     807                 :            : 
     808   [ #  #  #  #  :          0 :         switch (old->count) {
                      # ]
     809                 :            :         case 0:
     810                 :            :                 synaptics_mt_state_set(mt_state, 1, 0, -1);
     811                 :            :                 break;
     812                 :            :         case 1:
     813                 :            :                 /*
     814                 :            :                  * If mt_state_lost, then the previous transition was 3->1,
     815                 :            :                  * and SGM now contains either slot 0 or 1, but we don't know
     816                 :            :                  * which.  So, we just assume that the SGM now contains slot 1.
     817                 :            :                  *
     818                 :            :                  * If pending AGM and either:
     819                 :            :                  *   (a) the previous SGM slot contains slot 0, or
     820                 :            :                  *   (b) there was no SGM slot
     821                 :            :                  * then, the SGM now contains slot 1
     822                 :            :                  *
     823                 :            :                  * Case (a) happens with very rapid "drum roll" gestures, where
     824                 :            :                  * slot 0 finger is lifted and a new slot 1 finger touches
     825                 :            :                  * within one reporting interval.
     826                 :            :                  *
     827                 :            :                  * Case (b) happens if initially two or more fingers tap
     828                 :            :                  * briefly, and all but one lift before the end of the first
     829                 :            :                  * reporting interval.
     830                 :            :                  *
     831                 :            :                  * (In both these cases, slot 0 will becomes empty, so SGM
     832                 :            :                  * contains slot 1 with the new finger)
     833                 :            :                  *
     834                 :            :                  * Else, if there was no previous SGM, it now contains slot 0.
     835                 :            :                  *
     836                 :            :                  * Otherwise, SGM still contains the same slot.
     837                 :            :                  */
     838 [ #  # ][ #  # ]:          0 :                 if (priv->mt_state_lost ||
     839         [ #  # ]:          0 :                     (priv->agm_pending && old->sgm <= 0))
     840                 :            :                         synaptics_mt_state_set(mt_state, 1, 1, -1);
     841         [ #  # ]:          0 :                 else if (old->sgm == -1)
     842                 :            :                         synaptics_mt_state_set(mt_state, 1, 0, -1);
     843                 :            :                 break;
     844                 :            :         case 2:
     845                 :            :                 /*
     846                 :            :                  * If mt_state_lost, we don't know which finger SGM contains.
     847                 :            :                  *
     848                 :            :                  * So, report 1 finger, but with both slots empty.
     849                 :            :                  * We will use slot 1 on subsequent 1->1
     850                 :            :                  */
     851         [ #  # ]:          0 :                 if (priv->mt_state_lost) {
     852                 :            :                         synaptics_mt_state_set(mt_state, 1, -1, -1);
     853                 :            :                         break;
     854                 :            :                 }
     855                 :            :                 /*
     856                 :            :                  * Since the last AGM was NOT (0,0,0), it was the finger in
     857                 :            :                  * slot 0 that has been removed.
     858                 :            :                  * So, SGM now contains previous AGM's slot, and AGM is now
     859                 :            :                  * empty.
     860                 :            :                  */
     861                 :          0 :                 synaptics_mt_state_set(mt_state, 1, old->agm, -1);
     862                 :            :                 break;
     863                 :            :         case 3:
     864                 :            :                 /*
     865                 :            :                  * Since last AGM was not (0,0,0), we don't know which finger
     866                 :            :                  * is left.
     867                 :            :                  *
     868                 :            :                  * So, report 1 finger, but with both slots empty.
     869                 :            :                  * We will use slot 1 on subsequent 1->1
     870                 :            :                  */
     871                 :            :                 synaptics_mt_state_set(mt_state, 1, -1, -1);
     872                 :          0 :                 priv->mt_state_lost = true;
     873                 :          0 :                 break;
     874                 :            :         case 4:
     875                 :            :         case 5:
     876                 :            :                 /* mt_state was updated by AGM-CONTACT packet */
     877                 :            :                 break;
     878                 :            :         }
     879                 :            : }
     880                 :            : 
     881                 :            : /* Handle case where mt_state->count = 2 */
     882                 :          0 : static void synaptics_image_sensor_2f(struct synaptics_data *priv,
     883                 :            :                                       struct synaptics_mt_state *mt_state)
     884                 :            : {
     885                 :            :         struct synaptics_mt_state *old = &priv->mt_state;
     886                 :            : 
     887   [ #  #  #  #  :          0 :         switch (old->count) {
                      # ]
     888                 :            :         case 0:
     889                 :            :                 synaptics_mt_state_set(mt_state, 2, 0, 1);
     890                 :            :                 break;
     891                 :            :         case 1:
     892                 :            :                 /*
     893                 :            :                  * If previous SGM contained slot 1 or higher, SGM now contains
     894                 :            :                  * slot 0 (the newly touching finger) and AGM contains SGM's
     895                 :            :                  * previous slot.
     896                 :            :                  *
     897                 :            :                  * Otherwise, SGM still contains slot 0 and AGM now contains
     898                 :            :                  * slot 1.
     899                 :            :                  */
     900         [ #  # ]:          0 :                 if (old->sgm >= 1)
     901                 :            :                         synaptics_mt_state_set(mt_state, 2, 0, old->sgm);
     902                 :            :                 else
     903                 :            :                         synaptics_mt_state_set(mt_state, 2, 0, 1);
     904                 :            :                 break;
     905                 :            :         case 2:
     906                 :            :                 /*
     907                 :            :                  * If mt_state_lost, SGM now contains either finger 1 or 2, but
     908                 :            :                  * we don't know which.
     909                 :            :                  * So, we just assume that the SGM contains slot 0 and AGM 1.
     910                 :            :                  */
     911         [ #  # ]:          0 :                 if (priv->mt_state_lost)
     912                 :            :                         synaptics_mt_state_set(mt_state, 2, 0, 1);
     913                 :            :                 /*
     914                 :            :                  * Otherwise, use the same mt_state, since it either hasn't
     915                 :            :                  * changed, or was updated by a recently received AGM-CONTACT
     916                 :            :                  * packet.
     917                 :            :                  */
     918                 :            :                 break;
     919                 :            :         case 3:
     920                 :            :                 /*
     921                 :            :                  * 3->2 transitions have two unsolvable problems:
     922                 :            :                  *  1) no indication is given which finger was removed
     923                 :            :                  *  2) no way to tell if agm packet was for finger 3
     924                 :            :                  *     before 3->2, or finger 2 after 3->2.
     925                 :            :                  *
     926                 :            :                  * So, report 2 fingers, but empty all slots.
     927                 :            :                  * We will guess slots [0,1] on subsequent 2->2.
     928                 :            :                  */
     929                 :            :                 synaptics_mt_state_set(mt_state, 2, -1, -1);
     930                 :          0 :                 priv->mt_state_lost = true;
     931                 :          0 :                 break;
     932                 :            :         case 4:
     933                 :            :         case 5:
     934                 :            :                 /* mt_state was updated by AGM-CONTACT packet */
     935                 :            :                 break;
     936                 :            :         }
     937                 :          0 : }
     938                 :            : 
     939                 :            : /* Handle case where mt_state->count = 3 */
     940                 :          0 : static void synaptics_image_sensor_3f(struct synaptics_data *priv,
     941                 :            :                                       struct synaptics_mt_state *mt_state)
     942                 :            : {
     943                 :            :         struct synaptics_mt_state *old = &priv->mt_state;
     944                 :            : 
     945   [ #  #  #  #  :          0 :         switch (old->count) {
                      # ]
     946                 :            :         case 0:
     947                 :            :                 synaptics_mt_state_set(mt_state, 3, 0, 2);
     948                 :            :                 break;
     949                 :            :         case 1:
     950                 :            :                 /*
     951                 :            :                  * If previous SGM contained slot 2 or higher, SGM now contains
     952                 :            :                  * slot 0 (one of the newly touching fingers) and AGM contains
     953                 :            :                  * SGM's previous slot.
     954                 :            :                  *
     955                 :            :                  * Otherwise, SGM now contains slot 0 and AGM contains slot 2.
     956                 :            :                  */
     957         [ #  # ]:          0 :                 if (old->sgm >= 2)
     958                 :            :                         synaptics_mt_state_set(mt_state, 3, 0, old->sgm);
     959                 :            :                 else
     960                 :            :                         synaptics_mt_state_set(mt_state, 3, 0, 2);
     961                 :            :                 break;
     962                 :            :         case 2:
     963                 :            :                 /*
     964                 :            :                  * If the AGM previously contained slot 3 or higher, then the
     965                 :            :                  * newly touching finger is in the lowest available slot.
     966                 :            :                  *
     967                 :            :                  * If SGM was previously 1 or higher, then the new SGM is
     968                 :            :                  * now slot 0 (with a new finger), otherwise, the new finger
     969                 :            :                  * is now in a hidden slot between 0 and AGM's slot.
     970                 :            :                  *
     971                 :            :                  * In all such cases, the SGM now contains slot 0, and the AGM
     972                 :            :                  * continues to contain the same slot as before.
     973                 :            :                  */
     974         [ #  # ]:          0 :                 if (old->agm >= 3) {
     975                 :            :                         synaptics_mt_state_set(mt_state, 3, 0, old->agm);
     976                 :            :                         break;
     977                 :            :                 }
     978                 :            : 
     979                 :            :                 /*
     980                 :            :                  * After some 3->1 and all 3->2 transitions, we lose track
     981                 :            :                  * of which slot is reported by SGM and AGM.
     982                 :            :                  *
     983                 :            :                  * For 2->3 in this state, report 3 fingers, but empty all
     984                 :            :                  * slots, and we will guess (0,2) on a subsequent 0->3.
     985                 :            :                  *
     986                 :            :                  * To userspace, the resulting transition will look like:
     987                 :            :                  *    2:[0,1] -> 3:[-1,-1] -> 3:[0,2]
     988                 :            :                  */
     989         [ #  # ]:          0 :                 if (priv->mt_state_lost) {
     990                 :            :                         synaptics_mt_state_set(mt_state, 3, -1, -1);
     991                 :            :                         break;
     992                 :            :                 }
     993                 :            : 
     994                 :            :                 /*
     995                 :            :                  * If the (SGM,AGM) really previously contained slots (0, 1),
     996                 :            :                  * then we cannot know what slot was just reported by the AGM,
     997                 :            :                  * because the 2->3 transition can occur either before or after
     998                 :            :                  * the AGM packet. Thus, this most recent AGM could contain
     999                 :            :                  * either the same old slot 1 or the new slot 2.
    1000                 :            :                  * Subsequent AGMs will be reporting slot 2.
    1001                 :            :                  *
    1002                 :            :                  * To userspace, the resulting transition will look like:
    1003                 :            :                  *    2:[0,1] -> 3:[0,-1] -> 3:[0,2]
    1004                 :            :                  */
    1005                 :            :                 synaptics_mt_state_set(mt_state, 3, 0, -1);
    1006                 :            :                 break;
    1007                 :            :         case 3:
    1008                 :            :                 /*
    1009                 :            :                  * If, for whatever reason, the previous agm was invalid,
    1010                 :            :                  * Assume SGM now contains slot 0, AGM now contains slot 2.
    1011                 :            :                  */
    1012         [ #  # ]:          0 :                 if (old->agm <= 2)
    1013                 :            :                         synaptics_mt_state_set(mt_state, 3, 0, 2);
    1014                 :            :                 /*
    1015                 :            :                  * mt_state either hasn't changed, or was updated by a recently
    1016                 :            :                  * received AGM-CONTACT packet.
    1017                 :            :                  */
    1018                 :            :                 break;
    1019                 :            : 
    1020                 :            :         case 4:
    1021                 :            :         case 5:
    1022                 :            :                 /* mt_state was updated by AGM-CONTACT packet */
    1023                 :            :                 break;
    1024                 :            :         }
    1025                 :          0 : }
    1026                 :            : 
    1027                 :            : /* Handle case where mt_state->count = 4, or = 5 */
    1028                 :            : static void synaptics_image_sensor_45f(struct synaptics_data *priv,
    1029                 :            :                                        struct synaptics_mt_state *mt_state)
    1030                 :            : {
    1031                 :            :         /* mt_state was updated correctly by AGM-CONTACT packet */
    1032                 :          0 :         priv->mt_state_lost = false;
    1033                 :            : }
    1034                 :            : 
    1035                 :          0 : static void synaptics_image_sensor_process(struct psmouse *psmouse,
    1036                 :            :                                            struct synaptics_hw_state *sgm)
    1037                 :            : {
    1038                 :          0 :         struct synaptics_data *priv = psmouse->private;
    1039                 :            :         struct synaptics_hw_state *agm = &priv->agm;
    1040                 :            :         struct synaptics_mt_state mt_state;
    1041                 :            : 
    1042                 :            :         /* Initialize using current mt_state (as updated by last agm) */
    1043                 :          0 :         mt_state = agm->mt_state;
    1044                 :            : 
    1045                 :            :         /*
    1046                 :            :          * Update mt_state using the new finger count and current mt_state.
    1047                 :            :          */
    1048         [ #  # ]:          0 :         if (sgm->z == 0)
    1049                 :            :                 synaptics_image_sensor_0f(priv, &mt_state);
    1050         [ #  # ]:          0 :         else if (sgm->w >= 4)
    1051                 :          0 :                 synaptics_image_sensor_1f(priv, &mt_state);
    1052         [ #  # ]:          0 :         else if (sgm->w == 0)
    1053                 :          0 :                 synaptics_image_sensor_2f(priv, &mt_state);
    1054 [ #  # ][ #  # ]:          0 :         else if (sgm->w == 1 && mt_state.count <= 3)
    1055                 :          0 :                 synaptics_image_sensor_3f(priv, &mt_state);
    1056                 :            :         else
    1057                 :            :                 synaptics_image_sensor_45f(priv, &mt_state);
    1058                 :            : 
    1059                 :            :         /* Send resulting input events to user space */
    1060                 :          0 :         synaptics_report_mt_data(psmouse, &mt_state, sgm);
    1061                 :            : 
    1062                 :            :         /* Store updated mt_state */
    1063                 :          0 :         priv->mt_state = agm->mt_state = mt_state;
    1064                 :          0 :         priv->agm_pending = false;
    1065                 :          0 : }
    1066                 :            : 
    1067                 :            : /*
    1068                 :            :  *  called for each full received packet from the touchpad
    1069                 :            :  */
    1070                 :          0 : static void synaptics_process_packet(struct psmouse *psmouse)
    1071                 :            : {
    1072                 :          0 :         struct input_dev *dev = psmouse->dev;
    1073                 :          0 :         struct synaptics_data *priv = psmouse->private;
    1074                 :            :         struct synaptics_hw_state hw;
    1075                 :            :         int num_fingers;
    1076                 :            :         int finger_width;
    1077                 :            : 
    1078         [ #  # ]:          0 :         if (synaptics_parse_hw_state(psmouse->packet, priv, &hw))
    1079                 :          0 :                 return;
    1080                 :            : 
    1081         [ #  # ]:          0 :         if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) {
    1082                 :          0 :                 synaptics_image_sensor_process(psmouse, &hw);
    1083                 :          0 :                 return;
    1084                 :            :         }
    1085                 :            : 
    1086         [ #  # ]:          0 :         if (hw.scroll) {
    1087                 :          0 :                 priv->scroll += hw.scroll;
    1088                 :            : 
    1089         [ #  # ]:          0 :                 while (priv->scroll >= 4) {
    1090                 :          0 :                         input_report_key(dev, BTN_BACK, !hw.down);
    1091                 :            :                         input_sync(dev);
    1092                 :          0 :                         input_report_key(dev, BTN_BACK, hw.down);
    1093                 :            :                         input_sync(dev);
    1094                 :          0 :                         priv->scroll -= 4;
    1095                 :            :                 }
    1096         [ #  # ]:          0 :                 while (priv->scroll <= -4) {
    1097                 :          0 :                         input_report_key(dev, BTN_FORWARD, !hw.up);
    1098                 :            :                         input_sync(dev);
    1099                 :          0 :                         input_report_key(dev, BTN_FORWARD, hw.up);
    1100                 :            :                         input_sync(dev);
    1101                 :          0 :                         priv->scroll += 4;
    1102                 :            :                 }
    1103                 :            :                 return;
    1104                 :            :         }
    1105                 :            : 
    1106 [ #  # ][ #  # ]:          0 :         if (hw.z > 0 && hw.x > 1) {
    1107                 :            :                 num_fingers = 1;
    1108                 :            :                 finger_width = 5;
    1109         [ #  # ]:          0 :                 if (SYN_CAP_EXTENDED(priv->capabilities)) {
    1110      [ #  #  # ]:          0 :                         switch (hw.w) {
    1111                 :            :                         case 0 ... 1:
    1112         [ #  # ]:          0 :                                 if (SYN_CAP_MULTIFINGER(priv->capabilities))
    1113                 :          0 :                                         num_fingers = hw.w + 2;
    1114                 :            :                                 break;
    1115                 :            :                         case 2:
    1116                 :            :                                 if (SYN_MODEL_PEN(priv->model_id))
    1117                 :            :                                         ;   /* Nothing, treat a pen as a single finger */
    1118                 :            :                                 break;
    1119                 :            :                         case 4 ... 15:
    1120         [ #  # ]:          0 :                                 if (SYN_CAP_PALMDETECT(priv->capabilities))
    1121                 :            :                                         finger_width = hw.w;
    1122                 :            :                                 break;
    1123                 :            :                         }
    1124                 :            :                 }
    1125                 :            :         } else {
    1126                 :            :                 num_fingers = 0;
    1127                 :            :                 finger_width = 0;
    1128                 :            :         }
    1129                 :            : 
    1130         [ #  # ]:          0 :         if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
    1131                 :          0 :                 synaptics_report_semi_mt_data(dev, &hw, &priv->agm,
    1132                 :            :                                               num_fingers);
    1133                 :            : 
    1134                 :            :         /* Post events
    1135                 :            :          * BTN_TOUCH has to be first as mousedev relies on it when doing
    1136                 :            :          * absolute -> relative conversion
    1137                 :            :          */
    1138         [ #  # ]:          0 :         if (hw.z > 30) input_report_key(dev, BTN_TOUCH, 1);
    1139         [ #  # ]:          0 :         if (hw.z < 25) input_report_key(dev, BTN_TOUCH, 0);
    1140                 :            : 
    1141         [ #  # ]:          0 :         if (num_fingers > 0) {
    1142                 :          0 :                 input_report_abs(dev, ABS_X, hw.x);
    1143                 :          0 :                 input_report_abs(dev, ABS_Y, synaptics_invert_y(hw.y));
    1144                 :            :         }
    1145                 :          0 :         input_report_abs(dev, ABS_PRESSURE, hw.z);
    1146                 :            : 
    1147         [ #  # ]:          0 :         if (SYN_CAP_PALMDETECT(priv->capabilities))
    1148                 :            :                 input_report_abs(dev, ABS_TOOL_WIDTH, finger_width);
    1149                 :            : 
    1150                 :          0 :         input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1);
    1151         [ #  # ]:          0 :         if (SYN_CAP_MULTIFINGER(priv->capabilities)) {
    1152                 :          0 :                 input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2);
    1153                 :          0 :                 input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3);
    1154                 :            :         }
    1155                 :            : 
    1156                 :          0 :         synaptics_report_buttons(psmouse, &hw);
    1157                 :            : 
    1158                 :            :         input_sync(dev);
    1159                 :            : }
    1160                 :            : 
    1161                 :          0 : static int synaptics_validate_byte(struct psmouse *psmouse,
    1162                 :            :                                    int idx, unsigned char pkt_type)
    1163                 :            : {
    1164                 :            :         static const unsigned char newabs_mask[]        = { 0xC8, 0x00, 0x00, 0xC8, 0x00 };
    1165                 :            :         static const unsigned char newabs_rel_mask[]    = { 0xC0, 0x00, 0x00, 0xC0, 0x00 };
    1166                 :            :         static const unsigned char newabs_rslt[]        = { 0x80, 0x00, 0x00, 0xC0, 0x00 };
    1167                 :            :         static const unsigned char oldabs_mask[]        = { 0xC0, 0x60, 0x00, 0xC0, 0x60 };
    1168                 :            :         static const unsigned char oldabs_rslt[]        = { 0xC0, 0x00, 0x00, 0x80, 0x00 };
    1169                 :          0 :         const char *packet = psmouse->packet;
    1170                 :            : 
    1171         [ #  # ]:          0 :         if (idx < 0 || idx > 4)
    1172                 :            :                 return 0;
    1173                 :            : 
    1174   [ #  #  #  # ]:          0 :         switch (pkt_type) {
    1175                 :            : 
    1176                 :            :         case SYN_NEWABS:
    1177                 :            :         case SYN_NEWABS_RELAXED:
    1178                 :          0 :                 return (packet[idx] & newabs_rel_mask[idx]) == newabs_rslt[idx];
    1179                 :            : 
    1180                 :            :         case SYN_NEWABS_STRICT:
    1181                 :          0 :                 return (packet[idx] & newabs_mask[idx]) == newabs_rslt[idx];
    1182                 :            : 
    1183                 :            :         case SYN_OLDABS:
    1184                 :          0 :                 return (packet[idx] & oldabs_mask[idx]) == oldabs_rslt[idx];
    1185                 :            : 
    1186                 :            :         default:
    1187                 :          0 :                 psmouse_err(psmouse, "unknown packet type %d\n", pkt_type);
    1188                 :          0 :                 return 0;
    1189                 :            :         }
    1190                 :            : }
    1191                 :            : 
    1192                 :          0 : static unsigned char synaptics_detect_pkt_type(struct psmouse *psmouse)
    1193                 :            : {
    1194                 :            :         int i;
    1195                 :            : 
    1196         [ #  # ]:          0 :         for (i = 0; i < 5; i++)
    1197         [ #  # ]:          0 :                 if (!synaptics_validate_byte(psmouse, i, SYN_NEWABS_STRICT)) {
    1198                 :          0 :                         psmouse_info(psmouse, "using relaxed packet validation\n");
    1199                 :          0 :                         return SYN_NEWABS_RELAXED;
    1200                 :            :                 }
    1201                 :            : 
    1202                 :            :         return SYN_NEWABS_STRICT;
    1203                 :            : }
    1204                 :            : 
    1205                 :          0 : static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse)
    1206                 :            : {
    1207                 :          0 :         struct synaptics_data *priv = psmouse->private;
    1208                 :            : 
    1209         [ #  # ]:          0 :         if (psmouse->pktcnt >= 6) { /* Full packet received */
    1210         [ #  # ]:          0 :                 if (unlikely(priv->pkt_type == SYN_NEWABS))
    1211                 :          0 :                         priv->pkt_type = synaptics_detect_pkt_type(psmouse);
    1212                 :            : 
    1213 [ #  # ][ #  # ]:          0 :                 if (SYN_CAP_PASS_THROUGH(priv->capabilities) &&
    1214                 :            :                     synaptics_is_pt_packet(psmouse->packet)) {
    1215         [ #  # ]:          0 :                         if (priv->pt_port)
    1216                 :          0 :                                 synaptics_pass_pt_packet(priv->pt_port, psmouse->packet);
    1217                 :            :                 } else
    1218                 :          0 :                         synaptics_process_packet(psmouse);
    1219                 :            : 
    1220                 :            :                 return PSMOUSE_FULL_PACKET;
    1221                 :            :         }
    1222                 :            : 
    1223                 :          0 :         return synaptics_validate_byte(psmouse, psmouse->pktcnt - 1, priv->pkt_type) ?
    1224                 :          0 :                 PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
    1225                 :            : }
    1226                 :            : 
    1227                 :            : /*****************************************************************************
    1228                 :            :  *      Driver initialization/cleanup functions
    1229                 :            :  ****************************************************************************/
    1230                 :          0 : static void set_abs_position_params(struct input_dev *dev,
    1231                 :            :                                     struct synaptics_data *priv, int x_code,
    1232                 :            :                                     int y_code)
    1233                 :            : {
    1234         [ #  # ]:          0 :         int x_min = priv->x_min ?: XMIN_NOMINAL;
    1235         [ #  # ]:          0 :         int x_max = priv->x_max ?: XMAX_NOMINAL;
    1236         [ #  # ]:          0 :         int y_min = priv->y_min ?: YMIN_NOMINAL;
    1237         [ #  # ]:          0 :         int y_max = priv->y_max ?: YMAX_NOMINAL;
    1238                 :          0 :         int fuzz = SYN_CAP_REDUCED_FILTERING(priv->ext_cap_0c) ?
    1239         [ #  # ]:          0 :                         SYN_REDUCED_FILTER_FUZZ : 0;
    1240                 :            : 
    1241                 :          0 :         input_set_abs_params(dev, x_code, x_min, x_max, fuzz, 0);
    1242                 :          0 :         input_set_abs_params(dev, y_code, y_min, y_max, fuzz, 0);
    1243                 :          0 :         input_abs_set_res(dev, x_code, priv->x_res);
    1244                 :          0 :         input_abs_set_res(dev, y_code, priv->y_res);
    1245                 :          0 : }
    1246                 :            : 
    1247                 :          0 : static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
    1248                 :            : {
    1249                 :            :         int i;
    1250                 :            : 
    1251                 :            :         /* Things that apply to both modes */
    1252                 :            :         __set_bit(INPUT_PROP_POINTER, dev->propbit);
    1253                 :            :         __set_bit(EV_KEY, dev->evbit);
    1254                 :            :         __set_bit(BTN_LEFT, dev->keybit);
    1255                 :            :         __set_bit(BTN_RIGHT, dev->keybit);
    1256                 :            : 
    1257         [ #  # ]:          0 :         if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
    1258                 :            :                 __set_bit(BTN_MIDDLE, dev->keybit);
    1259                 :            : 
    1260         [ #  # ]:          0 :         if (!priv->absolute_mode) {
    1261                 :            :                 /* Relative mode */
    1262                 :            :                 __set_bit(EV_REL, dev->evbit);
    1263                 :            :                 __set_bit(REL_X, dev->relbit);
    1264                 :            :                 __set_bit(REL_Y, dev->relbit);
    1265                 :          0 :                 return;
    1266                 :            :         }
    1267                 :            : 
    1268                 :            :         /* Absolute mode */
    1269                 :            :         __set_bit(EV_ABS, dev->evbit);
    1270                 :          0 :         set_abs_position_params(dev, priv, ABS_X, ABS_Y);
    1271                 :          0 :         input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
    1272                 :            : 
    1273         [ #  # ]:          0 :         if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) {
    1274                 :          0 :                 set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
    1275                 :            :                                         ABS_MT_POSITION_Y);
    1276                 :            :                 /* Image sensors can report per-contact pressure */
    1277                 :          0 :                 input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
    1278                 :          0 :                 input_mt_init_slots(dev, 2, INPUT_MT_POINTER);
    1279                 :            : 
    1280                 :            :                 /* Image sensors can signal 4 and 5 finger clicks */
    1281                 :            :                 __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
    1282                 :            :                 __set_bit(BTN_TOOL_QUINTTAP, dev->keybit);
    1283         [ #  # ]:          0 :         } else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
    1284                 :            :                 /* Non-image sensors with AGM use semi-mt */
    1285                 :            :                 __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
    1286                 :          0 :                 input_mt_init_slots(dev, 2, 0);
    1287                 :          0 :                 set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
    1288                 :            :                                         ABS_MT_POSITION_Y);
    1289                 :            :         }
    1290                 :            : 
    1291         [ #  # ]:          0 :         if (SYN_CAP_PALMDETECT(priv->capabilities))
    1292                 :          0 :                 input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0);
    1293                 :            : 
    1294                 :            :         __set_bit(BTN_TOUCH, dev->keybit);
    1295                 :            :         __set_bit(BTN_TOOL_FINGER, dev->keybit);
    1296                 :            : 
    1297         [ #  # ]:          0 :         if (SYN_CAP_MULTIFINGER(priv->capabilities)) {
    1298                 :            :                 __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
    1299                 :            :                 __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit);
    1300                 :            :         }
    1301                 :            : 
    1302         [ #  # ]:          0 :         if (SYN_CAP_FOUR_BUTTON(priv->capabilities) ||
    1303                 :            :             SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) {
    1304                 :            :                 __set_bit(BTN_FORWARD, dev->keybit);
    1305                 :            :                 __set_bit(BTN_BACK, dev->keybit);
    1306                 :            :         }
    1307                 :            : 
    1308         [ #  # ]:          0 :         for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
    1309                 :          0 :                 __set_bit(BTN_0 + i, dev->keybit);
    1310                 :            : 
    1311                 :            :         __clear_bit(EV_REL, dev->evbit);
    1312                 :            :         __clear_bit(REL_X, dev->relbit);
    1313                 :            :         __clear_bit(REL_Y, dev->relbit);
    1314                 :            : 
    1315         [ #  # ]:          0 :         if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
    1316                 :            :                 __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
    1317                 :            :                 /* Clickpads report only left button */
    1318                 :            :                 __clear_bit(BTN_RIGHT, dev->keybit);
    1319                 :            :                 __clear_bit(BTN_MIDDLE, dev->keybit);
    1320                 :            :         }
    1321                 :            : }
    1322                 :            : 
    1323                 :          0 : static ssize_t synaptics_show_disable_gesture(struct psmouse *psmouse,
    1324                 :            :                                               void *data, char *buf)
    1325                 :            : {
    1326                 :          0 :         struct synaptics_data *priv = psmouse->private;
    1327                 :            : 
    1328         [ #  # ]:          0 :         return sprintf(buf, "%c\n", priv->disable_gesture ? '1' : '0');
    1329                 :            : }
    1330                 :            : 
    1331                 :          0 : static ssize_t synaptics_set_disable_gesture(struct psmouse *psmouse,
    1332                 :            :                                              void *data, const char *buf,
    1333                 :            :                                              size_t len)
    1334                 :            : {
    1335                 :          0 :         struct synaptics_data *priv = psmouse->private;
    1336                 :            :         unsigned int value;
    1337                 :            :         int err;
    1338                 :            : 
    1339                 :          0 :         err = kstrtouint(buf, 10, &value);
    1340         [ #  # ]:          0 :         if (err)
    1341                 :            :                 return err;
    1342                 :            : 
    1343         [ #  # ]:          0 :         if (value > 1)
    1344                 :            :                 return -EINVAL;
    1345                 :            : 
    1346         [ #  # ]:          0 :         if (value == priv->disable_gesture)
    1347                 :          0 :                 return len;
    1348                 :            : 
    1349                 :          0 :         priv->disable_gesture = value;
    1350         [ #  # ]:          0 :         if (value)
    1351                 :          0 :                 priv->mode |= SYN_BIT_DISABLE_GESTURE;
    1352                 :            :         else
    1353                 :          0 :                 priv->mode &= ~SYN_BIT_DISABLE_GESTURE;
    1354                 :            : 
    1355         [ #  # ]:          0 :         if (synaptics_mode_cmd(psmouse, priv->mode))
    1356                 :            :                 return -EIO;
    1357                 :            : 
    1358                 :          0 :         return len;
    1359                 :            : }
    1360                 :            : 
    1361                 :            : PSMOUSE_DEFINE_ATTR(disable_gesture, S_IWUSR | S_IRUGO, NULL,
    1362                 :            :                     synaptics_show_disable_gesture,
    1363                 :            :                     synaptics_set_disable_gesture);
    1364                 :            : 
    1365                 :          0 : static void synaptics_disconnect(struct psmouse *psmouse)
    1366                 :            : {
    1367                 :          0 :         struct synaptics_data *priv = psmouse->private;
    1368                 :            : 
    1369 [ #  # ][ #  # ]:          0 :         if (!priv->absolute_mode && SYN_ID_DISGEST_SUPPORTED(priv->identity))
    1370                 :          0 :                 device_remove_file(&psmouse->ps2dev.serio->dev,
    1371                 :            :                                    &psmouse_attr_disable_gesture.dattr);
    1372                 :            : 
    1373                 :            :         synaptics_reset(psmouse);
    1374                 :          0 :         kfree(priv);
    1375                 :          0 :         psmouse->private = NULL;
    1376                 :          0 : }
    1377                 :            : 
    1378                 :          0 : static int synaptics_reconnect(struct psmouse *psmouse)
    1379                 :            : {
    1380                 :          0 :         struct synaptics_data *priv = psmouse->private;
    1381                 :          0 :         struct synaptics_data old_priv = *priv;
    1382                 :            :         unsigned char param[2];
    1383                 :            :         int retry = 0;
    1384                 :            :         int error;
    1385                 :            : 
    1386                 :            :         do {
    1387                 :          0 :                 psmouse_reset(psmouse);
    1388         [ #  # ]:          0 :                 if (retry) {
    1389                 :            :                         /*
    1390                 :            :                          * On some boxes, right after resuming, the touchpad
    1391                 :            :                          * needs some time to finish initializing (I assume
    1392                 :            :                          * it needs time to calibrate) and start responding
    1393                 :            :                          * to Synaptics-specific queries, so let's wait a
    1394                 :            :                          * bit.
    1395                 :            :                          */
    1396                 :            :                         ssleep(1);
    1397                 :            :                 }
    1398                 :          0 :                 ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETID);
    1399                 :          0 :                 error = synaptics_detect(psmouse, 0);
    1400 [ #  # ][ #  # ]:          0 :         } while (error && ++retry < 3);
    1401                 :            : 
    1402         [ #  # ]:          0 :         if (error)
    1403                 :            :                 return -1;
    1404                 :            : 
    1405                 :            :         if (retry > 1)
    1406                 :            :                 psmouse_dbg(psmouse, "reconnected after %d tries\n", retry);
    1407                 :            : 
    1408         [ #  # ]:          0 :         if (synaptics_query_hardware(psmouse)) {
    1409                 :          0 :                 psmouse_err(psmouse, "Unable to query device.\n");
    1410                 :          0 :                 return -1;
    1411                 :            :         }
    1412                 :            : 
    1413         [ #  # ]:          0 :         if (synaptics_set_mode(psmouse)) {
    1414                 :          0 :                 psmouse_err(psmouse, "Unable to initialize device.\n");
    1415                 :          0 :                 return -1;
    1416                 :            :         }
    1417                 :            : 
    1418 [ #  # ][ #  # ]:          0 :         if (old_priv.identity != priv->identity ||
    1419         [ #  # ]:          0 :             old_priv.model_id != priv->model_id ||
    1420         [ #  # ]:          0 :             old_priv.capabilities != priv->capabilities ||
    1421                 :          0 :             old_priv.ext_cap != priv->ext_cap) {
    1422                 :          0 :                 psmouse_err(psmouse,
    1423                 :            :                             "hardware appears to be different: id(%ld-%ld), model(%ld-%ld), caps(%lx-%lx), ext(%lx-%lx).\n",
    1424                 :            :                             old_priv.identity, priv->identity,
    1425                 :            :                             old_priv.model_id, priv->model_id,
    1426                 :            :                             old_priv.capabilities, priv->capabilities,
    1427                 :            :                             old_priv.ext_cap, priv->ext_cap);
    1428                 :          0 :                 return -1;
    1429                 :            :         }
    1430                 :            : 
    1431                 :            :         return 0;
    1432                 :            : }
    1433                 :            : 
    1434                 :            : static bool impaired_toshiba_kbc;
    1435                 :            : 
    1436                 :            : static const struct dmi_system_id toshiba_dmi_table[] __initconst = {
    1437                 :            : #if defined(CONFIG_DMI) && defined(CONFIG_X86)
    1438                 :            :         {
    1439                 :            :                 /* Toshiba Satellite */
    1440                 :            :                 .matches = {
    1441                 :            :                         DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
    1442                 :            :                         DMI_MATCH(DMI_PRODUCT_NAME, "Satellite"),
    1443                 :            :                 },
    1444                 :            :         },
    1445                 :            :         {
    1446                 :            :                 /* Toshiba Dynabook */
    1447                 :            :                 .matches = {
    1448                 :            :                         DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
    1449                 :            :                         DMI_MATCH(DMI_PRODUCT_NAME, "dynabook"),
    1450                 :            :                 },
    1451                 :            :         },
    1452                 :            :         {
    1453                 :            :                 /* Toshiba Portege M300 */
    1454                 :            :                 .matches = {
    1455                 :            :                         DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
    1456                 :            :                         DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M300"),
    1457                 :            :                 },
    1458                 :            : 
    1459                 :            :         },
    1460                 :            :         {
    1461                 :            :                 /* Toshiba Portege M300 */
    1462                 :            :                 .matches = {
    1463                 :            :                         DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
    1464                 :            :                         DMI_MATCH(DMI_PRODUCT_NAME, "Portable PC"),
    1465                 :            :                         DMI_MATCH(DMI_PRODUCT_VERSION, "Version 1.0"),
    1466                 :            :                 },
    1467                 :            : 
    1468                 :            :         },
    1469                 :            : #endif
    1470                 :            :         { }
    1471                 :            : };
    1472                 :            : 
    1473                 :            : static bool broken_olpc_ec;
    1474                 :            : 
    1475                 :            : static const struct dmi_system_id olpc_dmi_table[] __initconst = {
    1476                 :            : #if defined(CONFIG_DMI) && defined(CONFIG_OLPC)
    1477                 :            :         {
    1478                 :            :                 /* OLPC XO-1 or XO-1.5 */
    1479                 :            :                 .matches = {
    1480                 :            :                         DMI_MATCH(DMI_SYS_VENDOR, "OLPC"),
    1481                 :            :                         DMI_MATCH(DMI_PRODUCT_NAME, "XO"),
    1482                 :            :                 },
    1483                 :            :         },
    1484                 :            : #endif
    1485                 :            :         { }
    1486                 :            : };
    1487                 :            : 
    1488                 :          0 : void __init synaptics_module_init(void)
    1489                 :            : {
    1490                 :          0 :         impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table);
    1491                 :          0 :         broken_olpc_ec = dmi_check_system(olpc_dmi_table);
    1492                 :          0 : }
    1493                 :            : 
    1494                 :          0 : static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode)
    1495                 :            : {
    1496                 :            :         struct synaptics_data *priv;
    1497                 :            :         int err = -1;
    1498                 :            : 
    1499                 :            :         /*
    1500                 :            :          * The OLPC XO has issues with Synaptics' absolute mode; the constant
    1501                 :            :          * packet spew overloads the EC such that key presses on the keyboard
    1502                 :            :          * are missed.  Given that, don't even attempt to use Absolute mode.
    1503                 :            :          * Relative mode seems to work just fine.
    1504                 :            :          */
    1505 [ #  # ][ #  # ]:          0 :         if (absolute_mode && broken_olpc_ec) {
    1506                 :          0 :                 psmouse_info(psmouse,
    1507                 :            :                              "OLPC XO detected, not enabling Synaptics protocol.\n");
    1508                 :          0 :                 return -ENODEV;
    1509                 :            :         }
    1510                 :            : 
    1511                 :          0 :         psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL);
    1512         [ #  # ]:          0 :         if (!priv)
    1513                 :            :                 return -ENOMEM;
    1514                 :            : 
    1515                 :          0 :         psmouse_reset(psmouse);
    1516                 :            : 
    1517         [ #  # ]:          0 :         if (synaptics_query_hardware(psmouse)) {
    1518                 :          0 :                 psmouse_err(psmouse, "Unable to query device.\n");
    1519                 :          0 :                 goto init_fail;
    1520                 :            :         }
    1521                 :            : 
    1522                 :          0 :         priv->absolute_mode = absolute_mode;
    1523         [ #  # ]:          0 :         if (SYN_ID_DISGEST_SUPPORTED(priv->identity))
    1524                 :          0 :                 priv->disable_gesture = true;
    1525                 :            : 
    1526         [ #  # ]:          0 :         if (synaptics_set_mode(psmouse)) {
    1527                 :          0 :                 psmouse_err(psmouse, "Unable to initialize device.\n");
    1528                 :          0 :                 goto init_fail;
    1529                 :            :         }
    1530                 :            : 
    1531         [ #  # ]:          0 :         priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS;
    1532                 :            : 
    1533                 :          0 :         psmouse_info(psmouse,
    1534                 :            :                      "Touchpad model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx, board id: %lu, fw id: %lu\n",
    1535                 :            :                      SYN_ID_MODEL(priv->identity),
    1536                 :            :                      SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
    1537                 :            :                      priv->model_id,
    1538                 :            :                      priv->capabilities, priv->ext_cap, priv->ext_cap_0c,
    1539                 :            :                      priv->board_id, priv->firmware_id);
    1540                 :            : 
    1541                 :          0 :         set_input_params(psmouse->dev, priv);
    1542                 :            : 
    1543                 :            :         /*
    1544                 :            :          * Encode touchpad model so that it can be used to set
    1545                 :            :          * input device->id.version and be visible to userspace.
    1546                 :            :          * Because version is __u16 we have to drop something.
    1547                 :            :          * Hardware info bits seem to be good candidates as they
    1548                 :            :          * are documented to be for Synaptics corp. internal use.
    1549                 :            :          */
    1550                 :          0 :         psmouse->model = ((priv->model_id & 0x00ff0000) >> 8) |
    1551                 :          0 :                           (priv->model_id & 0x000000ff);
    1552                 :            : 
    1553         [ #  # ]:          0 :         if (absolute_mode) {
    1554                 :          0 :                 psmouse->protocol_handler = synaptics_process_byte;
    1555                 :          0 :                 psmouse->pktsize = 6;
    1556                 :            :         } else {
    1557                 :            :                 /* Relative mode follows standard PS/2 mouse protocol */
    1558                 :          0 :                 psmouse->protocol_handler = psmouse_process_byte;
    1559                 :          0 :                 psmouse->pktsize = 3;
    1560                 :            :         }
    1561                 :            : 
    1562                 :          0 :         psmouse->set_rate = synaptics_set_rate;
    1563                 :          0 :         psmouse->disconnect = synaptics_disconnect;
    1564                 :          0 :         psmouse->reconnect = synaptics_reconnect;
    1565                 :          0 :         psmouse->cleanup = synaptics_reset;
    1566                 :            :         /* Synaptics can usually stay in sync without extra help */
    1567                 :          0 :         psmouse->resync_time = 0;
    1568                 :            : 
    1569         [ #  # ]:          0 :         if (SYN_CAP_PASS_THROUGH(priv->capabilities))
    1570                 :          0 :                 synaptics_pt_create(psmouse);
    1571                 :            : 
    1572                 :            :         /*
    1573                 :            :          * Toshiba's KBC seems to have trouble handling data from
    1574                 :            :          * Synaptics at full rate.  Switch to a lower rate (roughly
    1575                 :            :          * the same rate as a standard PS/2 mouse).
    1576                 :            :          */
    1577 [ #  # ][ #  # ]:          0 :         if (psmouse->rate >= 80 && impaired_toshiba_kbc) {
    1578                 :          0 :                 psmouse_info(psmouse,
    1579                 :            :                              "Toshiba %s detected, limiting rate to 40pps.\n",
    1580                 :            :                              dmi_get_system_info(DMI_PRODUCT_NAME));
    1581                 :          0 :                 psmouse->rate = 40;
    1582                 :            :         }
    1583                 :            : 
    1584 [ #  # ][ #  # ]:          0 :         if (!priv->absolute_mode && SYN_ID_DISGEST_SUPPORTED(priv->identity)) {
    1585                 :          0 :                 err = device_create_file(&psmouse->ps2dev.serio->dev,
    1586                 :            :                                          &psmouse_attr_disable_gesture.dattr);
    1587         [ #  # ]:          0 :                 if (err) {
    1588                 :          0 :                         psmouse_err(psmouse,
    1589                 :            :                                     "Failed to create disable_gesture attribute (%d)",
    1590                 :            :                                     err);
    1591                 :          0 :                         goto init_fail;
    1592                 :            :                 }
    1593                 :            :         }
    1594                 :            : 
    1595                 :            :         return 0;
    1596                 :            : 
    1597                 :            :  init_fail:
    1598                 :          0 :         kfree(priv);
    1599                 :          0 :         return err;
    1600                 :            : }
    1601                 :            : 
    1602                 :          0 : int synaptics_init(struct psmouse *psmouse)
    1603                 :            : {
    1604                 :          0 :         return __synaptics_init(psmouse, true);
    1605                 :            : }
    1606                 :            : 
    1607                 :          0 : int synaptics_init_relative(struct psmouse *psmouse)
    1608                 :            : {
    1609                 :          0 :         return __synaptics_init(psmouse, false);
    1610                 :            : }
    1611                 :            : 
    1612                 :          0 : bool synaptics_supported(void)
    1613                 :            : {
    1614                 :          0 :         return true;
    1615                 :            : }
    1616                 :            : 
    1617                 :            : #else /* CONFIG_MOUSE_PS2_SYNAPTICS */
    1618                 :            : 
    1619                 :            : void __init synaptics_module_init(void)
    1620                 :            : {
    1621                 :            : }
    1622                 :            : 
    1623                 :            : int synaptics_init(struct psmouse *psmouse)
    1624                 :            : {
    1625                 :            :         return -ENOSYS;
    1626                 :            : }
    1627                 :            : 
    1628                 :            : bool synaptics_supported(void)
    1629                 :            : {
    1630                 :            :         return false;
    1631                 :            : }
    1632                 :            : 
    1633                 :            : #endif /* CONFIG_MOUSE_PS2_SYNAPTICS */

Generated by: LCOV version 1.9