diff options
author | Michael Brown <mcb30@ipxe.org> | 2022-02-16 00:14:38 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2022-02-16 14:06:33 +0000 |
commit | 304333dace992ea4b876a074c42bb7fd752137ca (patch) | |
tree | 021f862d948ef4a6d567fafcd9c841795bf6a5b1 /src/core | |
parent | 674963e2a63c2b16b60db815b6017b1c3f3e86c2 (diff) | |
download | ipxe-304333dace992ea4b876a074c42bb7fd752137ca.tar.gz |
[console] Support changing keyboard map at runtime
Provide the special keyboard map named "dynamic" which allows the
active keyboard map to be selected at runtime via the ${keymap}
setting, e.g.:
#define KEYBOARD_MAP dynamic
iPXE> set keymap uk
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/dynkeymap.c | 131 | ||||
-rw-r--r-- | src/core/keymap.c | 42 |
2 files changed, 171 insertions, 2 deletions
diff --git a/src/core/dynkeymap.c b/src/core/dynkeymap.c new file mode 100644 index 000000000..2f7c49937 --- /dev/null +++ b/src/core/dynkeymap.c @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2022 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program 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 any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * You can also choose to distribute this program under the terms of + * the Unmodified Binary Distribution Licence (as given in the file + * COPYING.UBDL), provided that you have satisfied its requirements. + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +/** @file + * + * Dynamic keyboard mappings + * + */ + +#include <stdlib.h> +#include <errno.h> +#include <ipxe/settings.h> +#include <ipxe/keymap.h> + +/** + * Require a keyboard map + * + * @v name Keyboard map name + */ +#define REQUIRE_KEYMAP( name ) REQUIRE_OBJECT ( keymap_ ## name ) + +/** Keyboard map setting */ +const struct setting keymap_setting __setting ( SETTING_MISC, keymap ) = { + .name = "keymap", + .description = "Keyboard map", + .type = &setting_type_string, +}; + +/** + * Apply keyboard map settings + * + * @ret rc Return status code + */ +static int keymap_apply ( void ) { + struct keymap *keymap; + char *name; + int rc; + + /* Fetch keyboard map name */ + fetch_string_setting_copy ( NULL, &keymap_setting, &name ); + + /* Identify keyboard map */ + if ( name ) { + /* Identify named keyboard map */ + keymap = keymap_find ( name ); + if ( ! keymap ) { + DBGC ( &keymap_setting, "KEYMAP could not identify " + "\"%s\"\n", name ); + rc = -ENOENT; + goto err_unknown; + } + } else { + /* Use default keyboard map */ + keymap = NULL; + } + + /* Set keyboard map */ + keymap_set ( keymap ); + + /* Success */ + rc = 0; + + err_unknown: + free ( name ); + return rc; +} + +/** Keyboard map setting applicator */ +struct settings_applicator keymap_applicator __settings_applicator = { + .apply = keymap_apply, +}; + +/* Provide virtual "dynamic" keyboard map for linker */ +PROVIDE_SYMBOL ( obj_keymap_dynamic ); + +/* Drag in keyboard maps via keymap_setting */ +REQUIRING_SYMBOL ( keymap_setting ); + +/* Require all known keyboard maps */ +REQUIRE_KEYMAP ( al ); +REQUIRE_KEYMAP ( by ); +REQUIRE_KEYMAP ( cf ); +REQUIRE_KEYMAP ( cz ); +REQUIRE_KEYMAP ( de ); +REQUIRE_KEYMAP ( dk ); +REQUIRE_KEYMAP ( es ); +REQUIRE_KEYMAP ( et ); +REQUIRE_KEYMAP ( fi ); +REQUIRE_KEYMAP ( fr ); +REQUIRE_KEYMAP ( gr ); +REQUIRE_KEYMAP ( hu ); +REQUIRE_KEYMAP ( il ); +REQUIRE_KEYMAP ( it ); +REQUIRE_KEYMAP ( lt ); +REQUIRE_KEYMAP ( mk ); +REQUIRE_KEYMAP ( mt ); +REQUIRE_KEYMAP ( nl ); +REQUIRE_KEYMAP ( no ); +REQUIRE_KEYMAP ( no_latin1 ); +REQUIRE_KEYMAP ( pl ); +REQUIRE_KEYMAP ( pt ); +REQUIRE_KEYMAP ( ro ); +REQUIRE_KEYMAP ( ru ); +REQUIRE_KEYMAP ( se ); +REQUIRE_KEYMAP ( sg ); +REQUIRE_KEYMAP ( sr_latin ); +REQUIRE_KEYMAP ( ua ); +REQUIRE_KEYMAP ( uk ); +REQUIRE_KEYMAP ( us ); diff --git a/src/core/keymap.c b/src/core/keymap.c index 3fa85f74e..36db7bd4c 100644 --- a/src/core/keymap.c +++ b/src/core/keymap.c @@ -23,6 +23,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); +#include <string.h> #include <ctype.h> #include <ipxe/keys.h> #include <ipxe/keymap.h> @@ -49,7 +50,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); static TABLE_START ( keymap_start, KEYMAP ); /** Current keyboard mapping */ -static struct keymap *keymap = keymap_start; +static struct keymap *keymap_current = keymap_start; /** * Remap a key @@ -58,6 +59,7 @@ static struct keymap *keymap = keymap_start; * @ret mapped Mapped character */ unsigned int key_remap ( unsigned int character ) { + struct keymap *keymap = keymap_current; unsigned int mapped = ( character & KEYMAP_MASK ); struct keymap_key *key; @@ -88,6 +90,42 @@ unsigned int key_remap ( unsigned int character ) { /* Clear flags */ mapped &= ASCII_MASK; - DBGC2 ( &keymap, "KEYMAP mapped %04x => %02x\n", character, mapped ); + DBGC2 ( &keymap_current, "KEYMAP mapped %04x => %02x\n", + character, mapped ); return mapped; } + +/** + * Find keyboard map by name + * + * @v name Keyboard map name + * @ret keymap Keyboard map, or NULL if not found + */ +struct keymap * keymap_find ( const char *name ) { + struct keymap *keymap; + + /* Find matching keyboard map */ + for_each_table_entry ( keymap, KEYMAP ) { + if ( strcmp ( keymap->name, name ) == 0 ) + return keymap; + } + + return NULL; +} + +/** + * Set keyboard map + * + * @v keymap Keyboard map, or NULL to use default + */ +void keymap_set ( struct keymap *keymap ) { + + /* Use default keymap if none specified */ + if ( ! keymap ) + keymap = keymap_start; + + /* Set new keyboard map */ + if ( keymap != keymap_current ) + DBGC ( &keymap_current, "KEYMAP using \"%s\"\n", keymap->name ); + keymap_current = keymap; +} |