summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--console-client/Makefile29
-rw-r--r--console-client/pc-kbd.c285
2 files changed, 303 insertions, 11 deletions
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 ();