[systemd-devel] [PATCH] Add support for initial state of NumLock

Stanislav Brabec sbrabec at suse.cz
Fri Apr 12 09:53:53 PDT 2013


Add support for setting of initial state of NumLock. Supported values
are "yes", "no" and "bios" (on x86 platforms).

It sets NumLock in virtual consoles. If NumLock should be turned on, it
also creates empty /run/numlock-on, which can be used e. g. for setting
of X session default.

This ports a feature that exists for a long time in SUSE to systemd.

---
 Makefile.am                             | 13 ++++++++++++
 configure.ac                            |  3 +++
 man/systemd-vconsole-setup.service.xml  |  7 +++++++
 man/vconsole.conf.xml                   | 17 +++++++++++++++-
 rules/73-seat-numlock.rules             |  8 ++++++++
 src/login/numlock-on.c                  | 36 +++++++++++++++++++++++++++++++++
 src/vconsole/vconsole-setup.c           | 26 ++++++++++++++++++++++++
 units/systemd-vconsole-setup.service.in |  2 +-
 8 files changed, 110 insertions(+), 2 deletions(-)
 create mode 100644 rules/73-seat-numlock.rules
 create mode 100644 src/login/numlock-on.c

diff --git a/Makefile.am b/Makefile.am
index eee73e5..5cab8a1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2194,6 +2194,19 @@ dist_udevrules_DATA += \
 	rules/61-accelerometer.rules
 
 # ------------------------------------------------------------------------------
+numlock_on_SOURCES = \
+	src/login/numlock-on.c
+
+numlock_on_CFLAGS = \
+	$(AM_CFLAGS)
+
+udevlibexec_PROGRAMS += \
+	numlock-on
+
+dist_udevrules_DATA += \
+	rules/73-seat-numlock.rules
+
+# ------------------------------------------------------------------------------
 if ENABLE_GUDEV
 if ENABLE_GTK_DOC
 SUBDIRS += \
diff --git a/configure.ac b/configure.ac
index 33b0ca9..abc5f47 100644
--- a/configure.ac
+++ b/configure.ac
@@ -778,6 +778,9 @@ AM_CONDITIONAL(ENABLE_MANPAGES, [test "x$have_manpages" = "xyes"])
 
 # ------------------------------------------------------------------------------
 
+AC_PATH_PROG([SETLEDS], [setleds], [/bin/setleds], [/usr/sbin:/sbin:/usr/bin:/bin])
+AC_DEFINE_UNQUOTED([SETLEDS], ["${SETLEDS}"], [Path to setleds binary.])
+
 # Location of the init scripts as mandated by LSB
 SYSTEM_SYSVINIT_PATH=/etc/init.d
 SYSTEM_SYSVRCND_PATH=/etc/rc.d
diff --git a/man/systemd-vconsole-setup.service.xml b/man/systemd-vconsole-setup.service.xml
index 3c50799..f87b2a8 100644
--- a/man/systemd-vconsole-setup.service.xml
+++ b/man/systemd-vconsole-setup.service.xml
@@ -97,6 +97,13 @@
 
 
                         </varlistentry>
+                        <varlistentry>
+                                <term><varname>vconsole.kbd.numlock=</varname></term>
+
+                                <listitem><para>Controls proposal for
+                                the initial status of
+                                NumLock.</para></listitem>
+                        </varlistentry>
                 </variablelist>
 
                 <para>See
diff --git a/man/vconsole.conf.xml b/man/vconsole.conf.xml
index f60b571..4861ba6 100644
--- a/man/vconsole.conf.xml
+++ b/man/vconsole.conf.xml
@@ -74,7 +74,8 @@
                 <varname>vconsole.keymap.toggle=</varname>,
                 <varname>vconsole.font=</varname>,
                 <varname>vconsole.font.map=</varname>,
-                <varname>vconsole.font.unimap=</varname> may be used
+                <varname>vconsole.font.unimap=</varname>,
+                <varname>vconsole.kbd.numlock=</varname> may be used
                 to override the console settings at boot.</para>
 
                 <para>Depending on the operating system other
@@ -115,6 +116,20 @@
                                 font map.</para></listitem>
                         </varlistentry>
 
+                        <varlistentry>
+                                <term><varname>KBD_NUMLOCK=</varname></term>
+
+                                <listitem><para>Configures the initial
+                                proposal for NumLock. If it proposes to
+                                turn it on, file
+                                <filename>/run/numlock-on</filename> is
+                                created.</para>
+                                <para>Allowed values are:
+                                <literal>yes</literal>: propose NumLock
+                                on, <literal>no</literal>: do nothing
+                                (default), <literal>bios</literal>:
+                                read BIOS settings.</para></listitem>
+                        </varlistentry>
                 </variablelist>
         </refsect1>
 
