diff options
-rw-r--r-- | src/core/dynkeymap.c | 131 | ||||
-rw-r--r-- | src/core/keymap.c | 42 | ||||
-rw-r--r-- | src/include/ipxe/errfile.h | 1 | ||||
-rw-r--r-- | src/include/ipxe/keymap.h | 2 |
4 files changed, 174 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; +} diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h index 23e406b62..81f555725 100644 --- a/src/include/ipxe/errfile.h +++ b/src/include/ipxe/errfile.h @@ -395,6 +395,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #define ERRFILE_efi_cachedhcp ( ERRFILE_OTHER | 0x00550000 ) #define ERRFILE_linux_sysfs ( ERRFILE_OTHER | 0x00560000 ) #define ERRFILE_linux_acpi ( ERRFILE_OTHER | 0x00570000 ) +#define ERRFILE_dynkeymap ( ERRFILE_OTHER | 0x00580000 ) /** @} */ diff --git a/src/include/ipxe/keymap.h b/src/include/ipxe/keymap.h index 392d3ab8f..8bfbe07a5 100644 --- a/src/include/ipxe/keymap.h +++ b/src/include/ipxe/keymap.h @@ -73,5 +73,7 @@ struct keymap { #define KEYMAP_ALTGR 0x0800 extern unsigned int key_remap ( unsigned int character ); +extern struct keymap * keymap_find ( const char *name ); +extern void keymap_set ( struct keymap *keymap ); #endif /* _IPXE_KEYMAP_H */ |