[BUG] usbhid: logitech bolt (046d:c548) spuriously wakes system from suspend

"Tomas Leypold" <[email protected]>
Newsgroups org.kernel.vger.linux-usb,org.kernel.vger.linux-input,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Hi, I've got an logitech mx keys s keyboard with a logi bolt receiver
(046d:c548)
that wakes my pc from suspend on its own, no input involved, just a
moment after it goes to sleep. Reproducible on two different machines,
both nixos. One's a laptop with s2idle, the other's a pc with s3/deep.

Aug 09 00:08:07 w01 kernel: PM: suspend entry (deep)
Aug 09 00:08:12 w01 kernel: ACPI: PM: Preparing to enter system sleep
state S3
Aug 09 00:08:12 w01 kernel: ACPI: PM: Waking up from system sleep state S3
Aug 09 00:08:12 w01 kernel: PM: suspend exit

Sometimes replugging the receiver into a different USB port fixes it
temporarily, for a while.

HID_QUIRK_ALWAYS_POLL
(https://lore.kernel.org/linux-input/20260407-logi-bolt-hid-quirk-always-poll-v1-1-4dae0fda344e@collabora.com/)
doesn't seem relevant to this issue. 6.18.41 doesn't have that quirk,
7.1.6 does, and the bug happens on both.

In forums, people with the same problem recommend a udev rule setting
power/wakeup to disabled. That disables keyboard wake entirely.

After some debugging I found a more targeted workaround with no
downsides that I know of: unbinding usbhid from interface 0 (the
keyboard interface) right before suspend, rebinding after resume.
Remote wakeup stays armed, so a keypress still wakes the machine
normally.

Tried unbinding each of the four interfaces on its own, only interface
0 makes a difference.

Here's the systemd-sleep script, drop it in
/usr/lib/systemd/system-sleep/50-bolt-unbind, or wherever your distro
puts these, and chmod +x:

#!/bin/sh
find_dev() {
   for d in /sys/bus/usb/devices/*/idProduct; do
     [ -r "$d" ] || continue
     v=$(cat "$(dirname "$d")/idVendor" 2>/dev/null)
     p=$(cat "$d" 2>/dev/null)
     [ "$v" = "046d" ] && [ "$p" = "c548" ] && basename "$(dirname
"$d")" && return
   done
}
case "$1" in
   pre)
     dev=$(find_dev)
     [ -n "$dev" ] || exit 0
     echo "$dev:1.0" > /sys/bus/usb/drivers/usbhid/unbind
     ;;
   post)
     dev=$(find_dev)
     [ -n "$dev" ] || exit 0
     echo "$dev:1.0" > /sys/bus/usb/drivers/usbhid/bind
     ;;
esac

No idea what the right fix looks like on the kernel side, just wanted
to share what I found.

Happy to run further tests and try out patches.

Best regards,
Tomas Leypold
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.