From 364f8fa84e956c411ae4524d10643a75eb042fb2 Mon Sep 17 00:00:00 2001 From: Diego Nieto Cid Date: Wed, 29 Dec 2010 14:32:02 -0300 Subject: Translate scancodes using XKB. * console-client/Makefile (pc-kbd-CFLAGS): New variable. (PC_KBD_SO_SRCS): Add sources from xkb directory. (LCLHDRS): Add includes from xkb directory. (lex.c, parser.tab.h): New targets. (VPATH): New variable. (CPPFLAGS): Add xkb directory to include search path. (LFLAGS, YFLAGS): New variables. (DIST_FILES): New variable. * console-client/pc-kbd.c [XKB_SUPPORT]: Include xkb/xkb.h. (cd): Removed static qualifier. [XKB_SUPPORT] (ctrlaltbs): New variable. [XKB_SUPPORT] (xkb_repeat_delay, xkb_repeat_interval): Likewise. (gnumach_v1_input_next) [XKB_SUPPORT]: Skip conversion to set 2. [XKB_SUPPORT] (read_keycode): New function. [XKB_SUPPORT] (input_loop): Pass keycode to xkb_input_key. (struct arguments): New type. (options) [XKB_SUPPORT]: New options xkbdir, keymapfile, keymap compose, ctrlaltbs, no-ctrlaltbs, repeat-delay and repeat-interval. (parse_opt) [XKB_SUPPORT]: Handle new options. (pc_kbd_init) [XKB_SUPPORT]: Initialize XKB and load layout. (pc_kbd_start) [XKB_SUPPORT]: Initialize xkb timers. --- console-client/Makefile | 29 ++++- console-client/pc-kbd.c | 285 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 303 insertions(+), 11 deletions(-) (limited to 'console-client') diff --git a/console-client/Makefile b/console-client/Makefile index 22a492a9..b7f3763d 100644 --- a/console-client/Makefile +++ b/console-client/Makefile @@ -22,7 +22,10 @@ makemode := utilities targets = console CONSOLE_SRCS = console.c timer.c driver.c trans.c VGA_SO_SRCS = bdf.c vga-dynafont.c vga-dynacolor.c vga-support.c vga.c -PC_KBD_SO_SRCS = pc-kbd.c kbd-repeat.c +PC_KBD_SO_SRCS = pc-kbd.c kbd-repeat.c \ + xkb/compose.c xkb/kstoucs.c xkb/parser.y xkb/lex.l \ + xkb/symname.c xkb/xkb.c xkb/xkbdata.c xkb/xkbdefaults.c \ + xkb/xkbtimer.c PC_MOUSE_SO_SRCS = pc-mouse.c GENERIC_SPEAKER_SO_SRCS = generic-speaker.c CURRENT_VCS_SO_SRCS = current-vcs.c @@ -35,17 +38,27 @@ SRCS = $(CONSOLE_SRCS) \ LCLHDRS = timer.h driver.h display.h input.h bell.h \ unicode.h bdf.h mach-inputdev.h \ vga-dynafont.h vga-dynacolor.h vga-hw.h vga-support.h \ - trans.h + trans.h \ + xkb/keysymdef.h xkb/ks_tables.h xkb/xkb.h -OBJS = $(SRCS:.c=.o) kdioctlServer.o +VPATH += $(srcdir)/xkb +OBJS = $(addsuffix .o,$(basename $(notdir $(SRCS)))) kdioctlServer.o HURDLIBS = cons threads ports netfs fshelp iohelp ihash shouldbeinlibc LDLIBS = -ldl module-dir = $(libdir)/hurd/console console-LDFLAGS = -Wl,-E +CPPFLAGS += -I$(srcdir)/xkb +LFLAGS = -i +YFLAGS = -by + # In seeking, thou shalt find it! CPPFLAGS += -DQUAERENDO_INVENIETIS +DIST_FILES = xkb/HACKING xkb/MISSING-FEATURES xkb/README xkb/TODO \ + xkb/Compose xkb/default.xkb xkb/makeconf.sh \ + $(wildcard xkb/xkb-data/*/hurd) + include ../Makeconf driver-CPPFLAGS = -D'CONSOLE_DEFPATH="$(module-dir)\0"' \ @@ -59,8 +72,9 @@ console: $(CONSOLE_SRCS:.c=.o) \ modules = vga pc_kbd generic_speaker pc_mouse current_vcs vga-CPPFLAGS = -DDEFAULT_VGA_FONT_DIR=\"${datadir}/hurd/\" +pc-kbd-CFLAGS = -DXKB_SUPPORT -DXKB_DATA_DIR=\"$(datadir)/X11/xkb\" vga.so.$(hurd-version): $(patsubst %.c,%_pic.o,$(VGA_SO_SRCS)) -pc_kbd.so.$(hurd-version): $(patsubst %.c,%_pic.o,$(PC_KBD_SO_SRCS)) \ +pc_kbd.so.$(hurd-version): $(addsuffix _pic.o, $(basename $(notdir $(PC_KBD_SO_SRCS)))) \ kdioctlServer_pic.o pc_mouse.so.$(hurd-version): $(patsubst %.c,%_pic.o,$(PC_MOUSE_SO_SRCS)) generic_speaker.so.$(hurd-version): $(patsubst %.c,%_pic.o,$(GENERIC_SPEAKER_SO_SRCS)) @@ -91,3 +105,10 @@ $(module-dir)/%: % $(CC) -shared -Wl,-soname=$@ -o $@ $(rpath) \ $(CFLAGS) $($*-CFLAGS) $(LDFLAGS) \ '-Wl,-(' $($*-LDLIBS) '-Wl,-)' $^ + +lex.c: lex.l parser.tab.h +parser.tab.h: parser.y + if $(YACC) $(YFLAGS) -d $<; then \ + mv y.tab.h $@; \ + rm y.tab.c; \ + fi diff --git a/console-client/pc-kbd.c b/console-client/pc-kbd.c index 35e25617..fdc749d7 100644 --- a/console-client/pc-kbd.c +++ b/console-client/pc-kbd.c @@ -34,6 +34,10 @@ #include "driver.h" #include "mach-inputdev.h" +#ifdef XKB_SUPPORT +#include "xkb/xkb.h" +#endif + /* The default name of the node of the repeater. */ #define DEFAULT_REPEATER_NODE "kbd" @@ -41,8 +45,11 @@ /* The keyboard device in the kernel. */ static device_t kbd_dev; -/* The converter. */ -static iconv_t cd; +/* The converter. + XXX: Here it is used by the fixed US layout code. It's not static because + xkb.c also needs a converter. This variable and it's initialization should + be moved there once XKB is supported in OSKit. */ +iconv_t cd; /* The status of various LEDs. */ struct { @@ -62,6 +69,18 @@ static char *repeater_node; /* The repeater node. */ static consnode_t cnode; + +#ifdef XKB_SUPPORT +/* CTRL + Alt + Backspace will terminate the console client by + default, this hardcoded behaviour can be disabled. */ +static int ctrlaltbs; + +/* The number of jiffies until repetition starts. */ +static int xkb_repeat_delay; + +/* The number of jiffies until the next repetition is generated. */ +static int xkb_repeat_interval; +#endif /* A list of scan codes generated by the keyboard, in the set 2 encoding. */ enum scancode @@ -597,6 +616,10 @@ gnumach_v1_input_next () } while (data_buf.type != KEYBD_EVENT); +#ifdef XKB_SUPPORT + /* XKB code work with set1 scancodes. */ + return data_buf.value.sc; +#else /* not XKB_SUPPORT */ /* Some fixed codes which are the same in set 1 and set 2, and have the UP flag set. */ if (data_buf.value.sc == SC_EXTENDED1 @@ -609,6 +632,7 @@ gnumach_v1_input_next () sc = sc_set1_to_set2[data_buf.value.sc &~ SC_SET1_FLAG_UP]; return sc | (up ? SC_FLAG_UP : 0); +#endif /* not XKB_SUPPORT */ } @@ -676,11 +700,139 @@ input_next () return sc; } +#ifdef XKB_SUPPORT +/* Read a keycode using the input_next routine. The translation from + scancodes is hardcoded. A configuration file should be used in the + near future because this is an UGLY HACK. */ +keycode_t +read_keycode (void) +{ + scancode_t sc = input_next (); + int release = 0; + + /* The keypress generated two keycodes. */ + if (sc == 0xE0) + { + sc = input_next (); + + release = sc & 0x80; + sc &= ~0x80; + + switch (sc) + { + case 0x1D: /* RCTRL. */ + sc = 101; + break; + case 0x38: /* RALT. */ + sc = 105; + break; + /* LRGUI MENU. */ + case 0x5B: /* LGUI. */ + sc = 107; + break; + case 0x5C: /* RGUI. */ + sc = 108; + break; + case 0x5D: /* MENU. */ + sc = 109; + break; + case 0x52: /* Insert. */ + sc = 98; + break; + case 0x47: /* Home. */ + sc = 89; + break; + case 0x49: /* Pg Up. */ + sc = 91; + break; + case 0x53: /* Delete. */ + sc = 99; + break; + case 0x4F: /* End. */ + sc = 95; + break; + case 0x51: /* Pg Down. */ + sc = 97; + break; + case 0x48: /* Arrow up. */ + sc = 90; + break; + case 0x50: /* Arrow down. */ + sc = 96; + break; + case 0x4b: /* Arrow left. */ + sc = 92; + break; + case 0x4d: /* Arrow right. */ + sc = 94; + break; + case 0x35: /* '/' */ + sc = 104; + break; + case 0x1C: /* KP_Enter. */ + sc = 100; + break; + default: + sc += 0x78; + } + + sc |= release; + } + else + release = sc & 0x80; + + return sc; +} +#endif /* XKB_SUPPORT */ /* The input loop. */ static any_t input_loop (any_t unused) { +#ifdef XKB_SUPPORT + /* XXX: until conversion from scancode to keycode is properly implemented + XKB won't work on anything but scancode set 1. + In the meanwhile, a fixed US layout implementation is used for OSKit + Mach. **/ + if (gnumach_v1_compat) + { + /* The previous keypress. */ + keycode_t prevkey = 0; + + while (1) + { + keypress_t key; + + key.keycode = read_keycode () + min_keys; + key.rel = key.keycode & 0x80; + key.redir = 0; + + if (!key.rel && key.keycode == prevkey) + key.repeat = 1; + else + key.repeat = 0; + + if (key.repeat) + continue; + + /* The keycombination CTRL+Alt+Backspace terminates the console + client. Keycodes instead of modifiers+symbols are used to + make it able to exit the client, even when the keymaps are + faulty. */ + if ((keystate[64].keypressed || keystate[113].keypressed) /* Alt */ + && (keystate[37].keypressed || keystate[109].keypressed) /* CTRL*/ + && keystate[22].keypressed && ctrlaltbs) /* Backspace. */ + console_exit (); + + if (!key.repeat) + xkb_input_key (key.keycode); + prevkey = key.keycode; + } + + return 0; + } +#endif /* XKB_SUPPORT */ + while (1) { enum scancode fsc = input_next (); @@ -1029,8 +1181,43 @@ input_loop (any_t unused) static const char doc[] = "PC Keyboard Driver"; +struct arguments +{ + int pos; +#ifdef XKB_SUPPORT + char *xkbdir; + char *keymapfile; + char *keymap; + char *composefile; + int ctrlaltbs; + int repeat_delay; + int repeat_interval; +#endif +}; + static const struct argp_option options[] = { +#ifdef XKB_SUPPORT +/* Some random ids for options available only in long form. */ +#define REPEAT_DELAY_ID 25425 +#define REPEAT_INTERVAL_ID 5322 + {"xkbdir", 'x', "DIR", 0, + "Directory containing the XKB configuration files" }, + {"keymapfile", 'f', "FILE", 0, + "File containing the keymap" }, + {"keymap", 'k', "SECTIONNAME" , 0, + "Choose keymap"}, + {"compose", 'o', "COMPOSEFILE", 0, + "Compose file to load (default none)"}, + {"ctrlaltbs", 'c', 0 , 0, + "CTRL + Alt + Backspace will exit the console client (default)."}, + {"no-ctrlaltbs", 'n', 0 , 0, + "CTRL + Alt + Backspace will not exit the console client."}, + {"repeat-delay", REPEAT_DELAY_ID, "DELAY", 0, + "Delay before pressed key starts repeating (measured in jiffies)"}, + {"repeat-interval", REPEAT_INTERVAL_ID, "INTERVAL", 0, + "Time elapsed between repeated keys (measured in jiffies)"}, +#endif /* XKB_SUPPORT */ {"repeat", 'r', "NODE", OPTION_ARG_OPTIONAL, "Set a repeater translator on NODE (default: " DEFAULT_REPEATER_NODE ")"}, { 0 } @@ -1039,10 +1226,43 @@ static const struct argp_option options[] = static error_t parse_opt (int key, char *arg, struct argp_state *state) { - int *pos = (int *) state->input; + struct arguments *arguments = state->input; switch (key) { +#ifdef XKB_SUPPORT + case 'x': + arguments->xkbdir = arg; + break; + + case 'f': + arguments->keymapfile = arg; + break; + + case 'k': + arguments->keymap = arg; + break; + + case 'o': + arguments->composefile = arg; + break; + + case 'c': + arguments->ctrlaltbs = 1; + break; + + case 'n': + arguments->ctrlaltbs = 0; + break; + + case REPEAT_DELAY_ID: + arguments->repeat_delay = atoi(arg); + break; + + case REPEAT_INTERVAL_ID: + arguments->repeat_interval = atoi(arg); + break; +#endif /* XKB_SUPPORT */ case 'r': repeater_node = arg ? arg: DEFAULT_REPEATER_NODE; break; @@ -1054,7 +1274,7 @@ parse_opt (int key, char *arg, struct argp_state *state) return ARGP_ERR_UNKNOWN; } - *pos = state->next; + arguments->pos = state->next; return 0; } @@ -1065,16 +1285,64 @@ static error_t pc_kbd_init (void **handle, int no_exit, int argc, char *argv[], int *next) { error_t err; - int pos = 1; + struct arguments arguments = + { + pos: 1 +#ifdef XKB_SUPPORT + , xkbdir: 0 + , keymapfile: 0 + , keymap: 0 + , composefile: 0 + , ctrlaltbs: 1 + , repeat_delay: -1 + , repeat_interval: -1 +#endif + }; /* Parse the arguments. */ err = argp_parse (&argp, argc, argv, ARGP_IN_ORDER | ARGP_NO_EXIT - | ARGP_SILENT, 0 , &pos); - *next += pos - 1; + | ARGP_SILENT, 0 , &arguments); + *next += arguments.pos - 1; if (err && err != EINVAL) return err; +#ifdef XKB_SUPPORT + if (!arguments.xkbdir) + { + arguments.xkbdir = XKB_DATA_DIR; + } + if (!arguments.keymapfile) + { + arguments.keymapfile = "keymap/hurd"; + } + if (arguments.repeat_delay <= 0) + { + arguments.repeat_delay = 50; + } + if (arguments.repeat_interval <= 0) + { + arguments.repeat_interval = 10; + } + + ctrlaltbs = arguments.ctrlaltbs; + xkb_repeat_delay = arguments.repeat_delay; + xkb_repeat_interval = arguments.repeat_interval; + + if (arguments.composefile) + { + err = read_composefile (arguments.composefile); + if (err) + return err; + } + + xkb_data_init (); + err = xkb_load_layout (arguments.xkbdir, arguments.keymapfile, + arguments.keymap); + + if (err) + return err; +#endif /* XKB_SUPPORT */ return 0; } @@ -1124,6 +1392,9 @@ pc_kbd_start (void *handle) iconv_close (cd); return err; } +#ifdef XKB_SUPPORT + xkb_init_repeat (xkb_repeat_delay, xkb_repeat_interval); +#endif } update_leds (); -- cgit v1.2.3