[Pkg-systemd-maintainers] [PATCH] Improve acpi_fakekeyd

David Härdeman david at hardeman.nu
Sat Jan 4 22:36:13 GMT 2014


Add socket activation and lazy opening of /dev/uinput which makes
acpi_fakekeyd both more robust and helps speed up boot (by avoiding
sleeping in the init script).

An added benefit of the systemd socket activation is that the daemon
is never actually started on systems (like my laptop) where the "extra"
keys don't actually generate ACPI events.
---
 debian/acpi-fakekey.init         |   18 ++---
 debian/acpi-fakekey.install      |    3 +
 debian/acpi-fakekey.modules.conf |    3 +
 debian/acpi-fakekey.service      |    7 ++
 debian/acpi-fakekey.socket       |    9 ++
 debian/control                   |    3 +
 debian/patches/acpi_fakekey.diff |  148 +++++++++++++++++++++++---------------
 debian/rules                     |    2 -
 8 files changed, 121 insertions(+), 72 deletions(-)
 create mode 100644 debian/acpi-fakekey.modules.conf
 create mode 100644 debian/acpi-fakekey.service
 create mode 100644 debian/acpi-fakekey.socket

diff --git a/debian/acpi-fakekey.init b/debian/acpi-fakekey.init
index d276383..ce6196b 100644
--- a/debian/acpi-fakekey.init
+++ b/debian/acpi-fakekey.init
@@ -1,6 +1,6 @@
 #!/bin/sh
-# INIT script to check whether we're on batteries, and so start with laptop 
-# mode etc enabled.
+# INIT script to start the ACPI fakekey daemon that turns ACPI events into
+# input events via the kernel uinput module.
 
 ### BEGIN INIT INFO
 # Provides:          acpi-fakekey
@@ -25,19 +25,13 @@ case "$1" in
 			log_action_end_msg 1 "Modprobe uinput failed. Please use 'dmesg' to find out why"
 		fi
 	fi
-	# give udev time to create the devices
-	sleep 1
     fi
 
-    if [ -d /sys/devices/virtual/misc/uinput ]; then
-	if start-stop-daemon --start --quiet --oknodo --exec /usr/sbin/acpi_fakekeyd
-	then
-		log_action_end_msg 0
-	else
-		log_action_end_msg 1 "Could not start /usr/sbin/acpi_fakekeyd"
-	fi
-    else
+    if start-stop-daemon --start --quiet --oknodo --exec /usr/sbin/acpi_fakekeyd
+    then
 	log_action_end_msg 0
+    else
+	log_action_end_msg 1 "Could not start /usr/sbin/acpi_fakekeyd"
     fi
     ;;
   stop)
diff --git a/debian/acpi-fakekey.install b/debian/acpi-fakekey.install
index 28625f4..1ba5e32 100644
--- a/debian/acpi-fakekey.install
+++ b/debian/acpi-fakekey.install
@@ -1,2 +1,5 @@
 acpi_fakekey					/usr/bin
 acpi_fakekeyd					/usr/sbin
