Input: synaptics - fix device info appearing different on reconnect

User-modified input settings no longer survive a suspend/resume cycle.
Starting with 4.12, the touchpad is reinitialized on every reconnect
because the hardware appears to be different. This can be reproduced
by running the following as root:

echo -n reconnect >/sys/devices/platform/i8042/serio1/drvctl

A line like the following will show up in dmesg:

[30378.295794] psmouse serio1: synaptics: hardware appears to be
different: id(149271-149271), model(114865-114865),
caps(d047b3-d047b1), ext(b40000-b40000).

Note the single bit difference in caps: bit 1 (SYN_CAP_MULTIFINGER).

This happens because we modify our stored copy of the device info
capabilities when we enable advanced gesture mode but this change is
not reflected in the actual hardware capabilities.

It worked in the past because synaptics_query_hardware used to modify
the stored synaptics_device_info struct instead of filling in a new
one, as it does now.

Fix it by no longer faking the SYN_CAP_MULTIFINGER bit when setting
advanced gesture mode. This necessitated a small refactoring.

Fixes: 6c53694fb222 ("Input: synaptics - split device info into a separate structure")
Signed-off-by: Anthony Martin <ality@pbrane.org>
Cc: stable@vger.kernel.org
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by Anthony Martin and committed by Dmitry Torokhov 3f9db52d 4a646580

+20 -15
+20 -15
drivers/input/mouse/synaptics.c
··· 535 535 } 536 536 } 537 537 538 + static bool synaptics_has_agm(struct synaptics_data *priv) 539 + { 540 + return (SYN_CAP_ADV_GESTURE(priv->info.ext_cap_0c) || 541 + SYN_CAP_IMAGE_SENSOR(priv->info.ext_cap_0c)); 542 + } 543 + 538 544 static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse) 539 545 { 540 546 static u8 param = 0xc8; 541 - struct synaptics_data *priv = psmouse->private; 542 547 int error; 543 - 544 - if (!(SYN_CAP_ADV_GESTURE(priv->info.ext_cap_0c) || 545 - SYN_CAP_IMAGE_SENSOR(priv->info.ext_cap_0c))) 546 - return 0; 547 548 548 549 error = psmouse_sliced_command(psmouse, SYN_QUE_MODEL); 549 550 if (error) ··· 553 552 error = ps2_command(&psmouse->ps2dev, &param, PSMOUSE_CMD_SETRATE); 554 553 if (error) 555 554 return error; 556 - 557 - /* Advanced gesture mode also sends multi finger data */ 558 - priv->info.capabilities |= BIT(1); 559 555 560 556 return 0; 561 557 } ··· 576 578 if (error) 577 579 return error; 578 580 579 - if (priv->absolute_mode) { 581 + if (priv->absolute_mode && synaptics_has_agm(priv)) { 580 582 error = synaptics_set_advanced_gesture_mode(psmouse); 581 583 if (error) { 582 584 psmouse_err(psmouse, ··· 764 766 ((buf[0] & 0x04) >> 1) | 765 767 ((buf[3] & 0x04) >> 2)); 766 768 767 - if ((SYN_CAP_ADV_GESTURE(priv->info.ext_cap_0c) || 768 - SYN_CAP_IMAGE_SENSOR(priv->info.ext_cap_0c)) && 769 - hw->w == 2) { 769 + if (synaptics_has_agm(priv) && hw->w == 2) { 770 770 synaptics_parse_agm(buf, priv, hw); 771 771 return 1; 772 772 } ··· 1029 1033 synaptics_report_mt_data(psmouse, sgm, num_fingers); 1030 1034 } 1031 1035 1036 + static bool synaptics_has_multifinger(struct synaptics_data *priv) 1037 + { 1038 + if (SYN_CAP_MULTIFINGER(priv->info.capabilities)) 1039 + return true; 1040 + 1041 + /* Advanced gesture mode also sends multi finger data */ 1042 + return synaptics_has_agm(priv); 1043 + } 1044 + 1032 1045 /* 1033 1046 * called for each full received packet from the touchpad 1034 1047 */ ··· 1084 1079 if (SYN_CAP_EXTENDED(info->capabilities)) { 1085 1080 switch (hw.w) { 1086 1081 case 0 ... 1: 1087 - if (SYN_CAP_MULTIFINGER(info->capabilities)) 1082 + if (synaptics_has_multifinger(priv)) 1088 1083 num_fingers = hw.w + 2; 1089 1084 break; 1090 1085 case 2: ··· 1128 1123 input_report_abs(dev, ABS_TOOL_WIDTH, finger_width); 1129 1124 1130 1125 input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1); 1131 - if (SYN_CAP_MULTIFINGER(info->capabilities)) { 1126 + if (synaptics_has_multifinger(priv)) { 1132 1127 input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2); 1133 1128 input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3); 1134 1129 } ··· 1288 1283 __set_bit(BTN_TOUCH, dev->keybit); 1289 1284 __set_bit(BTN_TOOL_FINGER, dev->keybit); 1290 1285 1291 - if (SYN_CAP_MULTIFINGER(info->capabilities)) { 1286 + if (synaptics_has_multifinger(priv)) { 1292 1287 __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); 1293 1288 __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); 1294 1289 }