diff --git a/rules/73-seat-numlock.rules b/rules/73-seat-numlock.rules
new file mode 100644
index 0000000..e0061ed
--- /dev/null
+++ b/rules/73-seat-numlock.rules
@@ -0,0 +1,8 @@
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+
+SUBSYSTEM=="tty", ACTION=="add", KERNEL=="tty[0-9]|tty1[0-2]", TEST=="/run/numlock-on", RUN+="numlock-on $env{DEVNAME}"
diff --git a/src/login/numlock-on.c b/src/login/numlock-on.c
new file mode 100644
index 0000000..0a68859
--- /dev/null
+++ b/src/login/numlock-on.c
@@ -0,0 +1,36 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2012 Stanislav Brabec, SUSE Linux
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "config.h"
+#include <fcntl.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+int main (int argc, char *argv[]) {
+        static char *args[] = { SETLEDS, "-D", "+num", NULL };
+
+        if (argc != 2)
+                return EX_USAGE;
+        close (STDIN_FILENO);
+        if (open (argv[1], O_RDONLY) != STDIN_FILENO)
+                return EX_IOERR;
+        return execv(args[0], args);
+}
diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c
index ee1f3eb..1115985 100644
--- a/src/vconsole/vconsole-setup.c
+++ b/src/vconsole/vconsole-setup.c
@@ -41,6 +41,10 @@
 #include "virt.h"
 #include "fileio.h"
 
+#define BIOS_DATA_AREA  0x400
+#define BDA_KEYBOARD_STATUS_FLAGS_4 0x97
+#define BDA_KSF4_NUMLOCK_MASK 0x02
+
 static bool is_vconsole(int fd) {
         unsigned char data[1];
 
@@ -219,10 +223,12 @@ int main(int argc, char **argv) {
         char *vc_font = NULL;
         char *vc_font_map = NULL;
         char *vc_font_unimap = NULL;
+        char *vc_kbd_numlock = NULL;
         int fd = -1;
         bool utf8;
         pid_t font_pid = 0, keymap_pid = 0;
         bool font_copy = false;
+        bool numlock = false;
         int r = EXIT_FAILURE;
 
         log_set_target(LOG_TARGET_AUTO);
@@ -257,6 +263,7 @@ int main(int argc, char **argv) {
                            "FONT", &vc_font,
                            "FONT_MAP", &vc_font_map,
                            "FONT_UNIMAP", &vc_font_unimap,
+                           "KBD_NUMLOCK", &vc_kbd_numlock,
                            NULL);
 
         if (r < 0 && r != -ENOENT)
@@ -270,12 +277,27 @@ int main(int argc, char **argv) {
                                    "vconsole.font", &vc_font,
                                    "vconsole.font.map", &vc_font_map,
                                    "vconsole.font.unimap", &vc_font_unimap,
+                                   "vconsole.kbd.numlock", &vc_kbd_numlock,
                                    NULL);
 
                 if (r < 0 && r != -ENOENT)
                         log_warning("Failed to read /proc/cmdline: %s", strerror(-r));
         }
 
+#if defined(__i386__) || defined(__x86_64__)
+        if (vc_kbd_numlock && strcasecmp(vc_kbd_numlock, "bios") == 0) {
+                 int fd;
+                 char c;
+
+                 fd = open ("/dev/mem", O_RDONLY);
+                 lseek (fd, BIOS_DATA_AREA + BDA_KEYBOARD_STATUS_FLAGS_4, SEEK_SET);
+                 read (fd, &c, sizeof(char));
+                 if (c & BDA_KSF4_NUMLOCK_MASK)
+                         numlock = true;
+                 close(fd);
+        } else
+#endif
+                 numlock = vc_kbd_numlock && strcasecmp(vc_kbd_numlock, "yes") == 0;
         if (utf8)
                 enable_utf8(fd);
         else
@@ -289,6 +311,10 @@ int main(int argc, char **argv) {
 finish:
         if (keymap_pid > 0)
                 wait_for_terminate_and_warn(KBD_LOADKEYS, keymap_pid);
+        if (numlock)
+                close(open("/run/numlock-on", O_WRONLY|O_CREAT, 0644));
+        else
+                unlink("/run/numlock-on");
 
         if (font_pid > 0) {
                 wait_for_terminate_and_warn(KBD_SETFONT, font_pid);
diff --git a/units/systemd-vconsole-setup.service.in b/units/systemd-vconsole-setup.service.in
index 18faa63..44ebbd0 100644
--- a/units/systemd-vconsole-setup.service.in
+++ b/units/systemd-vconsole-setup.service.in
@@ -11,7 +11,7 @@ Documentation=man:systemd-vconsole-setup.service(8) man:vconsole.conf(5)
 DefaultDependencies=no
 Conflicts=shutdown.target
 After=systemd-readahead-collect.service systemd-readahead-replay.service
-Before=sysinit.target shutdown.target
+Before=sysinit.target shutdown.target systemd-udev-trigger.service
 ConditionPathExists=/dev/tty0
 
 [Service]
-- 
1.8.1.4

-- 
Best Regards / S pozdravem,

Stanislav Brabec
software developer
---------------------------------------------------------------------
SUSE LINUX, s. r. o.                          e-mail: sbrabec at suse.cz
Lihovarská 1060/12                            tel: +49 911 7405384547
190 00 Praha 9                                  fax: +420 284 028 951
Czech Republic                                    http://www.suse.cz/



More information about the systemd-devel mailing list