Skip to content

Commit 3f9db52

Browse files
alitydtor
authored andcommitted
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: 6c53694 ("Input: synaptics - split device info into a separate structure") Signed-off-by: Anthony Martin <[email protected]> Cc: [email protected] Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent 4a64658 commit 3f9db52

File tree

1 file changed

+20
-15
lines changed

1 file changed

+20
-15
lines changed

drivers/input/mouse/synaptics.c

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -535,16 +535,17 @@ static void synaptics_apply_quirks(struct psmouse *psmouse,
535535
}
536536
}
537537

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+
538544
static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse)
539545
{
540546
static u8 param = 0xc8;
541-
struct synaptics_data *priv = psmouse->private;
542547
int error;
543548

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-
548549
error = psmouse_sliced_command(psmouse, SYN_QUE_MODEL);
549550
if (error)
550551
return error;
@@ -553,9 +554,6 @@ static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse)
553554
if (error)
554555
return error;
555556

556-
/* Advanced gesture mode also sends multi finger data */
557-
priv->info.capabilities |= BIT(1);
558-
559557
return 0;
560558
}
561559

@@ -578,7 +576,7 @@ static int synaptics_set_mode(struct psmouse *psmouse)
578576
if (error)
579577
return error;
580578

581-
if (priv->absolute_mode) {
579+
if (priv->absolute_mode && synaptics_has_agm(priv)) {
582580
error = synaptics_set_advanced_gesture_mode(psmouse);
583581
if (error) {
584582
psmouse_err(psmouse,
@@ -766,9 +764,7 @@ static int synaptics_parse_hw_state(const u8 buf[],
766764
((buf[0] & 0x04) >> 1) |
767765
((buf[3] & 0x04) >> 2));
768766

769-
if ((SYN_CAP_ADV_GESTURE(priv->info.ext_cap_0c) ||
770-
SYN_CAP_IMAGE_SENSOR(priv->info.ext_cap_0c)) &&
771-
hw->w == 2) {
767+
if (synaptics_has_agm(priv) && hw->w == 2) {
772768
synaptics_parse_agm(buf, priv, hw);
773769
return 1;
774770
}
@@ -1033,6 +1029,15 @@ static void synaptics_image_sensor_process(struct psmouse *psmouse,
10331029
synaptics_report_mt_data(psmouse, sgm, num_fingers);
10341030
}
10351031

1032+
static 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+
10361041
/*
10371042
* called for each full received packet from the touchpad
10381043
*/
@@ -1079,7 +1084,7 @@ static void synaptics_process_packet(struct psmouse *psmouse)
10791084
if (SYN_CAP_EXTENDED(info->capabilities)) {
10801085
switch (hw.w) {
10811086
case 0 ... 1:
1082-
if (SYN_CAP_MULTIFINGER(info->capabilities))
1087+
if (synaptics_has_multifinger(priv))
10831088
num_fingers = hw.w + 2;
10841089
break;
10851090
case 2:
@@ -1123,7 +1128,7 @@ static void synaptics_process_packet(struct psmouse *psmouse)
11231128
input_report_abs(dev, ABS_TOOL_WIDTH, finger_width);
11241129

11251130
input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1);
1126-
if (SYN_CAP_MULTIFINGER(info->capabilities)) {
1131+
if (synaptics_has_multifinger(priv)) {
11271132
input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2);
11281133
input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3);
11291134
}
@@ -1283,7 +1288,7 @@ static void set_input_params(struct psmouse *psmouse,
12831288
__set_bit(BTN_TOUCH, dev->keybit);
12841289
__set_bit(BTN_TOOL_FINGER, dev->keybit);
12851290

1286-
if (SYN_CAP_MULTIFINGER(info->capabilities)) {
1291+
if (synaptics_has_multifinger(priv)) {
12871292
__set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
12881293
__set_bit(BTN_TOOL_TRIPLETAP, dev->keybit);
12891294
}

0 commit comments

Comments
 (0)