aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2022-02-09 15:43:42 +0000
committerMichael Brown <mcb30@ipxe.org>2022-02-10 13:59:32 +0000
commit0bbd8967830097b9141945ba960e90339c230ccb (patch)
treeeca6637c24625b3ca50663d8f5e833f6e4f009b5
parent3f05a82fec6223a49df300a9cbf80c6245c3f99e (diff)
downloadipxe-0bbd8967830097b9141945ba960e90339c230ccb.zip
ipxe-0bbd8967830097b9141945ba960e90339c230ccb.tar.gz
ipxe-0bbd8967830097b9141945ba960e90339c230ccb.tar.bz2
[console] Handle remapping of scancode 86
The key with scancode 86 appears in the position between left shift and Z on a US keyboard, where it typically fails to exist entirely. Most US keyboard maps define this nonexistent key as generating "\|", with the notable exception of "loadkeys" which instead reports it as generating "<>". Both of these mapping choices duplicate keys that exist elsewhere in the map, which causes problems for our ASCII-based remapping mechanism. Work around these quirks by treating the key as generating "\|" with the high bit set, and making it subject to remapping. Where the BIOS generates "\|" as expected, this allows us to remap to the correct ASCII value. Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/arch/x86/interface/pcbios/bios_console.c9
-rw-r--r--src/core/keymap.c3
-rw-r--r--src/drivers/usb/usbkbd.c8
-rw-r--r--src/drivers/usb/usbkbd.h1
-rw-r--r--src/hci/keymap/keymap_al.c2
-rw-r--r--src/hci/keymap/keymap_az.c2
-rw-r--r--src/hci/keymap/keymap_by.c2
-rw-r--r--src/hci/keymap/keymap_de.c2
-rw-r--r--src/hci/keymap/keymap_dk.c2
-rw-r--r--src/hci/keymap/keymap_es.c2
-rw-r--r--src/hci/keymap/keymap_et.c2
-rw-r--r--src/hci/keymap/keymap_fi.c2
-rw-r--r--src/hci/keymap/keymap_fr.c2
-rw-r--r--src/hci/keymap/keymap_gr.c2
-rw-r--r--src/hci/keymap/keymap_il.c2
-rw-r--r--src/hci/keymap/keymap_it.c2
-rw-r--r--src/hci/keymap/keymap_mk.c2
-rw-r--r--src/hci/keymap/keymap_nl.c2
-rw-r--r--src/hci/keymap/keymap_no-latin1.c2
-rw-r--r--src/hci/keymap/keymap_no.c2
-rw-r--r--src/hci/keymap/keymap_pl.c2
-rw-r--r--src/hci/keymap/keymap_pt.c2
-rw-r--r--src/hci/keymap/keymap_ru.c2
-rw-r--r--src/hci/keymap/keymap_sg.c2
-rw-r--r--src/hci/keymap/keymap_sr-latin.c2
-rw-r--r--src/hci/keymap/keymap_ua.c2
-rw-r--r--src/include/ipxe/keymap.h3
-rwxr-xr-xsrc/util/genkeymap.py31
28 files changed, 93 insertions, 6 deletions
diff --git a/src/arch/x86/interface/pcbios/bios_console.c b/src/arch/x86/interface/pcbios/bios_console.c
index 443513e..438a01d 100644
--- a/src/arch/x86/interface/pcbios/bios_console.c
+++ b/src/arch/x86/interface/pcbios/bios_console.c
@@ -68,6 +68,13 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*/
#define SCANCODE_RSHIFT 0x36
+/** Scancode for the "non-US \ and |" key
+ *
+ * This is the key that appears between Left Shift and Z on non-US
+ * keyboards.
+ */
+#define SCANCODE_NON_US 0x56
+
/* Set default console usage if applicable */
#if ! ( defined ( CONSOLE_PCBIOS ) && CONSOLE_EXPLICIT ( CONSOLE_PCBIOS ) )
#undef CONSOLE_PCBIOS
@@ -383,6 +390,8 @@ static int bios_getchar ( void ) {
if ( character && ( character < 0x80 ) ) {
if ( scancode < SCANCODE_RSHIFT ) {
return key_remap ( character );
+ } else if ( scancode == SCANCODE_NON_US ) {
+ return key_remap ( character | KEYMAP_PSEUDO );
} else {
return character;
}
diff --git a/src/core/keymap.c b/src/core/keymap.c
index a6707a2..5054e47 100644
--- a/src/core/keymap.c
+++ b/src/core/keymap.c
@@ -48,5 +48,8 @@ unsigned int key_remap ( unsigned int character ) {
}
}
+ /* Clear pseudo key flag */
+ character &= ~KEYMAP_PSEUDO;
+
return character;
}
diff --git a/src/drivers/usb/usbkbd.c b/src/drivers/usb/usbkbd.c
index ba4b2d4..6954cd6 100644
--- a/src/drivers/usb/usbkbd.c
+++ b/src/drivers/usb/usbkbd.c
@@ -114,13 +114,19 @@ static unsigned int usbkbd_map ( unsigned int keycode, unsigned int modifiers,
};
key = keypad[ keycode - USBKBD_KEY_PAD_1 ];
};
+ } else if ( keycode == USBKBD_KEY_NON_US ) {
+ /* Non-US \ and | */
+ key = ( ( modifiers & USBKBD_SHIFT ) ?
+ ( KEYMAP_PSEUDO | '|' ) : ( KEYMAP_PSEUDO | '\\' ) );
} else {
key = 0;
}
/* Remap key if applicable */
- if ( keycode < USBKBD_KEY_CAPS_LOCK )
+ if ( ( keycode < USBKBD_KEY_CAPS_LOCK ) ||
+ ( keycode == USBKBD_KEY_NON_US ) ) {
key = key_remap ( key );
+ }
/* Handle upper/lower case and Ctrl-<key> */
if ( islower ( key ) ) {
diff --git a/src/drivers/usb/usbkbd.h b/src/drivers/usb/usbkbd.h
index cedebfe..1a3fea1 100644
--- a/src/drivers/usb/usbkbd.h
+++ b/src/drivers/usb/usbkbd.h
@@ -75,6 +75,7 @@ enum usb_keycode {
USBKBD_KEY_PAD_ENTER = 0x58,
USBKBD_KEY_PAD_1 = 0x59,
USBKBD_KEY_PAD_DOT = 0x63,
+ USBKBD_KEY_NON_US = 0x64,
};
/** USB keyboard LEDs */
diff --git a/src/hci/keymap/keymap_al.c b/src/hci/keymap/keymap_al.c
index e441836..6b46634 100644
--- a/src/hci/keymap/keymap_al.c
+++ b/src/hci/keymap/keymap_al.c
@@ -30,4 +30,6 @@ struct key_mapping al_mapping[] __keymap = {
{ 0x7c, 0x7d }, /* '|' => '}' */
{ 0x7d, 0x27 }, /* '}' => '\'' */
{ 0x7e, 0x7c }, /* '~' => '|' */
+ { 0xdc, 0x3c }, /* Pseudo-'\\' => '<' */
+ { 0xfc, 0x3e }, /* Pseudo-'|' => '>' */
};
diff --git a/src/hci/keymap/keymap_az.c b/src/hci/keymap/keymap_az.c
index 525ab23..91a2434 100644
--- a/src/hci/keymap/keymap_az.c
+++ b/src/hci/keymap/keymap_az.c
@@ -21,4 +21,6 @@ struct key_mapping az_mapping[] __keymap = {
{ 0x40, 0x22 }, /* '@' => '"' */
{ 0x5e, 0x3a }, /* '^' => ':' */
{ 0x7c, 0x2f }, /* '|' => '/' */
+ { 0xdc, 0x3c }, /* Pseudo-'\\' => '<' */
+ { 0xfc, 0x3e }, /* Pseudo-'|' => '>' */
};
diff --git a/src/hci/keymap/keymap_by.c b/src/hci/keymap/keymap_by.c
index 514d0b5..43fb746 100644
--- a/src/hci/keymap/keymap_by.c
+++ b/src/hci/keymap/keymap_by.c
@@ -12,4 +12,6 @@ FILE_LICENCE ( PUBLIC_DOMAIN );
/** "by" keyboard mapping */
struct key_mapping by_mapping[] __keymap = {
+ { 0xdc, 0x3c }, /* Pseudo-'\\' => '<' */
+ { 0xfc, 0x3e }, /* Pseudo-'|' => '>' */
};
diff --git a/src/hci/keymap/keymap_de.c b/src/hci/keymap/keymap_de.c
index 2559e15..85574d4 100644
--- a/src/hci/keymap/keymap_de.c
+++ b/src/hci/keymap/keymap_de.c
@@ -36,4 +36,6 @@ struct key_mapping de_mapping[] __keymap = {
{ 0x7a, 0x79 }, /* 'z' => 'y' */
{ 0x7c, 0x27 }, /* '|' => '\'' */
{ 0x7d, 0x2a }, /* '}' => '*' */
+ { 0xdc, 0x3c }, /* Pseudo-'\\' => '<' */
+ { 0xfc, 0x3e }, /* Pseudo-'|' => '>' */
};
diff --git a/src/hci/keymap/keymap_dk.c b/src/hci/keymap/keymap_dk.c
index 05110dc..4e1d5a7 100644
--- a/src/hci/keymap/keymap_dk.c
+++ b/src/hci/keymap/keymap_dk.c
@@ -28,4 +28,6 @@ struct key_mapping dk_mapping[] __keymap = {
{ 0x5e, 0x26 }, /* '^' => '&' */
{ 0x5f, 0x3f }, /* '_' => '?' */
{ 0x7c, 0x2a }, /* '|' => '*' */
+ { 0xdc, 0x3c }, /* Pseudo-'\\' => '<' */
+ { 0xfc, 0x3e }, /* Pseudo-'|' => '>' */
};
diff --git a/src/hci/keymap/keymap_es.c b/src/hci/keymap/keymap_es.c
index 51dedff..91327ea 100644
--- a/src/hci/keymap/keymap_es.c
+++ b/src/hci/keymap/keymap_es.c
@@ -28,4 +28,6 @@ struct key_mapping es_mapping[] __keymap = {
{ 0x5e, 0x26 }, /* '^' => '&' */
{ 0x5f, 0x3f }, /* '_' => '?' */
{ 0x7d, 0x2a }, /* '}' => '*' */
+ { 0xdc, 0x3c }, /* Pseudo-'\\' => '<' */
+ { 0xfc, 0x3e }, /* Pseudo-'|' => '>' */
};
diff --git a/src/hci/keymap/keymap_et.c b/src/hci/keymap/keymap_et.c
index dd0f879..493ec93 100644
--- a/src/hci/keymap/keymap_et.c
+++ b/src/hci/keymap/keymap_et.c
@@ -26,4 +26,6 @@ struct key_mapping et_mapping[] __keymap = {
{ 0x5e, 0x26 }, /* '^' => '&' */
{ 0x5f, 0x3f }, /* '_' => '?' */
{ 0x7c, 0x2a }, /* '|' => '*' */
+ { 0xdc, 0x3c }, /* Pseudo-'\\' => '<' */
+ { 0xfc, 0x3e }, /* Pseudo-'|' => '>' */
};
diff --git a/src/hci/keymap/keymap_fi.c b/src/hci/keymap/keymap_fi.c
index c489bf0..18f48d4 100644
--- a/src/hci/keymap/keymap_fi.c
+++ b/src/hci/keymap/keymap_fi.c
@@ -26,4 +26,6 @@ struct key_mapping fi_mapping[] __keymap = {
{ 0x5e, 0x26 }, /* '^' => '&' */
{ 0x5f, 0x3f }, /* '_' => '?' */
{ 0x7c, 0x2a }, /* '|' => '*' */
+ { 0xdc, 0x3c }, /* Pseudo-'\\' => '<' */
+ { 0xfc, 0x3e }, /* Pseudo-'|' => '>' */
};
diff --git a/src/hci/keymap/keymap_fr.c b/src/hci/keymap/keymap_fr.c
index 8f3b499..808cd79 100644
--- a/src/hci/keymap/keymap_fr.c
+++ b/src/hci/keymap/keymap_fr.c
@@ -57,4 +57,6 @@ struct key_mapping fr_mapping[] __keymap = {
{ 0x71, 0x61 }, /* 'q' => 'a' */
{ 0x77, 0x7a }, /* 'w' => 'z' */
{ 0x7a, 0x77 }, /* 'z' => 'w' */
+ { 0xdc, 0x3c }, /* Pseudo-'\\' => '<' */
+ { 0xfc, 0x3e }, /* Pseudo-'|' => '>' */
};
diff --git a/src/hci/keymap/keymap_gr.c b/src/hci/keymap/keymap_gr.c
index 42b6418..b48142e 100644
--- a/src/hci/keymap/keymap_gr.c
+++ b/src/hci/keymap/keymap_gr.c
@@ -12,4 +12,6 @@ FILE_LICENCE ( PUBLIC_DOMAIN );
/** "gr" keyboard mapping */
struct key_mapping gr_mapping[] __keymap = {
+ { 0xdc, 0x3c }, /* Pseudo-'\\' => '<' */
+ { 0xfc, 0x3e }, /* Pseudo-'|' => '>' */
};
diff --git a/src/hci/keymap/keymap_il.c b/src/hci/keymap/keymap_il.c
index f631f7a..78e7fa9 100644
--- a/src/hci/keymap/keymap_il.c
+++ b/src/hci/keymap/keymap_il.c
@@ -24,4 +24,6 @@ struct key_mapping il_mapping[] __keymap = {
{ 0x60, 0x3b }, /* '`' => ';' */
{ 0x7b, 0x7d }, /* '{' => '}' */
{ 0x7d, 0x7b }, /* '}' => '{' */
+ { 0xdc, 0x3c }, /* Pseudo-'\\' => '<' */
+ { 0xfc, 0x3e }, /* Pseudo-'|' => '>' */
};
diff --git a/src/hci/keymap/keymap_it.c b/src/hci/keymap/keymap_it.c
index d96102c..5a8e2b3 100644
--- a/src/hci/keymap/keymap_it.c
+++ b/src/hci/keymap/keymap_it.c
@@ -30,4 +30,6 @@ struct key_mapping it_mapping[] __keymap = {
{ 0x60, 0x5c }, /* '`' => '\\' */
{ 0x7d, 0x2a }, /* '}' => '*' */
{ 0x7e, 0x7c }, /* '~' => '|' */
+ { 0xdc, 0x3c }, /* Pseudo-'\\' => '<' */
+ { 0xfc, 0x3e }, /* Pseudo-'|' => '>' */
};
diff --git a/src/hci/keymap/keymap_mk.c b/src/hci/keymap/keymap_mk.c
index 8f50607..9f2cff7 100644
--- a/src/hci/keymap/keymap_mk.c
+++ b/src/hci/keymap/keymap_mk.c
@@ -12,4 +12,6 @@ FILE_LICENCE ( PUBLIC_DOMAIN );
/** "mk" keyboard mapping */
struct key_mapping mk_mapping[] __keymap = {
+ { 0xdc, 0x3c }, /* Pseudo-'\\' => '<' */
+ { 0xfc, 0x3e }, /* Pseudo-'|' => '>' */
};
diff --git a/src/hci/keymap/keymap_nl.c b/src/hci/keymap/keymap_nl.c
index 2a0fbbc..d248fc8 100644
--- a/src/hci/keymap/keymap_nl.c
+++ b/src/hci/keymap/keymap_nl.c
@@ -33,4 +33,6 @@ struct key_mapping nl_mapping[] __keymap = {
{ 0x60, 0x40 }, /* '`' => '@' */
{ 0x7c, 0x3e }, /* '|' => '>' */
{ 0x7d, 0x7c }, /* '}' => '|' */
+ { 0xdc, 0x5d }, /* Pseudo-'\\' => ']' */
+ { 0xfc, 0x5b }, /* Pseudo-'|' => '[' */
};
diff --git a/src/hci/keymap/keymap_no-latin1.c b/src/hci/keymap/keymap_no-latin1.c
index 655e4ce..d5a721a 100644
--- a/src/hci/keymap/keymap_no-latin1.c
+++ b/src/hci/keymap/keymap_no-latin1.c
@@ -32,4 +32,6 @@ struct key_mapping no_latin1_mapping[] __keymap = {
{ 0x60, 0x7c }, /* '`' => '|' */
{ 0x7c, 0x2a }, /* '|' => '*' */
{ 0x7d, 0x5e }, /* '}' => '^' */
+ { 0xdc, 0x3c }, /* Pseudo-'\\' => '<' */
+ { 0xfc, 0x3e }, /* Pseudo-'|' => '>' */
};
diff --git a/src/hci/keymap/keymap_no.c b/src/hci/keymap/keymap_no.c
index 7a2df7c..b6190da 100644
--- a/src/hci/keymap/keymap_no.c
+++ b/src/hci/keymap/keymap_no.c
@@ -30,4 +30,6 @@ struct key_mapping no_mapping[] __keymap = {
{ 0x5f, 0x3f }, /* '_' => '?' */
{ 0x60, 0x7c }, /* '`' => '|' */
{ 0x7c, 0x2a }, /* '|' => '*' */
+ { 0xdc, 0x3c }, /* Pseudo-'\\' => '<' */
+ { 0xfc, 0x3e }, /* Pseudo-'|' => '>' */
};
diff --git a/src/hci/keymap/keymap_pl.c b/src/hci/keymap/keymap_pl.c
index 51822e0..224fbde 100644
--- a/src/hci/keymap/keymap_pl.c
+++ b/src/hci/keymap/keymap_pl.c
@@ -12,4 +12,6 @@ FILE_LICENCE ( PUBLIC_DOMAIN );
/** "pl" keyboard mapping */
struct key_mapping pl_mapping[] __keymap = {
+ { 0xdc, 0x3c }, /* Pseudo-'\\' => '<' */
+ { 0xfc, 0x3e }, /* Pseudo-'|' => '>' */
};
diff --git a/src/hci/keymap/keymap_pt.c b/src/hci/keymap/keymap_pt.c
index b993902..6d850fe 100644
--- a/src/hci/keymap/keymap_pt.c
+++ b/src/hci/keymap/keymap_pt.c
@@ -29,4 +29,6 @@ struct key_mapping pt_mapping[] __keymap = {
{ 0x60, 0x5c }, /* '`' => '\\' */
{ 0x7b, 0x2a }, /* '{' => '*' */
{ 0x7e, 0x7c }, /* '~' => '|' */
+ { 0xdc, 0x3c }, /* Pseudo-'\\' => '<' */
+ { 0xfc, 0x3e }, /* Pseudo-'|' => '>' */
};
diff --git a/src/hci/keymap/keymap_ru.c b/src/hci/keymap/keymap_ru.c
index c120ffd..f7611c3 100644
--- a/src/hci/keymap/keymap_ru.c
+++ b/src/hci/keymap/keymap_ru.c
@@ -13,4 +13,6 @@ FILE_LICENCE ( PUBLIC_DOMAIN );
/** "ru" keyboard mapping */
struct key_mapping ru_mapping[] __keymap = {
{ 0x0d, 0x0a }, /* Ctrl-M => Ctrl-J */
+ { 0xdc, 0x3c }, /* Pseudo-'\\' => '<' */
+ { 0xfc, 0x3e }, /* Pseudo-'|' => '>' */
};
diff --git a/src/hci/keymap/keymap_sg.c b/src/hci/keymap/keymap_sg.c
index 0b08209..9a515c7 100644
--- a/src/hci/keymap/keymap_sg.c
+++ b/src/hci/keymap/keymap_sg.c
@@ -38,4 +38,6 @@ struct key_mapping sg_mapping[] __keymap = {
{ 0x7a, 0x79 }, /* 'z' => 'y' */
{ 0x7c, 0x24 }, /* '|' => '$' */
{ 0x7d, 0x21 }, /* '}' => '!' */
+ { 0xdc, 0x3c }, /* Pseudo-'\\' => '<' */
+ { 0xfc, 0x3e }, /* Pseudo-'|' => '>' */
};
diff --git a/src/hci/keymap/keymap_sr-latin.c b/src/hci/keymap/keymap_sr-latin.c
index 9d76e8a..1d45887 100644
--- a/src/hci/keymap/keymap_sr-latin.c
+++ b/src/hci/keymap/keymap_sr-latin.c
@@ -12,4 +12,6 @@ FILE_LICENCE ( PUBLIC_DOMAIN );
/** "sr-latin" keyboard mapping */
struct key_mapping sr_latin_mapping[] __keymap = {
+ { 0xdc, 0x3c }, /* Pseudo-'\\' => '<' */
+ { 0xfc, 0x3e }, /* Pseudo-'|' => '>' */
};
diff --git a/src/hci/keymap/keymap_ua.c b/src/hci/keymap/keymap_ua.c
index 1106a8b..50f2e18 100644
--- a/src/hci/keymap/keymap_ua.c
+++ b/src/hci/keymap/keymap_ua.c
@@ -12,4 +12,6 @@ FILE_LICENCE ( PUBLIC_DOMAIN );
/** "ua" keyboard mapping */
struct key_mapping ua_mapping[] __keymap = {
+ { 0xdc, 0x3c }, /* Pseudo-'\\' => '<' */
+ { 0xfc, 0x3e }, /* Pseudo-'|' => '>' */
};
diff --git a/src/include/ipxe/keymap.h b/src/include/ipxe/keymap.h
index 62b3bb1..93c9e73 100644
--- a/src/include/ipxe/keymap.h
+++ b/src/include/ipxe/keymap.h
@@ -27,6 +27,9 @@ struct key_mapping {
/** Define a keyboard mapping */
#define __keymap __table_entry ( KEYMAP, 01 )
+/** Pseudo key flag */
+#define KEYMAP_PSEUDO 0x80
+
extern unsigned int key_remap ( unsigned int character );
#endif /* _IPXE_KEYMAP_H */
diff --git a/src/util/genkeymap.py b/src/util/genkeymap.py
index 1bb494f..081e314 100755
--- a/src/util/genkeymap.py
+++ b/src/util/genkeymap.py
@@ -219,12 +219,28 @@ class KeyMapping(UserDict[KeyModifiers, Sequence[Key]]):
class BiosKeyMapping(KeyMapping):
- """Keyboard mapping as used by the BIOS"""
+ """Keyboard mapping as used by the BIOS
+
+ To allow for remappings of the somewhat interesting key 86, we
+ arrange for our keyboard drivers to generate this key as "\\|"
+ with the high bit set.
+ """
+
+ KEY_PSEUDO: ClassVar[int] = 0x80
+ """Flag used to indicate a fake ASCII value"""
+
+ KEY_NON_US_UNSHIFTED: ClassVar[str] = chr(KEY_PSEUDO | ord('\\'))
+ """Fake ASCII value generated for unshifted key code 86"""
+
+ KEY_NON_US_SHIFTED: ClassVar[str] = chr(KEY_PSEUDO | ord('|'))
+ """Fake ASCII value generated for shifted key code 86"""
@property
def inverse(self) -> MutableMapping[str, Key]:
inverse = super().inverse
assert len(inverse) == 0x7f
+ inverse[self.KEY_NON_US_UNSHIFTED] = self.unshifted[self.KEY_NON_US]
+ inverse[self.KEY_NON_US_SHIFTED] = self.shifted[self.KEY_NON_US]
assert all(x.modifiers in {KeyModifiers.NONE, KeyModifiers.SHIFT,
KeyModifiers.CTRL}
for x in inverse.values())
@@ -251,12 +267,13 @@ class KeyRemapping:
raw = {source: self.target[key.modifiers][key.keycode].ascii
for source, key in self.source.inverse.items()}
# Eliminate any null mappings, mappings that attempt to remap
- # the backspace key, or identity mappings
+ # the backspace key, or mappings that would become identity
+ # mappings after clearing the high bit
table = {source: target for source, target in raw.items()
if target
and ord(source) != 0x7f
and ord(target) != 0x7f
- and ord(source) != ord(target)}
+ and ord(source) & ~BiosKeyMapping.KEY_PSEUDO != ord(target)}
# Recursively delete any mappings that would produce
# unreachable alphanumerics (e.g. the "il" keymap, which maps
# away the whole lower-case alphabet)
@@ -281,13 +298,17 @@ class KeyRemapping:
"""C variable name"""
return re.sub(r'\W', '_', self.name) + "_mapping"
- @staticmethod
- def ascii_name(char: str) -> str:
+ @classmethod
+ def ascii_name(cls, char: str) -> str:
"""ASCII character name"""
if char == '\\':
name = "'\\\\'"
elif char == '\'':
name = "'\\\''"
+ elif ord(char) & BiosKeyMapping.KEY_PSEUDO:
+ name = "Pseudo-%s" % cls.ascii_name(
+ chr(ord(char) & ~BiosKeyMapping.KEY_PSEUDO)
+ )
elif char.isprintable():
name = "'%s'" % char
elif ord(char) <= 0x1a: