aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnthony Martin <ality@pbrane.org>2017-08-28 13:26:12 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2017-08-28 13:36:46 -0400
commit3f9db52dc87b003a1732f3e03f7f5fc8701ef4ad (patch)
tree766314d2b21823d76deda7781e3771eee83ff487
parent4a646580f793d19717f7e034c8d473b509c27d49 (diff)
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>
-rw-r--r--drivers/input/mouse/synaptics.c35
1 files changed, 20 insertions, 15 deletions
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 16c30460ef04..5af0b7d200bc 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -535,16 +535,17 @@ static void synaptics_apply_quirks(struct psmouse *psmouse,
535 } 535 }
536} 536}
537 537
538static 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
538static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse) 544static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse)
539{ 545{
540 static u8 param = 0xc8; 546 static u8 param = 0xc8;
541 struct synaptics_data *priv = psmouse->private;
542 int error; 547 int error;
543 548
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 error = psmouse_sliced_command(psmouse, SYN_QUE_MODEL);
549 if (error) 550 if (error)
550 return error; 551 return error;
@@ -553,9 +554,6 @@ static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse)
553 if (error) 554 if (error)
554 return error; 555 return error;
555 556
556 /* Advanced gesture mode also sends multi finger data */
557 priv->info.capabilities |= BIT(1);
558
559 return 0; 557 return 0;
560} 558}
561 559
@@ -578,7 +576,7 @@ static int synaptics_set_mode(struct psmouse *psmouse)
578 if (error) 576 if (error)
579 return error; 577 return error;
580 578
581 if (priv->absolute_mode) { 579 if (priv->absolute_mode && synaptics_has_agm(priv)) {
582 error = synaptics_set_advanced_gesture_mode(psmouse); 580 error = synaptics_set_advanced_gesture_mode(psmouse);
583 if (error) { 581 if (error) {
584 psmouse_err(psmouse, 582 psmouse_err(psmouse,
@@ -766,9 +764,7 @@ static int synaptics_parse_hw_state(const u8 buf[],
766 ((buf[0] & 0x04) >> 1) | 764 ((buf[0] & 0x04) >> 1) |
767 ((buf[3] & 0x04) >> 2)); 765 ((buf[3] & 0x04) >> 2));
768 766
769 if ((SYN_CAP_ADV_GESTURE(priv->info.ext_cap_0c) || 767 if (synaptics_has_agm(priv) && hw->w == 2) {
770 SYN_CAP_IMAGE_SENSOR(priv->info.ext_cap_0c)) &&
771 hw->w == 2) {
772 synaptics_parse_agm(buf, priv, hw); 768 synaptics_parse_agm(buf, priv, hw);
773 return 1; 769 return 1;
774 } 770 }
@@ -1033,6 +1029,15 @@ static void synaptics_image_sensor_process(struct psmouse *psmouse,
1033 synaptics_report_mt_data(psmouse, sgm, num_fingers); 1029 synaptics_report_mt_data(psmouse, sgm, num_fingers);
1034} 1030}
1035 1031
1032static bool synaptics_has_multifinger(struct synaptics_data *priv)
1033{
1034 if (SYN_CAP_MULTIFINGER(priv->info.capabilities))
1035 return true;
1036
1037 /* Advanced gesture mode also sends multi finger data */
1038 return synaptics_has_agm(priv);
1039}
1040
1036/* 1041/*
1037 * called for each full received packet from the touchpad 1042 * called for each full received packet from the touchpad
1038 */ 1043 */
@@ -1079,7 +1084,7 @@ static void synaptics_process_packet(struct psmouse *psmouse)
1079 if (SYN_CAP_EXTENDED(info->capabilities)) { 1084 if (SYN_CAP_EXTENDED(info->capabilities)) {
1080 switch (hw.w) { 1085 switch (hw.w) {
1081 case 0 ... 1: 1086 case 0 ... 1:
1082 if (SYN_CAP_MULTIFINGER(info->capabilities)) 1087 if (synaptics_has_multifinger(priv))
1083 num_fingers = hw.w + 2; 1088 num_fingers = hw.w + 2;
1084 break; 1089 break;
1085 case 2: 1090 case 2:
@@ -1123,7 +1128,7 @@ static void synaptics_process_packet(struct psmouse *psmouse)
1123 input_report_abs(dev, ABS_TOOL_WIDTH, finger_width); 1128 input_report_abs(dev, ABS_TOOL_WIDTH, finger_width);
1124 1129
1125 input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1); 1130 input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1);
1126 if (SYN_CAP_MULTIFINGER(info->capabilities)) { 1131 if (synaptics_has_multifinger(priv)) {
1127 input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2); 1132 input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2);
1128 input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3); 1133 input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3);
1129 } 1134 }
@@ -1283,7 +1288,7 @@ static void set_input_params(struct psmouse *psmouse,
1283 __set_bit(BTN_TOUCH, dev->keybit); 1288 __set_bit(BTN_TOUCH, dev->keybit);
1284 __set_bit(BTN_TOOL_FINGER, dev->keybit); 1289 __set_bit(BTN_TOOL_FINGER, dev->keybit);
1285 1290
1286 if (SYN_CAP_MULTIFINGER(info->capabilities)) { 1291 if (synaptics_has_multifinger(priv)) {
1287 __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); 1292 __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
1288 __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); 1293 __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit);
1289 } 1294 }