Use ioctl 'KDGKBLED' on Linux

The legacy ioctl 'KDGETLED' (which also exists on BSD) is used to get the
state of keyboard LEDs, which, however, can be used to display arbitrary
information!  So the new ioctl 'KDGKBLED' should be used to get the keyboard
flags (CapsLock, NumLock, ScrollLock), and this ioctl has a separate set of
macros ('K_NUMLOCK', 'K_CAPSLOCK') to check the flags.

See the ioctl_console(2) man page for more details.
This commit is contained in:
Aaron LI 2018-10-07 21:49:05 +08:00
parent 2cf3ba8713
commit 4753f57f1c
1 changed files with 22 additions and 8 deletions

View File

@ -4,6 +4,7 @@
#include "util.h" #include "util.h"
#include "config.h" #include "config.h"
#include "widgets.h" #include "widgets.h"
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
@ -11,6 +12,8 @@
#include <sys/time.h> #include <sys/time.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <stdio.h> #include <stdio.h>
#include <stdbool.h>
#include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#if defined(__DragonFly__) || defined(__FreeBSD__) #if defined(__DragonFly__) || defined(__FreeBSD__)
# include <sys/kbio.h> # include <sys/kbio.h>
@ -212,22 +215,33 @@ void draw_f_commands()
// numlock and capslock info // numlock and capslock info
void draw_lock_state() void draw_lock_state()
{ {
FILE* console = fopen(config.console_dev, "r"); int fd;
if ((fd = open(config.console_dev, O_RDONLY)) < 0)
if (console == NULL)
{ {
info_line = lang.err_console_dev; info_line = lang.err_console_dev;
return; return;
} }
int fd = fileno(console); bool numlock_on;
char led; bool capslock_on;
#if defined(__DragonFly__) || defined(__FreeBSD__)
int led;
ioctl(fd, KDGETLED, &led); ioctl(fd, KDGETLED, &led);
fclose(console); numlock_on = led & LED_NUM;
capslock_on = led & LED_CAP;
#else /* Linux */
char led;
ioctl(fd, KDGKBLED, &led);
numlock_on = led & K_NUMLOCK;
capslock_on = led & K_CAPSLOCK;
#endif
close(fd);
u16 pos_x = width - strlen(lang.numlock); u16 pos_x = width - strlen(lang.numlock);
if (led & LED_NUM) if (numlock_on)
{ {
struct tb_cell* numlock = str_cell(lang.numlock); struct tb_cell* numlock = str_cell(lang.numlock);
tb_blit(pos_x, 0, strlen(lang.numlock), 1, numlock); tb_blit(pos_x, 0, strlen(lang.numlock), 1, numlock);
@ -236,7 +250,7 @@ void draw_lock_state()
pos_x -= strlen(lang.capslock) + 1; pos_x -= strlen(lang.capslock) + 1;
if (led & LED_CAP) if (capslock_on)
{ {
struct tb_cell* capslock = str_cell(lang.capslock); struct tb_cell* capslock = str_cell(lang.capslock);
tb_blit(pos_x, 0, strlen(lang.capslock), 1, capslock); tb_blit(pos_x, 0, strlen(lang.capslock), 1, capslock);