From 421df69cc9d37b1868e2cab5e80d0f0092d6caf7 Mon Sep 17 00:00:00 2001 From: Marty Oehme <contact@martyoeh.me> Date: Thu, 13 Mar 2025 10:43:35 +0100 Subject: [PATCH] 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. --- roles/acpi/files/actions/button-lid.sh | 36 ++++++++++ roles/acpi/files/default-handler.sh | 97 ++++++++++++++++++++++++++ roles/acpi/files/events/button-lid | 3 + roles/acpi/handlers/main.yaml | 9 +++ roles/acpi/tasks/main.yaml | 34 +++++++++ 5 files changed, 179 insertions(+) create mode 100644 roles/acpi/files/actions/button-lid.sh create mode 100644 roles/acpi/files/default-handler.sh create mode 100644 roles/acpi/files/events/button-lid create mode 100644 roles/acpi/handlers/main.yaml diff --git a/roles/acpi/files/actions/button-lid.sh b/roles/acpi/files/actions/button-lid.sh new file mode 100644 index 0000000..2c68ff7 --- /dev/null +++ b/roles/acpi/files/actions/button-lid.sh @@ -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 diff --git a/roles/acpi/files/default-handler.sh b/roles/acpi/files/default-handler.sh new file mode 100644 index 0000000..0fa5e2a --- /dev/null +++ b/roles/acpi/files/default-handler.sh @@ -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 diff --git a/roles/acpi/files/events/button-lid b/roles/acpi/files/events/button-lid new file mode 100644 index 0000000..a803632 --- /dev/null +++ b/roles/acpi/files/events/button-lid @@ -0,0 +1,3 @@ +# Only pass lid events +event=button/lid +action=/etc/acpi/actions/button-lid.sh %e diff --git a/roles/acpi/handlers/main.yaml b/roles/acpi/handlers/main.yaml new file mode 100644 index 0000000..aa586d0 --- /dev/null +++ b/roles/acpi/handlers/main.yaml @@ -0,0 +1,9 @@ +--- +- name: Reload acpid rules + become: true + ansible.builtin.command: + argv: + - pkill + - -1 + - acpid + listen: acpi-rule-reload diff --git a/roles/acpi/tasks/main.yaml b/roles/acpi/tasks/main.yaml index 19e924b..57b26cd 100644 --- a/roles/acpi/tasks/main.yaml +++ b/roles/acpi/tasks/main.yaml @@ -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"