Set NumLock according to /etc/sysconfig/keyboard. https://bugzilla.novell.com/show_bug.cgi?id=746595 Authors: Stanislav Brabec Cristian Rodríguez --- Makefile.am | 13 ++++++++++ rules/73-seat-numlock.rules | 8 ++++++ src/login/numlock-on.c | 34 ++++++++++++++++++++++++++ src/vconsole/vconsole-setup.c | 41 ++++++++++++++++++++++++++++++-- units/systemd-vconsole-setup.service.in | 2 - 5 files changed, 95 insertions(+), 3 deletions(-) Index: systemd-228/Makefile.am =================================================================== --- systemd-228.orig/Makefile.am +++ systemd-228/Makefile.am @@ -3825,6 +3825,19 @@ dist_udevrules_DATA += \ rules/60-persistent-v4l.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 + +# ------------------------------------------------------------------------------ mtd_probe_SOURCES = \ src/udev/mtd_probe/mtd_probe.c \ src/udev/mtd_probe/mtd_probe.h \ Index: systemd-228/rules/73-seat-numlock.rules =================================================================== --- /dev/null +++ systemd-228/rules/73-seat-numlock.rules @@ -0,0 +1,8 @@ +# This file is part of SUSE customization 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}" Index: systemd-228/src/login/numlock-on.c =================================================================== --- /dev/null +++ systemd-228/src/login/numlock-on.c @@ -0,0 +1,34 @@ +/* + * numlock-on.c: Turn numlock-on + * + * This file may be freely copied under the terms of the GNU General + * Public License (GPL), version 2, or at your option any later + * version. + + * Copyright (C) 2013 Stanislav Brabec, SUSE + * + * based on setleds.c, which is + * Copyright (C) 1994-1999 Andries E. Brouwer + */ + +#include +#include +#include +#include + +int +main(int argc, char **argv) { + char flags; + + if (ioctl(0, KDGKBLED, &flags)) { + perror("KDGKBLED"); + exit(1); + } + + if (ioctl(0, KDSKBLED, flags | LED_NUM | (LED_NUM << 4))) { + perror("KDSKBLED"); + exit(1); + } + + exit(0); +} Index: systemd-228/src/vconsole/vconsole-setup.c =================================================================== --- systemd-228.orig/src/vconsole/vconsole-setup.c +++ systemd-228/src/vconsole/vconsole-setup.c @@ -36,6 +36,7 @@ #include "fileio.h" #include "macro.h" #include "strv.h" +#include "fs-util.h" #include "io-util.h" #include "locale-util.h" #include "log.h" @@ -46,6 +47,10 @@ #include "util.h" #include "virt.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]; @@ -364,9 +369,10 @@ int main(int argc, char **argv) { #ifdef HAVE_SYSV_COMPAT _cleanup_free_ char *vc_kbd_delay = NULL, *vc_kbd_rate = NULL, - *vc_kbd_disable_caps_lock = NULL, *vc_compose_table = NULL; + *vc_kbd_disable_caps_lock = NULL, *vc_compose_table = NULL, + *vc_kbd_numlock = NULL; #endif - bool disable_capslock = false; + bool disable_capslock = false, numlock = false; bool comp_ok, rate_ok; _cleanup_close_ int fd = -1; bool utf8, font_copy = false, font_ok, keyboard_ok; @@ -404,6 +410,7 @@ int main(int argc, char **argv) { "KBD_DELAY", &vc_kbd_delay, "KBD_RATE", &vc_kbd_rate, "KBD_DISABLE_CAPS_LOCK", &vc_kbd_disable_caps_lock, + "KBD_NUMLOCK", &vc_kbd_numlock, "COMPOSETABLE", &vc_compose_table, NULL); if (r < 0 && r != -ENOENT) @@ -421,6 +428,35 @@ int main(int argc, char **argv) { disable_capslock = vc_kbd_disable_caps_lock && strcasecmp(vc_kbd_disable_caps_lock, "YES") == 0; + numlock = vc_kbd_numlock && strcaseeq(vc_kbd_numlock, "yes"); +#if defined(__i386__) || defined(__x86_64__) + if (vc_kbd_numlock && strcaseeq(vc_kbd_numlock, "bios")) { + int _cleanup_close_ fdmem; + char c; + + fdmem = open ("/dev/mem", O_RDONLY); + if (fdmem < 0) { + log_warning_errno(errno, "Failed to open /dev/mem: %m"); + goto finish; + } + + if (lseek(fdmem, BIOS_DATA_AREA + BDA_KEYBOARD_STATUS_FLAGS_4, SEEK_SET) == (off_t) -1) { + log_warning_errno(errno, "Failed to seek /dev/mem: %m"); + goto finish; + } + + if (read(fdmem, &c, sizeof(char)) == -1) { + log_warning_errno(errno, "Failed to read /dev/mem: %m"); + goto finish; + } + + if (c & BDA_KSF4_NUMLOCK_MASK) + numlock = true; + finish: + if (fdmem >= 0) + close(fdmem); + } +#endif /* x86 */ #endif /* HAVE_SYSV_COMPAT */ r = parse_env_file("/etc/vconsole.conf", NEWLINE, @@ -456,6 +492,10 @@ int main(int argc, char **argv) { font_ok = font_load_and_wait(vc, vc_font, vc_font_map, vc_font_unimap) > 0; keyboard_ok = keyboard_load_and_wait(vc, vc_keymap, vc_keymap_toggle, utf8, disable_capslock) > 0; + if (numlock) + touch("/run/numlock-on"); + else + unlink("/run/numlock-on"); #ifdef HAVE_SYSV_COMPAT comp_ok = compose_load_and_wait(vc, vc_compose_table); rate_ok = kbdrate_set_and_wait(vc, vc_kbd_rate, vc_kbd_delay); Index: systemd-228/units/systemd-vconsole-setup.service.in =================================================================== --- systemd-228.orig/units/systemd-vconsole-setup.service.in +++ systemd-228/units/systemd-vconsole-setup.service.in @@ -10,7 +10,7 @@ Description=Setup Virtual Console Documentation=man:systemd-vconsole-setup.service(8) man:vconsole.conf(5) DefaultDependencies=no Conflicts=shutdown.target -Before=sysinit.target shutdown.target +Before=sysinit.target shutdown.target systemd-udev-trigger.service ConditionPathExists=/dev/tty0 [Service]