+debian/acpi-fakekey.service			/lib/systemd/system
+debian/acpi-fakekey.socket			/lib/systemd/system
+debian/acpi-fakekey.modules.conf		/etc/modules-load.d
diff --git a/debian/acpi-fakekey.modules.conf b/debian/acpi-fakekey.modules.conf
new file mode 100644
index 0000000..3a1c6b0
--- /dev/null
+++ b/debian/acpi-fakekey.modules.conf
@@ -0,0 +1,3 @@
+# /etc/modules-load.d/acpi-fakekey.modules.conf
+# The uinput module is used by the acpi-fakekeyd daemon (package acpi-fakekey)
+uinput
diff --git a/debian/acpi-fakekey.service b/debian/acpi-fakekey.service
new file mode 100644
index 0000000..b1e4535
--- /dev/null
+++ b/debian/acpi-fakekey.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=ACPI fakekey daemon
+Requires=acpi-fakekey.socket
+
+[Service]
+Type=simple
+ExecStart=/usr/sbin/acpi_fakekeyd -f
diff --git a/debian/acpi-fakekey.socket b/debian/acpi-fakekey.socket
new file mode 100644
index 0000000..99769bf
--- /dev/null
+++ b/debian/acpi-fakekey.socket
@@ -0,0 +1,9 @@
+[Unit]
+Description=ACPI fakekey daemon FIFO
+
+[Socket]
+ListenFIFO=/var/run/acpi_fakekey
+SocketMode=0200
+
+[Install]
+WantedBy=sockets.target
diff --git a/debian/control b/debian/control
index 5938b24..8c1f36e 100644
--- a/debian/control
+++ b/debian/control
@@ -3,7 +3,8 @@ Section: admin
 Priority: optional
 Maintainer: Debian Acpi Team <pkg-acpi-devel at lists.alioth.debian.org>
 Uploaders: Michael Meskes <meskes at debian.org>
-Build-Depends: debhelper (>= 7.0.50~), quilt (>= 0.40)
+Build-Depends: debhelper (>= 7.0.50~), quilt (>= 0.40),
+	libsystemd-daemon-dev [linux-any], dh-systemd (>= 1.5), pkg-config
 Vcs-Git: git://git.debian.org/git/pkg-acpi/acpi-support.git
 Vcs-Browser: http://git.debian.org/?p=pkg-acpi/acpi-support.git
 Standards-Version: 3.9.3
diff --git a/debian/patches/acpi_fakekey.diff b/debian/patches/acpi_fakekey.diff
index 74656b9..fdb9a1a 100644
--- a/debian/patches/acpi_fakekey.diff
+++ b/debian/patches/acpi_fakekey.diff
@@ -1,6 +1,5 @@
-diff -Nru acpi-support-0.115/acpi_fakekey.c /tmp/Umsn0ebzYy/acpi-support-0.115+thjaeger1/acpi_fakekey.c
---- acpi-support-0.115/acpi_fakekey.c	2008-09-26 00:14:34.000000000 +0100
-+++ acpi-support-0.115+thjaeger1/acpi_fakekey.c	2009-01-19 09:09:31.000000000 +0000
+--- a/acpi_fakekey.c
++++ b/acpi_fakekey.c
 @@ -1,68 +1,29 @@
  #include <unistd.h>
  #include <fcntl.h>
@@ -85,9 +84,8 @@ diff -Nru acpi-support-0.115/acpi_fakekey.c /tmp/Umsn0ebzYy/acpi-support-0.115+t
 +	return EXIT_SUCCESS;
  }
 -
-diff -Nru /tmp/clWVJzRiJd/acpi-support-0.115/Makefile /tmp/Umsn0ebzYy/acpi-support-0.115+thjaeger1/Makefile
---- acpi-support-0.115/Makefile	2008-09-26 00:14:34.000000000 +0100
-+++ acpi-support-0.115+thjaeger1/Makefile	2009-01-19 09:09:31.000000000 +0000
+--- a/Makefile
++++ b/Makefile
 @@ -1,8 +1,10 @@
 -all: acpi_fakekey
 +all: acpi_fakekey acpi_fakekeyd
@@ -98,19 +96,20 @@ diff -Nru /tmp/clWVJzRiJd/acpi-support-0.115/Makefile /tmp/Umsn0ebzYy/acpi-suppo
 +	gcc -Wall $(shell dpkg-buildflags --get CFLAGS) $(shell dpkg-buildflags --get CPPFLAGS) $(shell dpkg-buildflags --get LDFLAGS) -o $@ $<
 +
 +acpi_fakekeyd: acpi_fakekeyd.c
-+	gcc -Wall $(shell dpkg-buildflags --get CFLAGS) $(shell dpkg-buildflags --get CPPFLAGS) $(shell dpkg-buildflags --get LDFLAGS) -o $@ $<
++	gcc -Wall $(shell dpkg-buildflags --get CFLAGS) $(shell dpkg-buildflags --get CPPFLAGS) $(shell dpkg-buildflags --get LDFLAGS) $(shell pkg-config --cflags --libs libsystemd-daemon) -o $@ $<
  
  # Keep this manually generated so that it doesn't build-dep on
  # 'linux-headers' and stays predictable.
-@@ -15,4 +19,4 @@
+@@ -15,4 +17,4 @@
  	test -f aliased-keys && cat aliased-keys >> $@
  
  clean:
 -	rm -f acpi_fakekey
 +	$(RM) acpi_fakekey acpi_fakekeyd
---- acpi-support/acpi_fakekeyd.c	2010-06-15 12:35:38.846063228 +0200
-+++ acpi-support/acpi_fakekeyd.c	2010-06-15 18:22:03.000000000 +0200
-@@ -0,0 +1,103 @@
+--- /dev/null
++++ b/acpi_fakekeyd.c
+@@ -0,0 +1,137 @@
++#define _BSD_SOURCE
 +#include <unistd.h>
 +#include <fcntl.h>
 +#include <string.h>
@@ -118,99 +117,132 @@ diff -Nru /tmp/clWVJzRiJd/acpi-support-0.115/Makefile /tmp/Umsn0ebzYy/acpi-suppo
 +#include <stdio.h>
 +#include <linux/uinput.h>
 +#include <sys/stat.h>
++#include <systemd/sd-daemon.h>
 +
 +#define FIFO "/var/run/acpi_fakekey"
 +
