Skip to content

Commit 2f2bd7c

Browse files
lentinjBenjamin Tissoires
authored andcommitted
hid: lenovo: Resend all settings on reset_resume for compact keyboards
The USB Compact Keyboard variant requires a reset_resume function to restore keyboard configuration after a suspend in some situations. Move configuration normally done on probe to lenovo_features_set_cptkbd(), then recycle this for use on reset_resume. Without, the keyboard and driver would end up in an inconsistent state, breaking middle-button scrolling amongst other problems, and twiddling sysfs values wouldn't help as the middle-button mode won't be set until the driver is reloaded. Tested on a USB and Bluetooth Thinkpad Compact Keyboard. CC: [email protected] Fixes: 94eefa2 ("HID: lenovo: Use native middle-button mode for compact keyboards") Signed-off-by: Jamie Lentin <[email protected]> Signed-off-by: Martin Kepplinger <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Benjamin Tissoires <[email protected]>
1 parent 46a0a2c commit 2f2bd7c

File tree

1 file changed

+34
-16
lines changed

1 file changed

+34
-16
lines changed

drivers/hid/hid-lenovo.c

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,19 @@ static void lenovo_features_set_cptkbd(struct hid_device *hdev)
526526
int ret;
527527
struct lenovo_drvdata *cptkbd_data = hid_get_drvdata(hdev);
528528

529+
/*
530+
* Tell the keyboard a driver understands it, and turn F7, F9, F11 into
531+
* regular keys
532+
*/
533+
ret = lenovo_send_cmd_cptkbd(hdev, 0x01, 0x03);
534+
if (ret)
535+
hid_warn(hdev, "Failed to switch F7/9/11 mode: %d\n", ret);
536+
537+
/* Switch middle button to native mode */
538+
ret = lenovo_send_cmd_cptkbd(hdev, 0x09, 0x01);
539+
if (ret)
540+
hid_warn(hdev, "Failed to switch middle button: %d\n", ret);
541+
529542
ret = lenovo_send_cmd_cptkbd(hdev, 0x05, cptkbd_data->fn_lock);
530543
if (ret)
531544
hid_err(hdev, "Fn-lock setting failed: %d\n", ret);
@@ -1148,22 +1161,6 @@ static int lenovo_probe_cptkbd(struct hid_device *hdev)
11481161
}
11491162
hid_set_drvdata(hdev, cptkbd_data);
11501163

1151-
/*
1152-
* Tell the keyboard a driver understands it, and turn F7, F9, F11 into
1153-
* regular keys (Compact only)
1154-
*/
1155-
if (hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD ||
1156-
hdev->product == USB_DEVICE_ID_LENOVO_CBTKBD) {
1157-
ret = lenovo_send_cmd_cptkbd(hdev, 0x01, 0x03);
1158-
if (ret)
1159-
hid_warn(hdev, "Failed to switch F7/9/11 mode: %d\n", ret);
1160-
}
1161-
1162-
/* Switch middle button to native mode */
1163-
ret = lenovo_send_cmd_cptkbd(hdev, 0x09, 0x01);
1164-
if (ret)
1165-
hid_warn(hdev, "Failed to switch middle button: %d\n", ret);
1166-
11671164
/* Set keyboard settings to known state */
11681165
cptkbd_data->middlebutton_state = 0;
11691166
cptkbd_data->fn_lock = true;
@@ -1286,6 +1283,24 @@ static int lenovo_probe(struct hid_device *hdev,
12861283
return ret;
12871284
}
12881285

1286+
#ifdef CONFIG_PM
1287+
static int lenovo_reset_resume(struct hid_device *hdev)
1288+
{
1289+
switch (hdev->product) {
1290+
case USB_DEVICE_ID_LENOVO_CUSBKBD:
1291+
case USB_DEVICE_ID_LENOVO_TPIIUSBKBD:
1292+
if (hdev->type == HID_TYPE_USBMOUSE)
1293+
lenovo_features_set_cptkbd(hdev);
1294+
1295+
break;
1296+
default:
1297+
break;
1298+
}
1299+
1300+
return 0;
1301+
}
1302+
#endif
1303+
12891304
static void lenovo_remove_tpkbd(struct hid_device *hdev)
12901305
{
12911306
struct lenovo_drvdata *data_pointer = hid_get_drvdata(hdev);
@@ -1402,6 +1417,9 @@ static struct hid_driver lenovo_driver = {
14021417
.raw_event = lenovo_raw_event,
14031418
.event = lenovo_event,
14041419
.report_fixup = lenovo_report_fixup,
1420+
#ifdef CONFIG_PM
1421+
.reset_resume = lenovo_reset_resume,
1422+
#endif
14051423
};
14061424
module_hid_driver(lenovo_driver);
14071425

0 commit comments

Comments
 (0)