Message ID | 20230921092140.120533-1-martink@posteo.de |
---|---|
State | New |
Headers | show |
Series | HID: lenovo: Fix middle-button behaviour for system suspend | expand |
On 2023-09-21 10:21, Martin Kepplinger wrote: > After system suspend the middle-button mode is being reset to > compatibility mode which simply breaks functionality for the devices > where native mode is configured during probe(). > > Fix this by setting native mode in reset_resume() for the appropriate > devices. > > Fixes: 94eefa271323 ("HID: lenovo: Use native middle-button mode for > compact keyboards") > Signed-off-by: Martin Kepplinger <martink@posteo.de> > --- > drivers/hid/hid-lenovo.c | 25 +++++++++++++++++++++++++ > 1 file changed, 25 insertions(+) > > diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c > index 44763c0da444..d20562b9eca6 100644 > --- a/drivers/hid/hid-lenovo.c > +++ b/drivers/hid/hid-lenovo.c > @@ -1344,6 +1344,28 @@ static int lenovo_input_configured(struct > hid_device *hdev, > return 0; > } > > +static int __maybe_unused lenovo_resume(struct hid_device *hdev) > +{ > + int ret; > + > + switch (hdev->product) { > + case USB_DEVICE_ID_LENOVO_CUSBKBD: > + case USB_DEVICE_ID_LENOVO_CBTKBD: > + case USB_DEVICE_ID_LENOVO_TPIIUSBKBD: > + case USB_DEVICE_ID_LENOVO_TPIIBTKBD: > + /* Switch middle button to native mode again */ > + ret = lenovo_send_cmd_cptkbd(hdev, 0x09, 0x01); This will only reset the middle button state and not the Function key state, which I believe has similar problems. This was my attempt at solving this: https://github.com/lentinj/linux/commit/f1c4e2de780abf8526bcdc9496c463f1ff4fe53b ...which should ensure everything is in a consistent state with what the kernel expects. I never submitted this since sending commands was sporadically resulting in timeouts, although I'm fairly sure it was unrelated to this patch, and quite possibly a hardware problem with my keyboard. I'd be interested to know how you get on. Also, the above will send the command to both the USB keyboard & mouse devices, only the mouse will respond. So worth prepending something like: if (((hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD) || (hdev->product == USB_DEVICE_ID_LENOVO_TPIIUSBKBD)) && hdev->type != HID_TYPE_USBMOUSE) { hid_dbg(hdev, "Ignoring keyboard half of device\n"); return 0; } ...to avoid sending known-useless messages. > + if (ret) > + hid_warn(hdev, "Failed to switch middle button: %d\n", > + ret); > + break; > + default: > + ret = 0; > + break; > + } > + > + return ret; > +} > > static const struct hid_device_id lenovo_devices[] = { > { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) }, > @@ -1380,6 +1402,9 @@ static struct hid_driver lenovo_driver = { > .raw_event = lenovo_raw_event, > .event = lenovo_event, > .report_fixup = lenovo_report_fixup, > +#ifdef CONFIG_PM > + .reset_resume = lenovo_resume, > +#endif > }; > module_hid_driver(lenovo_driver);
diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c index 44763c0da444..d20562b9eca6 100644 --- a/drivers/hid/hid-lenovo.c +++ b/drivers/hid/hid-lenovo.c @@ -1344,6 +1344,28 @@ static int lenovo_input_configured(struct hid_device *hdev, return 0; } +static int __maybe_unused lenovo_resume(struct hid_device *hdev) +{ + int ret; + + switch (hdev->product) { + case USB_DEVICE_ID_LENOVO_CUSBKBD: + case USB_DEVICE_ID_LENOVO_CBTKBD: + case USB_DEVICE_ID_LENOVO_TPIIUSBKBD: + case USB_DEVICE_ID_LENOVO_TPIIBTKBD: + /* Switch middle button to native mode again */ + ret = lenovo_send_cmd_cptkbd(hdev, 0x09, 0x01); + if (ret) + hid_warn(hdev, "Failed to switch middle button: %d\n", + ret); + break; + default: + ret = 0; + break; + } + + return ret; +} static const struct hid_device_id lenovo_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) }, @@ -1380,6 +1402,9 @@ static struct hid_driver lenovo_driver = { .raw_event = lenovo_raw_event, .event = lenovo_event, .report_fixup = lenovo_report_fixup, +#ifdef CONFIG_PM + .reset_resume = lenovo_resume, +#endif }; module_hid_driver(lenovo_driver);
After system suspend the middle-button mode is being reset to compatibility mode which simply breaks functionality for the devices where native mode is configured during probe(). Fix this by setting native mode in reset_resume() for the appropriate devices. Fixes: 94eefa271323 ("HID: lenovo: Use native middle-button mode for compact keyboards") Signed-off-by: Martin Kepplinger <martink@posteo.de> --- drivers/hid/hid-lenovo.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)