-+void fail(const char *str) {
++static void fail(const char *str) {
 +	perror(str);
 +	exit(EXIT_FAILURE);
 +}
 +
-+void daemonize() {
-+	int pid;
-+	if ((pid = fork()) == -1)
-+		fail("fork");
-+
-+	if (pid)
-+		exit(EXIT_SUCCESS);
 +
-+	if (setsid() == -1)
-+		fail("setsid");
-+
-+	if (chdir("/") == -1)
-+		fail("chdir");
++static int create_fifo() {
++	int fifo, n;
++
++	n = sd_listen_fds(1);
++	if (n > 1)
++		fail("sd_listen_fds");
++	else if (n == 1) {
++		fifo = SD_LISTEN_FDS_START + 0;
++		if (!sd_is_fifo(fifo, FIFO))
++			fail("sd_is_fifo");
++	} else {
++		remove(FIFO);
++		if (mkfifo(FIFO, 0200) == -1)
++			fail("mkfifo");
++		if ((fifo = open(FIFO, O_RDWR | O_NONBLOCK)) == -1)
++			fail("open fifo");
++	}
 +
-+	if (!freopen("/dev/null", "r", stdin))
-+		fail("freopen");
-+	if (!freopen("/dev/null", "w", stdout))
-+		fail("freopen");
-+	if (!freopen("/dev/null", "w", stderr))
-+		fail("freopen");
++	return fifo;
 +}
 +
-+int main(int argc, char** argv) {
-+	int fd;
-+	int fifo;
-+	int i;
++static int create_uinputdev() {
++	int udev, i;
 +	struct uinput_user_dev dev;
-+	fd_set sfd;
 +
-+	if ((fd = open("/dev/uinput", O_WRONLY | O_NDELAY)) == -1)
-+		fail("open device");
++	/* Failure to open dev is not fatal, module might be loaded later */
++	udev = open("/dev/uinput", O_WRONLY | O_NDELAY);
++	if (udev < 0) {
++		perror("failed to open /dev/uinput");
++		return -1;
++	}
 +
 +	memset(&dev, 0, sizeof(dev));
 +	strncpy(dev.name, "ACPI Virtual Keyboard Device", UINPUT_MAX_NAME_SIZE);
 +	dev.id.version = 4;
 +	dev.id.bustype = BUS_USB;
 +
-+	ioctl(fd, UI_SET_EVBIT, EV_KEY);
++	ioctl(udev, UI_SET_EVBIT, EV_KEY);
 +	for (i = 0; i < 256; i++)
-+		ioctl(fd, UI_SET_KEYBIT, i);
-+	if (write(fd, &dev, sizeof(dev)) == -1)
++		ioctl(udev, UI_SET_KEYBIT, i);
++
++	if (write(udev, &dev, sizeof(dev)) == -1)
 +		fail("write");
 +
-+	if (ioctl(fd, UI_DEV_CREATE) == -1)
++	if (ioctl(udev, UI_DEV_CREATE) == -1)
 +		fail("create device");
 +
-+	remove(FIFO);
-+	if (mkfifo(FIFO, 0200) == -1)
-+		fail("mkfifo");
-+	
-+	if ((fifo = open(FIFO, O_RDWR | O_NONBLOCK)) == -1)
-+		fail("open fifo");
++	return udev;
++}
++
++int main(int argc, char **argv) {
++	int do_daemonize = 1;
++	int udev;
++	int fifo;
++	fd_set sfd;
 +
-+	daemonize();
++	if (argc == 2 && !strcmp(argv[1], "-f"))
++		do_daemonize = 0;
++	else if (argc > 1)
++		fail("invalid arguments");
++
++	udev = create_uinputdev();
++
++	fifo = create_fifo();
++
++	if (do_daemonize && (daemon(0, 0) != 0))
++		fail("daemon");
 +
 +	FD_ZERO(&sfd);
 +	FD_SET(fifo, &sfd);
-+	while (select(fifo+1, &sfd, 0, 0, 0) != -1) {
++	while (select(fifo + 1, &sfd, 0, 0, 0) != -1) {
 +		int n;
-+		unsigned char key; 
++		unsigned char key;
 +		struct input_event event;
-+		if ((n = read(fifo, &key, 1)) == -1)
++
++		n = read(fifo, &key, 1);
++		if (n < 0)
 +			break;
-+		if (!n)
++		if (n == 0)
 +			continue;
 +
++		/* Try again to create a uinput device if necessary */
++		if (udev < 0) {
++			udev = create_uinputdev();
++			if (udev < 0)
++				continue;
++		}
++
++		/* Key pressed */
++		memset(&event, 0, sizeof(event));
 +		event.type = EV_KEY;
 +		event.code = key;
 +		event.value = 1;
-+		if (write(fd, &event, sizeof event) == -1)
++		if (write(udev, &event, sizeof(event)) == -1)
 +			break;
++
++		/* Key released */
++		memset(&event, 0, sizeof(event));
++		event.type = EV_KEY;
++		event.code = key;
 +		event.value = 0;
-+		if (write(fd, &event, sizeof event) == -1)
++		if (write(udev, &event, sizeof(event)) == -1)
 +			break;
-+		/* Need to write sync event */
++
++		/* Sync */
 +		memset(&event, 0, sizeof(event));
 +		event.type = EV_SYN;
 +		event.code = SYN_REPORT;
 +		event.value = 0;
-+		if (write(fd, &event, sizeof event) == -1)
++		if (write(udev, &event, sizeof(event)) == -1)
 +			break;
 +	}
 +
-+	ioctl(fd, UI_DEV_DESTROY);
-+	close(fd);
++	ioctl(udev, UI_DEV_DESTROY);
++	close(udev);
++	close(fifo);
 +	remove(FIFO);
 +	return EXIT_FAILURE;
 +}
diff --git a/debian/rules b/debian/rules
index 1eba9a1..c716e45 100755
--- a/debian/rules
+++ b/debian/rules
@@ -8,7 +8,7 @@ arch-depends := -V'arch:Suggests=toshset'
 endif
 
 %:
-	dh ${@} --with quilt
+	dh ${@} --with quilt,systemd
 
 override_dh_auto_clean:
 	dh_auto_clean





More information about the Pkg-systemd-maintainers mailing list