feat(acpi): Add custom LID event handling

We disable the default ACPI handler script logic for LID events.
We _only_ disable that in the script - the default handler script will
still fire for LID events, just not do anything in its routine. That is
so that in the future it is easy to rectify with any upstream changes.
If, over time we add more custom event and action chain to our ACPI
settings, we can think about spinning out all event types into our own
rules and completely disabling the deafult handler script.

Our custom LID action only fires for LID open close events, and only
logs that the lid has been opened for open events. For close events, it
adds one extra step before suspending: Checking if any DP screens are
connected - and inhibiting suspend then. That way we still automatically
suspend when closing the screen lid if we are in portable mode (no
external screens connected) but do nothing if they are.
This commit is contained in:
Marty Oehme 2025-03-13 10:43:35 +01:00
parent d168115f81
commit 421df69cc9
Signed by: Marty
GPG key ID: 4E535BC19C61886E
5 changed files with 179 additions and 0 deletions
roles/acpi

View file

@ -0,0 +1,36 @@
#!/bin/sh
# Specifically handling LID events
# Can take the form:
# button/lid LID close
# button/lid LID open
# We are only interested in value $3.
# Do not turn off machine if external screens are connected.
case "$3" in
close)
should_sleep=true
screens=$(find /sys/devices -type f -wholename '*drm/*card*-DP-*/status')
while IFS= read -r screen; do
if [ "$(cat "$screen")" = connected ]; then
should_sleep=false
fi
done <<EOF
$screens
EOF
if [ "$should_sleep" = true ]; then
suspend-to-ram
logger "LID closed, no external screens, suspending..."
zzz
else
logger "LID closed, external screens, not suspending."
fi
;;
open) logger "LID opened" ;;
*) logger "ACPI action undefined (LID): $*" ;;
esac

View file

@ -0,0 +1,97 @@
#!/bin/sh
# Default acpi script that takes an entry for all actions
# NOTE: This is a 2.6-centric script. If you use 2.4.x, you'll have to
# modify it to not use /sys
# $1 should be + or - to step up or down the brightness.
step_backlight() {
for backlight in /sys/class/backlight/*/; do
[ -d "$backlight" ] || continue
step=$(( $(cat "$backlight/max_brightness") / 20 ))
[ "$step" -gt "1" ] || step=1 #fallback if gradation is too low
printf '%s' "$(( $(cat "$backlight/brightness") $1 step ))" >"$backlight/brightness"
done
}
minspeed="/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq"
maxspeed="/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq"
setspeed="/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed"
case "$1" in
button/power)
case "$2" in
PBTN|PWRF)
logger "PowerButton pressed: $2, shutting down..."
shutdown -P now
;;
*) logger "ACPI action undefined: $2" ;;
esac
;;
button/sleep)
case "$2" in
SBTN|SLPB)
# suspend-to-ram
logger "Sleep Button pressed: $2, suspending..."
zzz
;;
*) logger "ACPI action undefined: $2" ;;
esac
;;
ac_adapter)
case "$2" in
AC|ACAD|ADP0)
case "$4" in
00000000)
cat "$minspeed" >"$setspeed"
#/etc/laptop-mode/laptop-mode start
;;
00000001)
cat "$maxspeed" >"$setspeed"
#/etc/laptop-mode/laptop-mode stop
;;
esac
;;
*) logger "ACPI action undefined: $2" ;;
esac
;;
battery)
case "$2" in
BAT0)
case "$4" in
00000000) #echo "offline" >/dev/tty5
;;
00000001) #echo "online" >/dev/tty5
;;
esac
;;
CPU0)
;;
*) logger "ACPI action undefined: $2" ;;
esac
;;
# HANDLED IN SEPARATE ACTION FILE
button/lid) ;;
# case "$3" in
# close)
# # suspend-to-ram
# # logger "LID closed, suspending..."
# # zzz
# ;;
# open)
# logger "LID opened"
# ;;
# *) logger "ACPI action undefined (LID): $2";;
# esac
# ;;
video/brightnessdown)
step_backlight -
;;
video/brightnessup)
step_backlight +
;;
*)
logger "ACPI group/action undefined: $1 / $2"
;;
esac

View file

@ -0,0 +1,3 @@
# Only pass lid events
event=button/lid
action=/etc/acpi/actions/button-lid.sh %e

View file

@ -0,0 +1,9 @@
---
- name: Reload acpid rules
become: true
ansible.builtin.command:
argv:
- pkill
- -1
- acpid
listen: acpi-rule-reload

View file

@ -1,4 +1,38 @@
---
# ACPI comes preinstalled on void systems
- name: Remove lid handling from default handler
ansible.builtin.copy:
src: default-handler.sh
dest: /etc/acpi/handler.sh
mode: 0755
force: true
notify: acpi-rule-reload
- name: Ensure acpi config directories exist
ansible.builtin.file:
dest: "/etc/acpi/{{ item }}"
state: directory
mode: 0755
loop:
- events
- actions
- name: Add separate lid button event rule
ansible.builtin.copy:
src: events/button-lid
dest: /etc/acpi/events/button-lid
mode: 0644
force: true
notify: acpi-rule-reload
- name: Add corresponding lid handler action
ansible.builtin.copy:
src: actions/button-lid.sh
dest: /etc/acpi/actions/button-lid.sh
mode: 0755
force: true
notify: acpi-rule-reload
- name: Activate acpid service
ansible.builtin.file:
src: "/etc/sv/acpid"