From: Carles Pina i Estany <carles@pina.cat>
To: grub-devel@gnu.org
Subject: keyboard layout patches
Date: Mon, 18 Jan 2010 00:10:16 +0000 [thread overview]
Message-ID: <20100118001016.GA12122@pina.cat> (raw)
[-- Attachment #1: Type: text/plain, Size: 1020 bytes --]
Hello,
I've done a first version of keyboard_layout. Find a patch attached, or
check the branch:
bzr.savannah.gnu.org/srv/bzr/grub/people/cpina/keyboard_layouts
I've tested only in at_keyboard. Using something like:
insmod at_keyboard
terminal_input at_keyboard
insmod keyboard_layouts
set keymaps_dir=/boot/grub/layouts
load_keyboard es
and before I generate the file called "es" and copied into
/boot/grub/layouts using grub-mklayout es
How could grub-mkinstall (00_header.in) know the current keyboard in the
system? I wold tweak 00_header.in to generate the keymap file and setup
it.
Comments about the current patch are welcomed, I would change it on next
days.
Some days ago I read:
"There are 2 hard problems in computer science: cache invalidation,
naming things, and off-by-1 errors."
Don't hesitate to tell me how would you rename some things, I'll do.
I'm not happy with the name of some variables/functions but I cannot
think about it today :-)
Cheers,
--
Carles Pina i Estany
http://pinux.info
[-- Attachment #2: keyboard_layout01.patch --]
[-- Type: text/x-diff, Size: 16743 bytes --]
=== modified file 'conf/common.rmk'
--- conf/common.rmk 2010-01-14 14:04:44 +0000
+++ conf/common.rmk 2010-01-17 14:35:00 +0000
@@ -88,6 +88,10 @@ endif
bin_UTILITIES += grub-mkrelpath
grub_mkrelpath_SOURCES = gnulib/progname.c util/grub-mkrelpath.c util/misc.c
+# For grub-mklayouts.
+bin_UTILITIES += grub-mklayouts
+grub_mklayouts_SOURCES = gnulib/progname.c util/grub-mklayouts.c util/misc.c
+
# For the parser.
grub_script.tab.c grub_script.tab.h: script/parser.y
$(YACC) -d -p grub_script_yy -b grub_script $(srcdir)/script/parser.y
@@ -647,6 +651,12 @@ gettext_mod_SOURCES = gettext/gettext.c
gettext_mod_CFLAGS = $(COMMON_CFLAGS)
gettext_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For keyboard_layouts.mod
+pkglib_MODULES += keyboard_layouts.mod
+keyboard_layouts_mod_SOURCES = keyboard_layouts/keyboard_layouts.c
+keyboard_layouts_mod_CFLAGS = $(COMMON_CFLAGS)
+keyboard_layouts_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
# Misc.
pkglib_MODULES += xnu_uuid.mod
=== added file 'include/grub/keys.h'
--- include/grub/keys.h 1970-01-01 00:00:00 +0000
+++ include/grub/keys.h 2010-01-17 18:21:42 +0000
@@ -0,0 +1,36 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2010 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_KEYS_HEADER
+#define GRUB_KEYS_HEADER 1
+
+/* Internal codes used by GRUB to represent terminal input. */
+#define GRUB_TERM_LEFT 2
+#define GRUB_TERM_RIGHT 6
+#define GRUB_TERM_UP 16
+#define GRUB_TERM_DOWN 14
+#define GRUB_TERM_HOME 1
+#define GRUB_TERM_END 5
+#define GRUB_TERM_DC 4
+#define GRUB_TERM_PPAGE 7
+#define GRUB_TERM_NPAGE 3
+#define GRUB_TERM_ESC '\e'
+#define GRUB_TERM_TAB '\t'
+#define GRUB_TERM_BACKSPACE 8
+
+#endif /* ! GRUB_KEYS_HEADER */
=== modified file 'include/grub/term.h'
--- include/grub/term.h 2010-01-09 22:42:17 +0000
+++ include/grub/term.h 2010-01-17 22:25:58 +0000
@@ -19,19 +19,7 @@
#ifndef GRUB_TERM_HEADER
#define GRUB_TERM_HEADER 1
-/* Internal codes used by GRUB to represent terminal input. */
-#define GRUB_TERM_LEFT 2
-#define GRUB_TERM_RIGHT 6
-#define GRUB_TERM_UP 16
-#define GRUB_TERM_DOWN 14
-#define GRUB_TERM_HOME 1
-#define GRUB_TERM_END 5
-#define GRUB_TERM_DC 4
-#define GRUB_TERM_PPAGE 7
-#define GRUB_TERM_NPAGE 3
-#define GRUB_TERM_ESC '\e'
-#define GRUB_TERM_TAB '\t'
-#define GRUB_TERM_BACKSPACE 8
+#include <grub/keys.h>
#ifndef ASM_FILE
@@ -198,6 +186,14 @@ extern struct grub_term_input *EXPORT_VA
extern struct grub_term_output *EXPORT_VAR(grub_term_outputs);
extern struct grub_term_input *EXPORT_VAR(grub_term_inputs);
+struct grub_keyboard_map_s
+{
+ char *normal;
+ char *shift;
+};
+
+extern struct grub_keyboard_map_s *EXPORT_VAR(grub_keyboard_map);
+
static inline void
grub_term_register_input (const char *name __attribute__ ((unused)),
grub_term_input_t term)
=== modified file 'kern/term.c'
--- kern/term.c 2009-12-27 21:35:40 +0000
+++ kern/term.c 2010-01-17 21:52:16 +0000
@@ -30,6 +30,8 @@ struct grub_term_input *grub_term_inputs
void (*grub_newline_hook) (void) = NULL;
+struct grub_keyboard_map_s *grub_keyboard_map = NULL;
+
/* Put a Unicode character. */
void
grub_putcode (grub_uint32_t code, struct grub_term_output *term)
=== added directory 'keyboard_layouts'
=== added file 'keyboard_layouts/keyboard_layouts.c'
--- keyboard_layouts/keyboard_layouts.c 1970-01-01 00:00:00 +0000
+++ keyboard_layouts/keyboard_layouts.c 2010-01-17 22:59:21 +0000
@@ -0,0 +1,160 @@
+/* keyboard_layouts.c - keyboard_layouts module*/
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2010 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/normal.h>
+#include <grub/file.h>
+#include <grub/kernel.h>
+#include <grub/i18n.h>
+
+#include <grub/term.h>
+
+static char original_keyboard_layout_normal[128];
+static char original_keyboard_layout_shift[128];
+
+static char *active_layout;
+
+/* Layout file format constants. */
+static const char file_magic[7] = { 'G', 'R', 'U', 'B', 'L', 'A', 'Y' };
+
+static grub_err_t
+grub_cmd_load_keyboardlayout (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char **args)
+{
+ char magic[8];
+ int check;
+ char *filename;
+ char *prefix;
+
+ if (argc != 1)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "usage: load_keyboard layout");
+
+ prefix = grub_env_get ("keymaps_dir");
+ if (!prefix)
+ return grub_error (GRUB_ERR_READ_ERROR,
+ "`keymaps_dir' variable not set up");
+
+ filename =
+ grub_malloc (grub_strlen (prefix) + grub_strlen ("/") +
+ grub_strlen (args[0]) + 1);
+ grub_sprintf (filename, "%s/%s", prefix, args[0]);
+
+ grub_file_t keyboard_file;
+ keyboard_file = grub_file_open (filename);
+
+ if (!keyboard_file)
+ {
+ return grub_error (GRUB_ERR_READ_ERROR, "cannot open file `%s'",
+ filename);
+ return 0;
+ }
+
+ check = grub_file_read (keyboard_file, magic, 7);
+
+ if (check != 7)
+ {
+ return grub_error (GRUB_ERR_READ_ERROR,
+ "cannot read the file header from `%s'", filename);
+ }
+
+ if (grub_memcmp (magic, file_magic, 7) != 0)
+ {
+ grub_file_close (keyboard_file);
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "file not recognised (`%s')",
+ filename);
+ }
+ grub_uint32_t version;
+ check = grub_file_read (keyboard_file, &version, 4);
+
+ if (check != 4)
+ {
+ grub_file_close (keyboard_file);
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+ "cannot check file version (`%s')", filename);
+ }
+
+ version = grub_be_to_cpu32 (version);
+ if (version != 1)
+ {
+ grub_file_close (keyboard_file);
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+ "invalid file version: %d (`%s')", version,
+ filename);
+ }
+
+
+
+ check = grub_file_read (keyboard_file, grub_keyboard_map->normal, 128);
+ if (check != 128)
+ {
+ grub_file_close (keyboard_file);
+ return grub_error (GRUB_ERR_READ_ERROR,
+ "problem reading normal keyboard from `%s'",
+ filename);
+ }
+
+ check = grub_file_read (keyboard_file, grub_keyboard_map->shift, 128);
+ if (check != 128)
+ {
+ grub_file_close (keyboard_file);
+ return grub_error (GRUB_ERR_READ_ERROR,
+ "problem reading shift keyboard from `%s'",
+ filename);
+ }
+
+ grub_free (active_layout);
+ active_layout = grub_strdup (args[0]);
+
+ grub_file_close (keyboard_file);
+ return 0;
+}
+
+static grub_err_t
+grub_cmd_show_active_keyboardlayout (grub_command_t cmd __attribute__ ((unused)),
+ int argc __attribute__ ((unused)),
+ char **args __attribute__ ((unused)))
+{
+ grub_printf ("Active layout: `%s'.\n", active_layout);
+ return 0;
+}
+
+GRUB_MOD_INIT (keyboard_layouts)
+{
+ grub_memcpy (original_keyboard_layout_normal, grub_keyboard_map->normal, 128);
+ grub_memcpy (original_keyboard_layout_shift, grub_keyboard_map->shift, 128);
+
+ active_layout = grub_strdup ("default");
+
+ grub_register_command_p1 ("load_keyboard", grub_cmd_load_keyboardlayout,
+ N_("LAYOUT"), N_("Set up the new layout."));
+
+ grub_register_command_p1 ("show_layout", grub_cmd_show_active_keyboardlayout,
+ 0, N_("Show the active layout."));
+
+}
+
+GRUB_MOD_FINI (keyboard_layouts)
+{
+ grub_memcpy (grub_keyboard_map->normal, original_keyboard_layout_normal, 128);
+ grub_memcpy (grub_keyboard_map->shift, original_keyboard_layout_shift, 128);
+}
=== modified file 'term/i386/pc/at_keyboard.c'
--- term/i386/pc/at_keyboard.c 2010-01-09 22:42:17 +0000
+++ term/i386/pc/at_keyboard.c 2010-01-17 21:56:50 +0000
@@ -22,6 +22,7 @@
#include <grub/i386/io.h>
#include <grub/misc.h>
#include <grub/term.h>
+#include <grub/mm.h>
static short at_keyboard_status = 0;
@@ -40,7 +41,7 @@ static grub_uint8_t led_status;
#define KEYBOARD_LED_NUM (1 << 1)
#define KEYBOARD_LED_CAPS (1 << 2)
-static char keyboard_map[128] =
+static char keyboard_map_normal[128] =
{
'\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6',
'7', '8', '9', '0', '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB,
@@ -213,12 +214,12 @@ grub_at_keyboard_getkey_noblock (void)
break;
default:
if (at_keyboard_status & (KEYBOARD_STATUS_CTRL_L | KEYBOARD_STATUS_CTRL_R))
- key = keyboard_map[code] - 'a' + 1;
+ key = grub_keyboard_map->normal[code] - 'a' + 1;
else if ((at_keyboard_status & (KEYBOARD_STATUS_SHIFT_L | KEYBOARD_STATUS_SHIFT_R))
&& keyboard_map_shift[code])
key = keyboard_map_shift[code];
else
- key = keyboard_map[code];
+ key = grub_keyboard_map->normal[code];
if (key == 0)
grub_dprintf ("atkeyb", "Unknown key 0x%x detected\n", code);
@@ -279,6 +280,9 @@ static struct grub_term_input grub_at_ke
GRUB_MOD_INIT(at_keyboard)
{
grub_term_register_input ("at_keyboard", &grub_at_keyboard_term);
+
+ grub_keyboard_map->normal = keyboard_map_normal;
+ grub_keyboard_map->shift = keyboard_map_shift;
}
GRUB_MOD_FINI(at_keyboard)
=== added file 'util/grub-mklayouts.c'
--- util/grub-mklayouts.c 1970-01-01 00:00:00 +0000
+++ util/grub-mklayouts.c 2010-01-17 23:17:07 +0000
@@ -0,0 +1,287 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2010 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/util/misc.h>
+#include <grub/keys.h>
+#include <grub/i18n.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+
+#include "progname.h"
+
+#define CKBCOMP "ckbcomp"
+
+static struct option options[] = {
+ {"output", required_argument, 0, 'o'},
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'V'},
+ {"verbose", no_argument, 0, 'v'},
+ {0, 0, 0, 0}
+};
+
+struct console_grub_equivalence
+{
+ char *layout;
+ char grub;
+};
+
+static struct console_grub_equivalence console_grub_equivalences[] = {
+ {"Escape", GRUB_TERM_ESC},
+ {"Tab", GRUB_TERM_TAB},
+ {"Delete", GRUB_TERM_BACKSPACE},
+
+ {"KP_Enter", '\n'},
+ {"Return", '\n'},
+ {"", '\0'}
+};
+
+static void
+usage (int status)
+{
+ if (status)
+ fprintf (stderr, "Try `%s --help' for more information.\n", program_name);
+ else
+ printf ("\
+Usage: %s [OPTIONS] LAYOUT\n\
+ -o, --output set output file name. Default is LAYOUT.\n\
+ -h, --help display this message and exit.\n\
+ -V, --version print version information and exit.\n\
+ -v, --verbose print verbose messages.\n\
+\n\
+Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT);
+
+ exit (status);
+}
+
+void
+add_special_keys (char keyboard_map[128])
+{
+ keyboard_map[71] = GRUB_TERM_HOME;
+ keyboard_map[72] = GRUB_TERM_UP;
+ keyboard_map[73] = GRUB_TERM_NPAGE;
+ keyboard_map[75] = GRUB_TERM_LEFT;
+ keyboard_map[77] = GRUB_TERM_RIGHT;
+ keyboard_map[79] = GRUB_TERM_END;
+ keyboard_map[80] = GRUB_TERM_DOWN;
+ keyboard_map[81] = GRUB_TERM_PPAGE;
+ keyboard_map[83] = GRUB_TERM_DC;
+
+/*
+ * TODO: defined in include/grub/i386/at_keyboard.h
+ keyboard_map[101] = OLPC_UP;
+ keyboard_map[102] = OLPC_DOWN;
+ keyboard_map[103] = OLPC_LEFT;
+ keyboard_map[104] = OLPC_RIGHT;
+*/
+
+}
+
+char
+lookup (char *code)
+{
+ int i;
+
+ for (i = 0; console_grub_equivalences[i].grub != '\0'; i++)
+ {
+ if (strcmp (code, console_grub_equivalences[i].layout) == 0)
+ {
+ return console_grub_equivalences[i].grub;
+ }
+ }
+
+ return '\0';
+}
+
+unsigned int
+get_grub_code (char *layout_code)
+{
+ unsigned int code;
+
+ if (strncmp (layout_code, "U+", sizeof ("U+") - 1) == 0)
+ {
+ sscanf (layout_code, "U+%x", &code);
+ }
+ else if (strncmp (layout_code, "+U+", sizeof ("+U+") - 1) == 0)
+ {
+ sscanf (layout_code, "+U+%x", &code);
+ }
+ else
+ {
+ code = lookup (layout_code);
+ }
+ return code;
+}
+
+void
+write_keymap (char *keymap, char *output_file)
+{
+ char keyboard_map_normal[128];
+ char keyboard_map_shift[128];
+
+ char line[2048];
+ char normal[64];
+ char shift[64];
+ int key_code;
+ int i;
+ int exit_status;
+
+ FILE *fp;
+ char *command;
+
+ command =
+ (char *) malloc (strlen (CKBCOMP) + strlen (keymap) + strlen (" ") + 1);
+
+ if (!command)
+ {
+ grub_util_error ("cannot prepare command");
+ exit (2);
+ }
+
+ sprintf (command, CKBCOMP " %s", keymap);
+
+ fp = popen (command, "r");
+
+ if (fp == NULL)
+ {
+ grub_util_error ("cannot execute `ckbcomp'");
+ exit (1);
+ }
+
+ for (i= 0; i < 128; i++)
+ {
+ keyboard_map_normal[i] = '\0';
+ keyboard_map_shift[i] = '\0';
+ }
+
+ /* Process the ckbcomp output and prepare the layouts. */
+ while (fgets (line, sizeof (line), fp))
+ {
+ if (strncmp (line, "keycode", sizeof ("keycode") - 1) == 0)
+ {
+ sscanf (line, "keycode %d = %s %s", &key_code, normal, shift);
+ if (key_code < 128)
+ {
+ keyboard_map_normal[key_code] = (char) get_grub_code (normal);
+ keyboard_map_shift[key_code] = (char) get_grub_code (shift);
+ }
+ }
+ }
+
+ add_special_keys (keyboard_map_normal);
+
+ exit_status = pclose (fp);
+
+ if (exit_status != 0)
+ {
+ fprintf (stderr, "ERROR: `%s' returned exit status %d.\n", command,
+ exit_status);
+ exit (1);
+ }
+
+ /* Save the layouts to the file. */
+ fp = fopen (output_file, "w");
+
+ if (!fp)
+ {
+ grub_util_error ("cannot open `%s'", output_file);
+ exit (1);
+ }
+
+ int version;
+ version = 1;
+ version = grub_cpu_to_be32 (version);
+
+ grub_util_write_image ("GRUBLAY", 7, fp);
+ grub_util_write_image ((char *) &version, 4, fp);
+
+ for (i= 0; i < 128; i++)
+ {
+ fprintf (fp, "%c", keyboard_map_normal[i]);
+ }
+
+ for (i = 0; i < 128; i++)
+ {
+ fprintf (fp, "%c", keyboard_map_shift[i]);
+ }
+ fclose (fp);
+
+ free (command);
+}
+
+int
+main (int argc, char *argv[])
+{
+ int verbosity;
+ char *output_file = NULL;
+
+ set_program_name (argv[0]);
+
+ verbosity = 0;
+
+ /* Check for options. */
+ while (1)
+ {
+ int c = getopt_long (argc, argv, "o:hVv", options, 0);
+
+ if (c == -1)
+ break;
+ else
+ switch (c)
+ {
+ case 'h':
+ usage (0);
+ break;
+
+ case 'o':
+ output_file = optarg;
+ break;
+
+ case 'V':
+ printf ("%s (%s) %s\n", program_name, PACKAGE_NAME,
+ PACKAGE_VERSION);
+ return 0;
+
+ case 'v':
+ verbosity++;
+ break;
+
+ default:
+ usage (1);
+ break;
+ }
+ }
+
+ /* Obtain LAYOUT. */
+ if (optind >= argc)
+ {
+ fprintf (stderr, "No layout is specified.\n");
+ usage (1);
+ }
+
+ if (output_file == NULL)
+ {
+ output_file = argv[optind];
+ }
+
+ write_keymap (argv[optind], output_file);
+
+ return 0;
+}
next reply other threads:[~2010-01-18 0:10 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-01-18 0:10 Carles Pina i Estany [this message]
2010-01-18 8:15 ` keyboard layout patches Felix Zielcke
2010-01-18 13:20 ` Vladimir 'φ-coder/phcoder' Serbinenko
2010-01-18 13:53 ` Carles Pina i Estany
2010-01-18 15:00 ` Vladimir 'φ-coder/phcoder' Serbinenko
2010-01-18 19:25 ` Carles Pina i Estany
2010-01-18 19:31 ` Colin Watson
2010-01-18 22:17 ` Carles Pina i Estany
2010-01-19 23:21 ` Robert Millan
2010-01-20 0:03 ` Carles Pina i Estany
2010-01-19 23:19 ` Robert Millan
2010-01-18 20:04 ` Carles Pina i Estany
2010-01-19 23:22 ` Robert Millan
2010-01-18 23:27 ` Carles Pina i Estany
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20100118001016.GA12122@pina.cat \
--to=carles@pina.cat \
--cc=grub-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.