Harald Hoyer fe20ad
From 032e57b4e9a90dc11352f1d6640ee246e3f32fb7 Mon Sep 17 00:00:00 2001
Harald Hoyer fe20ad
From: Lennart Poettering <lennart@poettering.net>
Harald Hoyer fe20ad
Date: Wed, 14 Aug 2013 01:57:02 +0200
Harald Hoyer fe20ad
Subject: [PATCH] backlight: add minimal tool to save/restore screen brightness
Harald Hoyer fe20ad
 across reboots
Harald Hoyer fe20ad
Harald Hoyer fe20ad
As many laptops don't save/restore screen brightness across reboots,
Harald Hoyer fe20ad
let's do this in systemd with a minimal tool, that restores the
Harald Hoyer fe20ad
brightness as early as possible, and saves it as late as possible. This
Harald Hoyer fe20ad
will cover consoles and graphical logins, but graphical desktops should
Harald Hoyer fe20ad
do their own per-user stuff probably.
Harald Hoyer fe20ad
Harald Hoyer fe20ad
This only touches firmware brightness controls for now.
Harald Hoyer fe20ad
---
Harald Hoyer fe20ad
 .gitignore                          |   1 +
Harald Hoyer fe20ad
 Makefile.am                         |  20 ++++++
Harald Hoyer fe20ad
 configure.ac                        |   9 +++
Harald Hoyer fe20ad
 rules/99-systemd.rules.in           |   4 ++
Harald Hoyer fe20ad
 rules/Makefile                      |   1 +
Harald Hoyer fe20ad
 src/backlight/Makefile              |   1 +
Harald Hoyer fe20ad
 src/backlight/backlight.c           | 126 ++++++++++++++++++++++++++++++++++++
Harald Hoyer fe20ad
 units/.gitignore                    |   1 +
Harald Hoyer fe20ad
 units/systemd-backlight@.service.in |  21 ++++++
Harald Hoyer fe20ad
 9 files changed, 184 insertions(+)
Harald Hoyer fe20ad
 create mode 120000 rules/Makefile
Harald Hoyer fe20ad
 create mode 120000 src/backlight/Makefile
Harald Hoyer fe20ad
 create mode 100644 src/backlight/backlight.c
Harald Hoyer fe20ad
 create mode 100644 units/systemd-backlight@.service.in
Harald Hoyer fe20ad
Harald Hoyer fe20ad
diff --git a/.gitignore b/.gitignore
Harald Hoyer fe20ad
index bdf9d4a..379a3c1 100644
Harald Hoyer fe20ad
--- a/.gitignore
Harald Hoyer fe20ad
+++ b/.gitignore
Harald Hoyer fe20ad
@@ -29,6 +29,7 @@
Harald Hoyer fe20ad
 /systemd-ac-power
Harald Hoyer fe20ad
 /systemd-analyze
Harald Hoyer fe20ad
 /systemd-ask-password
Harald Hoyer fe20ad
+/systemd-backlight
Harald Hoyer fe20ad
 /systemd-binfmt
Harald Hoyer fe20ad
 /systemd-bootchart
Harald Hoyer fe20ad
 /systemd-cat
Harald Hoyer fe20ad
diff --git a/Makefile.am b/Makefile.am
Harald Hoyer fe20ad
index 7933de6..0059b1d 100644
Harald Hoyer fe20ad
--- a/Makefile.am
Harald Hoyer fe20ad
+++ b/Makefile.am
Harald Hoyer fe20ad
@@ -3267,6 +3267,26 @@ EXTRA_DIST += \
Harald Hoyer fe20ad
 	units/systemd-random-seed.service.in
Harald Hoyer fe20ad
 
Harald Hoyer fe20ad
 # ------------------------------------------------------------------------------
Harald Hoyer fe20ad
+if ENABLE_BACKLIGHT
Harald Hoyer fe20ad
+rootlibexec_PROGRAMS += \
Harald Hoyer fe20ad
+	systemd-backlight
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+nodist_systemunit_DATA += \
Harald Hoyer fe20ad
+	units/systemd-backlight@.service
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+systemd_backlight_SOURCES = \
Harald Hoyer fe20ad
+	src/backlight/backlight.c
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+systemd_backlight_LDADD = \
Harald Hoyer fe20ad
+	libsystemd-label.la \
Harald Hoyer fe20ad
+	libsystemd-shared.la \
Harald Hoyer fe20ad
+	libudev-private.la
Harald Hoyer fe20ad
+endif
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+EXTRA_DIST += \
Harald Hoyer fe20ad
+	units/systemd-backlight@.service.in
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+# ------------------------------------------------------------------------------
Harald Hoyer fe20ad
 if HAVE_LIBCRYPTSETUP
Harald Hoyer fe20ad
 rootlibexec_PROGRAMS += \
Harald Hoyer fe20ad
 	systemd-cryptsetup
Harald Hoyer fe20ad
diff --git a/configure.ac b/configure.ac
Harald Hoyer fe20ad
index 759073a..f7237bd 100644
Harald Hoyer fe20ad
--- a/configure.ac
Harald Hoyer fe20ad
+++ b/configure.ac
Harald Hoyer fe20ad
@@ -667,6 +667,14 @@ fi
Harald Hoyer fe20ad
 AM_CONDITIONAL(ENABLE_RANDOMSEED, [test "$have_randomseed" = "yes"])
Harald Hoyer fe20ad
 
Harald Hoyer fe20ad
 # ------------------------------------------------------------------------------
Harald Hoyer fe20ad
+have_backlight=no
Harald Hoyer fe20ad
+AC_ARG_ENABLE(backlight, AS_HELP_STRING([--disable-backlight], [disable backlight tools]))
Harald Hoyer fe20ad
+if test "x$enable_backlight" != "xno"; then
Harald Hoyer fe20ad
+        have_backlight=yes
Harald Hoyer fe20ad
+fi
Harald Hoyer fe20ad
+AM_CONDITIONAL(ENABLE_BACKLIGHT, [test "$have_backlight" = "yes"])
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+# ------------------------------------------------------------------------------
Harald Hoyer fe20ad
 have_logind=no
Harald Hoyer fe20ad
 AC_ARG_ENABLE(logind, AS_HELP_STRING([--disable-logind], [disable login daemon]))
Harald Hoyer fe20ad
 if test "x$enable_logind" != "xno"; then
Harald Hoyer fe20ad
@@ -992,6 +1000,7 @@ AC_MSG_RESULT([
Harald Hoyer fe20ad
         quotacheck:              ${have_quotacheck}
Harald Hoyer fe20ad
         tmpfiles:                ${have_tmpfiles}
Harald Hoyer fe20ad
         randomseed:              ${have_randomseed}
Harald Hoyer fe20ad
+        backlight:               ${have_backlight}
Harald Hoyer fe20ad
         logind:                  ${have_logind}
Harald Hoyer fe20ad
         machined:                ${have_machined}
Harald Hoyer fe20ad
         hostnamed:               ${have_hostnamed}
Harald Hoyer fe20ad
diff --git a/rules/99-systemd.rules.in b/rules/99-systemd.rules.in
Harald Hoyer fe20ad
index e9b2da7..ac4bc86 100644
Harald Hoyer fe20ad
--- a/rules/99-systemd.rules.in
Harald Hoyer fe20ad
+++ b/rules/99-systemd.rules.in
Harald Hoyer fe20ad
@@ -51,6 +51,10 @@ SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{ID_USB_INTERFACES}=="*:0701??:
Harald Hoyer fe20ad
 
Harald Hoyer fe20ad
 ACTION=="add", SUBSYSTEM=="net", KERNEL!="lo", RUN+="@rootlibexecdir@/systemd-sysctl --prefix=/proc/sys/net/ipv4/conf/$name --prefix=/proc/sys/net/ipv4/neigh/$name --prefix=/proc/sys/net/ipv6/conf/$name --prefix=/proc/sys/net/ipv6/neigh/$name"
Harald Hoyer fe20ad
 
Harald Hoyer fe20ad
+# Pull in backlight save/restore for all firmware backlight devices
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+ACTION=="add", SUBSYSTEM=="backlight", ATTR{type}=="firmware", TAG+="systemd", ENV{SYSTEMD_WANTS}+="systemd-backlight@sys%p.service"
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
 # Asynchronously mount file systems implemented by these modules as
Harald Hoyer fe20ad
 # soon as they are loaded.
Harald Hoyer fe20ad
 
Harald Hoyer fe20ad
diff --git a/rules/Makefile b/rules/Makefile
Harald Hoyer fe20ad
new file mode 120000
Harald Hoyer fe20ad
index 0000000..bd10475
Harald Hoyer fe20ad
--- /dev/null
Harald Hoyer fe20ad
+++ b/rules/Makefile
Harald Hoyer fe20ad
@@ -0,0 +1 @@
Harald Hoyer fe20ad
+../src/Makefile
Harald Hoyer fe20ad
\ No newline at end of file
Harald Hoyer fe20ad
diff --git a/src/backlight/Makefile b/src/backlight/Makefile
Harald Hoyer fe20ad
new file mode 120000
Harald Hoyer fe20ad
index 0000000..d0b0e8e
Harald Hoyer fe20ad
--- /dev/null
Harald Hoyer fe20ad
+++ b/src/backlight/Makefile
Harald Hoyer fe20ad
@@ -0,0 +1 @@
Harald Hoyer fe20ad
+../Makefile
Harald Hoyer fe20ad
\ No newline at end of file
Harald Hoyer fe20ad
diff --git a/src/backlight/backlight.c b/src/backlight/backlight.c
Harald Hoyer fe20ad
new file mode 100644
Harald Hoyer fe20ad
index 0000000..3378907
Harald Hoyer fe20ad
--- /dev/null
Harald Hoyer fe20ad
+++ b/src/backlight/backlight.c
Harald Hoyer fe20ad
@@ -0,0 +1,126 @@
Harald Hoyer fe20ad
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+/***
Harald Hoyer fe20ad
+  This file is part of systemd.
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+  Copyright 2013 Lennart Poettering
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+  systemd is free software; you can redistribute it and/or modify it
Harald Hoyer fe20ad
+  under the terms of the GNU Lesser General Public License as published by
Harald Hoyer fe20ad
+  the Free Software Foundation; either version 2.1 of the License, or
Harald Hoyer fe20ad
+  (at your option) any later version.
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+  systemd is distributed in the hope that it will be useful, but
Harald Hoyer fe20ad
+  WITHOUT ANY WARRANTY; without even the implied warranty of
Harald Hoyer fe20ad
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Harald Hoyer fe20ad
+  Lesser General Public License for more details.
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+  You should have received a copy of the GNU Lesser General Public License
Harald Hoyer fe20ad
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
Harald Hoyer fe20ad
+***/
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+#include <libudev.h>
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+#include "util.h"
Harald Hoyer fe20ad
+#include "mkdir.h"
Harald Hoyer fe20ad
+#include "fileio.h"
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+int main(int argc, char *argv[]) {
Harald Hoyer fe20ad
+        struct udev *udev = NULL;
Harald Hoyer fe20ad
+        struct udev_device *device = NULL;
Harald Hoyer fe20ad
+        _cleanup_free_ char *saved = NULL;
Harald Hoyer fe20ad
+        int r;
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+        if (argc != 3) {
Harald Hoyer fe20ad
+                log_error("This program requires two arguments.");
Harald Hoyer fe20ad
+                return EXIT_FAILURE;
Harald Hoyer fe20ad
+        }
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+        log_set_target(LOG_TARGET_AUTO);
Harald Hoyer fe20ad
+        log_parse_environment();
Harald Hoyer fe20ad
+        log_open();
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+        umask(0022);
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+        r = mkdir_p("/var/lib/backlight", 0755);
Harald Hoyer fe20ad
+        if (r < 0) {
Harald Hoyer fe20ad
+                log_error("Failed to create backlight directory: %s", strerror(-r));
Harald Hoyer fe20ad
+                goto finish;
Harald Hoyer fe20ad
+        }
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+        udev = udev_new();
Harald Hoyer fe20ad
+        if (!udev) {
Harald Hoyer fe20ad
+                r = log_oom();
Harald Hoyer fe20ad
+                goto finish;
Harald Hoyer fe20ad
+        }
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+        device = udev_device_new_from_syspath(udev, argv[2]);
Harald Hoyer fe20ad
+        if (!device) {
Harald Hoyer fe20ad
+                r = log_oom();
Harald Hoyer fe20ad
+                goto finish;
Harald Hoyer fe20ad
+        }
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+        if (!streq_ptr(udev_device_get_subsystem(device), "backlight")) {
Harald Hoyer fe20ad
+                log_error("Not a backlight device: %s", argv[2]);
Harald Hoyer fe20ad
+                r = -ENODEV;
Harald Hoyer fe20ad
+                goto finish;
Harald Hoyer fe20ad
+        }
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+        saved = strappend("/var/lib/backlight/", udev_device_get_sysname(device));
Harald Hoyer fe20ad
+        if (!saved) {
Harald Hoyer fe20ad
+                r = log_oom();
Harald Hoyer fe20ad
+                goto finish;
Harald Hoyer fe20ad
+        }
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+        if (streq(argv[1], "load")) {
Harald Hoyer fe20ad
+                _cleanup_free_ char *value = NULL;
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+                r = read_one_line_file(saved, &value);
Harald Hoyer fe20ad
+                if (r < 0) {
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+                        if (r == -ENOENT) {
Harald Hoyer fe20ad
+                                r = 0;
Harald Hoyer fe20ad
+                                goto finish;
Harald Hoyer fe20ad
+                        }
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+                        log_error("Failed to read %s: %s", saved, strerror(-r));
Harald Hoyer fe20ad
+                        goto finish;
Harald Hoyer fe20ad
+                }
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+                r = udev_device_set_sysattr_value(device, "brightness", value);
Harald Hoyer fe20ad
+                if (r < 0) {
Harald Hoyer fe20ad
+                        log_error("Failed to write system attribute: %s", strerror(-r));
Harald Hoyer fe20ad
+                        goto finish;
Harald Hoyer fe20ad
+                }
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+        } else if (streq(argv[1], "save")) {
Harald Hoyer fe20ad
+                const char *value;
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+                value = udev_device_get_sysattr_value(device, "brightness");
Harald Hoyer fe20ad
+                if (!value) {
Harald Hoyer fe20ad
+                        log_error("Failed to read system attribute: %s", strerror(-r));
Harald Hoyer fe20ad
+                        goto finish;
Harald Hoyer fe20ad
+                }
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+                r = write_string_file(saved, value);
Harald Hoyer fe20ad
+                if (r < 0) {
Harald Hoyer fe20ad
+                        log_error("Failed to write %s: %s", saved, strerror(-r));
Harald Hoyer fe20ad
+                        goto finish;
Harald Hoyer fe20ad
+                }
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+        } else {
Harald Hoyer fe20ad
+                log_error("Unknown verb %s.", argv[1]);
Harald Hoyer fe20ad
+                r = -EINVAL;
Harald Hoyer fe20ad
+                goto finish;
Harald Hoyer fe20ad
+        }
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+finish:
Harald Hoyer fe20ad
+        if (device)
Harald Hoyer fe20ad
+                udev_device_unref(device);
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+        if (udev)
Harald Hoyer fe20ad
+                udev_unref(udev);
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+}
Harald Hoyer fe20ad
diff --git a/units/.gitignore b/units/.gitignore
Harald Hoyer fe20ad
index 9aee00f..9c65075 100644
Harald Hoyer fe20ad
--- a/units/.gitignore
Harald Hoyer fe20ad
+++ b/units/.gitignore
Harald Hoyer fe20ad
@@ -1,3 +1,4 @@
Harald Hoyer fe20ad
+/systemd-backlight@.service
Harald Hoyer fe20ad
 /halt-local.service
Harald Hoyer fe20ad
 /rc-local.service
Harald Hoyer fe20ad
 /systemd-hybrid-sleep.service
Harald Hoyer fe20ad
diff --git a/units/systemd-backlight@.service.in b/units/systemd-backlight@.service.in
Harald Hoyer fe20ad
new file mode 100644
Harald Hoyer fe20ad
index 0000000..14b1219
Harald Hoyer fe20ad
--- /dev/null
Harald Hoyer fe20ad
+++ b/units/systemd-backlight@.service.in
Harald Hoyer fe20ad
@@ -0,0 +1,21 @@
Harald Hoyer fe20ad
+#  This file is part of systemd.
Harald Hoyer fe20ad
+#
Harald Hoyer fe20ad
+#  systemd is free software; you can redistribute it and/or modify it
Harald Hoyer fe20ad
+#  under the terms of the GNU Lesser General Public License as published by
Harald Hoyer fe20ad
+#  the Free Software Foundation; either version 2.1 of the License, or
Harald Hoyer fe20ad
+#  (at your option) any later version.
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+[Unit]
Harald Hoyer fe20ad
+Description=Load/Save Screen Backlight Brightness of %f
Harald Hoyer fe20ad
+Documentation=man:systemd-backlight@.service(8)
Harald Hoyer fe20ad
+DefaultDependencies=no
Harald Hoyer fe20ad
+RequiresMountsFor=/var/lib/backlight
Harald Hoyer fe20ad
+Conflicts=shutdown.target
Harald Hoyer fe20ad
+After=systemd-readahead-collect.service systemd-readahead-replay.service systemd-remount-fs.service
Harald Hoyer fe20ad
+Before=sysinit.target shutdown.target
Harald Hoyer fe20ad
+
Harald Hoyer fe20ad
+[Service]
Harald Hoyer fe20ad
+Type=oneshot
Harald Hoyer fe20ad
+RemainAfterExit=yes
Harald Hoyer fe20ad
+ExecStart=@rootlibexecdir@/systemd-backlight load %f
Harald Hoyer fe20ad
+ExecStop=@rootlibexecdir@/systemd-backlight save %f