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