LCOV - code coverage report
Current view: top level - drivers/input/mouse - alps.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 25 1478 1.7 %
Date: 2022-04-01 13:59:58 Functions: 3 72 4.2 %
Branches: 14 892 1.6 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /*
       3                 :            :  * ALPS touchpad PS/2 mouse driver
       4                 :            :  *
       5                 :            :  * Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au>
       6                 :            :  * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com>
       7                 :            :  * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru>
       8                 :            :  * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
       9                 :            :  * Copyright (c) 2009 Sebastian Kapfer <sebastian_kapfer@gmx.net>
      10                 :            :  *
      11                 :            :  * ALPS detection, tap switching and status querying info is taken from
      12                 :            :  * tpconfig utility (by C. Scott Ananian and Bruce Kall).
      13                 :            :  */
      14                 :            : 
      15                 :            : #include <linux/slab.h>
      16                 :            : #include <linux/input.h>
      17                 :            : #include <linux/input/mt.h>
      18                 :            : #include <linux/serio.h>
      19                 :            : #include <linux/libps2.h>
      20                 :            : #include <linux/dmi.h>
      21                 :            : 
      22                 :            : #include "psmouse.h"
      23                 :            : #include "alps.h"
      24                 :            : #include "trackpoint.h"
      25                 :            : 
      26                 :            : /*
      27                 :            :  * Definitions for ALPS version 3 and 4 command mode protocol
      28                 :            :  */
      29                 :            : #define ALPS_CMD_NIBBLE_10      0x01f2
      30                 :            : 
      31                 :            : #define ALPS_REG_BASE_RUSHMORE  0xc2c0
      32                 :            : #define ALPS_REG_BASE_V7        0xc2c0
      33                 :            : #define ALPS_REG_BASE_PINNACLE  0x0000
      34                 :            : 
      35                 :            : static const struct alps_nibble_commands alps_v3_nibble_commands[] = {
      36                 :            :         { PSMOUSE_CMD_SETPOLL,          0x00 }, /* 0 */
      37                 :            :         { PSMOUSE_CMD_RESET_DIS,        0x00 }, /* 1 */
      38                 :            :         { PSMOUSE_CMD_SETSCALE21,       0x00 }, /* 2 */
      39                 :            :         { PSMOUSE_CMD_SETRATE,          0x0a }, /* 3 */
      40                 :            :         { PSMOUSE_CMD_SETRATE,          0x14 }, /* 4 */
      41                 :            :         { PSMOUSE_CMD_SETRATE,          0x28 }, /* 5 */
      42                 :            :         { PSMOUSE_CMD_SETRATE,          0x3c }, /* 6 */
      43                 :            :         { PSMOUSE_CMD_SETRATE,          0x50 }, /* 7 */
      44                 :            :         { PSMOUSE_CMD_SETRATE,          0x64 }, /* 8 */
      45                 :            :         { PSMOUSE_CMD_SETRATE,          0xc8 }, /* 9 */
      46                 :            :         { ALPS_CMD_NIBBLE_10,           0x00 }, /* a */
      47                 :            :         { PSMOUSE_CMD_SETRES,           0x00 }, /* b */
      48                 :            :         { PSMOUSE_CMD_SETRES,           0x01 }, /* c */
      49                 :            :         { PSMOUSE_CMD_SETRES,           0x02 }, /* d */
      50                 :            :         { PSMOUSE_CMD_SETRES,           0x03 }, /* e */
      51                 :            :         { PSMOUSE_CMD_SETSCALE11,       0x00 }, /* f */
      52                 :            : };
      53                 :            : 
      54                 :            : static const struct alps_nibble_commands alps_v4_nibble_commands[] = {
      55                 :            :         { PSMOUSE_CMD_ENABLE,           0x00 }, /* 0 */
      56                 :            :         { PSMOUSE_CMD_RESET_DIS,        0x00 }, /* 1 */
      57                 :            :         { PSMOUSE_CMD_SETSCALE21,       0x00 }, /* 2 */
      58                 :            :         { PSMOUSE_CMD_SETRATE,          0x0a }, /* 3 */
      59                 :            :         { PSMOUSE_CMD_SETRATE,          0x14 }, /* 4 */
      60                 :            :         { PSMOUSE_CMD_SETRATE,          0x28 }, /* 5 */
      61                 :            :         { PSMOUSE_CMD_SETRATE,          0x3c }, /* 6 */
      62                 :            :         { PSMOUSE_CMD_SETRATE,          0x50 }, /* 7 */
      63                 :            :         { PSMOUSE_CMD_SETRATE,          0x64 }, /* 8 */
      64                 :            :         { PSMOUSE_CMD_SETRATE,          0xc8 }, /* 9 */
      65                 :            :         { ALPS_CMD_NIBBLE_10,           0x00 }, /* a */
      66                 :            :         { PSMOUSE_CMD_SETRES,           0x00 }, /* b */
      67                 :            :         { PSMOUSE_CMD_SETRES,           0x01 }, /* c */
      68                 :            :         { PSMOUSE_CMD_SETRES,           0x02 }, /* d */
      69                 :            :         { PSMOUSE_CMD_SETRES,           0x03 }, /* e */
      70                 :            :         { PSMOUSE_CMD_SETSCALE11,       0x00 }, /* f */
      71                 :            : };
      72                 :            : 
      73                 :            : static const struct alps_nibble_commands alps_v6_nibble_commands[] = {
      74                 :            :         { PSMOUSE_CMD_ENABLE,           0x00 }, /* 0 */
      75                 :            :         { PSMOUSE_CMD_SETRATE,          0x0a }, /* 1 */
      76                 :            :         { PSMOUSE_CMD_SETRATE,          0x14 }, /* 2 */
      77                 :            :         { PSMOUSE_CMD_SETRATE,          0x28 }, /* 3 */
      78                 :            :         { PSMOUSE_CMD_SETRATE,          0x3c }, /* 4 */
      79                 :            :         { PSMOUSE_CMD_SETRATE,          0x50 }, /* 5 */
      80                 :            :         { PSMOUSE_CMD_SETRATE,          0x64 }, /* 6 */
      81                 :            :         { PSMOUSE_CMD_SETRATE,          0xc8 }, /* 7 */
      82                 :            :         { PSMOUSE_CMD_GETID,            0x00 }, /* 8 */
      83                 :            :         { PSMOUSE_CMD_GETINFO,          0x00 }, /* 9 */
      84                 :            :         { PSMOUSE_CMD_SETRES,           0x00 }, /* a */
      85                 :            :         { PSMOUSE_CMD_SETRES,           0x01 }, /* b */
      86                 :            :         { PSMOUSE_CMD_SETRES,           0x02 }, /* c */
      87                 :            :         { PSMOUSE_CMD_SETRES,           0x03 }, /* d */
      88                 :            :         { PSMOUSE_CMD_SETSCALE21,       0x00 }, /* e */
      89                 :            :         { PSMOUSE_CMD_SETSCALE11,       0x00 }, /* f */
      90                 :            : };
      91                 :            : 
      92                 :            : 
      93                 :            : #define ALPS_DUALPOINT          0x02    /* touchpad has trackstick */
      94                 :            : #define ALPS_PASS               0x04    /* device has a pass-through port */
      95                 :            : 
      96                 :            : #define ALPS_WHEEL              0x08    /* hardware wheel present */
      97                 :            : #define ALPS_FW_BK_1            0x10    /* front & back buttons present */
      98                 :            : #define ALPS_FW_BK_2            0x20    /* front & back buttons present */
      99                 :            : #define ALPS_FOUR_BUTTONS       0x40    /* 4 direction button present */
     100                 :            : #define ALPS_PS2_INTERLEAVED    0x80    /* 3-byte PS/2 packet interleaved with
     101                 :            :                                            6-byte ALPS packet */
     102                 :            : #define ALPS_STICK_BITS         0x100   /* separate stick button bits */
     103                 :            : #define ALPS_BUTTONPAD          0x200   /* device is a clickpad */
     104                 :            : #define ALPS_DUALPOINT_WITH_PRESSURE    0x400   /* device can report trackpoint pressure */
     105                 :            : 
     106                 :            : static const struct alps_model_info alps_model_data[] = {
     107                 :            :         /*
     108                 :            :          * XXX This entry is suspicious. First byte has zero lower nibble,
     109                 :            :          * which is what a normal mouse would report. Also, the value 0x0e
     110                 :            :          * isn't valid per PS/2 spec.
     111                 :            :          */
     112                 :            :         { { 0x20, 0x02, 0x0e }, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } },
     113                 :            : 
     114                 :            :         { { 0x22, 0x02, 0x0a }, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } },
     115                 :            :         { { 0x22, 0x02, 0x14 }, { ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT } },    /* Dell Latitude D600 */
     116                 :            :         { { 0x32, 0x02, 0x14 }, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } },    /* Toshiba Salellite Pro M10 */
     117                 :            :         { { 0x33, 0x02, 0x0a }, { ALPS_PROTO_V1, 0x88, 0xf8, 0 } },                             /* UMAX-530T */
     118                 :            :         { { 0x52, 0x01, 0x14 }, { ALPS_PROTO_V2, 0xff, 0xff,
     119                 :            :                 ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED } },                          /* Toshiba Tecra A11-11L */
     120                 :            :         { { 0x53, 0x02, 0x0a }, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
     121                 :            :         { { 0x53, 0x02, 0x14 }, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
     122                 :            :         { { 0x60, 0x03, 0xc8 }, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },                             /* HP ze1115 */
     123                 :            :         { { 0x62, 0x02, 0x14 }, { ALPS_PROTO_V2, 0xcf, 0xcf,
     124                 :            :                 ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED } },                          /* Dell Latitude E5500, E6400, E6500, Precision M4400 */
     125                 :            :         { { 0x63, 0x02, 0x0a }, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
     126                 :            :         { { 0x63, 0x02, 0x14 }, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
     127                 :            :         { { 0x63, 0x02, 0x28 }, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 } },                  /* Fujitsu Siemens S6010 */
     128                 :            :         { { 0x63, 0x02, 0x3c }, { ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL } },                    /* Toshiba Satellite S2400-103 */
     129                 :            :         { { 0x63, 0x02, 0x50 }, { ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 } },                  /* NEC Versa L320 */
     130                 :            :         { { 0x63, 0x02, 0x64 }, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
     131                 :            :         { { 0x63, 0x03, 0xc8 }, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } },    /* Dell Latitude D800 */
     132                 :            :         { { 0x73, 0x00, 0x0a }, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT } },                /* ThinkPad R61 8918-5QG */
     133                 :            :         { { 0x73, 0x00, 0x14 }, { ALPS_PROTO_V6, 0xff, 0xff, ALPS_DUALPOINT } },                /* Dell XT2 */
     134                 :            :         { { 0x73, 0x02, 0x0a }, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
     135                 :            :         { { 0x73, 0x02, 0x14 }, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 } },                  /* Ahtec Laptop */
     136                 :            :         { { 0x73, 0x02, 0x50 }, { ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS } },             /* Dell Vostro 1400 */
     137                 :            : };
     138                 :            : 
     139                 :            : static const struct alps_protocol_info alps_v3_protocol_data = {
     140                 :            :         ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT | ALPS_DUALPOINT_WITH_PRESSURE
     141                 :            : };
     142                 :            : 
     143                 :            : static const struct alps_protocol_info alps_v3_rushmore_data = {
     144                 :            :         ALPS_PROTO_V3_RUSHMORE, 0x8f, 0x8f, ALPS_DUALPOINT | ALPS_DUALPOINT_WITH_PRESSURE
     145                 :            : };
     146                 :            : 
     147                 :            : static const struct alps_protocol_info alps_v4_protocol_data = {
     148                 :            :         ALPS_PROTO_V4, 0x8f, 0x8f, 0
     149                 :            : };
     150                 :            : 
     151                 :            : static const struct alps_protocol_info alps_v5_protocol_data = {
     152                 :            :         ALPS_PROTO_V5, 0xc8, 0xd8, 0
     153                 :            : };
     154                 :            : 
     155                 :            : static const struct alps_protocol_info alps_v7_protocol_data = {
     156                 :            :         ALPS_PROTO_V7, 0x48, 0x48, ALPS_DUALPOINT | ALPS_DUALPOINT_WITH_PRESSURE
     157                 :            : };
     158                 :            : 
     159                 :            : static const struct alps_protocol_info alps_v8_protocol_data = {
     160                 :            :         ALPS_PROTO_V8, 0x18, 0x18, 0
     161                 :            : };
     162                 :            : 
     163                 :            : static const struct alps_protocol_info alps_v9_protocol_data = {
     164                 :            :         ALPS_PROTO_V9, 0xc8, 0xc8, 0
     165                 :            : };
     166                 :            : 
     167                 :            : /*
     168                 :            :  * Some v2 models report the stick buttons in separate bits
     169                 :            :  */
     170                 :            : static const struct dmi_system_id alps_dmi_has_separate_stick_buttons[] = {
     171                 :            : #if defined(CONFIG_DMI) && defined(CONFIG_X86)
     172                 :            :         {
     173                 :            :                 /* Extrapolated from other entries */
     174                 :            :                 .matches = {
     175                 :            :                         DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
     176                 :            :                         DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D420"),
     177                 :            :                 },
     178                 :            :         },
     179                 :            :         {
     180                 :            :                 /* Reported-by: Hans de Bruin <jmdebruin@xmsnet.nl> */
     181                 :            :                 .matches = {
     182                 :            :                         DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
     183                 :            :                         DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D430"),
     184                 :            :                 },
     185                 :            :         },
     186                 :            :         {
     187                 :            :                 /* Reported-by: Hans de Goede <hdegoede@redhat.com> */
     188                 :            :                 .matches = {
     189                 :            :                         DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
     190                 :            :                         DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D620"),
     191                 :            :                 },
     192                 :            :         },
     193                 :            :         {
     194                 :            :                 /* Extrapolated from other entries */
     195                 :            :                 .matches = {
     196                 :            :                         DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
     197                 :            :                         DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D630"),
     198                 :            :                 },
     199                 :            :         },
     200                 :            : #endif
     201                 :            :         { }
     202                 :            : };
     203                 :            : 
     204                 :            : static void alps_set_abs_params_st(struct alps_data *priv,
     205                 :            :                                    struct input_dev *dev1);
     206                 :            : static void alps_set_abs_params_semi_mt(struct alps_data *priv,
     207                 :            :                                         struct input_dev *dev1);
     208                 :            : static void alps_set_abs_params_v7(struct alps_data *priv,
     209                 :            :                                    struct input_dev *dev1);
     210                 :            : static void alps_set_abs_params_ss4_v2(struct alps_data *priv,
     211                 :            :                                        struct input_dev *dev1);
     212                 :            : 
     213                 :            : /* Packet formats are described in Documentation/input/devices/alps.rst */
     214                 :            : 
     215                 :          0 : static bool alps_is_valid_first_byte(struct alps_data *priv,
     216                 :            :                                      unsigned char data)
     217                 :            : {
     218                 :          0 :         return (data & priv->mask0) == priv->byte0;
     219                 :            : }
     220                 :            : 
     221                 :          0 : static void alps_report_buttons(struct input_dev *dev1, struct input_dev *dev2,
     222                 :            :                                 int left, int right, int middle)
     223                 :            : {
     224                 :          0 :         struct input_dev *dev;
     225                 :            : 
     226                 :            :         /*
     227                 :            :          * If shared button has already been reported on the
     228                 :            :          * other device (dev2) then this event should be also
     229                 :            :          * sent through that device.
     230                 :            :          */
     231   [ #  #  #  # ]:          0 :         dev = (dev2 && test_bit(BTN_LEFT, dev2->key)) ? dev2 : dev1;
     232                 :          0 :         input_report_key(dev, BTN_LEFT, left);
     233                 :            : 
     234   [ #  #  #  # ]:          0 :         dev = (dev2 && test_bit(BTN_RIGHT, dev2->key)) ? dev2 : dev1;
     235                 :          0 :         input_report_key(dev, BTN_RIGHT, right);
     236                 :            : 
     237   [ #  #  #  # ]:          0 :         dev = (dev2 && test_bit(BTN_MIDDLE, dev2->key)) ? dev2 : dev1;
     238                 :          0 :         input_report_key(dev, BTN_MIDDLE, middle);
     239                 :            : 
     240                 :            :         /*
     241                 :            :          * Sync the _other_ device now, we'll do the first
     242                 :            :          * device later once we report the rest of the events.
     243                 :            :          */
     244         [ #  # ]:          0 :         if (dev2)
     245                 :          0 :                 input_sync(dev2);
     246                 :          0 : }
     247                 :            : 
     248                 :          0 : static void alps_process_packet_v1_v2(struct psmouse *psmouse)
     249                 :            : {
     250                 :          0 :         struct alps_data *priv = psmouse->private;
     251                 :          0 :         unsigned char *packet = psmouse->packet;
     252                 :          0 :         struct input_dev *dev = psmouse->dev;
     253                 :          0 :         struct input_dev *dev2 = priv->dev2;
     254                 :          0 :         int x, y, z, ges, fin, left, right, middle;
     255                 :          0 :         int back = 0, forward = 0;
     256                 :            : 
     257         [ #  # ]:          0 :         if (priv->proto_version == ALPS_PROTO_V1) {
     258                 :          0 :                 left = packet[2] & 0x10;
     259                 :          0 :                 right = packet[2] & 0x08;
     260                 :          0 :                 middle = 0;
     261                 :          0 :                 x = packet[1] | ((packet[0] & 0x07) << 7);
     262                 :          0 :                 y = packet[4] | ((packet[3] & 0x07) << 7);
     263                 :          0 :                 z = packet[5];
     264                 :            :         } else {
     265                 :          0 :                 left = packet[3] & 1;
     266                 :          0 :                 right = packet[3] & 2;
     267                 :          0 :                 middle = packet[3] & 4;
     268                 :          0 :                 x = packet[1] | ((packet[2] & 0x78) << (7 - 3));
     269                 :          0 :                 y = packet[4] | ((packet[3] & 0x70) << (7 - 4));
     270                 :          0 :                 z = packet[5];
     271                 :            :         }
     272                 :            : 
     273         [ #  # ]:          0 :         if (priv->flags & ALPS_FW_BK_1) {
     274                 :          0 :                 back = packet[0] & 0x10;
     275                 :          0 :                 forward = packet[2] & 4;
     276                 :            :         }
     277                 :            : 
     278         [ #  # ]:          0 :         if (priv->flags & ALPS_FW_BK_2) {
     279                 :          0 :                 back = packet[3] & 4;
     280                 :          0 :                 forward = packet[2] & 4;
     281         [ #  # ]:          0 :                 if ((middle = forward && back))
     282                 :          0 :                         forward = back = 0;
     283                 :            :         }
     284                 :            : 
     285                 :          0 :         ges = packet[2] & 1;
     286                 :          0 :         fin = packet[2] & 2;
     287                 :            : 
     288   [ #  #  #  # ]:          0 :         if ((priv->flags & ALPS_DUALPOINT) && z == 127) {
     289         [ #  # ]:          0 :                 input_report_rel(dev2, REL_X,  (x > 383 ? (x - 768) : x));
     290         [ #  # ]:          0 :                 input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y));
     291                 :            : 
     292                 :          0 :                 alps_report_buttons(dev2, dev, left, right, middle);
     293                 :            : 
     294                 :          0 :                 input_sync(dev2);
     295                 :          0 :                 return;
     296                 :            :         }
     297                 :            : 
     298                 :            :         /* Some models have separate stick button bits */
     299         [ #  # ]:          0 :         if (priv->flags & ALPS_STICK_BITS) {
     300                 :          0 :                 left |= packet[0] & 1;
     301                 :          0 :                 right |= packet[0] & 2;
     302                 :          0 :                 middle |= packet[0] & 4;
     303                 :            :         }
     304                 :            : 
     305                 :          0 :         alps_report_buttons(dev, dev2, left, right, middle);
     306                 :            : 
     307                 :            :         /* Convert hardware tap to a reasonable Z value */
     308         [ #  # ]:          0 :         if (ges && !fin)
     309                 :          0 :                 z = 40;
     310                 :            : 
     311                 :            :         /*
     312                 :            :          * A "tap and drag" operation is reported by the hardware as a transition
     313                 :            :          * from (!fin && ges) to (fin && ges). This should be translated to the
     314                 :            :          * sequence Z>0, Z==0, Z>0, so the Z==0 event has to be generated manually.
     315                 :            :          */
     316   [ #  #  #  # ]:          0 :         if (ges && fin && !priv->prev_fin) {
     317                 :          0 :                 input_report_abs(dev, ABS_X, x);
     318                 :          0 :                 input_report_abs(dev, ABS_Y, y);
     319                 :          0 :                 input_report_abs(dev, ABS_PRESSURE, 0);
     320                 :          0 :                 input_report_key(dev, BTN_TOOL_FINGER, 0);
     321                 :          0 :                 input_sync(dev);
     322                 :            :         }
     323                 :          0 :         priv->prev_fin = fin;
     324                 :            : 
     325         [ #  # ]:          0 :         if (z > 30)
     326                 :          0 :                 input_report_key(dev, BTN_TOUCH, 1);
     327         [ #  # ]:          0 :         if (z < 25)
     328                 :          0 :                 input_report_key(dev, BTN_TOUCH, 0);
     329                 :            : 
     330         [ #  # ]:          0 :         if (z > 0) {
     331                 :          0 :                 input_report_abs(dev, ABS_X, x);
     332                 :          0 :                 input_report_abs(dev, ABS_Y, y);
     333                 :            :         }
     334                 :            : 
     335                 :          0 :         input_report_abs(dev, ABS_PRESSURE, z);
     336                 :          0 :         input_report_key(dev, BTN_TOOL_FINGER, z > 0);
     337                 :            : 
     338         [ #  # ]:          0 :         if (priv->flags & ALPS_WHEEL)
     339                 :          0 :                 input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07));
     340                 :            : 
     341         [ #  # ]:          0 :         if (priv->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
     342                 :          0 :                 input_report_key(dev, BTN_FORWARD, forward);
     343                 :          0 :                 input_report_key(dev, BTN_BACK, back);
     344                 :            :         }
     345                 :            : 
     346         [ #  # ]:          0 :         if (priv->flags & ALPS_FOUR_BUTTONS) {
     347                 :          0 :                 input_report_key(dev, BTN_0, packet[2] & 4);
     348                 :          0 :                 input_report_key(dev, BTN_1, packet[0] & 0x10);
     349                 :          0 :                 input_report_key(dev, BTN_2, packet[3] & 4);
     350                 :          0 :                 input_report_key(dev, BTN_3, packet[0] & 0x20);
     351                 :            :         }
     352                 :            : 
     353                 :          0 :         input_sync(dev);
     354                 :            : }
     355                 :            : 
     356                 :            : static void alps_get_bitmap_points(unsigned int map,
     357                 :            :                                    struct alps_bitmap_point *low,
     358                 :            :                                    struct alps_bitmap_point *high,
     359                 :            :                                    int *fingers)
     360                 :            : {
     361                 :            :         struct alps_bitmap_point *point;
     362                 :            :         int i, bit, prev_bit = 0;
     363                 :            : 
     364                 :            :         point = low;
     365   [ #  #  #  # ]:          0 :         for (i = 0; map != 0; i++, map >>= 1) {
     366                 :          0 :                 bit = map & 1;
     367   [ #  #  #  # ]:          0 :                 if (bit) {
     368   [ #  #  #  # ]:          0 :                         if (!prev_bit) {
     369                 :          0 :                                 point->start_bit = i;
     370                 :          0 :                                 point->num_bits = 0;
     371                 :          0 :                                 (*fingers)++;
     372                 :            :                         }
     373                 :          0 :                         point->num_bits++;
     374                 :            :                 } else {
     375   [ #  #  #  # ]:          0 :                         if (prev_bit)
     376                 :          0 :                                 point = high;
     377                 :            :                 }
     378                 :          0 :                 prev_bit = bit;
     379                 :            :         }
     380                 :            : }
     381                 :            : 
     382                 :            : /*
     383                 :            :  * Process bitmap data from semi-mt protocols. Returns the number of
     384                 :            :  * fingers detected. A return value of 0 means at least one of the
     385                 :            :  * bitmaps was empty.
     386                 :            :  *
     387                 :            :  * The bitmaps don't have enough data to track fingers, so this function
     388                 :            :  * only generates points representing a bounding box of all contacts.
     389                 :            :  * These points are returned in fields->mt when the return value
     390                 :            :  * is greater than 0.
     391                 :            :  */
     392                 :          0 : static int alps_process_bitmap(struct alps_data *priv,
     393                 :            :                                struct alps_fields *fields)
     394                 :            : {
     395                 :          0 :         int i, fingers_x = 0, fingers_y = 0, fingers, closest;
     396                 :          0 :         struct alps_bitmap_point x_low = {0,}, x_high = {0,};
     397                 :          0 :         struct alps_bitmap_point y_low = {0,}, y_high = {0,};
     398                 :          0 :         struct input_mt_pos corner[4];
     399                 :            : 
     400   [ #  #  #  # ]:          0 :         if (!fields->x_map || !fields->y_map)
     401                 :            :                 return 0;
     402                 :            : 
     403                 :            :         alps_get_bitmap_points(fields->x_map, &x_low, &x_high, &fingers_x);
     404                 :            :         alps_get_bitmap_points(fields->y_map, &y_low, &y_high, &fingers_y);
     405                 :            : 
     406                 :            :         /*
     407                 :            :          * Fingers can overlap, so we use the maximum count of fingers
     408                 :            :          * on either axis as the finger count.
     409                 :            :          */
     410                 :          0 :         fingers = max(fingers_x, fingers_y);
     411                 :            : 
     412                 :            :         /*
     413                 :            :          * If an axis reports only a single contact, we have overlapping or
     414                 :            :          * adjacent fingers. Divide the single contact between the two points.
     415                 :            :          */
     416         [ #  # ]:          0 :         if (fingers_x == 1) {
     417                 :          0 :                 i = (x_low.num_bits - 1) / 2;
     418                 :          0 :                 x_low.num_bits = x_low.num_bits - i;
     419                 :          0 :                 x_high.start_bit = x_low.start_bit + i;
     420                 :          0 :                 x_high.num_bits = max(i, 1);
     421                 :            :         }
     422         [ #  # ]:          0 :         if (fingers_y == 1) {
     423                 :          0 :                 i = (y_low.num_bits - 1) / 2;
     424                 :          0 :                 y_low.num_bits = y_low.num_bits - i;
     425                 :          0 :                 y_high.start_bit = y_low.start_bit + i;
     426                 :          0 :                 y_high.num_bits = max(i, 1);
     427                 :            :         }
     428                 :            : 
     429                 :            :         /* top-left corner */
     430                 :          0 :         corner[0].x =
     431                 :          0 :                 (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) /
     432                 :          0 :                 (2 * (priv->x_bits - 1));
     433                 :          0 :         corner[0].y =
     434                 :          0 :                 (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) /
     435                 :          0 :                 (2 * (priv->y_bits - 1));
     436                 :            : 
     437                 :            :         /* top-right corner */
     438                 :          0 :         corner[1].x =
     439                 :          0 :                 (priv->x_max * (2 * x_high.start_bit + x_high.num_bits - 1)) /
     440                 :            :                 (2 * (priv->x_bits - 1));
     441                 :          0 :         corner[1].y =
     442                 :            :                 (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) /
     443                 :            :                 (2 * (priv->y_bits - 1));
     444                 :            : 
     445                 :            :         /* bottom-right corner */
     446                 :          0 :         corner[2].x =
     447                 :            :                 (priv->x_max * (2 * x_high.start_bit + x_high.num_bits - 1)) /
     448                 :            :                 (2 * (priv->x_bits - 1));
     449                 :          0 :         corner[2].y =
     450                 :          0 :                 (priv->y_max * (2 * y_high.start_bit + y_high.num_bits - 1)) /
     451                 :            :                 (2 * (priv->y_bits - 1));
     452                 :            : 
     453                 :            :         /* bottom-left corner */
     454                 :          0 :         corner[3].x =
     455                 :            :                 (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) /
     456                 :            :                 (2 * (priv->x_bits - 1));
     457                 :          0 :         corner[3].y =
     458                 :            :                 (priv->y_max * (2 * y_high.start_bit + y_high.num_bits - 1)) /
     459                 :            :                 (2 * (priv->y_bits - 1));
     460                 :            : 
     461                 :            :         /* x-bitmap order is reversed on v5 touchpads  */
     462         [ #  # ]:          0 :         if (priv->proto_version == ALPS_PROTO_V5) {
     463         [ #  # ]:          0 :                 for (i = 0; i < 4; i++)
     464                 :          0 :                         corner[i].x = priv->x_max - corner[i].x;
     465                 :            :         }
     466                 :            : 
     467                 :            :         /* y-bitmap order is reversed on v3 and v4 touchpads  */
     468         [ #  # ]:          0 :         if (priv->proto_version == ALPS_PROTO_V3 ||
     469                 :            :             priv->proto_version == ALPS_PROTO_V4) {
     470         [ #  # ]:          0 :                 for (i = 0; i < 4; i++)
     471                 :          0 :                         corner[i].y = priv->y_max - corner[i].y;
     472                 :            :         }
     473                 :            : 
     474                 :            :         /*
     475                 :            :          * We only select a corner for the second touch once per 2 finger
     476                 :            :          * touch sequence to avoid the chosen corner (and thus the coordinates)
     477                 :            :          * jumping around when the first touch is in the middle.
     478                 :            :          */
     479         [ #  # ]:          0 :         if (priv->second_touch == -1) {
     480                 :            :                 /* Find corner closest to our st coordinates */
     481                 :            :                 closest = 0x7fffffff;
     482         [ #  # ]:          0 :                 for (i = 0; i < 4; i++) {
     483                 :          0 :                         int dx = fields->st.x - corner[i].x;
     484                 :          0 :                         int dy = fields->st.y - corner[i].y;
     485                 :          0 :                         int distance = dx * dx + dy * dy;
     486                 :            : 
     487         [ #  # ]:          0 :                         if (distance < closest) {
     488                 :          0 :                                 priv->second_touch = i;
     489                 :          0 :                                 closest = distance;
     490                 :            :                         }
     491                 :            :                 }
     492                 :            :                 /* And select the opposite corner to use for the 2nd touch */
     493                 :          0 :                 priv->second_touch = (priv->second_touch + 2) % 4;
     494                 :            :         }
     495                 :            : 
     496                 :          0 :         fields->mt[0] = fields->st;
     497                 :          0 :         fields->mt[1] = corner[priv->second_touch];
     498                 :            : 
     499                 :          0 :         return fingers;
     500                 :            : }
     501                 :            : 
     502                 :          0 : static void alps_set_slot(struct input_dev *dev, int slot, int x, int y)
     503                 :            : {
     504                 :          0 :         input_mt_slot(dev, slot);
     505                 :          0 :         input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
     506                 :          0 :         input_report_abs(dev, ABS_MT_POSITION_X, x);
     507                 :          0 :         input_report_abs(dev, ABS_MT_POSITION_Y, y);
     508                 :          0 : }
     509                 :            : 
     510                 :            : static void alps_report_mt_data(struct psmouse *psmouse, int n)
     511                 :            : {
     512                 :            :         struct alps_data *priv = psmouse->private;
     513                 :            :         struct input_dev *dev = psmouse->dev;
     514                 :            :         struct alps_fields *f = &priv->f;
     515                 :            :         int i, slot[MAX_TOUCHES];
     516                 :            : 
     517                 :            :         input_mt_assign_slots(dev, slot, f->mt, n, 0);
     518                 :            :         for (i = 0; i < n; i++)
     519                 :            :                 alps_set_slot(dev, slot[i], f->mt[i].x, f->mt[i].y);
     520                 :            : 
     521                 :            :         input_mt_sync_frame(dev);
     522                 :            : }
     523                 :            : 
     524                 :            : static void alps_report_semi_mt_data(struct psmouse *psmouse, int fingers)
     525                 :            : {
     526                 :            :         struct alps_data *priv = psmouse->private;
     527                 :            :         struct input_dev *dev = psmouse->dev;
     528                 :            :         struct alps_fields *f = &priv->f;
     529                 :            : 
     530                 :            :         /* Use st data when we don't have mt data */
     531                 :            :         if (fingers < 2) {
     532                 :            :                 f->mt[0].x = f->st.x;
     533                 :            :                 f->mt[0].y = f->st.y;
     534                 :            :                 fingers = f->pressure > 0 ? 1 : 0;
     535                 :            :                 priv->second_touch = -1;
     536                 :            :         }
     537                 :            : 
     538                 :            :         if (fingers >= 1)
     539                 :            :                 alps_set_slot(dev, 0, f->mt[0].x, f->mt[0].y);
     540                 :            :         if (fingers >= 2)
     541                 :            :                 alps_set_slot(dev, 1, f->mt[1].x, f->mt[1].y);
     542                 :            :         input_mt_sync_frame(dev);
     543                 :            : 
     544                 :            :         input_mt_report_finger_count(dev, fingers);
     545                 :            : 
     546                 :            :         input_report_key(dev, BTN_LEFT, f->left);
     547                 :            :         input_report_key(dev, BTN_RIGHT, f->right);
     548                 :            :         input_report_key(dev, BTN_MIDDLE, f->middle);
     549                 :            : 
     550                 :            :         input_report_abs(dev, ABS_PRESSURE, f->pressure);
     551                 :            : 
     552                 :            :         input_sync(dev);
     553                 :            : }
     554                 :            : 
     555                 :          0 : static void alps_process_trackstick_packet_v3(struct psmouse *psmouse)
     556                 :            : {
     557                 :          0 :         struct alps_data *priv = psmouse->private;
     558                 :          0 :         unsigned char *packet = psmouse->packet;
     559                 :          0 :         struct input_dev *dev = priv->dev2;
     560                 :          0 :         int x, y, z, left, right, middle;
     561                 :            : 
     562                 :            :         /* It should be a DualPoint when received trackstick packet */
     563         [ #  # ]:          0 :         if (!(priv->flags & ALPS_DUALPOINT)) {
     564                 :          0 :                 psmouse_warn(psmouse,
     565                 :            :                              "Rejected trackstick packet from non DualPoint device");
     566                 :          0 :                 return;
     567                 :            :         }
     568                 :            : 
     569                 :            :         /* Sanity check packet */
     570         [ #  # ]:          0 :         if (!(packet[0] & 0x40)) {
     571                 :            :                 psmouse_dbg(psmouse, "Bad trackstick packet, discarding\n");
     572                 :            :                 return;
     573                 :            :         }
     574                 :            : 
     575                 :            :         /*
     576                 :            :          * There's a special packet that seems to indicate the end
     577                 :            :          * of a stream of trackstick data. Filter these out.
     578                 :            :          */
     579   [ #  #  #  #  :          0 :         if (packet[1] == 0x7f && packet[2] == 0x7f && packet[4] == 0x7f)
                   #  # ]
     580                 :            :                 return;
     581                 :            : 
     582                 :          0 :         x = (s8)(((packet[0] & 0x20) << 2) | (packet[1] & 0x7f));
     583                 :          0 :         y = (s8)(((packet[0] & 0x10) << 3) | (packet[2] & 0x7f));
     584                 :          0 :         z = packet[4] & 0x7f;
     585                 :            : 
     586                 :            :         /*
     587                 :            :          * The x and y values tend to be quite large, and when used
     588                 :            :          * alone the trackstick is difficult to use. Scale them down
     589                 :            :          * to compensate.
     590                 :            :          */
     591                 :          0 :         x /= 8;
     592                 :          0 :         y /= 8;
     593                 :            : 
     594                 :          0 :         input_report_rel(dev, REL_X, x);
     595                 :          0 :         input_report_rel(dev, REL_Y, -y);
     596                 :          0 :         input_report_abs(dev, ABS_PRESSURE, z);
     597                 :            : 
     598                 :            :         /*
     599                 :            :          * Most ALPS models report the trackstick buttons in the touchpad
     600                 :            :          * packets, but a few report them here. No reliable way has been
     601                 :            :          * found to differentiate between the models upfront, so we enable
     602                 :            :          * the quirk in response to seeing a button press in the trackstick
     603                 :            :          * packet.
     604                 :            :          */
     605                 :          0 :         left = packet[3] & 0x01;
     606                 :          0 :         right = packet[3] & 0x02;
     607                 :          0 :         middle = packet[3] & 0x04;
     608                 :            : 
     609   [ #  #  #  # ]:          0 :         if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) &&
     610                 :            :             (left || right || middle))
     611                 :          0 :                 priv->quirks |= ALPS_QUIRK_TRACKSTICK_BUTTONS;
     612                 :            : 
     613         [ #  # ]:          0 :         if (priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) {
     614                 :          0 :                 input_report_key(dev, BTN_LEFT, left);
     615                 :          0 :                 input_report_key(dev, BTN_RIGHT, right);
     616                 :          0 :                 input_report_key(dev, BTN_MIDDLE, middle);
     617                 :            :         }
     618                 :            : 
     619                 :          0 :         input_sync(dev);
     620                 :            :         return;
     621                 :            : }
     622                 :            : 
     623                 :          0 : static void alps_decode_buttons_v3(struct alps_fields *f, unsigned char *p)
     624                 :            : {
     625                 :          0 :         f->left = !!(p[3] & 0x01);
     626                 :          0 :         f->right = !!(p[3] & 0x02);
     627                 :          0 :         f->middle = !!(p[3] & 0x04);
     628                 :            : 
     629                 :          0 :         f->ts_left = !!(p[3] & 0x10);
     630                 :          0 :         f->ts_right = !!(p[3] & 0x20);
     631                 :          0 :         f->ts_middle = !!(p[3] & 0x40);
     632                 :          0 : }
     633                 :            : 
     634                 :          0 : static int alps_decode_pinnacle(struct alps_fields *f, unsigned char *p,
     635                 :            :                                  struct psmouse *psmouse)
     636                 :            : {
     637                 :          0 :         f->first_mp = !!(p[4] & 0x40);
     638                 :          0 :         f->is_mp = !!(p[0] & 0x40);
     639                 :            : 
     640         [ #  # ]:          0 :         if (f->is_mp) {
     641                 :          0 :                 f->fingers = (p[5] & 0x3) + 1;
     642                 :          0 :                 f->x_map = ((p[4] & 0x7e) << 8) |
     643                 :          0 :                            ((p[1] & 0x7f) << 2) |
     644                 :          0 :                            ((p[0] & 0x30) >> 4);
     645                 :          0 :                 f->y_map = ((p[3] & 0x70) << 4) |
     646                 :          0 :                            ((p[2] & 0x7f) << 1) |
     647                 :          0 :                            (p[4] & 0x01);
     648                 :            :         } else {
     649                 :          0 :                 f->st.x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) |
     650                 :          0 :                        ((p[0] & 0x30) >> 4);
     651                 :          0 :                 f->st.y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f);
     652                 :          0 :                 f->pressure = p[5] & 0x7f;
     653                 :            : 
     654                 :          0 :                 alps_decode_buttons_v3(f, p);
     655                 :            :         }
     656                 :            : 
     657                 :          0 :         return 0;
     658                 :            : }
     659                 :            : 
     660                 :          0 : static int alps_decode_rushmore(struct alps_fields *f, unsigned char *p,
     661                 :            :                                  struct psmouse *psmouse)
     662                 :            : {
     663                 :          0 :         f->first_mp = !!(p[4] & 0x40);
     664                 :          0 :         f->is_mp = !!(p[5] & 0x40);
     665                 :            : 
     666         [ #  # ]:          0 :         if (f->is_mp) {
     667                 :          0 :                 f->fingers = max((p[5] & 0x3), ((p[5] >> 2) & 0x3)) + 1;
     668                 :          0 :                 f->x_map = ((p[5] & 0x10) << 11) |
     669                 :          0 :                            ((p[4] & 0x7e) << 8) |
     670                 :          0 :                            ((p[1] & 0x7f) << 2) |
     671                 :          0 :                            ((p[0] & 0x30) >> 4);
     672                 :          0 :                 f->y_map = ((p[5] & 0x20) << 6) |
     673                 :          0 :                            ((p[3] & 0x70) << 4) |
     674                 :          0 :                            ((p[2] & 0x7f) << 1) |
     675                 :          0 :                            (p[4] & 0x01);
     676                 :            :         } else {
     677                 :          0 :                 f->st.x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) |
     678                 :          0 :                        ((p[0] & 0x30) >> 4);
     679                 :          0 :                 f->st.y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f);
     680                 :          0 :                 f->pressure = p[5] & 0x7f;
     681                 :            : 
     682                 :          0 :                 alps_decode_buttons_v3(f, p);
     683                 :            :         }
     684                 :            : 
     685                 :          0 :         return 0;
     686                 :            : }
     687                 :            : 
     688                 :          0 : static int alps_decode_dolphin(struct alps_fields *f, unsigned char *p,
     689                 :            :                                 struct psmouse *psmouse)
     690                 :            : {
     691                 :          0 :         u64 palm_data = 0;
     692                 :          0 :         struct alps_data *priv = psmouse->private;
     693                 :            : 
     694                 :          0 :         f->first_mp = !!(p[0] & 0x02);
     695                 :          0 :         f->is_mp = !!(p[0] & 0x20);
     696                 :            : 
     697         [ #  # ]:          0 :         if (!f->is_mp) {
     698                 :          0 :                 f->st.x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7));
     699                 :          0 :                 f->st.y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3));
     700         [ #  # ]:          0 :                 f->pressure = (p[0] & 4) ? 0 : p[5] & 0x7f;
     701                 :          0 :                 alps_decode_buttons_v3(f, p);
     702                 :            :         } else {
     703                 :          0 :                 f->fingers = ((p[0] & 0x6) >> 1 |
     704                 :          0 :                      (p[0] & 0x10) >> 2);
     705                 :            : 
     706                 :          0 :                 palm_data = (p[1] & 0x7f) |
     707                 :          0 :                             ((p[2] & 0x7f) << 7) |
     708                 :          0 :                             ((p[4] & 0x7f) << 14) |
     709                 :          0 :                             ((p[5] & 0x7f) << 21) |
     710                 :          0 :                             ((p[3] & 0x07) << 28) |
     711                 :          0 :                             (((u64)p[3] & 0x70) << 27) |
     712                 :          0 :                             (((u64)p[0] & 0x01) << 34);
     713                 :            : 
     714                 :            :                 /* Y-profile is stored in P(0) to p(n-1), n = y_bits; */
     715                 :          0 :                 f->y_map = palm_data & (BIT(priv->y_bits) - 1);
     716                 :            : 
     717                 :            :                 /* X-profile is stored in p(n) to p(n+m-1), m = x_bits; */
     718                 :          0 :                 f->x_map = (palm_data >> priv->y_bits) &
     719                 :          0 :                            (BIT(priv->x_bits) - 1);
     720                 :            :         }
     721                 :            : 
     722                 :          0 :         return 0;
     723                 :            : }
     724                 :            : 
     725                 :          0 : static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
     726                 :            : {
     727                 :          0 :         struct alps_data *priv = psmouse->private;
     728                 :          0 :         unsigned char *packet = psmouse->packet;
     729                 :          0 :         struct input_dev *dev2 = priv->dev2;
     730                 :          0 :         struct alps_fields *f = &priv->f;
     731                 :          0 :         int fingers = 0;
     732                 :            : 
     733                 :          0 :         memset(f, 0, sizeof(*f));
     734                 :            : 
     735                 :          0 :         priv->decode_fields(f, packet, psmouse);
     736                 :            : 
     737                 :            :         /*
     738                 :            :          * There's no single feature of touchpad position and bitmap packets
     739                 :            :          * that can be used to distinguish between them. We rely on the fact
     740                 :            :          * that a bitmap packet should always follow a position packet with
     741                 :            :          * bit 6 of packet[4] set.
     742                 :            :          */
     743         [ #  # ]:          0 :         if (priv->multi_packet) {
     744                 :            :                 /*
     745                 :            :                  * Sometimes a position packet will indicate a multi-packet
     746                 :            :                  * sequence, but then what follows is another position
     747                 :            :                  * packet. Check for this, and when it happens process the
     748                 :            :                  * position packet as usual.
     749                 :            :                  */
     750         [ #  # ]:          0 :                 if (f->is_mp) {
     751                 :          0 :                         fingers = f->fingers;
     752                 :            :                         /*
     753                 :            :                          * Bitmap processing uses position packet's coordinate
     754                 :            :                          * data, so we need to do decode it first.
     755                 :            :                          */
     756                 :          0 :                         priv->decode_fields(f, priv->multi_data, psmouse);
     757         [ #  # ]:          0 :                         if (alps_process_bitmap(priv, f) == 0)
     758                 :          0 :                                 fingers = 0; /* Use st data */
     759                 :            :                 } else {
     760                 :          0 :                         priv->multi_packet = 0;
     761                 :            :                 }
     762                 :            :         }
     763                 :            : 
     764                 :            :         /*
     765                 :            :          * Bit 6 of byte 0 is not usually set in position packets. The only
     766                 :            :          * times it seems to be set is in situations where the data is
     767                 :            :          * suspect anyway, e.g. a palm resting flat on the touchpad. Given
     768                 :            :          * this combined with the fact that this bit is useful for filtering
     769                 :            :          * out misidentified bitmap packets, we reject anything with this
     770                 :            :          * bit set.
     771                 :            :          */
     772         [ #  # ]:          0 :         if (f->is_mp)
     773                 :            :                 return;
     774                 :            : 
     775   [ #  #  #  # ]:          0 :         if (!priv->multi_packet && f->first_mp) {
     776                 :          0 :                 priv->multi_packet = 1;
     777                 :          0 :                 memcpy(priv->multi_data, packet, sizeof(priv->multi_data));
     778                 :          0 :                 return;
     779                 :            :         }
     780                 :            : 
     781                 :          0 :         priv->multi_packet = 0;
     782                 :            : 
     783                 :            :         /*
     784                 :            :          * Sometimes the hardware sends a single packet with z = 0
     785                 :            :          * in the middle of a stream. Real releases generate packets
     786                 :            :          * with x, y, and z all zero, so these seem to be flukes.
     787                 :            :          * Ignore them.
     788                 :            :          */
     789   [ #  #  #  #  :          0 :         if (f->st.x && f->st.y && !f->pressure)
                   #  # ]
     790                 :            :                 return;
     791                 :            : 
     792                 :          0 :         alps_report_semi_mt_data(psmouse, fingers);
     793                 :            : 
     794         [ #  # ]:          0 :         if ((priv->flags & ALPS_DUALPOINT) &&
     795         [ #  # ]:          0 :             !(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) {
     796                 :          0 :                 input_report_key(dev2, BTN_LEFT, f->ts_left);
     797                 :          0 :                 input_report_key(dev2, BTN_RIGHT, f->ts_right);
     798                 :          0 :                 input_report_key(dev2, BTN_MIDDLE, f->ts_middle);
     799                 :          0 :                 input_sync(dev2);
     800                 :            :         }
     801                 :            : }
     802                 :            : 
     803                 :          0 : static void alps_process_packet_v3(struct psmouse *psmouse)
     804                 :            : {
     805                 :          0 :         unsigned char *packet = psmouse->packet;
     806                 :            : 
     807                 :            :         /*
     808                 :            :          * v3 protocol packets come in three types, two representing
     809                 :            :          * touchpad data and one representing trackstick data.
     810                 :            :          * Trackstick packets seem to be distinguished by always
     811                 :            :          * having 0x3f in the last byte. This value has never been
     812                 :            :          * observed in the last byte of either of the other types
     813                 :            :          * of packets.
     814                 :            :          */
     815         [ #  # ]:          0 :         if (packet[5] == 0x3f) {
     816                 :          0 :                 alps_process_trackstick_packet_v3(psmouse);
     817                 :          0 :                 return;
     818                 :            :         }
     819                 :            : 
     820                 :          0 :         alps_process_touchpad_packet_v3_v5(psmouse);
     821                 :            : }
     822                 :            : 
     823                 :          0 : static void alps_process_packet_v6(struct psmouse *psmouse)
     824                 :            : {
     825                 :          0 :         struct alps_data *priv = psmouse->private;
     826                 :          0 :         unsigned char *packet = psmouse->packet;
     827                 :          0 :         struct input_dev *dev = psmouse->dev;
     828                 :          0 :         struct input_dev *dev2 = priv->dev2;
     829                 :          0 :         int x, y, z;
     830                 :            : 
     831                 :            :         /*
     832                 :            :          * We can use Byte5 to distinguish if the packet is from Touchpad
     833                 :            :          * or Trackpoint.
     834                 :            :          * Touchpad:    0 - 0x7E
     835                 :            :          * Trackpoint:  0x7F
     836                 :            :          */
     837         [ #  # ]:          0 :         if (packet[5] == 0x7F) {
     838                 :            :                 /* It should be a DualPoint when received Trackpoint packet */
     839         [ #  # ]:          0 :                 if (!(priv->flags & ALPS_DUALPOINT)) {
     840                 :          0 :                         psmouse_warn(psmouse,
     841                 :            :                                      "Rejected trackstick packet from non DualPoint device");
     842                 :          0 :                         return;
     843                 :            :                 }
     844                 :            : 
     845                 :            :                 /* Trackpoint packet */
     846                 :          0 :                 x = packet[1] | ((packet[3] & 0x20) << 2);
     847                 :          0 :                 y = packet[2] | ((packet[3] & 0x40) << 1);
     848                 :          0 :                 z = packet[4];
     849                 :            : 
     850                 :            :                 /* To prevent the cursor jump when finger lifted */
     851   [ #  #  #  # ]:          0 :                 if (x == 0x7F && y == 0x7F && z == 0x7F)
     852                 :          0 :                         x = y = z = 0;
     853                 :            : 
     854                 :            :                 /* Divide 4 since trackpoint's speed is too fast */
     855                 :          0 :                 input_report_rel(dev2, REL_X, (char)x / 4);
     856                 :          0 :                 input_report_rel(dev2, REL_Y, -((char)y / 4));
     857                 :            : 
     858                 :          0 :                 psmouse_report_standard_buttons(dev2, packet[3]);
     859                 :            : 
     860                 :          0 :                 input_sync(dev2);
     861                 :          0 :                 return;
     862                 :            :         }
     863                 :            : 
     864                 :            :         /* Touchpad packet */
     865                 :          0 :         x = packet[1] | ((packet[3] & 0x78) << 4);
     866                 :          0 :         y = packet[2] | ((packet[4] & 0x78) << 4);
     867                 :          0 :         z = packet[5];
     868                 :            : 
     869         [ #  # ]:          0 :         if (z > 30)
     870                 :          0 :                 input_report_key(dev, BTN_TOUCH, 1);
     871         [ #  # ]:          0 :         if (z < 25)
     872                 :          0 :                 input_report_key(dev, BTN_TOUCH, 0);
     873                 :            : 
     874         [ #  # ]:          0 :         if (z > 0) {
     875                 :          0 :                 input_report_abs(dev, ABS_X, x);
     876                 :          0 :                 input_report_abs(dev, ABS_Y, y);
     877                 :            :         }
     878                 :            : 
     879                 :          0 :         input_report_abs(dev, ABS_PRESSURE, z);
     880                 :          0 :         input_report_key(dev, BTN_TOOL_FINGER, z > 0);
     881                 :            : 
     882                 :            :         /* v6 touchpad does not have middle button */
     883                 :          0 :         packet[3] &= ~BIT(2);
     884                 :          0 :         psmouse_report_standard_buttons(dev2, packet[3]);
     885                 :            : 
     886                 :          0 :         input_sync(dev);
     887                 :            : }
     888                 :            : 
     889                 :          0 : static void alps_process_packet_v4(struct psmouse *psmouse)
     890                 :            : {
     891                 :          0 :         struct alps_data *priv = psmouse->private;
     892                 :          0 :         unsigned char *packet = psmouse->packet;
     893                 :          0 :         struct alps_fields *f = &priv->f;
     894                 :          0 :         int offset;
     895                 :            : 
     896                 :            :         /*
     897                 :            :          * v4 has a 6-byte encoding for bitmap data, but this data is
     898                 :            :          * broken up between 3 normal packets. Use priv->multi_packet to
     899                 :            :          * track our position in the bitmap packet.
     900                 :            :          */
     901         [ #  # ]:          0 :         if (packet[6] & 0x40) {
     902                 :            :                 /* sync, reset position */
     903                 :          0 :                 priv->multi_packet = 0;
     904                 :            :         }
     905                 :            : 
     906   [ #  #  #  # ]:          0 :         if (WARN_ON_ONCE(priv->multi_packet > 2))
     907                 :            :                 return;
     908                 :            : 
     909                 :          0 :         offset = 2 * priv->multi_packet;
     910                 :          0 :         priv->multi_data[offset] = packet[6];
     911                 :          0 :         priv->multi_data[offset + 1] = packet[7];
     912                 :            : 
     913                 :          0 :         f->left = !!(packet[4] & 0x01);
     914                 :          0 :         f->right = !!(packet[4] & 0x02);
     915                 :            : 
     916                 :          0 :         f->st.x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) |
     917                 :          0 :                   ((packet[0] & 0x30) >> 4);
     918                 :          0 :         f->st.y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f);
     919                 :          0 :         f->pressure = packet[5] & 0x7f;
     920                 :            : 
     921         [ #  # ]:          0 :         if (++priv->multi_packet > 2) {
     922                 :          0 :                 priv->multi_packet = 0;
     923                 :            : 
     924                 :          0 :                 f->x_map = ((priv->multi_data[2] & 0x1f) << 10) |
     925                 :          0 :                            ((priv->multi_data[3] & 0x60) << 3) |
     926                 :          0 :                            ((priv->multi_data[0] & 0x3f) << 2) |
     927                 :          0 :                            ((priv->multi_data[1] & 0x60) >> 5);
     928                 :          0 :                 f->y_map = ((priv->multi_data[5] & 0x01) << 10) |
     929                 :          0 :                            ((priv->multi_data[3] & 0x1f) << 5) |
     930                 :          0 :                             (priv->multi_data[1] & 0x1f);
     931                 :            : 
     932                 :          0 :                 f->fingers = alps_process_bitmap(priv, f);
     933                 :            :         }
     934                 :            : 
     935                 :          0 :         alps_report_semi_mt_data(psmouse, f->fingers);
     936                 :            : }
     937                 :            : 
     938                 :          0 : static bool alps_is_valid_package_v7(struct psmouse *psmouse)
     939                 :            : {
     940   [ #  #  #  # ]:          0 :         switch (psmouse->pktcnt) {
     941                 :          0 :         case 3:
     942                 :          0 :                 return (psmouse->packet[2] & 0x40) == 0x40;
     943                 :          0 :         case 4:
     944                 :          0 :                 return (psmouse->packet[3] & 0x48) == 0x48;
     945                 :          0 :         case 6:
     946                 :          0 :                 return (psmouse->packet[5] & 0x40) == 0x00;
     947                 :            :         }
     948                 :            :         return true;
     949                 :            : }
     950                 :            : 
     951                 :          0 : static unsigned char alps_get_packet_id_v7(char *byte)
     952                 :            : {
     953                 :          0 :         unsigned char packet_id;
     954                 :            : 
     955         [ #  # ]:          0 :         if (byte[4] & 0x40)
     956                 :            :                 packet_id = V7_PACKET_ID_TWO;
     957         [ #  # ]:          0 :         else if (byte[4] & 0x01)
     958                 :            :                 packet_id = V7_PACKET_ID_MULTI;
     959   [ #  #  #  # ]:          0 :         else if ((byte[0] & 0x10) && !(byte[4] & 0x43))
     960                 :            :                 packet_id = V7_PACKET_ID_NEW;
     961   [ #  #  #  # ]:          0 :         else if (byte[1] == 0x00 && byte[4] == 0x00)
     962                 :            :                 packet_id = V7_PACKET_ID_IDLE;
     963                 :            :         else
     964                 :          0 :                 packet_id = V7_PACKET_ID_UNKNOWN;
     965                 :            : 
     966                 :          0 :         return packet_id;
     967                 :            : }
     968                 :            : 
     969                 :          0 : static void alps_get_finger_coordinate_v7(struct input_mt_pos *mt,
     970                 :            :                                           unsigned char *pkt,
     971                 :            :                                           unsigned char pkt_id)
     972                 :            : {
     973                 :          0 :         mt[0].x = ((pkt[2] & 0x80) << 4);
     974                 :          0 :         mt[0].x |= ((pkt[2] & 0x3F) << 5);
     975                 :          0 :         mt[0].x |= ((pkt[3] & 0x30) >> 1);
     976                 :          0 :         mt[0].x |= (pkt[3] & 0x07);
     977                 :          0 :         mt[0].y = (pkt[1] << 3) | (pkt[0] & 0x07);
     978                 :            : 
     979                 :          0 :         mt[1].x = ((pkt[3] & 0x80) << 4);
     980                 :          0 :         mt[1].x |= ((pkt[4] & 0x80) << 3);
     981                 :          0 :         mt[1].x |= ((pkt[4] & 0x3F) << 4);
     982                 :          0 :         mt[1].y = ((pkt[5] & 0x80) << 3);
     983                 :          0 :         mt[1].y |= ((pkt[5] & 0x3F) << 4);
     984                 :            : 
     985   [ #  #  #  # ]:          0 :         switch (pkt_id) {
     986                 :          0 :         case V7_PACKET_ID_TWO:
     987                 :          0 :                 mt[1].x &= ~0x000F;
     988                 :          0 :                 mt[1].y |= 0x000F;
     989                 :            :                 /* Detect false-postive touches where x & y report max value */
     990   [ #  #  #  # ]:          0 :                 if (mt[1].y == 0x7ff && mt[1].x == 0xff0) {
     991                 :          0 :                         mt[1].x = 0;
     992                 :            :                         /* y gets set to 0 at the end of this function */
     993                 :            :                 }
     994                 :            :                 break;
     995                 :            : 
     996                 :          0 :         case V7_PACKET_ID_MULTI:
     997                 :          0 :                 mt[1].x &= ~0x003F;
     998                 :          0 :                 mt[1].y &= ~0x0020;
     999                 :          0 :                 mt[1].y |= ((pkt[4] & 0x02) << 4);
    1000                 :          0 :                 mt[1].y |= 0x001F;
    1001                 :          0 :                 break;
    1002                 :            : 
    1003                 :          0 :         case V7_PACKET_ID_NEW:
    1004                 :          0 :                 mt[1].x &= ~0x003F;
    1005                 :          0 :                 mt[1].x |= (pkt[0] & 0x20);
    1006                 :          0 :                 mt[1].y |= 0x000F;
    1007                 :          0 :                 break;
    1008                 :            :         }
    1009                 :            : 
    1010                 :          0 :         mt[0].y = 0x7FF - mt[0].y;
    1011                 :          0 :         mt[1].y = 0x7FF - mt[1].y;
    1012                 :          0 : }
    1013                 :            : 
    1014                 :          0 : static int alps_get_mt_count(struct input_mt_pos *mt)
    1015                 :            : {
    1016                 :          0 :         int i, fingers = 0;
    1017                 :            : 
    1018   [ #  #  #  # ]:          0 :         for (i = 0; i < MAX_TOUCHES; i++) {
    1019   [ #  #  #  #  :          0 :                 if (mt[i].x != 0 || mt[i].y != 0)
             #  #  #  # ]
    1020                 :          0 :                         fingers++;
    1021                 :            :         }
    1022                 :            : 
    1023                 :          0 :         return fingers;
    1024                 :            : }
    1025                 :            : 
    1026                 :          0 : static int alps_decode_packet_v7(struct alps_fields *f,
    1027                 :            :                                   unsigned char *p,
    1028                 :            :                                   struct psmouse *psmouse)
    1029                 :            : {
    1030                 :          0 :         struct alps_data *priv = psmouse->private;
    1031                 :          0 :         unsigned char pkt_id;
    1032                 :            : 
    1033                 :          0 :         pkt_id = alps_get_packet_id_v7(p);
    1034         [ #  # ]:          0 :         if (pkt_id == V7_PACKET_ID_IDLE)
    1035                 :            :                 return 0;
    1036         [ #  # ]:          0 :         if (pkt_id == V7_PACKET_ID_UNKNOWN)
    1037                 :            :                 return -1;
    1038                 :            :         /*
    1039                 :            :          * NEW packets are send to indicate a discontinuity in the finger
    1040                 :            :          * coordinate reporting. Specifically a finger may have moved from
    1041                 :            :          * slot 0 to 1 or vice versa. INPUT_MT_TRACK takes care of this for
    1042                 :            :          * us.
    1043                 :            :          *
    1044                 :            :          * NEW packets have 3 problems:
    1045                 :            :          * 1) They do not contain middle / right button info (on non clickpads)
    1046                 :            :          *    this can be worked around by preserving the old button state
    1047                 :            :          * 2) They do not contain an accurate fingercount, and they are
    1048                 :            :          *    typically send when the number of fingers changes. We cannot use
    1049                 :            :          *    the old finger count as that may mismatch with the amount of
    1050                 :            :          *    touch coordinates we've available in the NEW packet
    1051                 :            :          * 3) Their x data for the second touch is inaccurate leading to
    1052                 :            :          *    a possible jump of the x coordinate by 16 units when the first
    1053                 :            :          *    non NEW packet comes in
    1054                 :            :          * Since problems 2 & 3 cannot be worked around, just ignore them.
    1055                 :            :          */
    1056         [ #  # ]:          0 :         if (pkt_id == V7_PACKET_ID_NEW)
    1057                 :            :                 return 1;
    1058                 :            : 
    1059                 :          0 :         alps_get_finger_coordinate_v7(f->mt, p, pkt_id);
    1060                 :            : 
    1061         [ #  # ]:          0 :         if (pkt_id == V7_PACKET_ID_TWO)
    1062                 :          0 :                 f->fingers = alps_get_mt_count(f->mt);
    1063                 :            :         else /* pkt_id == V7_PACKET_ID_MULTI */
    1064                 :          0 :                 f->fingers = 3 + (p[5] & 0x03);
    1065                 :            : 
    1066                 :          0 :         f->left = (p[0] & 0x80) >> 7;
    1067         [ #  # ]:          0 :         if (priv->flags & ALPS_BUTTONPAD) {
    1068         [ #  # ]:          0 :                 if (p[0] & 0x20)
    1069                 :          0 :                         f->fingers++;
    1070         [ #  # ]:          0 :                 if (p[0] & 0x10)
    1071                 :          0 :                         f->fingers++;
    1072                 :            :         } else {
    1073                 :          0 :                 f->right = (p[0] & 0x20) >> 5;
    1074                 :          0 :                 f->middle = (p[0] & 0x10) >> 4;
    1075                 :            :         }
    1076                 :            : 
    1077                 :            :         /* Sometimes a single touch is reported in mt[1] rather then mt[0] */
    1078   [ #  #  #  # ]:          0 :         if (f->fingers == 1 && f->mt[0].x == 0 && f->mt[0].y == 0) {
    1079                 :          0 :                 f->mt[0].x = f->mt[1].x;
    1080                 :          0 :                 f->mt[0].y = f->mt[1].y;
    1081                 :          0 :                 f->mt[1].x = 0;
    1082                 :          0 :                 f->mt[1].y = 0;
    1083                 :            :         }
    1084                 :            : 
    1085                 :            :         return 0;
    1086                 :            : }
    1087                 :            : 
    1088                 :          0 : static void alps_process_trackstick_packet_v7(struct psmouse *psmouse)
    1089                 :            : {
    1090                 :          0 :         struct alps_data *priv = psmouse->private;
    1091                 :          0 :         unsigned char *packet = psmouse->packet;
    1092                 :          0 :         struct input_dev *dev2 = priv->dev2;
    1093                 :          0 :         int x, y, z;
    1094                 :            : 
    1095                 :            :         /* It should be a DualPoint when received trackstick packet */
    1096         [ #  # ]:          0 :         if (!(priv->flags & ALPS_DUALPOINT)) {
    1097                 :          0 :                 psmouse_warn(psmouse,
    1098                 :            :                              "Rejected trackstick packet from non DualPoint device");
    1099                 :          0 :                 return;
    1100                 :            :         }
    1101                 :            : 
    1102                 :          0 :         x = ((packet[2] & 0xbf)) | ((packet[3] & 0x10) << 2);
    1103                 :          0 :         y = (packet[3] & 0x07) | (packet[4] & 0xb8) |
    1104                 :          0 :             ((packet[3] & 0x20) << 1);
    1105                 :          0 :         z = (packet[5] & 0x3f) | ((packet[3] & 0x80) >> 1);
    1106                 :            : 
    1107                 :          0 :         input_report_rel(dev2, REL_X, (char)x);
    1108                 :          0 :         input_report_rel(dev2, REL_Y, -((char)y));
    1109                 :          0 :         input_report_abs(dev2, ABS_PRESSURE, z);
    1110                 :            : 
    1111                 :          0 :         psmouse_report_standard_buttons(dev2, packet[1]);
    1112                 :            : 
    1113                 :          0 :         input_sync(dev2);
    1114                 :            : }
    1115                 :            : 
    1116                 :          0 : static void alps_process_touchpad_packet_v7(struct psmouse *psmouse)
    1117                 :            : {
    1118                 :          0 :         struct alps_data *priv = psmouse->private;
    1119                 :          0 :         struct input_dev *dev = psmouse->dev;
    1120                 :          0 :         struct alps_fields *f = &priv->f;
    1121                 :            : 
    1122                 :          0 :         memset(f, 0, sizeof(*f));
    1123                 :            : 
    1124         [ #  # ]:          0 :         if (priv->decode_fields(f, psmouse->packet, psmouse))
    1125                 :            :                 return;
    1126                 :            : 
    1127                 :          0 :         alps_report_mt_data(psmouse, alps_get_mt_count(f->mt));
    1128                 :            : 
    1129                 :          0 :         input_mt_report_finger_count(dev, f->fingers);
    1130                 :            : 
    1131                 :          0 :         input_report_key(dev, BTN_LEFT, f->left);
    1132                 :          0 :         input_report_key(dev, BTN_RIGHT, f->right);
    1133                 :          0 :         input_report_key(dev, BTN_MIDDLE, f->middle);
    1134                 :            : 
    1135                 :          0 :         input_sync(dev);
    1136                 :            : }
    1137                 :            : 
    1138                 :          0 : static void alps_process_packet_v7(struct psmouse *psmouse)
    1139                 :            : {
    1140                 :          0 :         unsigned char *packet = psmouse->packet;
    1141                 :            : 
    1142   [ #  #  #  # ]:          0 :         if (packet[0] == 0x48 && (packet[4] & 0x47) == 0x06)
    1143                 :          0 :                 alps_process_trackstick_packet_v7(psmouse);
    1144                 :            :         else
    1145                 :          0 :                 alps_process_touchpad_packet_v7(psmouse);
    1146                 :          0 : }
    1147                 :            : 
    1148                 :          0 : static enum SS4_PACKET_ID alps_get_pkt_id_ss4_v2(unsigned char *byte)
    1149                 :            : {
    1150                 :          0 :         enum SS4_PACKET_ID pkt_id = SS4_PACKET_ID_IDLE;
    1151                 :            : 
    1152   [ #  #  #  #  :          0 :         switch (byte[3] & 0x30) {
                      # ]
    1153                 :          0 :         case 0x00:
    1154   [ #  #  #  #  :          0 :                 if (SS4_IS_IDLE_V2(byte)) {
          #  #  #  #  #  
                #  #  # ]
    1155                 :            :                         pkt_id = SS4_PACKET_ID_IDLE;
    1156                 :            :                 } else {
    1157                 :          0 :                         pkt_id = SS4_PACKET_ID_ONE;
    1158                 :            :                 }
    1159                 :            :                 break;
    1160                 :          0 :         case 0x10:
    1161                 :            :                 /* two-finger finger positions */
    1162                 :          0 :                 pkt_id = SS4_PACKET_ID_TWO;
    1163                 :          0 :                 break;
    1164                 :          0 :         case 0x20:
    1165                 :            :                 /* stick pointer */
    1166                 :          0 :                 pkt_id = SS4_PACKET_ID_STICK;
    1167                 :          0 :                 break;
    1168                 :          0 :         case 0x30:
    1169                 :            :                 /* third and fourth finger positions */
    1170                 :          0 :                 pkt_id = SS4_PACKET_ID_MULTI;
    1171                 :          0 :                 break;
    1172                 :            :         }
    1173                 :            : 
    1174                 :          0 :         return pkt_id;
    1175                 :            : }
    1176                 :            : 
    1177                 :          0 : static int alps_decode_ss4_v2(struct alps_fields *f,
    1178                 :            :                               unsigned char *p, struct psmouse *psmouse)
    1179                 :            : {
    1180                 :          0 :         struct alps_data *priv = psmouse->private;
    1181                 :          0 :         enum SS4_PACKET_ID pkt_id;
    1182                 :          0 :         unsigned int no_data_x, no_data_y;
    1183                 :            : 
    1184                 :          0 :         pkt_id = alps_get_pkt_id_ss4_v2(p);
    1185                 :            : 
    1186                 :            :         /* Current packet is 1Finger coordinate packet */
    1187   [ #  #  #  #  :          0 :         switch (pkt_id) {
                      # ]
    1188                 :          0 :         case SS4_PACKET_ID_ONE:
    1189                 :          0 :                 f->mt[0].x = SS4_1F_X_V2(p);
    1190                 :          0 :                 f->mt[0].y = SS4_1F_Y_V2(p);
    1191                 :          0 :                 f->pressure = ((SS4_1F_Z_V2(p)) * 2) & 0x7f;
    1192                 :            :                 /*
    1193                 :            :                  * When a button is held the device will give us events
    1194                 :            :                  * with x, y, and pressure of 0. This causes annoying jumps
    1195                 :            :                  * if a touch is released while the button is held.
    1196                 :            :                  * Handle this by claiming zero contacts.
    1197                 :            :                  */
    1198                 :          0 :                 f->fingers = f->pressure > 0 ? 1 : 0;
    1199                 :          0 :                 f->first_mp = 0;
    1200                 :          0 :                 f->is_mp = 0;
    1201                 :          0 :                 break;
    1202                 :            : 
    1203                 :          0 :         case SS4_PACKET_ID_TWO:
    1204         [ #  # ]:          0 :                 if (priv->flags & ALPS_BUTTONPAD) {
    1205   [ #  #  #  # ]:          0 :                         if (IS_SS4PLUS_DEV(priv->dev_id)) {
    1206                 :          0 :                                 f->mt[0].x = SS4_PLUS_BTL_MF_X_V2(p, 0);
    1207                 :          0 :                                 f->mt[1].x = SS4_PLUS_BTL_MF_X_V2(p, 1);
    1208                 :            :                         } else {
    1209                 :          0 :                                 f->mt[0].x = SS4_BTL_MF_X_V2(p, 0);
    1210                 :          0 :                                 f->mt[1].x = SS4_BTL_MF_X_V2(p, 1);
    1211                 :            :                         }
    1212                 :          0 :                         f->mt[0].y = SS4_BTL_MF_Y_V2(p, 0);
    1213                 :          0 :                         f->mt[1].y = SS4_BTL_MF_Y_V2(p, 1);
    1214                 :            :                 } else {
    1215   [ #  #  #  # ]:          0 :                         if (IS_SS4PLUS_DEV(priv->dev_id)) {
    1216                 :          0 :                                 f->mt[0].x = SS4_PLUS_STD_MF_X_V2(p, 0);
    1217                 :          0 :                                 f->mt[1].x = SS4_PLUS_STD_MF_X_V2(p, 1);
    1218                 :            :                         } else {
    1219                 :          0 :                                 f->mt[0].x = SS4_STD_MF_X_V2(p, 0);
    1220                 :          0 :                                 f->mt[1].x = SS4_STD_MF_X_V2(p, 1);
    1221                 :            :                         }
    1222                 :          0 :                         f->mt[0].y = SS4_STD_MF_Y_V2(p, 0);
    1223                 :          0 :                         f->mt[1].y = SS4_STD_MF_Y_V2(p, 1);
    1224                 :            :                 }
    1225         [ #  # ]:          0 :                 f->pressure = SS4_MF_Z_V2(p, 0) ? 0x30 : 0;
    1226                 :            : 
    1227         [ #  # ]:          0 :                 if (SS4_IS_MF_CONTINUE(p)) {
    1228                 :          0 :                         f->first_mp = 1;
    1229                 :            :                 } else {
    1230                 :          0 :                         f->fingers = 2;
    1231                 :          0 :                         f->first_mp = 0;
    1232                 :            :                 }
    1233                 :          0 :                 f->is_mp = 0;
    1234                 :            : 
    1235                 :          0 :                 break;
    1236                 :            : 
    1237                 :          0 :         case SS4_PACKET_ID_MULTI:
    1238         [ #  # ]:          0 :                 if (priv->flags & ALPS_BUTTONPAD) {
    1239   [ #  #  #  # ]:          0 :                         if (IS_SS4PLUS_DEV(priv->dev_id)) {
    1240                 :          0 :                                 f->mt[2].x = SS4_PLUS_BTL_MF_X_V2(p, 0);
    1241                 :          0 :                                 f->mt[3].x = SS4_PLUS_BTL_MF_X_V2(p, 1);
    1242                 :          0 :                                 no_data_x = SS4_PLUS_MFPACKET_NO_AX_BL;
    1243                 :            :                         } else {
    1244                 :          0 :                                 f->mt[2].x = SS4_BTL_MF_X_V2(p, 0);
    1245                 :          0 :                                 f->mt[3].x = SS4_BTL_MF_X_V2(p, 1);
    1246                 :          0 :                                 no_data_x = SS4_MFPACKET_NO_AX_BL;
    1247                 :            :                         }
    1248                 :          0 :                         no_data_y = SS4_MFPACKET_NO_AY_BL;
    1249                 :            : 
    1250                 :          0 :                         f->mt[2].y = SS4_BTL_MF_Y_V2(p, 0);
    1251                 :          0 :                         f->mt[3].y = SS4_BTL_MF_Y_V2(p, 1);
    1252                 :            :                 } else {
    1253   [ #  #  #  # ]:          0 :                         if (IS_SS4PLUS_DEV(priv->dev_id)) {
    1254                 :          0 :                                 f->mt[2].x = SS4_PLUS_STD_MF_X_V2(p, 0);
    1255                 :          0 :                                 f->mt[3].x = SS4_PLUS_STD_MF_X_V2(p, 1);
    1256                 :          0 :                                 no_data_x = SS4_PLUS_MFPACKET_NO_AX;
    1257                 :            :                         } else {
    1258                 :          0 :                                 f->mt[2].x = SS4_STD_MF_X_V2(p, 0);
    1259                 :          0 :                                 f->mt[3].x = SS4_STD_MF_X_V2(p, 1);
    1260                 :          0 :                                 no_data_x = SS4_MFPACKET_NO_AX;
    1261                 :            :                         }
    1262                 :          0 :                         no_data_y = SS4_MFPACKET_NO_AY;
    1263                 :            : 
    1264                 :          0 :                         f->mt[2].y = SS4_STD_MF_Y_V2(p, 0);
    1265                 :          0 :                         f->mt[3].y = SS4_STD_MF_Y_V2(p, 1);
    1266                 :            :                 }
    1267                 :            : 
    1268                 :          0 :                 f->first_mp = 0;
    1269                 :          0 :                 f->is_mp = 1;
    1270                 :            : 
    1271         [ #  # ]:          0 :                 if (SS4_IS_5F_DETECTED(p)) {
    1272                 :          0 :                         f->fingers = 5;
    1273         [ #  # ]:          0 :                 } else if (f->mt[3].x == no_data_x &&
    1274         [ #  # ]:          0 :                              f->mt[3].y == no_data_y) {
    1275                 :          0 :                         f->mt[3].x = 0;
    1276                 :          0 :                         f->mt[3].y = 0;
    1277                 :          0 :                         f->fingers = 3;
    1278                 :            :                 } else {
    1279                 :          0 :                         f->fingers = 4;
    1280                 :            :                 }
    1281                 :            :                 break;
    1282                 :            : 
    1283                 :          0 :         case SS4_PACKET_ID_STICK:
    1284                 :            :                 /*
    1285                 :            :                  * x, y, and pressure are decoded in
    1286                 :            :                  * alps_process_packet_ss4_v2()
    1287                 :            :                  */
    1288                 :          0 :                 f->first_mp = 0;
    1289                 :          0 :                 f->is_mp = 0;
    1290                 :          0 :                 break;
    1291                 :            : 
    1292                 :          0 :         case SS4_PACKET_ID_IDLE:
    1293                 :            :         default:
    1294                 :          0 :                 memset(f, 0, sizeof(struct alps_fields));
    1295                 :          0 :                 break;
    1296                 :            :         }
    1297                 :            : 
    1298                 :            :         /* handle buttons */
    1299         [ #  # ]:          0 :         if (pkt_id == SS4_PACKET_ID_STICK) {
    1300                 :          0 :                 f->ts_left = !!(SS4_BTN_V2(p) & 0x01);
    1301                 :          0 :                 f->ts_right = !!(SS4_BTN_V2(p) & 0x02);
    1302                 :          0 :                 f->ts_middle = !!(SS4_BTN_V2(p) & 0x04);
    1303                 :            :         } else {
    1304                 :          0 :                 f->left = !!(SS4_BTN_V2(p) & 0x01);
    1305         [ #  # ]:          0 :                 if (!(priv->flags & ALPS_BUTTONPAD)) {
    1306                 :          0 :                         f->right = !!(SS4_BTN_V2(p) & 0x02);
    1307                 :          0 :                         f->middle = !!(SS4_BTN_V2(p) & 0x04);
    1308                 :            :                 }
    1309                 :            :         }
    1310                 :            : 
    1311                 :          0 :         return 0;
    1312                 :            : }
    1313                 :            : 
    1314                 :          0 : static void alps_process_packet_ss4_v2(struct psmouse *psmouse)
    1315                 :            : {
    1316                 :          0 :         struct alps_data *priv = psmouse->private;
    1317                 :          0 :         unsigned char *packet = psmouse->packet;
    1318                 :          0 :         struct input_dev *dev = psmouse->dev;
    1319                 :          0 :         struct input_dev *dev2 = priv->dev2;
    1320                 :          0 :         struct alps_fields *f = &priv->f;
    1321                 :            : 
    1322                 :          0 :         memset(f, 0, sizeof(struct alps_fields));
    1323                 :          0 :         priv->decode_fields(f, packet, psmouse);
    1324         [ #  # ]:          0 :         if (priv->multi_packet) {
    1325                 :            :                 /*
    1326                 :            :                  * Sometimes the first packet will indicate a multi-packet
    1327                 :            :                  * sequence, but sometimes the next multi-packet would not
    1328                 :            :                  * come. Check for this, and when it happens process the
    1329                 :            :                  * position packet as usual.
    1330                 :            :                  */
    1331         [ #  # ]:          0 :                 if (f->is_mp) {
    1332                 :            :                         /* Now process the 1st packet */
    1333                 :          0 :                         priv->decode_fields(f, priv->multi_data, psmouse);
    1334                 :            :                 } else {
    1335                 :          0 :                         priv->multi_packet = 0;
    1336                 :            :                 }
    1337                 :            :         }
    1338                 :            : 
    1339                 :            :         /*
    1340                 :            :          * "f.is_mp" would always be '0' after merging the 1st and 2nd packet.
    1341                 :            :          * When it is set, it means 2nd packet comes without 1st packet come.
    1342                 :            :          */
    1343         [ #  # ]:          0 :         if (f->is_mp)
    1344                 :            :                 return;
    1345                 :            : 
    1346                 :            :         /* Save the first packet */
    1347   [ #  #  #  # ]:          0 :         if (!priv->multi_packet && f->first_mp) {
    1348                 :          0 :                 priv->multi_packet = 1;
    1349                 :          0 :                 memcpy(priv->multi_data, packet, sizeof(priv->multi_data));
    1350                 :          0 :                 return;
    1351                 :            :         }
    1352                 :            : 
    1353                 :          0 :         priv->multi_packet = 0;
    1354                 :            : 
    1355                 :            :         /* Report trackstick */
    1356         [ #  # ]:          0 :         if (alps_get_pkt_id_ss4_v2(packet) == SS4_PACKET_ID_STICK) {
    1357         [ #  # ]:          0 :                 if (!(priv->flags & ALPS_DUALPOINT)) {
    1358                 :          0 :                         psmouse_warn(psmouse,
    1359                 :            :                                      "Rejected trackstick packet from non DualPoint device");
    1360                 :          0 :                         return;
    1361                 :            :                 }
    1362                 :            : 
    1363                 :          0 :                 input_report_rel(dev2, REL_X, SS4_TS_X_V2(packet));
    1364                 :          0 :                 input_report_rel(dev2, REL_Y, SS4_TS_Y_V2(packet));
    1365                 :          0 :                 input_report_abs(dev2, ABS_PRESSURE, SS4_TS_Z_V2(packet));
    1366                 :            : 
    1367                 :          0 :                 input_report_key(dev2, BTN_LEFT, f->ts_left);
    1368                 :          0 :                 input_report_key(dev2, BTN_RIGHT, f->ts_right);
    1369                 :          0 :                 input_report_key(dev2, BTN_MIDDLE, f->ts_middle);
    1370                 :            : 
    1371                 :          0 :                 input_sync(dev2);
    1372                 :          0 :                 return;
    1373                 :            :         }
    1374                 :            : 
    1375                 :            :         /* Report touchpad */
    1376                 :          0 :         alps_report_mt_data(psmouse, (f->fingers <= 4) ? f->fingers : 4);
    1377                 :            : 
    1378                 :          0 :         input_mt_report_finger_count(dev, f->fingers);
    1379                 :            : 
    1380                 :          0 :         input_report_key(dev, BTN_LEFT, f->left);
    1381                 :          0 :         input_report_key(dev, BTN_RIGHT, f->right);
    1382                 :          0 :         input_report_key(dev, BTN_MIDDLE, f->middle);
    1383                 :            : 
    1384                 :          0 :         input_report_abs(dev, ABS_PRESSURE, f->pressure);
    1385                 :          0 :         input_sync(dev);
    1386                 :            : }
    1387                 :            : 
    1388                 :          0 : static bool alps_is_valid_package_ss4_v2(struct psmouse *psmouse)
    1389                 :            : {
    1390   [ #  #  #  # ]:          0 :         if (psmouse->pktcnt == 4 && ((psmouse->packet[3] & 0x08) != 0x08))
    1391                 :            :                 return false;
    1392   [ #  #  #  # ]:          0 :         if (psmouse->pktcnt == 6 && ((psmouse->packet[5] & 0x10) != 0x0))
    1393                 :            :                 return false;
    1394                 :            :         return true;
    1395                 :            : }
    1396                 :            : 
    1397                 :            : static DEFINE_MUTEX(alps_mutex);
    1398                 :            : 
    1399                 :          0 : static void alps_register_bare_ps2_mouse(struct work_struct *work)
    1400                 :            : {
    1401                 :          0 :         struct alps_data *priv =
    1402                 :          0 :                 container_of(work, struct alps_data, dev3_register_work.work);
    1403                 :          0 :         struct psmouse *psmouse = priv->psmouse;
    1404                 :          0 :         struct input_dev *dev3;
    1405                 :          0 :         int error = 0;
    1406                 :            : 
    1407                 :          0 :         mutex_lock(&alps_mutex);
    1408                 :            : 
    1409         [ #  # ]:          0 :         if (priv->dev3)
    1410                 :          0 :                 goto out;
    1411                 :            : 
    1412                 :          0 :         dev3 = input_allocate_device();
    1413         [ #  # ]:          0 :         if (!dev3) {
    1414                 :          0 :                 psmouse_err(psmouse, "failed to allocate secondary device\n");
    1415                 :          0 :                 error = -ENOMEM;
    1416                 :          0 :                 goto out;
    1417                 :            :         }
    1418                 :            : 
    1419                 :          0 :         snprintf(priv->phys3, sizeof(priv->phys3), "%s/%s",
    1420                 :          0 :                  psmouse->ps2dev.serio->phys,
    1421         [ #  # ]:          0 :                  (priv->dev2 ? "input2" : "input1"));
    1422                 :          0 :         dev3->phys = priv->phys3;
    1423                 :            : 
    1424                 :            :         /*
    1425                 :            :          * format of input device name is: "protocol vendor name"
    1426                 :            :          * see function psmouse_switch_protocol() in psmouse-base.c
    1427                 :            :          */
    1428                 :          0 :         dev3->name = "PS/2 ALPS Mouse";
    1429                 :            : 
    1430                 :          0 :         dev3->id.bustype = BUS_I8042;
    1431                 :          0 :         dev3->id.vendor  = 0x0002;
    1432                 :          0 :         dev3->id.product = PSMOUSE_PS2;
    1433                 :          0 :         dev3->id.version = 0x0000;
    1434                 :          0 :         dev3->dev.parent = &psmouse->ps2dev.serio->dev;
    1435                 :            : 
    1436                 :          0 :         input_set_capability(dev3, EV_REL, REL_X);
    1437                 :          0 :         input_set_capability(dev3, EV_REL, REL_Y);
    1438                 :          0 :         input_set_capability(dev3, EV_KEY, BTN_LEFT);
    1439                 :          0 :         input_set_capability(dev3, EV_KEY, BTN_RIGHT);
    1440                 :          0 :         input_set_capability(dev3, EV_KEY, BTN_MIDDLE);
    1441                 :            : 
    1442                 :          0 :         __set_bit(INPUT_PROP_POINTER, dev3->propbit);
    1443                 :            : 
    1444                 :          0 :         error = input_register_device(dev3);
    1445         [ #  # ]:          0 :         if (error) {
    1446                 :          0 :                 psmouse_err(psmouse,
    1447                 :            :                             "failed to register secondary device: %d\n",
    1448                 :            :                             error);
    1449                 :          0 :                 input_free_device(dev3);
    1450                 :          0 :                 goto out;
    1451                 :            :         }
    1452                 :            : 
    1453                 :          0 :         priv->dev3 = dev3;
    1454                 :            : 
    1455                 :          0 : out:
    1456                 :            :         /*
    1457                 :            :          * Save the error code so that we can detect that we
    1458                 :            :          * already tried to create the device.
    1459                 :            :          */
    1460         [ #  # ]:          0 :         if (error)
    1461                 :          0 :                 priv->dev3 = ERR_PTR(error);
    1462                 :            : 
    1463                 :          0 :         mutex_unlock(&alps_mutex);
    1464                 :          0 : }
    1465                 :            : 
    1466                 :          0 : static void alps_report_bare_ps2_packet(struct psmouse *psmouse,
    1467                 :            :                                         unsigned char packet[],
    1468                 :            :                                         bool report_buttons)
    1469                 :            : {
    1470                 :          0 :         struct alps_data *priv = psmouse->private;
    1471                 :          0 :         struct input_dev *dev, *dev2 = NULL;
    1472                 :            : 
    1473                 :            :         /* Figure out which device to use to report the bare packet */
    1474         [ #  # ]:          0 :         if (priv->proto_version == ALPS_PROTO_V2 &&
    1475         [ #  # ]:          0 :             (priv->flags & ALPS_DUALPOINT)) {
    1476                 :            :                 /* On V2 devices the DualPoint Stick reports bare packets */
    1477                 :          0 :                 dev = priv->dev2;
    1478                 :          0 :                 dev2 = psmouse->dev;
    1479   [ #  #  #  # ]:          0 :         } else if (unlikely(IS_ERR_OR_NULL(priv->dev3))) {
    1480                 :            :                 /* Register dev3 mouse if we received PS/2 packet first time */
    1481         [ #  # ]:          0 :                 if (!IS_ERR(priv->dev3))
    1482                 :          0 :                         psmouse_queue_work(psmouse, &priv->dev3_register_work,
    1483                 :            :                                            0);
    1484                 :          0 :                 return;
    1485                 :            :         } else {
    1486                 :            :                 dev = priv->dev3;
    1487                 :            :         }
    1488                 :            : 
    1489         [ #  # ]:          0 :         if (report_buttons)
    1490                 :          0 :                 alps_report_buttons(dev, dev2,
    1491                 :          0 :                                 packet[0] & 1, packet[0] & 2, packet[0] & 4);
    1492                 :            : 
    1493                 :          0 :         psmouse_report_standard_motion(dev, packet);
    1494                 :            : 
    1495                 :          0 :         input_sync(dev);
    1496                 :            : }
    1497                 :            : 
    1498                 :          0 : static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse)
    1499                 :            : {
    1500                 :          0 :         struct alps_data *priv = psmouse->private;
    1501                 :            : 
    1502         [ #  # ]:          0 :         if (psmouse->pktcnt < 6)
    1503                 :            :                 return PSMOUSE_GOOD_DATA;
    1504                 :            : 
    1505         [ #  # ]:          0 :         if (psmouse->pktcnt == 6) {
    1506                 :            :                 /*
    1507                 :            :                  * Start a timer to flush the packet if it ends up last
    1508                 :            :                  * 6-byte packet in the stream. Timer needs to fire
    1509                 :            :                  * psmouse core times out itself. 20 ms should be enough
    1510                 :            :                  * to decide if we are getting more data or not.
    1511                 :            :                  */
    1512                 :          0 :                 mod_timer(&priv->timer, jiffies + msecs_to_jiffies(20));
    1513                 :          0 :                 return PSMOUSE_GOOD_DATA;
    1514                 :            :         }
    1515                 :            : 
    1516                 :          0 :         del_timer(&priv->timer);
    1517                 :            : 
    1518         [ #  # ]:          0 :         if (psmouse->packet[6] & 0x80) {
    1519                 :            : 
    1520                 :            :                 /*
    1521                 :            :                  * Highest bit is set - that means we either had
    1522                 :            :                  * complete ALPS packet and this is start of the
    1523                 :            :                  * next packet or we got garbage.
    1524                 :            :                  */
    1525                 :            : 
    1526                 :          0 :                 if (((psmouse->packet[3] |
    1527                 :          0 :                       psmouse->packet[4] |
    1528   [ #  #  #  # ]:          0 :                       psmouse->packet[5]) & 0x80) ||
    1529                 :            :                     (!alps_is_valid_first_byte(priv, psmouse->packet[6]))) {
    1530                 :            :                         psmouse_dbg(psmouse,
    1531                 :            :                                     "refusing packet %4ph (suspected interleaved ps/2)\n",
    1532                 :            :                                     psmouse->packet + 3);
    1533                 :            :                         return PSMOUSE_BAD_DATA;
    1534                 :            :                 }
    1535                 :            : 
    1536                 :          0 :                 priv->process_packet(psmouse);
    1537                 :            : 
    1538                 :            :                 /* Continue with the next packet */
    1539                 :          0 :                 psmouse->packet[0] = psmouse->packet[6];
    1540                 :          0 :                 psmouse->pktcnt = 1;
    1541                 :            : 
    1542                 :            :         } else {
    1543                 :            : 
    1544                 :            :                 /*
    1545                 :            :                  * High bit is 0 - that means that we indeed got a PS/2
    1546                 :            :                  * packet in the middle of ALPS packet.
    1547                 :            :                  *
    1548                 :            :                  * There is also possibility that we got 6-byte ALPS
    1549                 :            :                  * packet followed  by 3-byte packet from trackpoint. We
    1550                 :            :                  * can not distinguish between these 2 scenarios but
    1551                 :            :                  * because the latter is unlikely to happen in course of
    1552                 :            :                  * normal operation (user would need to press all
    1553                 :            :                  * buttons on the pad and start moving trackpoint
    1554                 :            :                  * without touching the pad surface) we assume former.
    1555                 :            :                  * Even if we are wrong the wost thing that would happen
    1556                 :            :                  * the cursor would jump but we should not get protocol
    1557                 :            :                  * de-synchronization.
    1558                 :            :                  */
    1559                 :            : 
    1560                 :          0 :                 alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3],
    1561                 :            :                                             false);
    1562                 :            : 
    1563                 :            :                 /*
    1564                 :            :                  * Continue with the standard ALPS protocol handling,
    1565                 :            :                  * but make sure we won't process it as an interleaved
    1566                 :            :                  * packet again, which may happen if all buttons are
    1567                 :            :                  * pressed. To avoid this let's reset the 4th bit which
    1568                 :            :                  * is normally 1.
    1569                 :            :                  */
    1570                 :          0 :                 psmouse->packet[3] = psmouse->packet[6] & 0xf7;
    1571                 :          0 :                 psmouse->pktcnt = 4;
    1572                 :            :         }
    1573                 :            : 
    1574                 :            :         return PSMOUSE_GOOD_DATA;
    1575                 :            : }
    1576                 :            : 
    1577                 :          0 : static void alps_flush_packet(struct timer_list *t)
    1578                 :            : {
    1579                 :          0 :         struct alps_data *priv = from_timer(priv, t, timer);
    1580                 :          0 :         struct psmouse *psmouse = priv->psmouse;
    1581                 :            : 
    1582                 :          0 :         serio_pause_rx(psmouse->ps2dev.serio);
    1583                 :            : 
    1584         [ #  # ]:          0 :         if (psmouse->pktcnt == psmouse->pktsize) {
    1585                 :            : 
    1586                 :            :                 /*
    1587                 :            :                  * We did not any more data in reasonable amount of time.
    1588                 :            :                  * Validate the last 3 bytes and process as a standard
    1589                 :            :                  * ALPS packet.
    1590                 :            :                  */
    1591                 :          0 :                 if ((psmouse->packet[3] |
    1592                 :          0 :                      psmouse->packet[4] |
    1593         [ #  # ]:          0 :                      psmouse->packet[5]) & 0x80) {
    1594                 :            :                         psmouse_dbg(psmouse,
    1595                 :            :                                     "refusing packet %3ph (suspected interleaved ps/2)\n",
    1596                 :            :                                     psmouse->packet + 3);
    1597                 :            :                 } else {
    1598                 :          0 :                         priv->process_packet(psmouse);
    1599                 :            :                 }
    1600                 :          0 :                 psmouse->pktcnt = 0;
    1601                 :            :         }
    1602                 :            : 
    1603                 :          0 :         serio_continue_rx(psmouse->ps2dev.serio);
    1604                 :          0 : }
    1605                 :            : 
    1606                 :          0 : static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
    1607                 :            : {
    1608                 :          0 :         struct alps_data *priv = psmouse->private;
    1609                 :            : 
    1610                 :            :         /*
    1611                 :            :          * Check if we are dealing with a bare PS/2 packet, presumably from
    1612                 :            :          * a device connected to the external PS/2 port. Because bare PS/2
    1613                 :            :          * protocol does not have enough constant bits to self-synchronize
    1614                 :            :          * properly we only do this if the device is fully synchronized.
    1615                 :            :          * Can not distinguish V8's first byte from PS/2 packet's
    1616                 :            :          */
    1617         [ #  # ]:          0 :         if (priv->proto_version != ALPS_PROTO_V8 &&
    1618         [ #  # ]:          0 :             !psmouse->out_of_sync_cnt &&
    1619         [ #  # ]:          0 :             (psmouse->packet[0] & 0xc8) == 0x08) {
    1620                 :            : 
    1621         [ #  # ]:          0 :                 if (psmouse->pktcnt == 3) {
    1622                 :          0 :                         alps_report_bare_ps2_packet(psmouse, psmouse->packet,
    1623                 :            :                                                     true);
    1624                 :          0 :                         return PSMOUSE_FULL_PACKET;
    1625                 :            :                 }
    1626                 :            :                 return PSMOUSE_GOOD_DATA;
    1627                 :            :         }
    1628                 :            : 
    1629                 :            :         /* Check for PS/2 packet stuffed in the middle of ALPS packet. */
    1630                 :            : 
    1631         [ #  # ]:          0 :         if ((priv->flags & ALPS_PS2_INTERLEAVED) &&
    1632   [ #  #  #  # ]:          0 :             psmouse->pktcnt >= 4 && (psmouse->packet[3] & 0x0f) == 0x0f) {
    1633                 :          0 :                 return alps_handle_interleaved_ps2(psmouse);
    1634                 :            :         }
    1635                 :            : 
    1636         [ #  # ]:          0 :         if (!alps_is_valid_first_byte(priv, psmouse->packet[0])) {
    1637                 :            :                 psmouse_dbg(psmouse,
    1638                 :            :                             "refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n",
    1639                 :            :                             psmouse->packet[0], priv->mask0, priv->byte0);
    1640                 :            :                 return PSMOUSE_BAD_DATA;
    1641                 :            :         }
    1642                 :            : 
    1643                 :            :         /* Bytes 2 - pktsize should have 0 in the highest bit */
    1644         [ #  # ]:          0 :         if (priv->proto_version < ALPS_PROTO_V5 &&
    1645   [ #  #  #  # ]:          0 :             psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize &&
    1646         [ #  # ]:          0 :             (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) {
    1647                 :          0 :                 psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
    1648                 :            :                             psmouse->pktcnt - 1,
    1649                 :            :                             psmouse->packet[psmouse->pktcnt - 1]);
    1650                 :            : 
    1651   [ #  #  #  # ]:          0 :                 if (priv->proto_version == ALPS_PROTO_V3_RUSHMORE &&
    1652                 :            :                     psmouse->pktcnt == psmouse->pktsize) {
    1653                 :            :                         /*
    1654                 :            :                          * Some Dell boxes, such as Latitude E6440 or E7440
    1655                 :            :                          * with closed lid, quite often smash last byte of
    1656                 :            :                          * otherwise valid packet with 0xff. Given that the
    1657                 :            :                          * next packet is very likely to be valid let's
    1658                 :            :                          * report PSMOUSE_FULL_PACKET but not process data,
    1659                 :            :                          * rather than reporting PSMOUSE_BAD_DATA and
    1660                 :            :                          * filling the logs.
    1661                 :            :                          */
    1662                 :            :                         return PSMOUSE_FULL_PACKET;
    1663                 :            :                 }
    1664                 :            : 
    1665                 :          0 :                 return PSMOUSE_BAD_DATA;
    1666                 :            :         }
    1667                 :            : 
    1668   [ #  #  #  # ]:          0 :         if ((priv->proto_version == ALPS_PROTO_V7 &&
    1669         [ #  # ]:          0 :                         !alps_is_valid_package_v7(psmouse)) ||
    1670                 :            :             (priv->proto_version == ALPS_PROTO_V8 &&
    1671                 :            :                         !alps_is_valid_package_ss4_v2(psmouse))) {
    1672                 :            :                 psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
    1673                 :            :                             psmouse->pktcnt - 1,
    1674                 :            :                             psmouse->packet[psmouse->pktcnt - 1]);
    1675                 :            :                 return PSMOUSE_BAD_DATA;
    1676                 :            :         }
    1677                 :            : 
    1678         [ #  # ]:          0 :         if (psmouse->pktcnt == psmouse->pktsize) {
    1679                 :          0 :                 priv->process_packet(psmouse);
    1680                 :          0 :                 return PSMOUSE_FULL_PACKET;
    1681                 :            :         }
    1682                 :            : 
    1683                 :            :         return PSMOUSE_GOOD_DATA;
    1684                 :            : }
    1685                 :            : 
    1686                 :          0 : static int alps_command_mode_send_nibble(struct psmouse *psmouse, int nibble)
    1687                 :            : {
    1688                 :          0 :         struct ps2dev *ps2dev = &psmouse->ps2dev;
    1689                 :          0 :         struct alps_data *priv = psmouse->private;
    1690                 :          0 :         int command;
    1691                 :          0 :         unsigned char *param;
    1692                 :          0 :         unsigned char dummy[4];
    1693                 :            : 
    1694         [ #  # ]:          0 :         BUG_ON(nibble > 0xf);
    1695                 :            : 
    1696                 :          0 :         command = priv->nibble_commands[nibble].command;
    1697                 :          0 :         param = (command & 0x0f00) ?
    1698         [ #  # ]:          0 :                 dummy : (unsigned char *)&priv->nibble_commands[nibble].data;
    1699                 :            : 
    1700         [ #  # ]:          0 :         if (ps2_command(ps2dev, param, command))
    1701                 :          0 :                 return -1;
    1702                 :            : 
    1703                 :            :         return 0;
    1704                 :            : }
    1705                 :            : 
    1706                 :          0 : static int alps_command_mode_set_addr(struct psmouse *psmouse, int addr)
    1707                 :            : {
    1708                 :          0 :         struct ps2dev *ps2dev = &psmouse->ps2dev;
    1709                 :          0 :         struct alps_data *priv = psmouse->private;
    1710                 :          0 :         int i, nibble;
    1711                 :            : 
    1712         [ #  # ]:          0 :         if (ps2_command(ps2dev, NULL, priv->addr_command))
    1713                 :            :                 return -1;
    1714                 :            : 
    1715         [ #  # ]:          0 :         for (i = 12; i >= 0; i -= 4) {
    1716                 :          0 :                 nibble = (addr >> i) & 0xf;
    1717         [ #  # ]:          0 :                 if (alps_command_mode_send_nibble(psmouse, nibble))
    1718                 :            :                         return -1;
    1719                 :            :         }
    1720                 :            : 
    1721                 :            :         return 0;
    1722                 :            : }
    1723                 :            : 
    1724                 :          0 : static int __alps_command_mode_read_reg(struct psmouse *psmouse, int addr)
    1725                 :            : {
    1726                 :          0 :         struct ps2dev *ps2dev = &psmouse->ps2dev;
    1727                 :          0 :         unsigned char param[4];
    1728                 :            : 
    1729         [ #  # ]:          0 :         if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
    1730                 :            :                 return -1;
    1731                 :            : 
    1732                 :            :         /*
    1733                 :            :          * The address being read is returned in the first two bytes
    1734                 :            :          * of the result. Check that this address matches the expected
    1735                 :            :          * address.
    1736                 :            :          */
    1737         [ #  # ]:          0 :         if (addr != ((param[0] << 8) | param[1]))
    1738                 :            :                 return -1;
    1739                 :            : 
    1740                 :          0 :         return param[2];
    1741                 :            : }
    1742                 :            : 
    1743                 :          0 : static int alps_command_mode_read_reg(struct psmouse *psmouse, int addr)
    1744                 :            : {
    1745         [ #  # ]:          0 :         if (alps_command_mode_set_addr(psmouse, addr))
    1746                 :            :                 return -1;
    1747                 :          0 :         return __alps_command_mode_read_reg(psmouse, addr);
    1748                 :            : }
    1749                 :            : 
    1750                 :          0 : static int __alps_command_mode_write_reg(struct psmouse *psmouse, u8 value)
    1751                 :            : {
    1752         [ #  # ]:          0 :         if (alps_command_mode_send_nibble(psmouse, (value >> 4) & 0xf))
    1753                 :            :                 return -1;
    1754         [ #  # ]:          0 :         if (alps_command_mode_send_nibble(psmouse, value & 0xf))
    1755                 :          0 :                 return -1;
    1756                 :            :         return 0;
    1757                 :            : }
    1758                 :            : 
    1759                 :          0 : static int alps_command_mode_write_reg(struct psmouse *psmouse, int addr,
    1760                 :            :                                        u8 value)
    1761                 :            : {
    1762         [ #  # ]:          0 :         if (alps_command_mode_set_addr(psmouse, addr))
    1763                 :            :                 return -1;
    1764                 :          0 :         return __alps_command_mode_write_reg(psmouse, value);
    1765                 :            : }
    1766                 :            : 
    1767                 :        234 : static int alps_rpt_cmd(struct psmouse *psmouse, int init_command,
    1768                 :            :                         int repeated_command, unsigned char *param)
    1769                 :            : {
    1770                 :        234 :         struct ps2dev *ps2dev = &psmouse->ps2dev;
    1771                 :            : 
    1772                 :        234 :         param[0] = 0;
    1773   [ +  -  +  - ]:        234 :         if (init_command && ps2_command(ps2dev, param, init_command))
    1774                 :            :                 return -EIO;
    1775                 :            : 
    1776   [ +  +  +  - ]:        390 :         if (ps2_command(ps2dev,  NULL, repeated_command) ||
    1777         [ -  + ]:        312 :             ps2_command(ps2dev,  NULL, repeated_command) ||
    1778                 :        156 :             ps2_command(ps2dev,  NULL, repeated_command))
    1779                 :         78 :                 return -EIO;
    1780                 :            : 
    1781                 :        156 :         param[0] = param[1] = param[2] = 0xff;
    1782         [ -  + ]:        156 :         if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
    1783                 :          0 :                 return -EIO;
    1784                 :            : 
    1785                 :            :         psmouse_dbg(psmouse, "%2.2X report: %3ph\n",
    1786                 :            :                     repeated_command, param);
    1787                 :            :         return 0;
    1788                 :            : }
    1789                 :            : 
    1790                 :          0 : static bool alps_check_valid_firmware_id(unsigned char id[])
    1791                 :            : {
    1792                 :          0 :         if (id[0] == 0x73)
    1793                 :            :                 return true;
    1794                 :            : 
    1795         [ #  # ]:          0 :         if (id[0] == 0x88 &&
    1796         [ #  # ]:          0 :             (id[1] == 0x07 ||
    1797         [ #  # ]:          0 :              id[1] == 0x08 ||
    1798         [ #  # ]:          0 :              (id[1] & 0xf0) == 0xb0 ||
    1799                 :            :              (id[1] & 0xf0) == 0xc0)) {
    1800                 :            :                 return true;
    1801                 :            :         }
    1802                 :            : 
    1803                 :            :         return false;
    1804                 :            : }
    1805                 :            : 
    1806                 :          0 : static int alps_enter_command_mode(struct psmouse *psmouse)
    1807                 :            : {
    1808                 :          0 :         unsigned char param[4];
    1809                 :            : 
    1810         [ #  # ]:          0 :         if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_RESET_WRAP, param)) {
    1811                 :          0 :                 psmouse_err(psmouse, "failed to enter command mode\n");
    1812                 :          0 :                 return -1;
    1813                 :            :         }
    1814                 :            : 
    1815         [ #  # ]:          0 :         if (!alps_check_valid_firmware_id(param)) {
    1816                 :          0 :                 psmouse_dbg(psmouse,
    1817                 :            :                             "unknown response while entering command mode\n");
    1818                 :          0 :                 return -1;
    1819                 :            :         }
    1820                 :            :         return 0;
    1821                 :            : }
    1822                 :            : 
    1823                 :          0 : static inline int alps_exit_command_mode(struct psmouse *psmouse)
    1824                 :            : {
    1825                 :          0 :         struct ps2dev *ps2dev = &psmouse->ps2dev;
    1826   [ #  #  #  #  :          0 :         if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM))
          #  #  #  #  #  
                      # ]
    1827                 :          0 :                 return -1;
    1828                 :            :         return 0;
    1829                 :            : }
    1830                 :            : 
    1831                 :            : /*
    1832                 :            :  * For DualPoint devices select the device that should respond to
    1833                 :            :  * subsequent commands. It looks like glidepad is behind stickpointer,
    1834                 :            :  * I'd thought it would be other way around...
    1835                 :            :  */
    1836                 :          0 : static int alps_passthrough_mode_v2(struct psmouse *psmouse, bool enable)
    1837                 :            : {
    1838                 :          0 :         struct ps2dev *ps2dev = &psmouse->ps2dev;
    1839         [ #  # ]:          0 :         int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11;
    1840                 :            : 
    1841   [ #  #  #  # ]:          0 :         if (ps2_command(ps2dev, NULL, cmd) ||
    1842         [ #  # ]:          0 :             ps2_command(ps2dev, NULL, cmd) ||
    1843         [ #  # ]:          0 :             ps2_command(ps2dev, NULL, cmd) ||
    1844                 :          0 :             ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE))
    1845                 :          0 :                 return -1;
    1846                 :            : 
    1847                 :            :         /* we may get 3 more bytes, just ignore them */
    1848                 :          0 :         ps2_drain(ps2dev, 3, 100);
    1849                 :            : 
    1850                 :          0 :         return 0;
    1851                 :            : }
    1852                 :            : 
    1853                 :          0 : static int alps_absolute_mode_v1_v2(struct psmouse *psmouse)
    1854                 :            : {
    1855                 :          0 :         struct ps2dev *ps2dev = &psmouse->ps2dev;
    1856                 :            : 
    1857                 :            :         /* Try ALPS magic knock - 4 disable before enable */
    1858   [ #  #  #  # ]:          0 :         if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
    1859         [ #  # ]:          0 :             ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
    1860         [ #  # ]:          0 :             ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
    1861         [ #  # ]:          0 :             ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
    1862                 :          0 :             ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE))
    1863                 :          0 :                 return -1;
    1864                 :            : 
    1865                 :            :         /*
    1866                 :            :          * Switch mouse to poll (remote) mode so motion data will not
    1867                 :            :          * get in our way
    1868                 :            :          */
    1869                 :          0 :         return ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL);
    1870                 :            : }
    1871                 :            : 
    1872                 :          0 : static int alps_monitor_mode_send_word(struct psmouse *psmouse, u16 word)
    1873                 :            : {
    1874                 :          0 :         int i, nibble;
    1875                 :            : 
    1876                 :            :         /*
    1877                 :            :          * b0-b11 are valid bits, send sequence is inverse.
    1878                 :            :          * e.g. when word = 0x0123, nibble send sequence is 3, 2, 1
    1879                 :            :          */
    1880   [ #  #  #  #  :          0 :         for (i = 0; i <= 8; i += 4) {
                   #  # ]
    1881                 :          0 :                 nibble = (word >> i) & 0xf;
    1882   [ #  #  #  #  :          0 :                 if (alps_command_mode_send_nibble(psmouse, nibble))
                   #  # ]
    1883                 :            :                         return -1;
    1884                 :            :         }
    1885                 :            : 
    1886                 :            :         return 0;
    1887                 :            : }
    1888                 :            : 
    1889                 :          0 : static int alps_monitor_mode_write_reg(struct psmouse *psmouse,
    1890                 :            :                                        u16 addr, u16 value)
    1891                 :            : {
    1892                 :          0 :         struct ps2dev *ps2dev = &psmouse->ps2dev;
    1893                 :            : 
    1894                 :            :         /* 0x0A0 is the command to write the word */
    1895   [ #  #  #  # ]:          0 :         if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE) ||
    1896         [ #  # ]:          0 :             alps_monitor_mode_send_word(psmouse, 0x0A0) ||
    1897         [ #  # ]:          0 :             alps_monitor_mode_send_word(psmouse, addr) ||
    1898         [ #  # ]:          0 :             alps_monitor_mode_send_word(psmouse, value) ||
    1899                 :          0 :             ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE))
    1900                 :          0 :                 return -1;
    1901                 :            : 
    1902                 :            :         return 0;
    1903                 :            : }
    1904                 :            : 
    1905                 :          0 : static int alps_monitor_mode(struct psmouse *psmouse, bool enable)
    1906                 :            : {
    1907                 :          0 :         struct ps2dev *ps2dev = &psmouse->ps2dev;
    1908                 :            : 
    1909         [ #  # ]:          0 :         if (enable) {
    1910                 :            :                 /* EC E9 F5 F5 E7 E6 E7 E9 to enter monitor mode */
    1911   [ #  #  #  # ]:          0 :                 if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) ||
    1912         [ #  # ]:          0 :                     ps2_command(ps2dev, NULL, PSMOUSE_CMD_GETINFO) ||
    1913         [ #  # ]:          0 :                     ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
    1914         [ #  # ]:          0 :                     ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
    1915         [ #  # ]:          0 :                     ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
    1916         [ #  # ]:          0 :                     ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
    1917         [ #  # ]:          0 :                     ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
    1918                 :          0 :                     ps2_command(ps2dev, NULL, PSMOUSE_CMD_GETINFO))
    1919                 :          0 :                         return -1;
    1920                 :            :         } else {
    1921                 :            :                 /* EC to exit monitor mode */
    1922         [ #  # ]:          0 :                 if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP))
    1923                 :          0 :                         return -1;
    1924                 :            :         }
    1925                 :            : 
    1926                 :            :         return 0;
    1927                 :            : }
    1928                 :            : 
    1929                 :          0 : static int alps_absolute_mode_v6(struct psmouse *psmouse)
    1930                 :            : {
    1931                 :          0 :         u16 reg_val = 0x181;
    1932                 :          0 :         int ret = -1;
    1933                 :            : 
    1934                 :            :         /* enter monitor mode, to write the register */
    1935         [ #  # ]:          0 :         if (alps_monitor_mode(psmouse, true))
    1936                 :            :                 return -1;
    1937                 :            : 
    1938                 :          0 :         ret = alps_monitor_mode_write_reg(psmouse, 0x000, reg_val);
    1939                 :            : 
    1940         [ #  # ]:          0 :         if (alps_monitor_mode(psmouse, false))
    1941                 :          0 :                 ret = -1;
    1942                 :            : 
    1943                 :            :         return ret;
    1944                 :            : }
    1945                 :            : 
    1946                 :          0 : static int alps_get_status(struct psmouse *psmouse, char *param)
    1947                 :            : {
    1948                 :            :         /* Get status: 0xF5 0xF5 0xF5 0xE9 */
    1949         [ #  # ]:          0 :         if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_DISABLE, param))
    1950                 :          0 :                 return -1;
    1951                 :            : 
    1952                 :            :         return 0;
    1953                 :            : }
    1954                 :            : 
    1955                 :            : /*
    1956                 :            :  * Turn touchpad tapping on or off. The sequences are:
    1957                 :            :  * 0xE9 0xF5 0xF5 0xF3 0x0A to enable,
    1958                 :            :  * 0xE9 0xF5 0xF5 0xE8 0x00 to disable.
    1959                 :            :  * My guess that 0xE9 (GetInfo) is here as a sync point.
    1960                 :            :  * For models that also have stickpointer (DualPoints) its tapping
    1961                 :            :  * is controlled separately (0xE6 0xE6 0xE6 0xF3 0x14|0x0A) but
    1962                 :            :  * we don't fiddle with it.
    1963                 :            :  */
    1964                 :          0 : static int alps_tap_mode(struct psmouse *psmouse, int enable)
    1965                 :            : {
    1966                 :          0 :         struct ps2dev *ps2dev = &psmouse->ps2dev;
    1967         [ #  # ]:          0 :         int cmd = enable ? PSMOUSE_CMD_SETRATE : PSMOUSE_CMD_SETRES;
    1968         [ #  # ]:          0 :         unsigned char tap_arg = enable ? 0x0A : 0x00;
    1969                 :          0 :         unsigned char param[4];
    1970                 :            : 
    1971   [ #  #  #  # ]:          0 :         if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO) ||
    1972         [ #  # ]:          0 :             ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
    1973         [ #  # ]:          0 :             ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
    1974                 :          0 :             ps2_command(ps2dev, &tap_arg, cmd))
    1975                 :          0 :                 return -1;
    1976                 :            : 
    1977                 :          0 :         if (alps_get_status(psmouse, param))
    1978                 :          0 :                 return -1;
    1979                 :            : 
    1980                 :            :         return 0;
    1981                 :            : }
    1982                 :            : 
    1983                 :            : /*
    1984                 :            :  * alps_poll() - poll the touchpad for current motion packet.
    1985                 :            :  * Used in resync.
    1986                 :            :  */
    1987                 :          0 : static int alps_poll(struct psmouse *psmouse)
    1988                 :            : {
    1989                 :          0 :         struct alps_data *priv = psmouse->private;
    1990                 :          0 :         unsigned char buf[sizeof(psmouse->packet)];
    1991                 :          0 :         bool poll_failed;
    1992                 :            : 
    1993         [ #  # ]:          0 :         if (priv->flags & ALPS_PASS)
    1994                 :          0 :                 alps_passthrough_mode_v2(psmouse, true);
    1995                 :            : 
    1996                 :          0 :         poll_failed = ps2_command(&psmouse->ps2dev, buf,
    1997                 :          0 :                                   PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0;
    1998                 :            : 
    1999         [ #  # ]:          0 :         if (priv->flags & ALPS_PASS)
    2000                 :          0 :                 alps_passthrough_mode_v2(psmouse, false);
    2001                 :            : 
    2002   [ #  #  #  # ]:          0 :         if (poll_failed || (buf[0] & priv->mask0) != priv->byte0)
    2003                 :            :                 return -1;
    2004                 :            : 
    2005         [ #  # ]:          0 :         if ((psmouse->badbyte & 0xc8) == 0x08) {
    2006                 :            : /*
    2007                 :            :  * Poll the track stick ...
    2008                 :            :  */
    2009         [ #  # ]:          0 :                 if (ps2_command(&psmouse->ps2dev, buf, PSMOUSE_CMD_POLL | (3 << 8)))
    2010                 :            :                         return -1;
    2011                 :            :         }
    2012                 :            : 
    2013                 :          0 :         memcpy(psmouse->packet, buf, sizeof(buf));
    2014                 :          0 :         return 0;
    2015                 :            : }
    2016                 :            : 
    2017                 :          0 : static int alps_hw_init_v1_v2(struct psmouse *psmouse)
    2018                 :            : {
    2019                 :          0 :         struct alps_data *priv = psmouse->private;
    2020                 :            : 
    2021   [ #  #  #  # ]:          0 :         if ((priv->flags & ALPS_PASS) &&
    2022                 :          0 :             alps_passthrough_mode_v2(psmouse, true)) {
    2023                 :            :                 return -1;
    2024                 :            :         }
    2025                 :            : 
    2026         [ #  # ]:          0 :         if (alps_tap_mode(psmouse, true)) {
    2027                 :          0 :                 psmouse_warn(psmouse, "Failed to enable hardware tapping\n");
    2028                 :          0 :                 return -1;
    2029                 :            :         }
    2030                 :            : 
    2031         [ #  # ]:          0 :         if (alps_absolute_mode_v1_v2(psmouse)) {
    2032                 :          0 :                 psmouse_err(psmouse, "Failed to enable absolute mode\n");
    2033                 :          0 :                 return -1;
    2034                 :            :         }
    2035                 :            : 
    2036   [ #  #  #  # ]:          0 :         if ((priv->flags & ALPS_PASS) &&
    2037                 :          0 :             alps_passthrough_mode_v2(psmouse, false)) {
    2038                 :            :                 return -1;
    2039                 :            :         }
    2040                 :            : 
    2041                 :            :         /* ALPS needs stream mode, otherwise it won't report any data */
    2042         [ #  # ]:          0 :         if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) {
    2043                 :          0 :                 psmouse_err(psmouse, "Failed to enable stream mode\n");
    2044                 :          0 :                 return -1;
    2045                 :            :         }
    2046                 :            : 
    2047                 :            :         return 0;
    2048                 :            : }
    2049                 :            : 
    2050                 :            : /* Must be in passthrough mode when calling this function */
    2051                 :          0 : static int alps_trackstick_enter_extended_mode_v3_v6(struct psmouse *psmouse)
    2052                 :            : {
    2053                 :          0 :         unsigned char param[2] = {0xC8, 0x14};
    2054                 :            : 
    2055   [ #  #  #  # ]:          0 :         if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
    2056         [ #  # ]:          0 :             ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
    2057         [ #  # ]:          0 :             ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
    2058         [ #  # ]:          0 :             ps2_command(&psmouse->ps2dev, &param[0], PSMOUSE_CMD_SETRATE) ||
    2059                 :          0 :             ps2_command(&psmouse->ps2dev, &param[1], PSMOUSE_CMD_SETRATE))
    2060                 :          0 :                 return -1;
    2061                 :            : 
    2062                 :            :         return 0;
    2063                 :            : }
    2064                 :            : 
    2065                 :          0 : static int alps_hw_init_v6(struct psmouse *psmouse)
    2066                 :            : {
    2067                 :          0 :         int ret;
    2068                 :            : 
    2069                 :            :         /* Enter passthrough mode to let trackpoint enter 6byte raw mode */
    2070         [ #  # ]:          0 :         if (alps_passthrough_mode_v2(psmouse, true))
    2071                 :            :                 return -1;
    2072                 :            : 
    2073                 :          0 :         ret = alps_trackstick_enter_extended_mode_v3_v6(psmouse);
    2074                 :            : 
    2075         [ #  # ]:          0 :         if (alps_passthrough_mode_v2(psmouse, false))
    2076                 :            :                 return -1;
    2077                 :            : 
    2078         [ #  # ]:          0 :         if (ret)
    2079                 :            :                 return ret;
    2080                 :            : 
    2081         [ #  # ]:          0 :         if (alps_absolute_mode_v6(psmouse)) {
    2082                 :          0 :                 psmouse_err(psmouse, "Failed to enable absolute mode\n");
    2083                 :          0 :                 return -1;
    2084                 :            :         }
    2085                 :            : 
    2086                 :            :         return 0;
    2087                 :            : }
    2088                 :            : 
    2089                 :            : /*
    2090                 :            :  * Enable or disable passthrough mode to the trackstick.
    2091                 :            :  */
    2092                 :          0 : static int alps_passthrough_mode_v3(struct psmouse *psmouse,
    2093                 :            :                                     int reg_base, bool enable)
    2094                 :            : {
    2095                 :          0 :         int reg_val, ret = -1;
    2096                 :            : 
    2097         [ #  # ]:          0 :         if (alps_enter_command_mode(psmouse))
    2098                 :            :                 return -1;
    2099                 :            : 
    2100                 :          0 :         reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008);
    2101         [ #  # ]:          0 :         if (reg_val == -1)
    2102                 :          0 :                 goto error;
    2103                 :            : 
    2104         [ #  # ]:          0 :         if (enable)
    2105                 :          0 :                 reg_val |= 0x01;
    2106                 :            :         else
    2107                 :          0 :                 reg_val &= ~0x01;
    2108                 :            : 
    2109                 :          0 :         ret = __alps_command_mode_write_reg(psmouse, reg_val);
    2110                 :            : 
    2111                 :          0 : error:
    2112                 :          0 :         if (alps_exit_command_mode(psmouse))
    2113                 :            :                 ret = -1;
    2114                 :            :         return ret;
    2115                 :            : }
    2116                 :            : 
    2117                 :            : /* Must be in command mode when calling this function */
    2118                 :          0 : static int alps_absolute_mode_v3(struct psmouse *psmouse)
    2119                 :            : {
    2120                 :          0 :         int reg_val;
    2121                 :            : 
    2122                 :          0 :         reg_val = alps_command_mode_read_reg(psmouse, 0x0004);
    2123         [ #  # ]:          0 :         if (reg_val == -1)
    2124                 :            :                 return -1;
    2125                 :            : 
    2126                 :          0 :         reg_val |= 0x06;
    2127         [ #  # ]:          0 :         if (__alps_command_mode_write_reg(psmouse, reg_val))
    2128                 :          0 :                 return -1;
    2129                 :            : 
    2130                 :            :         return 0;
    2131                 :            : }
    2132                 :            : 
    2133                 :          0 : static int alps_probe_trackstick_v3_v7(struct psmouse *psmouse, int reg_base)
    2134                 :            : {
    2135                 :          0 :         int ret = -EIO, reg_val;
    2136                 :            : 
    2137         [ #  # ]:          0 :         if (alps_enter_command_mode(psmouse))
    2138                 :          0 :                 goto error;
    2139                 :            : 
    2140                 :          0 :         reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08);
    2141         [ #  # ]:          0 :         if (reg_val == -1)
    2142                 :          0 :                 goto error;
    2143                 :            : 
    2144                 :            :         /* bit 7: trackstick is present */
    2145         [ #  # ]:          0 :         ret = reg_val & 0x80 ? 0 : -ENODEV;
    2146                 :            : 
    2147                 :          0 : error:
    2148                 :          0 :         alps_exit_command_mode(psmouse);
    2149                 :          0 :         return ret;
    2150                 :            : }
    2151                 :            : 
    2152                 :          0 : static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base)
    2153                 :            : {
    2154                 :          0 :         int ret = 0;
    2155                 :          0 :         int reg_val;
    2156                 :          0 :         unsigned char param[4];
    2157                 :            : 
    2158                 :            :         /*
    2159                 :            :          * We need to configure trackstick to report data for touchpad in
    2160                 :            :          * extended format. And also we need to tell touchpad to expect data
    2161                 :            :          * from trackstick in extended format. Without this configuration
    2162                 :            :          * trackstick packets sent from touchpad are in basic format which is
    2163                 :            :          * different from what we expect.
    2164                 :            :          */
    2165                 :            : 
    2166         [ #  # ]:          0 :         if (alps_passthrough_mode_v3(psmouse, reg_base, true))
    2167                 :            :                 return -EIO;
    2168                 :            : 
    2169                 :            :         /*
    2170                 :            :          * E7 report for the trackstick
    2171                 :            :          *
    2172                 :            :          * There have been reports of failures to seem to trace back
    2173                 :            :          * to the above trackstick check failing. When these occur
    2174                 :            :          * this E7 report fails, so when that happens we continue
    2175                 :            :          * with the assumption that there isn't a trackstick after
    2176                 :            :          * all.
    2177                 :            :          */
    2178         [ #  # ]:          0 :         if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_SETSCALE21, param)) {
    2179                 :          0 :                 psmouse_warn(psmouse, "Failed to initialize trackstick (E7 report failed)\n");
    2180                 :          0 :                 ret = -ENODEV;
    2181                 :            :         } else {
    2182                 :          0 :                 psmouse_dbg(psmouse, "trackstick E7 report: %3ph\n", param);
    2183         [ #  # ]:          0 :                 if (alps_trackstick_enter_extended_mode_v3_v6(psmouse)) {
    2184                 :          0 :                         psmouse_err(psmouse, "Failed to enter into trackstick extended mode\n");
    2185                 :          0 :                         ret = -EIO;
    2186                 :            :                 }
    2187                 :            :         }
    2188                 :            : 
    2189         [ #  # ]:          0 :         if (alps_passthrough_mode_v3(psmouse, reg_base, false))
    2190                 :            :                 return -EIO;
    2191                 :            : 
    2192         [ #  # ]:          0 :         if (ret)
    2193                 :            :                 return ret;
    2194                 :            : 
    2195         [ #  # ]:          0 :         if (alps_enter_command_mode(psmouse))
    2196                 :            :                 return -EIO;
    2197                 :            : 
    2198                 :          0 :         reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08);
    2199         [ #  # ]:          0 :         if (reg_val == -1) {
    2200                 :            :                 ret = -EIO;
    2201                 :            :         } else {
    2202                 :            :                 /*
    2203                 :            :                  * Tell touchpad that trackstick is now in extended mode.
    2204                 :            :                  * If bit 1 isn't set the packet format is different.
    2205                 :            :                  */
    2206                 :          0 :                 reg_val |= BIT(1);
    2207         [ #  # ]:          0 :                 if (__alps_command_mode_write_reg(psmouse, reg_val))
    2208                 :          0 :                         ret = -EIO;
    2209                 :            :         }
    2210                 :            : 
    2211                 :          0 :         if (alps_exit_command_mode(psmouse))
    2212                 :          0 :                 return -EIO;
    2213                 :            : 
    2214                 :            :         return ret;
    2215                 :            : }
    2216                 :            : 
    2217                 :          0 : static int alps_hw_init_v3(struct psmouse *psmouse)
    2218                 :            : {
    2219                 :          0 :         struct alps_data *priv = psmouse->private;
    2220                 :          0 :         struct ps2dev *ps2dev = &psmouse->ps2dev;
    2221                 :          0 :         int reg_val;
    2222                 :          0 :         unsigned char param[4];
    2223                 :            : 
    2224   [ #  #  #  # ]:          0 :         if ((priv->flags & ALPS_DUALPOINT) &&
    2225                 :          0 :             alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO)
    2226                 :          0 :                 goto error;
    2227                 :            : 
    2228   [ #  #  #  # ]:          0 :         if (alps_enter_command_mode(psmouse) ||
    2229                 :          0 :             alps_absolute_mode_v3(psmouse)) {
    2230                 :          0 :                 psmouse_err(psmouse, "Failed to enter absolute mode\n");
    2231                 :          0 :                 goto error;
    2232                 :            :         }
    2233                 :            : 
    2234                 :          0 :         reg_val = alps_command_mode_read_reg(psmouse, 0x0006);
    2235         [ #  # ]:          0 :         if (reg_val == -1)
    2236                 :          0 :                 goto error;
    2237         [ #  # ]:          0 :         if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01))
    2238                 :          0 :                 goto error;
    2239                 :            : 
    2240                 :          0 :         reg_val = alps_command_mode_read_reg(psmouse, 0x0007);
    2241         [ #  # ]:          0 :         if (reg_val == -1)
    2242                 :          0 :                 goto error;
    2243         [ #  # ]:          0 :         if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01))
    2244                 :          0 :                 goto error;
    2245                 :            : 
    2246         [ #  # ]:          0 :         if (alps_command_mode_read_reg(psmouse, 0x0144) == -1)
    2247                 :          0 :                 goto error;
    2248         [ #  # ]:          0 :         if (__alps_command_mode_write_reg(psmouse, 0x04))
    2249                 :          0 :                 goto error;
    2250                 :            : 
    2251         [ #  # ]:          0 :         if (alps_command_mode_read_reg(psmouse, 0x0159) == -1)
    2252                 :          0 :                 goto error;
    2253         [ #  # ]:          0 :         if (__alps_command_mode_write_reg(psmouse, 0x03))
    2254                 :          0 :                 goto error;
    2255                 :            : 
    2256         [ #  # ]:          0 :         if (alps_command_mode_read_reg(psmouse, 0x0163) == -1)
    2257                 :          0 :                 goto error;
    2258         [ #  # ]:          0 :         if (alps_command_mode_write_reg(psmouse, 0x0163, 0x03))
    2259                 :          0 :                 goto error;
    2260                 :            : 
    2261         [ #  # ]:          0 :         if (alps_command_mode_read_reg(psmouse, 0x0162) == -1)
    2262                 :          0 :                 goto error;
    2263         [ #  # ]:          0 :         if (alps_command_mode_write_reg(psmouse, 0x0162, 0x04))
    2264                 :          0 :                 goto error;
    2265                 :            : 
    2266                 :          0 :         alps_exit_command_mode(psmouse);
    2267                 :            : 
    2268                 :            :         /* Set rate and enable data reporting */
    2269                 :          0 :         param[0] = 0x64;
    2270   [ #  #  #  # ]:          0 :         if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) ||
    2271                 :          0 :             ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) {
    2272                 :          0 :                 psmouse_err(psmouse, "Failed to enable data reporting\n");
    2273                 :          0 :                 return -1;
    2274                 :            :         }
    2275                 :            : 
    2276                 :            :         return 0;
    2277                 :            : 
    2278                 :          0 : error:
    2279                 :            :         /*
    2280                 :            :          * Leaving the touchpad in command mode will essentially render
    2281                 :            :          * it unusable until the machine reboots, so exit it here just
    2282                 :            :          * to be safe
    2283                 :            :          */
    2284                 :          0 :         alps_exit_command_mode(psmouse);
    2285                 :            :         return -1;
    2286                 :            : }
    2287                 :            : 
    2288                 :          0 : static int alps_get_v3_v7_resolution(struct psmouse *psmouse, int reg_pitch)
    2289                 :            : {
    2290                 :          0 :         int reg, x_pitch, y_pitch, x_electrode, y_electrode, x_phys, y_phys;
    2291                 :          0 :         struct alps_data *priv = psmouse->private;
    2292                 :            : 
    2293                 :          0 :         reg = alps_command_mode_read_reg(psmouse, reg_pitch);
    2294         [ #  # ]:          0 :         if (reg < 0)
    2295                 :            :                 return reg;
    2296                 :            : 
    2297                 :          0 :         x_pitch = (char)(reg << 4) >> 4; /* sign extend lower 4 bits */
    2298                 :          0 :         x_pitch = 50 + 2 * x_pitch; /* In 0.1 mm units */
    2299                 :            : 
    2300                 :          0 :         y_pitch = (char)reg >> 4; /* sign extend upper 4 bits */
    2301                 :          0 :         y_pitch = 36 + 2 * y_pitch; /* In 0.1 mm units */
    2302                 :            : 
    2303                 :          0 :         reg = alps_command_mode_read_reg(psmouse, reg_pitch + 1);
    2304         [ #  # ]:          0 :         if (reg < 0)
    2305                 :            :                 return reg;
    2306                 :            : 
    2307                 :          0 :         x_electrode = (char)(reg << 4) >> 4; /* sign extend lower 4 bits */
    2308                 :          0 :         x_electrode = 17 + x_electrode;
    2309                 :            : 
    2310                 :          0 :         y_electrode = (char)reg >> 4; /* sign extend upper 4 bits */
    2311                 :          0 :         y_electrode = 13 + y_electrode;
    2312                 :            : 
    2313                 :          0 :         x_phys = x_pitch * (x_electrode - 1); /* In 0.1 mm units */
    2314                 :          0 :         y_phys = y_pitch * (y_electrode - 1); /* In 0.1 mm units */
    2315                 :            : 
    2316                 :          0 :         priv->x_res = priv->x_max * 10 / x_phys; /* units / mm */
    2317                 :          0 :         priv->y_res = priv->y_max * 10 / y_phys; /* units / mm */
    2318                 :            : 
    2319                 :          0 :         psmouse_dbg(psmouse,
    2320                 :            :                     "pitch %dx%d num-electrodes %dx%d physical size %dx%d mm res %dx%d\n",
    2321                 :            :                     x_pitch, y_pitch, x_electrode, y_electrode,
    2322                 :            :                     x_phys / 10, y_phys / 10, priv->x_res, priv->y_res);
    2323                 :            : 
    2324                 :          0 :         return 0;
    2325                 :            : }
    2326                 :            : 
    2327                 :          0 : static int alps_hw_init_rushmore_v3(struct psmouse *psmouse)
    2328                 :            : {
    2329                 :          0 :         struct alps_data *priv = psmouse->private;
    2330                 :          0 :         struct ps2dev *ps2dev = &psmouse->ps2dev;
    2331                 :          0 :         int reg_val, ret = -1;
    2332                 :            : 
    2333         [ #  # ]:          0 :         if (priv->flags & ALPS_DUALPOINT) {
    2334                 :          0 :                 reg_val = alps_setup_trackstick_v3(psmouse,
    2335                 :            :                                                    ALPS_REG_BASE_RUSHMORE);
    2336         [ #  # ]:          0 :                 if (reg_val == -EIO)
    2337                 :          0 :                         goto error;
    2338                 :            :         }
    2339                 :            : 
    2340   [ #  #  #  # ]:          0 :         if (alps_enter_command_mode(psmouse) ||
    2341         [ #  # ]:          0 :             alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 ||
    2342                 :          0 :             alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00))
    2343                 :          0 :                 goto error;
    2344                 :            : 
    2345         [ #  # ]:          0 :         if (alps_get_v3_v7_resolution(psmouse, 0xc2da))
    2346                 :          0 :                 goto error;
    2347                 :            : 
    2348                 :          0 :         reg_val = alps_command_mode_read_reg(psmouse, 0xc2c6);
    2349         [ #  # ]:          0 :         if (reg_val == -1)
    2350                 :          0 :                 goto error;
    2351         [ #  # ]:          0 :         if (__alps_command_mode_write_reg(psmouse, reg_val & 0xfd))
    2352                 :          0 :                 goto error;
    2353                 :            : 
    2354         [ #  # ]:          0 :         if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64))
    2355                 :          0 :                 goto error;
    2356                 :            : 
    2357                 :            :         /* enter absolute mode */
    2358                 :          0 :         reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4);
    2359         [ #  # ]:          0 :         if (reg_val == -1)
    2360                 :          0 :                 goto error;
    2361         [ #  # ]:          0 :         if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02))
    2362                 :          0 :                 goto error;
    2363                 :            : 
    2364                 :          0 :         alps_exit_command_mode(psmouse);
    2365                 :          0 :         return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
    2366                 :            : 
    2367                 :          0 : error:
    2368                 :          0 :         alps_exit_command_mode(psmouse);
    2369                 :            :         return ret;
    2370                 :            : }
    2371                 :            : 
    2372                 :            : /* Must be in command mode when calling this function */
    2373                 :          0 : static int alps_absolute_mode_v4(struct psmouse *psmouse)
    2374                 :            : {
    2375                 :          0 :         int reg_val;
    2376                 :            : 
    2377                 :          0 :         reg_val = alps_command_mode_read_reg(psmouse, 0x0004);
    2378         [ #  # ]:          0 :         if (reg_val == -1)
    2379                 :            :                 return -1;
    2380                 :            : 
    2381                 :          0 :         reg_val |= 0x02;
    2382         [ #  # ]:          0 :         if (__alps_command_mode_write_reg(psmouse, reg_val))
    2383                 :          0 :                 return -1;
    2384                 :            : 
    2385                 :            :         return 0;
    2386                 :            : }
    2387                 :            : 
    2388                 :          0 : static int alps_hw_init_v4(struct psmouse *psmouse)
    2389                 :            : {
    2390                 :          0 :         struct ps2dev *ps2dev = &psmouse->ps2dev;
    2391                 :          0 :         unsigned char param[4];
    2392                 :            : 
    2393         [ #  # ]:          0 :         if (alps_enter_command_mode(psmouse))
    2394                 :          0 :                 goto error;
    2395                 :            : 
    2396         [ #  # ]:          0 :         if (alps_absolute_mode_v4(psmouse)) {
    2397                 :          0 :                 psmouse_err(psmouse, "Failed to enter absolute mode\n");
    2398                 :          0 :                 goto error;
    2399                 :            :         }
    2400                 :            : 
    2401         [ #  # ]:          0 :         if (alps_command_mode_write_reg(psmouse, 0x0007, 0x8c))
    2402                 :          0 :                 goto error;
    2403                 :            : 
    2404         [ #  # ]:          0 :         if (alps_command_mode_write_reg(psmouse, 0x0149, 0x03))
    2405                 :          0 :                 goto error;
    2406                 :            : 
    2407         [ #  # ]:          0 :         if (alps_command_mode_write_reg(psmouse, 0x0160, 0x03))
    2408                 :          0 :                 goto error;
    2409                 :            : 
    2410         [ #  # ]:          0 :         if (alps_command_mode_write_reg(psmouse, 0x017f, 0x15))
    2411                 :          0 :                 goto error;
    2412                 :            : 
    2413         [ #  # ]:          0 :         if (alps_command_mode_write_reg(psmouse, 0x0151, 0x01))
    2414                 :          0 :                 goto error;
    2415                 :            : 
    2416         [ #  # ]:          0 :         if (alps_command_mode_write_reg(psmouse, 0x0168, 0x03))
    2417                 :          0 :                 goto error;
    2418                 :            : 
    2419         [ #  # ]:          0 :         if (alps_command_mode_write_reg(psmouse, 0x014a, 0x03))
    2420                 :          0 :                 goto error;
    2421                 :            : 
    2422         [ #  # ]:          0 :         if (alps_command_mode_write_reg(psmouse, 0x0161, 0x03))
    2423                 :          0 :                 goto error;
    2424                 :            : 
    2425                 :          0 :         alps_exit_command_mode(psmouse);
    2426                 :            : 
    2427                 :            :         /*
    2428                 :            :          * This sequence changes the output from a 9-byte to an
    2429                 :            :          * 8-byte format. All the same data seems to be present,
    2430                 :            :          * just in a more compact format.
    2431                 :            :          */
    2432                 :          0 :         param[0] = 0xc8;
    2433                 :          0 :         param[1] = 0x64;
    2434                 :          0 :         param[2] = 0x50;
    2435   [ #  #  #  # ]:          0 :         if (ps2_command(ps2dev, &param[0], PSMOUSE_CMD_SETRATE) ||
    2436         [ #  # ]:          0 :             ps2_command(ps2dev, &param[1], PSMOUSE_CMD_SETRATE) ||
    2437         [ #  # ]:          0 :             ps2_command(ps2dev, &param[2], PSMOUSE_CMD_SETRATE) ||
    2438                 :          0 :             ps2_command(ps2dev, param, PSMOUSE_CMD_GETID))
    2439                 :          0 :                 return -1;
    2440                 :            : 
    2441                 :            :         /* Set rate and enable data reporting */
    2442                 :          0 :         param[0] = 0x64;
    2443   [ #  #  #  # ]:          0 :         if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) ||
    2444                 :          0 :             ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) {
    2445                 :          0 :                 psmouse_err(psmouse, "Failed to enable data reporting\n");
    2446                 :          0 :                 return -1;
    2447                 :            :         }
    2448                 :            : 
    2449                 :            :         return 0;
    2450                 :            : 
    2451                 :          0 : error:
    2452                 :            :         /*
    2453                 :            :          * Leaving the touchpad in command mode will essentially render
    2454                 :            :          * it unusable until the machine reboots, so exit it here just
    2455                 :            :          * to be safe
    2456                 :            :          */
    2457                 :          0 :         alps_exit_command_mode(psmouse);
    2458                 :            :         return -1;
    2459                 :            : }
    2460                 :            : 
    2461                 :          0 : static int alps_get_otp_values_ss4_v2(struct psmouse *psmouse,
    2462                 :            :                                       unsigned char index, unsigned char otp[])
    2463                 :            : {
    2464                 :          0 :         struct ps2dev *ps2dev = &psmouse->ps2dev;
    2465                 :            : 
    2466      [ #  #  # ]:          0 :         switch (index) {
    2467                 :          0 :         case 0:
    2468   [ #  #  #  # ]:          0 :                 if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)  ||
    2469         [ #  # ]:          0 :                     ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)  ||
    2470                 :          0 :                     ps2_command(ps2dev, otp, PSMOUSE_CMD_GETINFO))
    2471                 :          0 :                         return -1;
    2472                 :            : 
    2473                 :            :                 break;
    2474                 :            : 
    2475                 :          0 :         case 1:
    2476   [ #  #  #  # ]:          0 :                 if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL)  ||
    2477         [ #  # ]:          0 :                     ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL)  ||
    2478                 :          0 :                     ps2_command(ps2dev, otp, PSMOUSE_CMD_GETINFO))
    2479                 :          0 :                         return -1;
    2480                 :            : 
    2481                 :            :                 break;
    2482                 :            :         }
    2483                 :            : 
    2484                 :            :         return 0;
    2485                 :            : }
    2486                 :            : 
    2487                 :          0 : static int alps_update_device_area_ss4_v2(unsigned char otp[][4],
    2488                 :            :                                           struct alps_data *priv)
    2489                 :            : {
    2490                 :          0 :         int num_x_electrode;
    2491                 :          0 :         int num_y_electrode;
    2492                 :          0 :         int x_pitch, y_pitch, x_phys, y_phys;
    2493                 :            : 
    2494   [ #  #  #  # ]:          0 :         if (IS_SS4PLUS_DEV(priv->dev_id)) {
    2495                 :          0 :                 num_x_electrode =
    2496                 :          0 :                         SS4PLUS_NUMSENSOR_XOFFSET + (otp[0][2] & 0x0F);
    2497                 :          0 :                 num_y_electrode =
    2498                 :          0 :                         SS4PLUS_NUMSENSOR_YOFFSET + ((otp[0][2] >> 4) & 0x0F);
    2499                 :            : 
    2500                 :          0 :                 priv->x_max =
    2501                 :          0 :                         (num_x_electrode - 1) * SS4PLUS_COUNT_PER_ELECTRODE;
    2502                 :          0 :                 priv->y_max =
    2503                 :          0 :                         (num_y_electrode - 1) * SS4PLUS_COUNT_PER_ELECTRODE;
    2504                 :            : 
    2505                 :          0 :                 x_pitch = (otp[0][1] & 0x0F) + SS4PLUS_MIN_PITCH_MM;
    2506                 :          0 :                 y_pitch = ((otp[0][1] >> 4) & 0x0F) + SS4PLUS_MIN_PITCH_MM;
    2507                 :            : 
    2508                 :            :         } else {
    2509                 :          0 :                 num_x_electrode =
    2510                 :          0 :                         SS4_NUMSENSOR_XOFFSET + (otp[1][0] & 0x0F);
    2511                 :          0 :                 num_y_electrode =
    2512                 :          0 :                         SS4_NUMSENSOR_YOFFSET + ((otp[1][0] >> 4) & 0x0F);
    2513                 :            : 
    2514                 :          0 :                 priv->x_max =
    2515                 :          0 :                         (num_x_electrode - 1) * SS4_COUNT_PER_ELECTRODE;
    2516                 :          0 :                 priv->y_max =
    2517                 :          0 :                         (num_y_electrode - 1) * SS4_COUNT_PER_ELECTRODE;
    2518                 :            : 
    2519                 :          0 :                 x_pitch = ((otp[1][2] >> 2) & 0x07) + SS4_MIN_PITCH_MM;
    2520                 :          0 :                 y_pitch = ((otp[1][2] >> 5) & 0x07) + SS4_MIN_PITCH_MM;
    2521                 :            :         }
    2522                 :            : 
    2523                 :          0 :         x_phys = x_pitch * (num_x_electrode - 1); /* In 0.1 mm units */
    2524                 :          0 :         y_phys = y_pitch * (num_y_electrode - 1); /* In 0.1 mm units */
    2525                 :            : 
    2526                 :          0 :         priv->x_res = priv->x_max * 10 / x_phys; /* units / mm */
    2527                 :          0 :         priv->y_res = priv->y_max * 10 / y_phys; /* units / mm */
    2528                 :            : 
    2529                 :          0 :         return 0;
    2530                 :            : }
    2531                 :            : 
    2532                 :          0 : static int alps_update_btn_info_ss4_v2(unsigned char otp[][4],
    2533                 :            :                                        struct alps_data *priv)
    2534                 :            : {
    2535                 :          0 :         unsigned char is_btnless;
    2536                 :            : 
    2537         [ #  # ]:          0 :         if (IS_SS4PLUS_DEV(priv->dev_id))
    2538                 :          0 :                 is_btnless = (otp[1][0] >> 1) & 0x01;
    2539                 :            :         else
    2540                 :          0 :                 is_btnless = (otp[1][1] >> 3) & 0x01;
    2541                 :            : 
    2542         [ #  # ]:          0 :         if (is_btnless)
    2543                 :          0 :                 priv->flags |= ALPS_BUTTONPAD;
    2544                 :            : 
    2545                 :          0 :         return 0;
    2546                 :            : }
    2547                 :            : 
    2548                 :            : static int alps_update_dual_info_ss4_v2(unsigned char otp[][4],
    2549                 :            :                                         struct alps_data *priv,
    2550                 :            :                                         struct psmouse *psmouse)
    2551                 :            : {
    2552                 :            :         bool is_dual = false;
    2553                 :            :         int reg_val = 0;
    2554                 :            :         struct ps2dev *ps2dev = &psmouse->ps2dev;
    2555                 :            : 
    2556                 :            :         if (IS_SS4PLUS_DEV(priv->dev_id)) {
    2557                 :            :                 is_dual = (otp[0][0] >> 4) & 0x01;
    2558                 :            : 
    2559                 :            :                 if (!is_dual) {
    2560                 :            :                         /* For support TrackStick of Thinkpad L/E series */
    2561                 :            :                         if (alps_exit_command_mode(psmouse) == 0 &&
    2562                 :            :                                 alps_enter_command_mode(psmouse) == 0) {
    2563                 :            :                                 reg_val = alps_command_mode_read_reg(psmouse,
    2564                 :            :                                                                         0xD7);
    2565                 :            :                         }
    2566                 :            :                         alps_exit_command_mode(psmouse);
    2567                 :            :                         ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
    2568                 :            : 
    2569                 :            :                         if (reg_val == 0x0C || reg_val == 0x1D)
    2570                 :            :                                 is_dual = true;
    2571                 :            :                 }
    2572                 :            :         }
    2573                 :            : 
    2574                 :            :         if (is_dual)
    2575                 :            :                 priv->flags |= ALPS_DUALPOINT |
    2576                 :            :                                         ALPS_DUALPOINT_WITH_PRESSURE;
    2577                 :            : 
    2578                 :            :         return 0;
    2579                 :            : }
    2580                 :            : 
    2581                 :          0 : static int alps_set_defaults_ss4_v2(struct psmouse *psmouse,
    2582                 :            :                                     struct alps_data *priv)
    2583                 :            : {
    2584                 :          0 :         unsigned char otp[2][4];
    2585                 :            : 
    2586                 :          0 :         memset(otp, 0, sizeof(otp));
    2587                 :            : 
    2588   [ #  #  #  # ]:          0 :         if (alps_get_otp_values_ss4_v2(psmouse, 1, &otp[1][0]) ||
    2589                 :          0 :             alps_get_otp_values_ss4_v2(psmouse, 0, &otp[0][0]))
    2590                 :          0 :                 return -1;
    2591                 :            : 
    2592                 :          0 :         alps_update_device_area_ss4_v2(otp, priv);
    2593                 :            : 
    2594         [ #  # ]:          0 :         alps_update_btn_info_ss4_v2(otp, priv);
    2595                 :            : 
    2596                 :          0 :         alps_update_dual_info_ss4_v2(otp, priv, psmouse);
    2597                 :            : 
    2598                 :          0 :         return 0;
    2599                 :            : }
    2600                 :            : 
    2601                 :          0 : static int alps_dolphin_get_device_area(struct psmouse *psmouse,
    2602                 :            :                                         struct alps_data *priv)
    2603                 :            : {
    2604                 :          0 :         struct ps2dev *ps2dev = &psmouse->ps2dev;
    2605                 :          0 :         unsigned char param[4] = {0};
    2606                 :          0 :         int num_x_electrode, num_y_electrode;
    2607                 :            : 
    2608         [ #  # ]:          0 :         if (alps_enter_command_mode(psmouse))
    2609                 :            :                 return -1;
    2610                 :            : 
    2611                 :          0 :         param[0] = 0x0a;
    2612   [ #  #  #  # ]:          0 :         if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) ||
    2613         [ #  # ]:          0 :             ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) ||
    2614         [ #  # ]:          0 :             ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) ||
    2615         [ #  # ]:          0 :             ps2_command(ps2dev, &param[0], PSMOUSE_CMD_SETRATE) ||
    2616                 :          0 :             ps2_command(ps2dev, &param[0], PSMOUSE_CMD_SETRATE))
    2617                 :          0 :                 return -1;
    2618                 :            : 
    2619         [ #  # ]:          0 :         if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
    2620                 :            :                 return -1;
    2621                 :            : 
    2622                 :            :         /*
    2623                 :            :          * Dolphin's sensor line number is not fixed. It can be calculated
    2624                 :            :          * by adding the device's register value with DOLPHIN_PROFILE_X/YOFFSET.
    2625                 :            :          * Further more, we can get device's x_max and y_max by multiplying
    2626                 :            :          * sensor line number with DOLPHIN_COUNT_PER_ELECTRODE.
    2627                 :            :          *
    2628                 :            :          * e.g. When we get register's sensor_x = 11 & sensor_y = 8,
    2629                 :            :          *      real sensor line number X = 11 + 8 = 19, and
    2630                 :            :          *      real sensor line number Y = 8 + 1 = 9.
    2631                 :            :          *      So, x_max = (19 - 1) * 64 = 1152, and
    2632                 :            :          *          y_max = (9 - 1) * 64 = 512.
    2633                 :            :          */
    2634                 :          0 :         num_x_electrode = DOLPHIN_PROFILE_XOFFSET + (param[2] & 0x0F);
    2635                 :          0 :         num_y_electrode = DOLPHIN_PROFILE_YOFFSET + ((param[2] >> 4) & 0x0F);
    2636                 :          0 :         priv->x_bits = num_x_electrode;
    2637                 :          0 :         priv->y_bits = num_y_electrode;
    2638                 :          0 :         priv->x_max = (num_x_electrode - 1) * DOLPHIN_COUNT_PER_ELECTRODE;
    2639                 :          0 :         priv->y_max = (num_y_electrode - 1) * DOLPHIN_COUNT_PER_ELECTRODE;
    2640                 :            : 
    2641                 :          0 :         if (alps_exit_command_mode(psmouse))
    2642                 :          0 :                 return -1;
    2643                 :            : 
    2644                 :            :         return 0;
    2645                 :            : }
    2646                 :            : 
    2647                 :          0 : static int alps_hw_init_dolphin_v1(struct psmouse *psmouse)
    2648                 :            : {
    2649                 :          0 :         struct ps2dev *ps2dev = &psmouse->ps2dev;
    2650                 :          0 :         unsigned char param[2];
    2651                 :            : 
    2652                 :            :         /* This is dolphin "v1" as empirically defined by florin9doi */
    2653                 :          0 :         param[0] = 0x64;
    2654                 :          0 :         param[1] = 0x28;
    2655                 :            : 
    2656   [ #  #  #  # ]:          0 :         if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) ||
    2657         [ #  # ]:          0 :             ps2_command(ps2dev, &param[0], PSMOUSE_CMD_SETRATE) ||
    2658                 :          0 :             ps2_command(ps2dev, &param[1], PSMOUSE_CMD_SETRATE))
    2659                 :          0 :                 return -1;
    2660                 :            : 
    2661                 :            :         return 0;
    2662                 :            : }
    2663                 :            : 
    2664                 :          0 : static int alps_hw_init_v7(struct psmouse *psmouse)
    2665                 :            : {
    2666                 :          0 :         struct ps2dev *ps2dev = &psmouse->ps2dev;
    2667                 :          0 :         int reg_val, ret = -1;
    2668                 :            : 
    2669   [ #  #  #  # ]:          0 :         if (alps_enter_command_mode(psmouse) ||
    2670                 :          0 :             alps_command_mode_read_reg(psmouse, 0xc2d9) == -1)
    2671                 :          0 :                 goto error;
    2672                 :            : 
    2673         [ #  # ]:          0 :         if (alps_get_v3_v7_resolution(psmouse, 0xc397))
    2674                 :          0 :                 goto error;
    2675                 :            : 
    2676         [ #  # ]:          0 :         if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64))
    2677                 :          0 :                 goto error;
    2678                 :            : 
    2679                 :          0 :         reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4);
    2680         [ #  # ]:          0 :         if (reg_val == -1)
    2681                 :          0 :                 goto error;
    2682         [ #  # ]:          0 :         if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02))
    2683                 :          0 :                 goto error;
    2684                 :            : 
    2685                 :          0 :         alps_exit_command_mode(psmouse);
    2686                 :          0 :         return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
    2687                 :            : 
    2688                 :          0 : error:
    2689                 :          0 :         alps_exit_command_mode(psmouse);
    2690                 :            :         return ret;
    2691                 :            : }
    2692                 :            : 
    2693                 :          0 : static int alps_hw_init_ss4_v2(struct psmouse *psmouse)
    2694                 :            : {
    2695                 :          0 :         struct ps2dev *ps2dev = &psmouse->ps2dev;
    2696                 :          0 :         char param[2] = {0x64, 0x28};
    2697                 :          0 :         int ret = -1;
    2698                 :            : 
    2699                 :            :         /* enter absolute mode */
    2700   [ #  #  #  # ]:          0 :         if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) ||
    2701         [ #  # ]:          0 :             ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) ||
    2702         [ #  # ]:          0 :             ps2_command(ps2dev, &param[0], PSMOUSE_CMD_SETRATE) ||
    2703                 :          0 :             ps2_command(ps2dev, &param[1], PSMOUSE_CMD_SETRATE)) {
    2704                 :          0 :                 goto error;
    2705                 :            :         }
    2706                 :            : 
    2707                 :            :         /* T.B.D. Decread noise packet number, delete in the future */
    2708         [ #  # ]:          0 :         if (alps_exit_command_mode(psmouse) ||
    2709         [ #  # ]:          0 :             alps_enter_command_mode(psmouse) ||
    2710                 :          0 :             alps_command_mode_write_reg(psmouse, 0x001D, 0x20)) {
    2711                 :          0 :                 goto error;
    2712                 :            :         }
    2713                 :          0 :         alps_exit_command_mode(psmouse);
    2714                 :            : 
    2715                 :          0 :         return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
    2716                 :            : 
    2717                 :          0 : error:
    2718                 :          0 :         alps_exit_command_mode(psmouse);
    2719                 :            :         return ret;
    2720                 :            : }
    2721                 :            : 
    2722                 :          0 : static int alps_set_protocol(struct psmouse *psmouse,
    2723                 :            :                              struct alps_data *priv,
    2724                 :            :                              const struct alps_protocol_info *protocol)
    2725                 :            : {
    2726                 :          0 :         psmouse->private = priv;
    2727                 :            : 
    2728                 :          0 :         timer_setup(&priv->timer, alps_flush_packet, 0);
    2729                 :            : 
    2730                 :          0 :         priv->proto_version = protocol->version;
    2731                 :          0 :         priv->byte0 = protocol->byte0;
    2732                 :          0 :         priv->mask0 = protocol->mask0;
    2733                 :          0 :         priv->flags = protocol->flags;
    2734                 :            : 
    2735                 :          0 :         priv->x_max = 2000;
    2736                 :          0 :         priv->y_max = 1400;
    2737                 :          0 :         priv->x_bits = 15;
    2738                 :          0 :         priv->y_bits = 11;
    2739                 :            : 
    2740   [ #  #  #  #  :          0 :         switch (priv->proto_version) {
             #  #  #  #  
                      # ]
    2741                 :          0 :         case ALPS_PROTO_V1:
    2742                 :            :         case ALPS_PROTO_V2:
    2743                 :          0 :                 priv->hw_init = alps_hw_init_v1_v2;
    2744                 :          0 :                 priv->process_packet = alps_process_packet_v1_v2;
    2745                 :          0 :                 priv->set_abs_params = alps_set_abs_params_st;
    2746                 :          0 :                 priv->x_max = 1023;
    2747                 :          0 :                 priv->y_max = 767;
    2748         [ #  # ]:          0 :                 if (dmi_check_system(alps_dmi_has_separate_stick_buttons))
    2749                 :          0 :                         priv->flags |= ALPS_STICK_BITS;
    2750                 :            :                 break;
    2751                 :            : 
    2752                 :          0 :         case ALPS_PROTO_V3:
    2753                 :          0 :                 priv->hw_init = alps_hw_init_v3;
    2754                 :          0 :                 priv->process_packet = alps_process_packet_v3;
    2755                 :          0 :                 priv->set_abs_params = alps_set_abs_params_semi_mt;
    2756                 :          0 :                 priv->decode_fields = alps_decode_pinnacle;
    2757                 :          0 :                 priv->nibble_commands = alps_v3_nibble_commands;
    2758                 :          0 :                 priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
    2759                 :            : 
    2760         [ #  # ]:          0 :                 if (alps_probe_trackstick_v3_v7(psmouse,
    2761                 :            :                                                 ALPS_REG_BASE_PINNACLE) < 0)
    2762                 :          0 :                         priv->flags &= ~ALPS_DUALPOINT;
    2763                 :            : 
    2764                 :            :                 break;
    2765                 :            : 
    2766                 :          0 :         case ALPS_PROTO_V3_RUSHMORE:
    2767                 :          0 :                 priv->hw_init = alps_hw_init_rushmore_v3;
    2768                 :          0 :                 priv->process_packet = alps_process_packet_v3;
    2769                 :          0 :                 priv->set_abs_params = alps_set_abs_params_semi_mt;
    2770                 :          0 :                 priv->decode_fields = alps_decode_rushmore;
    2771                 :          0 :                 priv->nibble_commands = alps_v3_nibble_commands;
    2772                 :          0 :                 priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
    2773                 :          0 :                 priv->x_bits = 16;
    2774                 :          0 :                 priv->y_bits = 12;
    2775                 :            : 
    2776         [ #  # ]:          0 :                 if (alps_probe_trackstick_v3_v7(psmouse,
    2777                 :            :                                                 ALPS_REG_BASE_RUSHMORE) < 0)
    2778                 :          0 :                         priv->flags &= ~ALPS_DUALPOINT;
    2779                 :            : 
    2780                 :            :                 break;
    2781                 :            : 
    2782                 :          0 :         case ALPS_PROTO_V4:
    2783                 :          0 :                 priv->hw_init = alps_hw_init_v4;
    2784                 :          0 :                 priv->process_packet = alps_process_packet_v4;
    2785                 :          0 :                 priv->set_abs_params = alps_set_abs_params_semi_mt;
    2786                 :          0 :                 priv->nibble_commands = alps_v4_nibble_commands;
    2787                 :          0 :                 priv->addr_command = PSMOUSE_CMD_DISABLE;
    2788                 :          0 :                 break;
    2789                 :            : 
    2790                 :          0 :         case ALPS_PROTO_V5:
    2791                 :          0 :                 priv->hw_init = alps_hw_init_dolphin_v1;
    2792                 :          0 :                 priv->process_packet = alps_process_touchpad_packet_v3_v5;
    2793                 :          0 :                 priv->decode_fields = alps_decode_dolphin;
    2794                 :          0 :                 priv->set_abs_params = alps_set_abs_params_semi_mt;
    2795                 :          0 :                 priv->nibble_commands = alps_v3_nibble_commands;
    2796                 :          0 :                 priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
    2797                 :          0 :                 priv->x_bits = 23;
    2798                 :          0 :                 priv->y_bits = 12;
    2799                 :            : 
    2800         [ #  # ]:          0 :                 if (alps_dolphin_get_device_area(psmouse, priv))
    2801                 :          0 :                         return -EIO;
    2802                 :            : 
    2803                 :            :                 break;
    2804                 :            : 
    2805                 :          0 :         case ALPS_PROTO_V6:
    2806                 :          0 :                 priv->hw_init = alps_hw_init_v6;
    2807                 :          0 :                 priv->process_packet = alps_process_packet_v6;
    2808                 :          0 :                 priv->set_abs_params = alps_set_abs_params_st;
    2809                 :          0 :                 priv->nibble_commands = alps_v6_nibble_commands;
    2810                 :          0 :                 priv->x_max = 2047;
    2811                 :          0 :                 priv->y_max = 1535;
    2812                 :          0 :                 break;
    2813                 :            : 
    2814                 :          0 :         case ALPS_PROTO_V7:
    2815                 :          0 :                 priv->hw_init = alps_hw_init_v7;
    2816                 :          0 :                 priv->process_packet = alps_process_packet_v7;
    2817                 :          0 :                 priv->decode_fields = alps_decode_packet_v7;
    2818                 :          0 :                 priv->set_abs_params = alps_set_abs_params_v7;
    2819                 :          0 :                 priv->nibble_commands = alps_v3_nibble_commands;
    2820                 :          0 :                 priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
    2821                 :          0 :                 priv->x_max = 0xfff;
    2822                 :          0 :                 priv->y_max = 0x7ff;
    2823                 :            : 
    2824         [ #  # ]:          0 :                 if (priv->fw_ver[1] != 0xba)
    2825                 :          0 :                         priv->flags |= ALPS_BUTTONPAD;
    2826                 :            : 
    2827         [ #  # ]:          0 :                 if (alps_probe_trackstick_v3_v7(psmouse, ALPS_REG_BASE_V7) < 0)
    2828                 :          0 :                         priv->flags &= ~ALPS_DUALPOINT;
    2829                 :            : 
    2830                 :            :                 break;
    2831                 :            : 
    2832                 :          0 :         case ALPS_PROTO_V8:
    2833                 :          0 :                 priv->hw_init = alps_hw_init_ss4_v2;
    2834                 :          0 :                 priv->process_packet = alps_process_packet_ss4_v2;
    2835                 :          0 :                 priv->decode_fields = alps_decode_ss4_v2;
    2836                 :          0 :                 priv->set_abs_params = alps_set_abs_params_ss4_v2;
    2837                 :          0 :                 priv->nibble_commands = alps_v3_nibble_commands;
    2838                 :          0 :                 priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
    2839                 :            : 
    2840         [ #  # ]:          0 :                 if (alps_set_defaults_ss4_v2(psmouse, priv))
    2841                 :          0 :                         return -EIO;
    2842                 :            : 
    2843                 :            :                 break;
    2844                 :            :         }
    2845                 :            : 
    2846                 :            :         return 0;
    2847                 :            : }
    2848                 :            : 
    2849                 :            : static const struct alps_protocol_info *alps_match_table(unsigned char *e7,
    2850                 :            :                                                          unsigned char *ec)
    2851                 :            : {
    2852                 :            :         const struct alps_model_info *model;
    2853                 :            :         int i;
    2854                 :            : 
    2855         [ #  # ]:          0 :         for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) {
    2856                 :          0 :                 model = &alps_model_data[i];
    2857                 :            : 
    2858         [ #  # ]:          0 :                 if (!memcmp(e7, model->signature, sizeof(model->signature)))
    2859                 :          0 :                         return &model->protocol_info;
    2860                 :            :         }
    2861                 :            : 
    2862                 :            :         return NULL;
    2863                 :            : }
    2864                 :            : 
    2865                 :          0 : static bool alps_is_cs19_trackpoint(struct psmouse *psmouse)
    2866                 :            : {
    2867                 :          0 :         u8 param[2] = { 0 };
    2868                 :            : 
    2869         [ #  # ]:          0 :         if (ps2_command(&psmouse->ps2dev,
    2870                 :            :                         param, MAKE_PS2_CMD(0, 2, TP_READ_ID)))
    2871                 :            :                 return false;
    2872                 :            : 
    2873                 :            :         /*
    2874                 :            :          * param[0] contains the trackpoint device variant_id while
    2875                 :            :          * param[1] contains the firmware_id. So far all alps
    2876                 :            :          * trackpoint-only devices have their variant_ids equal
    2877                 :            :          * TP_VARIANT_ALPS and their firmware_ids are in 0x20~0x2f range.
    2878                 :            :          */
    2879   [ #  #  #  # ]:          0 :         return param[0] == TP_VARIANT_ALPS && ((param[1] & 0xf0) == 0x20);
    2880                 :            : }
    2881                 :            : 
    2882                 :         78 : static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
    2883                 :            : {
    2884                 :         78 :         const struct alps_protocol_info *protocol;
    2885                 :         78 :         unsigned char e6[4], e7[4], ec[4];
    2886                 :         78 :         int error;
    2887                 :            : 
    2888                 :            :         /*
    2889                 :            :          * First try "E6 report".
    2890                 :            :          * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed.
    2891                 :            :          * The bits 0-2 of the first byte will be 1s if some buttons are
    2892                 :            :          * pressed.
    2893                 :            :          */
    2894         [ +  - ]:         78 :         if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES,
    2895                 :            :                          PSMOUSE_CMD_SETSCALE11, e6))
    2896                 :            :                 return -EIO;
    2897                 :            : 
    2898   [ +  -  +  -  :         78 :         if ((e6[0] & 0xf8) != 0 || e6[1] != 0 || (e6[2] != 10 && e6[2] != 100))
                   +  - ]
    2899                 :            :                 return -EINVAL;
    2900                 :            : 
    2901                 :            :         /*
    2902                 :            :          * Now get the "E7" and "EC" reports.  These will uniquely identify
    2903                 :            :          * most ALPS touchpads.
    2904                 :            :          */
    2905         [ +  - ]:         78 :         if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES,
    2906         [ -  + ]:         78 :                          PSMOUSE_CMD_SETSCALE21, e7) ||
    2907                 :         78 :             alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES,
    2908                 :            :                          PSMOUSE_CMD_RESET_WRAP, ec) ||
    2909                 :            :             alps_exit_command_mode(psmouse))
    2910                 :         78 :                 return -EIO;
    2911                 :            : 
    2912                 :            :         protocol = alps_match_table(e7, ec);
    2913         [ #  # ]:          0 :         if (!protocol) {
    2914   [ #  #  #  #  :          0 :                 if (e7[0] == 0x73 && e7[1] == 0x02 && e7[2] == 0x64 &&
                   #  # ]
    2915         [ #  # ]:          0 :                            ec[2] == 0x8a) {
    2916                 :            :                         protocol = &alps_v4_protocol_data;
    2917   [ #  #  #  #  :          0 :                 } else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 &&
                   #  # ]
    2918   [ #  #  #  # ]:          0 :                            ec[0] == 0x73 && (ec[1] == 0x01 || ec[1] == 0x02)) {
    2919                 :            :                         protocol = &alps_v5_protocol_data;
    2920         [ #  # ]:          0 :                 } else if (ec[0] == 0x88 &&
    2921         [ #  # ]:          0 :                            ((ec[1] & 0xf0) == 0xb0 || (ec[1] & 0xf0) == 0xc0)) {
    2922                 :            :                         protocol = &alps_v7_protocol_data;
    2923   [ #  #  #  # ]:          0 :                 } else if (ec[0] == 0x88 && ec[1] == 0x08) {
    2924                 :            :                         protocol = &alps_v3_rushmore_data;
    2925   [ #  #  #  # ]:          0 :                 } else if (ec[0] == 0x88 && ec[1] == 0x07 &&
    2926   [ #  #  #  # ]:          0 :                            ec[2] >= 0x90 && ec[2] <= 0x9d) {
    2927                 :            :                         protocol = &alps_v3_protocol_data;
    2928   [ #  #  #  # ]:          0 :                 } else if (e7[0] == 0x73 && e7[1] == 0x03 &&
    2929         [ #  # ]:          0 :                            (e7[2] == 0x14 || e7[2] == 0x28)) {
    2930                 :            :                         protocol = &alps_v8_protocol_data;
    2931   [ #  #  #  #  :          0 :                 } else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0xc8) {
                   #  # ]
    2932                 :          0 :                         protocol = &alps_v9_protocol_data;
    2933                 :          0 :                         psmouse_warn(psmouse,
    2934                 :            :                                      "Unsupported ALPS V9 touchpad: E7=%3ph, EC=%3ph\n",
    2935                 :            :                                      e7, ec);
    2936                 :          0 :                         return -EINVAL;
    2937                 :            :                 } else {
    2938                 :            :                         psmouse_dbg(psmouse,
    2939                 :            :                                     "Likely not an ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec);
    2940                 :            :                         return -EINVAL;
    2941                 :            :                 }
    2942                 :            :         }
    2943                 :            : 
    2944         [ #  # ]:          0 :         if (priv) {
    2945                 :            :                 /* Save Device ID and Firmware version */
    2946                 :          0 :                 memcpy(priv->dev_id, e7, 3);
    2947                 :          0 :                 memcpy(priv->fw_ver, ec, 3);
    2948                 :          0 :                 error = alps_set_protocol(psmouse, priv, protocol);
    2949         [ #  # ]:          0 :                 if (error)
    2950                 :          0 :                         return error;
    2951                 :            :         }
    2952                 :            : 
    2953                 :            :         return 0;
    2954                 :            : }
    2955                 :            : 
    2956                 :          0 : static int alps_reconnect(struct psmouse *psmouse)
    2957                 :            : {
    2958                 :          0 :         struct alps_data *priv = psmouse->private;
    2959                 :            : 
    2960                 :          0 :         psmouse_reset(psmouse);
    2961                 :            : 
    2962         [ #  # ]:          0 :         if (alps_identify(psmouse, priv) < 0)
    2963                 :            :                 return -1;
    2964                 :            : 
    2965                 :          0 :         return priv->hw_init(psmouse);
    2966                 :            : }
    2967                 :            : 
    2968                 :          0 : static void alps_disconnect(struct psmouse *psmouse)
    2969                 :            : {
    2970                 :          0 :         struct alps_data *priv = psmouse->private;
    2971                 :            : 
    2972                 :          0 :         psmouse_reset(psmouse);
    2973                 :          0 :         del_timer_sync(&priv->timer);
    2974         [ #  # ]:          0 :         if (priv->dev2)
    2975                 :          0 :                 input_unregister_device(priv->dev2);
    2976   [ #  #  #  # ]:          0 :         if (!IS_ERR_OR_NULL(priv->dev3))
    2977                 :          0 :                 input_unregister_device(priv->dev3);
    2978                 :          0 :         kfree(priv);
    2979                 :          0 : }
    2980                 :            : 
    2981                 :          0 : static void alps_set_abs_params_st(struct alps_data *priv,
    2982                 :            :                                    struct input_dev *dev1)
    2983                 :            : {
    2984                 :          0 :         input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0);
    2985                 :          0 :         input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0);
    2986                 :          0 :         input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
    2987                 :          0 : }
    2988                 :            : 
    2989                 :          0 : static void alps_set_abs_params_mt_common(struct alps_data *priv,
    2990                 :            :                                           struct input_dev *dev1)
    2991                 :            : {
    2992                 :          0 :         input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0);
    2993                 :          0 :         input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0);
    2994                 :            : 
    2995                 :          0 :         input_abs_set_res(dev1, ABS_MT_POSITION_X, priv->x_res);
    2996                 :          0 :         input_abs_set_res(dev1, ABS_MT_POSITION_Y, priv->y_res);
    2997                 :            : 
    2998                 :          0 :         set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit);
    2999                 :          0 :         set_bit(BTN_TOOL_QUADTAP, dev1->keybit);
    3000                 :          0 : }
    3001                 :            : 
    3002                 :          0 : static void alps_set_abs_params_semi_mt(struct alps_data *priv,
    3003                 :            :                                         struct input_dev *dev1)
    3004                 :            : {
    3005                 :          0 :         alps_set_abs_params_mt_common(priv, dev1);
    3006                 :          0 :         input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
    3007                 :            : 
    3008                 :          0 :         input_mt_init_slots(dev1, MAX_TOUCHES,
    3009                 :            :                             INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED |
    3010                 :            :                                 INPUT_MT_SEMI_MT);
    3011                 :          0 : }
    3012                 :            : 
    3013                 :          0 : static void alps_set_abs_params_v7(struct alps_data *priv,
    3014                 :            :                                    struct input_dev *dev1)
    3015                 :            : {
    3016                 :          0 :         alps_set_abs_params_mt_common(priv, dev1);
    3017                 :          0 :         set_bit(BTN_TOOL_QUINTTAP, dev1->keybit);
    3018                 :            : 
    3019                 :          0 :         input_mt_init_slots(dev1, MAX_TOUCHES,
    3020                 :            :                             INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED |
    3021                 :            :                                 INPUT_MT_TRACK);
    3022                 :            : 
    3023                 :          0 :         set_bit(BTN_TOOL_QUINTTAP, dev1->keybit);
    3024                 :          0 : }
    3025                 :            : 
    3026                 :          0 : static void alps_set_abs_params_ss4_v2(struct alps_data *priv,
    3027                 :            :                                        struct input_dev *dev1)
    3028                 :            : {
    3029                 :          0 :         alps_set_abs_params_mt_common(priv, dev1);
    3030                 :          0 :         input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
    3031                 :          0 :         set_bit(BTN_TOOL_QUINTTAP, dev1->keybit);
    3032                 :            : 
    3033                 :          0 :         input_mt_init_slots(dev1, MAX_TOUCHES,
    3034                 :            :                             INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED |
    3035                 :            :                                 INPUT_MT_TRACK);
    3036                 :          0 : }
    3037                 :            : 
    3038                 :          0 : int alps_init(struct psmouse *psmouse)
    3039                 :            : {
    3040                 :          0 :         struct alps_data *priv = psmouse->private;
    3041                 :          0 :         struct input_dev *dev1 = psmouse->dev;
    3042                 :          0 :         int error;
    3043                 :            : 
    3044                 :          0 :         error = priv->hw_init(psmouse);
    3045         [ #  # ]:          0 :         if (error)
    3046                 :          0 :                 goto init_fail;
    3047                 :            : 
    3048                 :            :         /*
    3049                 :            :          * Undo part of setup done for us by psmouse core since touchpad
    3050                 :            :          * is not a relative device.
    3051                 :            :          */
    3052                 :          0 :         __clear_bit(EV_REL, dev1->evbit);
    3053                 :          0 :         __clear_bit(REL_X, dev1->relbit);
    3054                 :          0 :         __clear_bit(REL_Y, dev1->relbit);
    3055                 :            : 
    3056                 :            :         /*
    3057                 :            :          * Now set up our capabilities.
    3058                 :            :          */
    3059                 :          0 :         dev1->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY);
    3060                 :          0 :         dev1->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH);
    3061                 :          0 :         dev1->keybit[BIT_WORD(BTN_TOOL_FINGER)] |= BIT_MASK(BTN_TOOL_FINGER);
    3062                 :          0 :         dev1->keybit[BIT_WORD(BTN_LEFT)] |=
    3063                 :            :                 BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT);
    3064                 :            : 
    3065                 :          0 :         dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS);
    3066                 :            : 
    3067                 :          0 :         priv->set_abs_params(priv, dev1);
    3068                 :            : 
    3069         [ #  # ]:          0 :         if (priv->flags & ALPS_WHEEL) {
    3070                 :          0 :                 dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL);
    3071                 :          0 :                 dev1->relbit[BIT_WORD(REL_WHEEL)] |= BIT_MASK(REL_WHEEL);
    3072                 :            :         }
    3073                 :            : 
    3074         [ #  # ]:          0 :         if (priv->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
    3075                 :          0 :                 dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD);
    3076                 :          0 :                 dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK);
    3077                 :            :         }
    3078                 :            : 
    3079         [ #  # ]:          0 :         if (priv->flags & ALPS_FOUR_BUTTONS) {
    3080                 :          0 :                 dev1->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0);
    3081                 :          0 :                 dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1);
    3082                 :          0 :                 dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2);
    3083                 :          0 :                 dev1->keybit[BIT_WORD(BTN_3)] |= BIT_MASK(BTN_3);
    3084         [ #  # ]:          0 :         } else if (priv->flags & ALPS_BUTTONPAD) {
    3085                 :          0 :                 set_bit(INPUT_PROP_BUTTONPAD, dev1->propbit);
    3086                 :          0 :                 clear_bit(BTN_RIGHT, dev1->keybit);
    3087                 :            :         } else {
    3088                 :          0 :                 dev1->keybit[BIT_WORD(BTN_MIDDLE)] |= BIT_MASK(BTN_MIDDLE);
    3089                 :            :         }
    3090                 :            : 
    3091         [ #  # ]:          0 :         if (priv->flags & ALPS_DUALPOINT) {
    3092                 :          0 :                 struct input_dev *dev2;
    3093                 :            : 
    3094                 :          0 :                 dev2 = input_allocate_device();
    3095         [ #  # ]:          0 :                 if (!dev2) {
    3096                 :          0 :                         psmouse_err(psmouse,
    3097                 :            :                                     "failed to allocate trackstick device\n");
    3098                 :          0 :                         error = -ENOMEM;
    3099                 :          0 :                         goto init_fail;
    3100                 :            :                 }
    3101                 :            : 
    3102                 :          0 :                 snprintf(priv->phys2, sizeof(priv->phys2), "%s/input1",
    3103                 :          0 :                          psmouse->ps2dev.serio->phys);
    3104                 :          0 :                 dev2->phys = priv->phys2;
    3105                 :            : 
    3106                 :            :                 /*
    3107                 :            :                  * format of input device name is: "protocol vendor name"
    3108                 :            :                  * see function psmouse_switch_protocol() in psmouse-base.c
    3109                 :            :                  */
    3110                 :          0 :                 dev2->name = "AlpsPS/2 ALPS DualPoint Stick";
    3111                 :            : 
    3112                 :          0 :                 dev2->id.bustype = BUS_I8042;
    3113                 :          0 :                 dev2->id.vendor  = 0x0002;
    3114                 :          0 :                 dev2->id.product = PSMOUSE_ALPS;
    3115                 :          0 :                 dev2->id.version = priv->proto_version;
    3116                 :          0 :                 dev2->dev.parent = &psmouse->ps2dev.serio->dev;
    3117                 :            : 
    3118                 :          0 :                 input_set_capability(dev2, EV_REL, REL_X);
    3119                 :          0 :                 input_set_capability(dev2, EV_REL, REL_Y);
    3120         [ #  # ]:          0 :                 if (priv->flags & ALPS_DUALPOINT_WITH_PRESSURE) {
    3121                 :          0 :                         input_set_capability(dev2, EV_ABS, ABS_PRESSURE);
    3122                 :          0 :                         input_set_abs_params(dev2, ABS_PRESSURE, 0, 127, 0, 0);
    3123                 :            :                 }
    3124                 :          0 :                 input_set_capability(dev2, EV_KEY, BTN_LEFT);
    3125                 :          0 :                 input_set_capability(dev2, EV_KEY, BTN_RIGHT);
    3126                 :          0 :                 input_set_capability(dev2, EV_KEY, BTN_MIDDLE);
    3127                 :            : 
    3128                 :          0 :                 __set_bit(INPUT_PROP_POINTER, dev2->propbit);
    3129                 :          0 :                 __set_bit(INPUT_PROP_POINTING_STICK, dev2->propbit);
    3130                 :            : 
    3131                 :          0 :                 error = input_register_device(dev2);
    3132         [ #  # ]:          0 :                 if (error) {
    3133                 :          0 :                         psmouse_err(psmouse,
    3134                 :            :                                     "failed to register trackstick device: %d\n",
    3135                 :            :                                     error);
    3136                 :          0 :                         input_free_device(dev2);
    3137                 :          0 :                         goto init_fail;
    3138                 :            :                 }
    3139                 :            : 
    3140                 :          0 :                 priv->dev2 = dev2;
    3141                 :            :         }
    3142                 :            : 
    3143                 :          0 :         priv->psmouse = psmouse;
    3144                 :            : 
    3145                 :          0 :         INIT_DELAYED_WORK(&priv->dev3_register_work,
    3146                 :            :                           alps_register_bare_ps2_mouse);
    3147                 :            : 
    3148                 :          0 :         psmouse->protocol_handler = alps_process_byte;
    3149                 :          0 :         psmouse->poll = alps_poll;
    3150                 :          0 :         psmouse->disconnect = alps_disconnect;
    3151                 :          0 :         psmouse->reconnect = alps_reconnect;
    3152         [ #  # ]:          0 :         psmouse->pktsize = priv->proto_version == ALPS_PROTO_V4 ? 8 : 6;
    3153                 :            : 
    3154                 :            :         /* We are having trouble resyncing ALPS touchpads so disable it for now */
    3155                 :          0 :         psmouse->resync_time = 0;
    3156                 :            : 
    3157                 :            :         /* Allow 2 invalid packets without resetting device */
    3158                 :          0 :         psmouse->resetafter = psmouse->pktsize * 2;
    3159                 :            : 
    3160                 :          0 :         return 0;
    3161                 :            : 
    3162                 :          0 : init_fail:
    3163                 :          0 :         psmouse_reset(psmouse);
    3164                 :            :         /*
    3165                 :            :          * Even though we did not allocate psmouse->private we do free
    3166                 :            :          * it here.
    3167                 :            :          */
    3168                 :          0 :         kfree(psmouse->private);
    3169                 :          0 :         psmouse->private = NULL;
    3170                 :          0 :         return error;
    3171                 :            : }
    3172                 :            : 
    3173                 :         78 : int alps_detect(struct psmouse *psmouse, bool set_properties)
    3174                 :            : {
    3175                 :         78 :         struct alps_data *priv;
    3176                 :         78 :         int error;
    3177                 :            : 
    3178                 :         78 :         error = alps_identify(psmouse, NULL);
    3179         [ -  + ]:         78 :         if (error)
    3180                 :            :                 return error;
    3181                 :            : 
    3182                 :            :         /*
    3183                 :            :          * ALPS cs19 is a trackpoint-only device, and uses different
    3184                 :            :          * protocol than DualPoint ones, so we return -EINVAL here and let
    3185                 :            :          * trackpoint.c drive this device. If the trackpoint driver is not
    3186                 :            :          * enabled, the device will fall back to a bare PS/2 mouse.
    3187                 :            :          * If ps2_command() fails here, we depend on the immediately
    3188                 :            :          * followed psmouse_reset() to reset the device to normal state.
    3189                 :            :          */
    3190         [ #  # ]:          0 :         if (alps_is_cs19_trackpoint(psmouse)) {
    3191                 :            :                 psmouse_dbg(psmouse,
    3192                 :            :                             "ALPS CS19 trackpoint-only device detected, ignoring\n");
    3193                 :            :                 return -EINVAL;
    3194                 :            :         }
    3195                 :            : 
    3196                 :            :         /*
    3197                 :            :          * Reset the device to make sure it is fully operational:
    3198                 :            :          * on some laptops, like certain Dell Latitudes, we may
    3199                 :            :          * fail to properly detect presence of trackstick if device
    3200                 :            :          * has not been reset.
    3201                 :            :          */
    3202                 :          0 :         psmouse_reset(psmouse);
    3203                 :            : 
    3204                 :          0 :         priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
    3205         [ #  # ]:          0 :         if (!priv)
    3206                 :            :                 return -ENOMEM;
    3207                 :            : 
    3208                 :          0 :         error = alps_identify(psmouse, priv);
    3209         [ #  # ]:          0 :         if (error) {
    3210                 :          0 :                 kfree(priv);
    3211                 :          0 :                 return error;
    3212                 :            :         }
    3213                 :            : 
    3214         [ #  # ]:          0 :         if (set_properties) {
    3215                 :          0 :                 psmouse->vendor = "ALPS";
    3216                 :          0 :                 psmouse->name = priv->flags & ALPS_DUALPOINT ?
    3217         [ #  # ]:          0 :                                 "DualPoint TouchPad" : "GlidePoint";
    3218                 :          0 :                 psmouse->model = priv->proto_version;
    3219                 :            :         } else {
    3220                 :            :                 /*
    3221                 :            :                  * Destroy alps_data structure we allocated earlier since
    3222                 :            :                  * this was just a "trial run". Otherwise we'll keep it
    3223                 :            :                  * to be used by alps_init() which has to be called if
    3224                 :            :                  * we succeed and set_properties is true.
    3225                 :            :                  */
    3226                 :          0 :                 kfree(priv);
    3227                 :          0 :                 psmouse->private = NULL;
    3228                 :            :         }
    3229                 :            : 
    3230                 :            :         return 0;
    3231                 :            : }
    3232                 :            : 

Generated by: LCOV version 1.14