Waking The Framework Up (And Not)
The piece of cloth in the photo above made all the difference between key prints and a nice, homogeneous display in my old Thinkpad X240. Perhaps my new Framework's metal case is sturdy enough to keep the screen print-free even without extra precautions, but for now I don't want to try.
However, the cloth sometimes presses keys when the lid is closed, which would wake the machine up. That suggests to me, incidentally, that protecting the screen probably is a smart thing even on the Framework. Anyway: the Framework's firmware makes it wake up both when I open the lid and when (almost) any key is pressed on the built-in keyboard. And that does not fit my interactions with the computer. Hence, I want to configure it to only wake up when I press the power button; lid and keyboard events should be ignored when the machine is in suspend.
ACPI is a Four-Letter Word
“No problem”, I thought, “done that before”. The conventional way to select what wakes a machine up from suspend is to echo sometimes slightly intransparent ACPI identifiers into /proc/acpi/wakeup. Each echo toggles whether or not the machine will wake up when some activity occurs on that source; this could be USB or network ports, but also buttons and switches.
On the Framework, that's not so simple. First off, most of the ACPI identifiers are positively opaque even by ACPI standards:
$ cat /proc/acpi/wakeup Device S-state Status Sysfs node AWAC S4 *disabled XDCI S4 *disabled XHCI S4 *disabled pci:0000:00:14.0 HDAS S4 *disabled pci:0000:00:1f.3 I3C0 S4 *disabled RP01 S4 *disabled pci:0000:00:1c.0 PXSX S4 *disabled pci:0000:a9:00.0 RP02 S4 *disabled PXSX S4 *disabled RP03 S4 *disabled PXSX S4 *disabled RP04 S4 *disabled PXSX S4 *disabled RP05 S4 *disabled PXSX S4 *disabled RP06 S4 *disabled pci:0000:00:1c.5 PXSX S4 *disabled pci:0000:aa:00.0 RP07 S4 *disabled PXSX S4 *disabled RP08 S4 *disabled PXSX S4 *disabled RP09 S4 *disabled PXSX S4 *disabled RP10 S4 *disabled PXSX S4 *disabled RP11 S4 *disabled PXSX S4 *disabled RP12 S4 *disabled PXSX S4 *disabled TXHC S4 *disabled pci:0000:00:0d.0 TDM0 S4 *disabled pci:0000:00:0d.2 TDM1 S4 *disabled pci:0000:00:0d.3 TRP0 S4 *disabled pci:0000:00:07.0 PXSX S4 *disabled TRP1 S4 *disabled pci:0000:00:07.1 PXSX S4 *disabled TRP2 S4 *disabled pci:0000:00:07.2 PXSX S4 *disabled TRP3 S4 *disabled pci:0000:00:07.3 PXSX S4 *disabled
(originally, not all of them were disabled). I had hoped for something containing the letters “LID”; I would then have said something like:
echo LID > /proc/acpi/wakeup
and the machine would have slept on.
Alas: No LID, nothing I could recognise at all (if you can decode the four-letter words in the Framework's /proc/acpi other than XHCI, please enlighten me). And worse: even when I disabled all sources (which is normally unwise because you can't get the machine to wake up then), the Framework would still wake up on key presses and lid opens.
Well: ACPI. Four letters that are clearly a botched acronym for “vendors never get it right“.[1] Even the number of characters doesn't match.
Finding Wakeup Sources in sysfs
But then there is a second API to communicate wakeup preferences; this is via wakeup files in sysfs, which probably maps directly to hardware rather than through usually broken firmware like ACPI. Here, I am interested in wakeup sources from input devices.
You might plan on finding them like this:
find /sys/class/input -name wakeup
But that does not work because find does not follow symlinks, and /sys is full of symlinks. The reason find ignores symlinks by default becomes evident if your override that default:
$ find /sys/class/input -name wakeup -follow |& head -5 find: File system loop detected; ‘/sys/class/input/input9/event7/device’ is part of the same file system loop as ‘/sys/class/input/input9’. find: File system loop detected; ‘/sys/class/input/input9/event7/subsystem’ is part of the same file system loop as ‘/sys/class/input’. find: File system loop detected; ‘/sys/class/input/input9/device/driver/module/drivers/platform:pcspkr’ is part of the same file system loop as ‘/sys/class/input/input9/device/driver’. find: File system loop detected; ‘/sys/class/input/input9/device/driver/pcspkr’ is part of the same file system loop as ‘/sys/class/input/input9/device’. /sys/class/input/input9/device/subsystem/devices/i2c_designware.1/firmware_node/wakeup [... and so on ad infinitum ...]
Fortunately, the locations of the wakeup files are predictable, and thus a plain shell pattern will work:
$ ls /sys/class/input/*/device/power/wakeup /sys/class/input/input0/device/power/wakeup /sys/class/input/input1/device/power/wakeup /sys/class/input/input2/device/power/wakeup
So, we have three input devices that can raise the machine from the half-dead. Originally, all of them were enabled; on my box, I now have:
$ cat /sys/class/input/*/device/power/wakeu disabled enabled disabled
Power Button Only, Please
How did I find out what input is what? Well, I had a look at the names of the devices:
$ cat /sys/class/input/input0/name Lid Switch
This technique furthermore shows that input 1 is the power switch, and input 2 is the keyboard. I have no idea how stable these numbers are over time, models, and kernel and firmware versions; for now, I assume they will not change on reboots and have put the following into my /etc/rc.local:
echo disabled > /sys/class/input/input0/device/power/wakeup echo disabled > /sys/class/input/input2/device/power/wakeup
If the paths turn out to be unstable, I think I'd do some grepping in that script to find, for instance, the path segment for the lid switch:
grep -i "Lid Switch" /sys/class/inputs/*/name | cut -f4 -d/
would give the lid switch's input path. But let's see if I will need that.
| [1] | There are, by the way, strong indications that ACPI's brokenness is no accident. In the 2000 Iowa class action suit Comes v Microsoft (eventually won by the plaintiffs), an e-mail by Bill Gates was presented as evidence in which he, in 1999, wondered: Maybe we could define the APIs so that they work well with NT and not with the others even if they are open. On the positive side: They didn't even work well with Windows NT. |
![[RSS]](./theme/image/rss.png)