SteamOS USB Wake
A simple dream
I was recently building a DIY steam machine. The parts came together nicely and everything was working as expected.
However, there was one issue that I encountered. The system would not wake up from sleep when turning on the controller. This was obviously less then ideal, and with Playstation and Xbox offering this kind of feature as well as the steamdeck itself I decided to look into the problem.
So at first I thought it was a hardware problem. After a quick peek into the BIOS I made certain that the USB ports weren’t part of any kind of odd sleep configuration. That seemed fine; so the next step was to look in steamOS itself to see what the issue might be.
As you can imagine that also went fine, with no obvious power saving features enabled.
Booting to desktop mode and exploring the KDE environment lead to the same conclusion; everything was fine.
At this point I was using a logitech k400 to enter commands. After walking away for lunch and coming back imagine my surprise when the system woke by a key press.
What is a keyboard?
After staring at my store page I went to my PC to do some thinking. Thankfully I run linux as a daily OS so I could do some testing.
Controllers report as HID devices just like keyboards or mice. The difference being that the signal sent is different. Keyboards and other wake devices send interrupts which the machine interprets and triggers a wake event. Controllers on the other hand do not send this type of wake event. Additionally, controllers may live behind a bluetooth connection, or 2.4ghz dongle that connect to a sleeping port or controller.
Wearing a mask
Ok, so if the controller does not send a wake event what does a controller do when it turns on? It turns out a few things.
Every USB device has a hardware and vendor ID that you can find by running lsusb in the terminal. Two things generally happen when a USB device wakes.
- The ID appears as connected to the system
- The ID changes because of a state change (8bitdo)
Now these events are logged even when the system is sleeping. The wake event comes from devices that support it, but what if we change the conditions of the wake event?
It should be possible to fire off a wake command when a change is connected on the USB controller.
Immutable
SteamOS is an immutable OS. Meaning that the system cannot be modified or updated without a complete reinstall. However, /etc/systemd persists.
If we can make a script or cronjob or otherwise persist a change we should be able to wake the system.
After some thought and testing on my desktop I decided the best way forward was to create a service, but there was a problem, /etc/ was read-only; thankfully you can unlock this with a few commands.
An hour or so later I managed to have a working example on my personal machine so now it was time to make it pretty and make it workable on steamOS.
This meant that I had to add a few user niceties. For example, I needed to make sure I put /etc/ back into read-only mode after my changes. I also needed to backup the existing configuration before I made any changes, and of course that meant including the ability to restore those backups.
That took several more hours, but eventually I was ready to test it on SteamOS.
A cure for the itch
Hybrid theory aside I had finally found and made my solution.
I wrote a systemd service that executed a one off config change that would allow the system to wake on any change detected to any device connected to a USB hub.
It also backed up the existing configuration before making any changes. The install script also included the ability to restore those backups.
With everything all tested, it was time to publish it. Enjoy.
https://github.com/Solaris17/SteamOS-USB-Wake