Disable USB devices and peripherals waking up your laptop from suspend or sleep
Feb 10, 2024
In this short blog post I will document the steps I’ve gone through to stop my Logitech Signature M650’s USB receiver, Logi Bolt to wake my Arch Linux system from suspend.
Finding the device
First things first, we have to pinpoint where the device is seen in the bus, and for that we’ll use lsusb:
$ lsusb This will print out connected devices along with bus and device numbers, like this:
...
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 003: ID 8087:0029 Intel Corp. AX200 Bluetooth
Bus 003 Device 005: ID 046d:c548 Logitech, Inc. Logi Bolt Receiver
... Now, we know that the device is identified with number 5, so we can get the port number using lsusb -t:
$ lsusb -t ...
/: Bus 002.Port 001: Dev 001, Class=root_hub, Driver=xhci_hcd/2p, 10000M
/: Bus 003.Port 001: Dev 001, Class=root_hub, Driver=xhci_hcd/4p, 480M
|__ Port 001: Dev 005, If 0, Class=Human Interface Device, Driver=usbhid, 12M
|__ Port 001: Dev 005, If 1, Class=Human Interface Device, Driver=usbhid, 12M
|__ Port 001: Dev 005, If 2, Class=Human Interface Device, Driver=usbhid, 12M
|__ Port 001: Dev 005, If 3, Class=Human Interface Device, Driver=usbhid, 12M
|__ Port 004: Dev 003, If 0, Class=Wireless, Driver=btusb, 12M
|__ Port 004: Dev 003, If 1, Class=Wireless, Driver=btusb, 12M
... Some devices create multiple interfaces over the same bus and port, and this is also valid in our case. We knew from the last step that the device number is 5, and it’s clear that it’s on port 1. We’ll use the bus and port number to pinpoint the power/wakeup file on /sys directory.
/sys directory is an interface directly to the kernel. It allows us to write and read kernel data structures, which in our case are the parameters related to connected devices. You can read more about /sys, or really the sysfs here in the kernel documents.
Writing to the wakeup file
The template for the correct file is the following:
/sys/bus/usb/devices/$BUS-$PORT/power/wakeup However, more wakeup files may be present, according to the interfaces created by the kernel. For example, we can recall that Logi Bolt has 4 interfaces, and alongside with them comes the directories:
/sys/bus/usb/devices/3-1/sys/bus/usb/devices/3-1:1.0/sys/bus/usb/devices/3-1:1.1/sys/bus/usb/devices/3-1:1.2/sys/bus/usb/devices/3-1:1.3
Even though there are 5 directories, only the first (/sys/bus/usb/devices/3-1) directory had the wakeup file.
It’s straightforward from here:
echo "disabled" > "/sys/bus/usb/devices/$BUS-$PORT" And voilà! It’s disabled.
Automating with systemd
Now on every boot, we want this rule to take effect. Normally what’d be the best way to implement this, according to my research is to use udev, however, the udev rule I’ve written doesn’t help at all. So I just created a service file (/etc/systemd/system/avoid-bolt-wakeup.service) that executes a shell script (/etc/systemd/system/disable-wakeup.sh to be exact) on multi-user.target.
[Unit]
Description = "Disables power/wakeup of Logi Bolt USB Receiver"
[Service]
ExecStart = /etc/systemd/system/disable-wakeup.sh
[Install]
WantedBy = multi-user.target #!/usr/bin/bash
echo "disabled" > /sys/bus/usb/devices/3-1/power/wakeup