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

Generated by: LCOV version 1.9