summaryrefslogtreecommitdiffstats
path: root/src/util
diff options
context:
space:
mode:
authorMichael Brown2022-02-09 16:43:42 +0100
committerMichael Brown2022-02-10 14:59:32 +0100
commit0bbd8967830097b9141945ba960e90339c230ccb (patch)
treeeca6637c24625b3ca50663d8f5e833f6e4f009b5 /src/util
parent[console] Update genkeymap to work with current databases (diff)
downloadipxe-0bbd8967830097b9141945ba960e90339c230ccb.tar.gz
ipxe-0bbd8967830097b9141945ba960e90339c230ccb.tar.xz
ipxe-0bbd8967830097b9141945ba960e90339c230ccb.zip
[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>
Diffstat (limited to 'src/util')
-rwxr-xr-xsrc/util/genkeymap.py31
1 files changed, 26 insertions, 5 deletions
diff --git a/src/util/genkeymap.py b/src/util/genkeymap.py
index 1bb494f8..081e314c 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: