summaryrefslogtreecommitdiffstats
path: root/src/core/keymap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/keymap.c')
-rw-r--r--src/core/keymap.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/src/core/keymap.c b/src/core/keymap.c
new file mode 100644
index 000000000..36db7bd4c
--- /dev/null
+++ b/src/core/keymap.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 );
+
+#include <string.h>
+#include <ctype.h>
+#include <ipxe/keys.h>
+#include <ipxe/keymap.h>
+
+/** @file
+ *
+ * Keyboard mappings
+ *
+ */
+
+/** ASCII character mask */
+#define ASCII_MASK 0x7f
+
+/** Control character mask */
+#define CTRL_MASK 0x1f
+
+/** Upper case character mask */
+#define UPPER_MASK 0x5f
+
+/** Case toggle bit */
+#define CASE_TOGGLE ( ASCII_MASK & ~UPPER_MASK )
+
+/** Default keyboard mapping */
+static TABLE_START ( keymap_start, KEYMAP );
+
+/** Current keyboard mapping */
+static struct keymap *keymap_current = keymap_start;
+
+/**
+ * Remap a key
+ *
+ * @v character Character read from console
+ * @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;
+
+ /* Invert case before remapping if applicable */
+ if ( ( character & KEYMAP_CAPSLOCK_UNDO ) && isalpha ( mapped ) )
+ mapped ^= CASE_TOGGLE;
+
+ /* Select remapping table */
+ key = ( ( character & KEYMAP_ALTGR ) ? keymap->altgr : keymap->basic );
+
+ /* Remap via table */
+ for ( ; key->from ; key++ ) {
+ if ( mapped == key->from ) {
+ mapped = key->to;
+ break;
+ }
+ }
+
+ /* Handle Ctrl-<key> and CapsLock */
+ if ( isalpha ( mapped ) ) {
+ if ( character & KEYMAP_CTRL ) {
+ mapped &= CTRL_MASK;
+ } else if ( character & KEYMAP_CAPSLOCK ) {
+ mapped ^= CASE_TOGGLE;
+ }
+ }
+
+ /* Clear flags */
+ mapped &= ASCII_MASK;
+
+ 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;
+}