mirror of https://github.com/ipxe/ipxe.git
[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>pull/594/head
parent
674963e2a6
commit
304333dace
|
@ -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 );
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 )
|
||||
|
||||
/** @} */
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue