diff options
-rw-r--r-- | src/Makefile | 2 | ||||
-rw-r--r-- | src/hci/keymap/keymap_al.c | 1 | ||||
-rw-r--r-- | src/hci/keymap/keymap_az.c | 2 | ||||
-rw-r--r-- | src/hci/keymap/keymap_cz.c | 33 | ||||
-rw-r--r-- | src/hci/keymap/keymap_de.c | 13 | ||||
-rw-r--r-- | src/hci/keymap/keymap_dk.c | 4 | ||||
-rw-r--r-- | src/hci/keymap/keymap_es.c | 2 | ||||
-rw-r--r-- | src/hci/keymap/keymap_et.c | 1 | ||||
-rw-r--r-- | src/hci/keymap/keymap_fi.c | 9 | ||||
-rw-r--r-- | src/hci/keymap/keymap_fr.c | 16 | ||||
-rw-r--r-- | src/hci/keymap/keymap_hu.c | 1 | ||||
-rw-r--r-- | src/hci/keymap/keymap_il.c | 12 | ||||
-rw-r--r-- | src/hci/keymap/keymap_it.c | 1 | ||||
-rw-r--r-- | src/hci/keymap/keymap_mt.c | 2 | ||||
-rw-r--r-- | src/hci/keymap/keymap_nl.c | 4 | ||||
-rw-r--r-- | src/hci/keymap/keymap_no-latin1.c | 1 | ||||
-rw-r--r-- | src/hci/keymap/keymap_no.c | 88 | ||||
-rw-r--r-- | src/hci/keymap/keymap_pt.c | 31 | ||||
-rw-r--r-- | src/hci/keymap/keymap_ru.c | 1 | ||||
-rw-r--r-- | src/hci/keymap/keymap_sr-latin.c (renamed from src/hci/keymap/keymap_bg.c) | 6 | ||||
-rw-r--r-- | src/hci/keymap/keymap_sr.c | 35 | ||||
-rw-r--r-- | src/hci/keymap/keymap_th.c | 15 | ||||
-rw-r--r-- | src/hci/keymap/keymap_wo.c | 55 | ||||
-rwxr-xr-x | src/util/genkeymap.pl | 238 | ||||
-rwxr-xr-x | src/util/genkeymap.py | 346 |
25 files changed, 434 insertions, 485 deletions
diff --git a/src/Makefile b/src/Makefile index 4c4abf1aa..83642e789 100644 --- a/src/Makefile +++ b/src/Makefile @@ -50,7 +50,7 @@ ELF2EFI64 := ./util/elf2efi64 EFIROM := ./util/efirom EFIFATBIN := ./util/efifatbin EINFO := ./util/einfo -GENKEYMAP := ./util/genkeymap.pl +GENKEYMAP := ./util/genkeymap.py DOXYGEN := doxygen LCAB := lcab QEMUIMG := qemu-img diff --git a/src/hci/keymap/keymap_al.c b/src/hci/keymap/keymap_al.c index caf295e8e..e4418361b 100644 --- a/src/hci/keymap/keymap_al.c +++ b/src/hci/keymap/keymap_al.c @@ -14,6 +14,7 @@ FILE_LICENCE ( PUBLIC_DOMAIN ); struct key_mapping al_mapping[] __keymap = { { 0x19, 0x1a }, /* Ctrl-Y => Ctrl-Z */ { 0x1a, 0x19 }, /* Ctrl-Z => Ctrl-Y */ + { 0x1c, 0x1d }, /* 0x1c => 0x1d */ { 0x22, 0x7b }, /* '"' => '{' */ { 0x27, 0x5b }, /* '\'' => '[' */ { 0x3c, 0x3b }, /* '<' => ';' */ diff --git a/src/hci/keymap/keymap_az.c b/src/hci/keymap/keymap_az.c index 27ce91e7d..525ab2336 100644 --- a/src/hci/keymap/keymap_az.c +++ b/src/hci/keymap/keymap_az.c @@ -12,7 +12,7 @@ FILE_LICENCE ( PUBLIC_DOMAIN ); /** "az" keyboard mapping */ struct key_mapping az_mapping[] __keymap = { - { 0x23, 0x27 }, /* '#' => '\'' */ + { 0x1e, 0x36 }, /* 0x1e => '6' */ { 0x24, 0x3b }, /* '$' => ';' */ { 0x26, 0x3f }, /* '&' => '?' */ { 0x2f, 0x2e }, /* '/' => '.' */ diff --git a/src/hci/keymap/keymap_cz.c b/src/hci/keymap/keymap_cz.c index 9280f84fd..2b4a21592 100644 --- a/src/hci/keymap/keymap_cz.c +++ b/src/hci/keymap/keymap_cz.c @@ -12,16 +12,35 @@ FILE_LICENCE ( PUBLIC_DOMAIN ); /** "cz" keyboard mapping */ struct key_mapping cz_mapping[] __keymap = { - { 0x21, 0x2b }, /* '!' => '+' */ + { 0x19, 0x1a }, /* Ctrl-Y => Ctrl-Z */ + { 0x1a, 0x19 }, /* Ctrl-Z => Ctrl-Y */ + { 0x1f, 0x1c }, /* 0x1f => 0x1c */ + { 0x21, 0x31 }, /* '!' => '1' */ + { 0x22, 0x21 }, /* '"' => '!' */ + { 0x23, 0x33 }, /* '#' => '3' */ + { 0x24, 0x34 }, /* '$' => '4' */ + { 0x25, 0x35 }, /* '%' => '5' */ + { 0x26, 0x37 }, /* '&' => '7' */ + { 0x28, 0x39 }, /* '(' => '9' */ + { 0x29, 0x30 }, /* ')' => '0' */ + { 0x2a, 0x38 }, /* '*' => '8' */ { 0x2d, 0x3d }, /* '-' => '=' */ { 0x2f, 0x2d }, /* '/' => '-' */ { 0x31, 0x2b }, /* '1' => '+' */ - { 0x3c, 0x2c }, /* '<' => ',' */ - { 0x3e, 0x2e }, /* '>' => '.' */ - { 0x3f, 0x2d }, /* '?' => '-' */ + { 0x3a, 0x22 }, /* ':' => '"' */ + { 0x3c, 0x3f }, /* '<' => '?' */ + { 0x3e, 0x3a }, /* '>' => ':' */ + { 0x3f, 0x5f }, /* '?' => '_' */ + { 0x40, 0x32 }, /* '@' => '2' */ + { 0x59, 0x5a }, /* 'Y' => 'Z' */ + { 0x5a, 0x59 }, /* 'Z' => 'Y' */ { 0x5d, 0x29 }, /* ']' => ')' */ - { 0x5f, 0x3d }, /* '_' => '=' */ + { 0x5e, 0x36 }, /* '^' => '6' */ + { 0x5f, 0x25 }, /* '_' => '%' */ { 0x60, 0x3b }, /* '`' => ';' */ - { 0x7d, 0x29 }, /* '}' => ')' */ - { 0x7e, 0x3b }, /* '~' => ';' */ + { 0x79, 0x7a }, /* 'y' => 'z' */ + { 0x7a, 0x79 }, /* 'z' => 'y' */ + { 0x7b, 0x2f }, /* '{' => '/' */ + { 0x7c, 0x27 }, /* '|' => '\'' */ + { 0x7d, 0x28 }, /* '}' => '(' */ }; diff --git a/src/hci/keymap/keymap_de.c b/src/hci/keymap/keymap_de.c index ffcf912f1..2559e1538 100644 --- a/src/hci/keymap/keymap_de.c +++ b/src/hci/keymap/keymap_de.c @@ -14,33 +14,26 @@ FILE_LICENCE ( PUBLIC_DOMAIN ); struct key_mapping de_mapping[] __keymap = { { 0x19, 0x1a }, /* Ctrl-Y => Ctrl-Z */ { 0x1a, 0x19 }, /* Ctrl-Z => Ctrl-Y */ - { 0x22, 0x7d }, /* '"' => '}' */ + { 0x1c, 0x23 }, /* 0x1c => '#' */ + { 0x1d, 0x1e }, /* 0x1d => 0x1e */ + { 0x1e, 0x36 }, /* 0x1e => '6' */ { 0x26, 0x2f }, /* '&' => '/' */ - { 0x27, 0x5d }, /* '\'' => ']' */ { 0x28, 0x29 }, /* '(' => ')' */ { 0x29, 0x3d }, /* ')' => '=' */ { 0x2a, 0x28 }, /* '*' => '(' */ - { 0x2b, 0x60 }, /* '+' => '`' */ - { 0x2d, 0x5c }, /* '-' => '\\' */ { 0x2f, 0x2d }, /* '/' => '-' */ - { 0x3a, 0x7b }, /* ':' => '{' */ - { 0x3b, 0x5b }, /* ';' => '[' */ { 0x3c, 0x3b }, /* '<' => ';' */ - { 0x3d, 0x27 }, /* '=' => '\'' */ { 0x3e, 0x3a }, /* '>' => ':' */ { 0x3f, 0x5f }, /* '?' => '_' */ { 0x40, 0x22 }, /* '@' => '"' */ { 0x59, 0x5a }, /* 'Y' => 'Z' */ { 0x5a, 0x59 }, /* 'Z' => 'Y' */ - { 0x5b, 0x40 }, /* '[' => '@' */ { 0x5c, 0x23 }, /* '\\' => '#' */ { 0x5d, 0x2b }, /* ']' => '+' */ { 0x5e, 0x26 }, /* '^' => '&' */ { 0x5f, 0x3f }, /* '_' => '?' */ - { 0x60, 0x5e }, /* '`' => '^' */ { 0x79, 0x7a }, /* 'y' => 'z' */ { 0x7a, 0x79 }, /* 'z' => 'y' */ - { 0x7b, 0x5c }, /* '{' => '\\' */ { 0x7c, 0x27 }, /* '|' => '\'' */ { 0x7d, 0x2a }, /* '}' => '*' */ }; diff --git a/src/hci/keymap/keymap_dk.c b/src/hci/keymap/keymap_dk.c index e409018c8..05110dc89 100644 --- a/src/hci/keymap/keymap_dk.c +++ b/src/hci/keymap/keymap_dk.c @@ -12,11 +12,12 @@ FILE_LICENCE ( PUBLIC_DOMAIN ); /** "dk" keyboard mapping */ struct key_mapping dk_mapping[] __keymap = { + { 0x1c, 0x27 }, /* 0x1c => '\'' */ + { 0x1e, 0x36 }, /* 0x1e => '6' */ { 0x26, 0x2f }, /* '&' => '/' */ { 0x28, 0x29 }, /* '(' => ')' */ { 0x29, 0x3d }, /* ')' => '=' */ { 0x2a, 0x28 }, /* '*' => '(' */ - { 0x2b, 0x60 }, /* '+' => '`' */ { 0x2d, 0x2b }, /* '-' => '+' */ { 0x2f, 0x2d }, /* '/' => '-' */ { 0x3c, 0x3b }, /* '<' => ';' */ @@ -27,5 +28,4 @@ struct key_mapping dk_mapping[] __keymap = { { 0x5e, 0x26 }, /* '^' => '&' */ { 0x5f, 0x3f }, /* '_' => '?' */ { 0x7c, 0x2a }, /* '|' => '*' */ - { 0x7d, 0x5e }, /* '}' => '^' */ }; diff --git a/src/hci/keymap/keymap_es.c b/src/hci/keymap/keymap_es.c index c1fe013a9..51dedfff7 100644 --- a/src/hci/keymap/keymap_es.c +++ b/src/hci/keymap/keymap_es.c @@ -12,6 +12,8 @@ FILE_LICENCE ( PUBLIC_DOMAIN ); /** "es" keyboard mapping */ struct key_mapping es_mapping[] __keymap = { + { 0x1c, 0x1d }, /* 0x1c => 0x1d */ + { 0x1e, 0x36 }, /* 0x1e => '6' */ { 0x26, 0x2f }, /* '&' => '/' */ { 0x28, 0x29 }, /* '(' => ')' */ { 0x29, 0x3d }, /* ')' => '=' */ diff --git a/src/hci/keymap/keymap_et.c b/src/hci/keymap/keymap_et.c index ad88cecc1..dd0f879b1 100644 --- a/src/hci/keymap/keymap_et.c +++ b/src/hci/keymap/keymap_et.c @@ -26,5 +26,4 @@ struct key_mapping et_mapping[] __keymap = { { 0x5e, 0x26 }, /* '^' => '&' */ { 0x5f, 0x3f }, /* '_' => '?' */ { 0x7c, 0x2a }, /* '|' => '*' */ - { 0x7f, 0x1b }, /* 0x7f => 0x1b */ }; diff --git a/src/hci/keymap/keymap_fi.c b/src/hci/keymap/keymap_fi.c index c8f6c3a06..c489bf0e5 100644 --- a/src/hci/keymap/keymap_fi.c +++ b/src/hci/keymap/keymap_fi.c @@ -12,27 +12,18 @@ FILE_LICENCE ( PUBLIC_DOMAIN ); /** "fi" keyboard mapping */ struct key_mapping fi_mapping[] __keymap = { - { 0x22, 0x5b }, /* '"' => '[' */ { 0x26, 0x2f }, /* '&' => '/' */ - { 0x27, 0x7b }, /* '\'' => '{' */ { 0x28, 0x29 }, /* '(' => ')' */ { 0x29, 0x3d }, /* ')' => '=' */ { 0x2a, 0x28 }, /* '*' => '(' */ - { 0x2b, 0x60 }, /* '+' => '`' */ { 0x2d, 0x2b }, /* '-' => '+' */ { 0x2f, 0x2d }, /* '/' => '-' */ - { 0x3a, 0x5c }, /* ':' => '\\' */ - { 0x3b, 0x7c }, /* ';' => '|' */ { 0x3c, 0x3b }, /* '<' => ';' */ - { 0x3d, 0x27 }, /* '=' => '\'' */ { 0x3e, 0x3a }, /* '>' => ':' */ { 0x3f, 0x5f }, /* '?' => '_' */ { 0x40, 0x22 }, /* '@' => '"' */ - { 0x5b, 0x7d }, /* '[' => '}' */ { 0x5c, 0x27 }, /* '\\' => '\'' */ { 0x5e, 0x26 }, /* '^' => '&' */ { 0x5f, 0x3f }, /* '_' => '?' */ - { 0x7b, 0x5d }, /* '{' => ']' */ { 0x7c, 0x2a }, /* '|' => '*' */ - { 0x7d, 0x5e }, /* '}' => '^' */ }; diff --git a/src/hci/keymap/keymap_fr.c b/src/hci/keymap/keymap_fr.c index fd615a456..8f3b4999d 100644 --- a/src/hci/keymap/keymap_fr.c +++ b/src/hci/keymap/keymap_fr.c @@ -16,13 +16,16 @@ struct key_mapping fr_mapping[] __keymap = { { 0x11, 0x01 }, /* Ctrl-Q => Ctrl-A */ { 0x17, 0x1a }, /* Ctrl-W => Ctrl-Z */ { 0x1a, 0x17 }, /* Ctrl-Z => Ctrl-W */ + { 0x1c, 0x2a }, /* 0x1c => '*' */ + { 0x1d, 0x24 }, /* 0x1d => '$' */ + { 0x1e, 0x1c }, /* 0x1e => 0x1c */ + { 0x1f, 0x1d }, /* 0x1f => 0x1d */ { 0x21, 0x31 }, /* '!' => '1' */ { 0x22, 0x25 }, /* '"' => '%' */ { 0x23, 0x33 }, /* '#' => '3' */ { 0x24, 0x34 }, /* '$' => '4' */ { 0x25, 0x35 }, /* '%' => '5' */ { 0x26, 0x37 }, /* '&' => '7' */ - { 0x27, 0x7c }, /* '\'' => '|' */ { 0x28, 0x39 }, /* '(' => '9' */ { 0x29, 0x30 }, /* ')' => '0' */ { 0x2a, 0x38 }, /* '*' => '8' */ @@ -30,39 +33,28 @@ struct key_mapping fr_mapping[] __keymap = { { 0x2d, 0x29 }, /* '-' => ')' */ { 0x2e, 0x3a }, /* '.' => ':' */ { 0x2f, 0x21 }, /* '/' => '!' */ - { 0x30, 0x40 }, /* '0' => '@' */ { 0x31, 0x26 }, /* '1' => '&' */ - { 0x32, 0x7b }, /* '2' => '{' */ { 0x33, 0x22 }, /* '3' => '"' */ { 0x34, 0x27 }, /* '4' => '\'' */ { 0x35, 0x28 }, /* '5' => '(' */ { 0x36, 0x2d }, /* '6' => '-' */ - { 0x37, 0x7d }, /* '7' => '}' */ { 0x38, 0x5f }, /* '8' => '_' */ - { 0x39, 0x2f }, /* '9' => '/' */ { 0x3a, 0x4d }, /* ':' => 'M' */ { 0x3b, 0x6d }, /* ';' => 'm' */ { 0x3c, 0x2e }, /* '<' => '.' */ { 0x3e, 0x2f }, /* '>' => '/' */ - { 0x3f, 0x5c }, /* '?' => '\\' */ { 0x40, 0x32 }, /* '@' => '2' */ { 0x41, 0x51 }, /* 'A' => 'Q' */ { 0x4d, 0x3f }, /* 'M' => '?' */ { 0x51, 0x41 }, /* 'Q' => 'A' */ { 0x57, 0x5a }, /* 'W' => 'Z' */ { 0x5a, 0x57 }, /* 'Z' => 'W' */ - { 0x5b, 0x5e }, /* '[' => '^' */ { 0x5c, 0x2a }, /* '\\' => '*' */ { 0x5d, 0x24 }, /* ']' => '$' */ { 0x5e, 0x36 }, /* '^' => '6' */ - { 0x5f, 0x5d }, /* '_' => ']' */ - { 0x60, 0x2a }, /* '`' => '*' */ { 0x61, 0x71 }, /* 'a' => 'q' */ { 0x6d, 0x2c }, /* 'm' => ',' */ { 0x71, 0x61 }, /* 'q' => 'a' */ { 0x77, 0x7a }, /* 'w' => 'z' */ { 0x7a, 0x77 }, /* 'z' => 'w' */ - { 0x7b, 0x3c }, /* '{' => '<' */ - { 0x7c, 0x23 }, /* '|' => '#' */ - { 0x7d, 0x3e }, /* '}' => '>' */ }; diff --git a/src/hci/keymap/keymap_hu.c b/src/hci/keymap/keymap_hu.c index 68eff2f4c..a2eadbc62 100644 --- a/src/hci/keymap/keymap_hu.c +++ b/src/hci/keymap/keymap_hu.c @@ -14,6 +14,7 @@ FILE_LICENCE ( PUBLIC_DOMAIN ); struct key_mapping hu_mapping[] __keymap = { { 0x19, 0x1a }, /* Ctrl-Y => Ctrl-Z */ { 0x1a, 0x19 }, /* Ctrl-Z => Ctrl-Y */ + { 0x1e, 0x36 }, /* 0x1e => '6' */ { 0x21, 0x27 }, /* '!' => '\'' */ { 0x23, 0x2b }, /* '#' => '+' */ { 0x24, 0x21 }, /* '$' => '!' */ diff --git a/src/hci/keymap/keymap_il.c b/src/hci/keymap/keymap_il.c index 478330c0c..f631f7ac9 100644 --- a/src/hci/keymap/keymap_il.c +++ b/src/hci/keymap/keymap_il.c @@ -12,4 +12,16 @@ FILE_LICENCE ( PUBLIC_DOMAIN ); /** "il" keyboard mapping */ struct key_mapping il_mapping[] __keymap = { + { 0x1d, 0x1b }, /* 0x1d => 0x1b */ + { 0x27, 0x2c }, /* '\'' => ',' */ + { 0x28, 0x29 }, /* '(' => ')' */ + { 0x29, 0x28 }, /* ')' => '(' */ + { 0x2f, 0x2e }, /* '/' => '.' */ + { 0x3c, 0x3e }, /* '<' => '>' */ + { 0x3e, 0x3c }, /* '>' => '<' */ + { 0x5b, 0x5d }, /* '[' => ']' */ + { 0x5d, 0x5b }, /* ']' => '[' */ + { 0x60, 0x3b }, /* '`' => ';' */ + { 0x7b, 0x7d }, /* '{' => '}' */ + { 0x7d, 0x7b }, /* '}' => '{' */ }; diff --git a/src/hci/keymap/keymap_it.c b/src/hci/keymap/keymap_it.c index 5bb05471c..d96102c9e 100644 --- a/src/hci/keymap/keymap_it.c +++ b/src/hci/keymap/keymap_it.c @@ -12,6 +12,7 @@ FILE_LICENCE ( PUBLIC_DOMAIN ); /** "it" keyboard mapping */ struct key_mapping it_mapping[] __keymap = { + { 0x1e, 0x36 }, /* 0x1e => '6' */ { 0x26, 0x2f }, /* '&' => '/' */ { 0x28, 0x29 }, /* '(' => ')' */ { 0x29, 0x3d }, /* ')' => '=' */ diff --git a/src/hci/keymap/keymap_mt.c b/src/hci/keymap/keymap_mt.c index 094a6fc60..dfca2ff66 100644 --- a/src/hci/keymap/keymap_mt.c +++ b/src/hci/keymap/keymap_mt.c @@ -12,8 +12,8 @@ FILE_LICENCE ( PUBLIC_DOMAIN ); /** "mt" keyboard mapping */ struct key_mapping mt_mapping[] __keymap = { + { 0x1c, 0x1e }, /* 0x1c => 0x1e */ { 0x22, 0x40 }, /* '"' => '@' */ - { 0x23, 0x04 }, /* '#' => Ctrl-D */ { 0x40, 0x22 }, /* '@' => '"' */ { 0x5c, 0x23 }, /* '\\' => '#' */ { 0x7c, 0x7e }, /* '|' => '~' */ diff --git a/src/hci/keymap/keymap_nl.c b/src/hci/keymap/keymap_nl.c index ba051705e..2a0fbbcbd 100644 --- a/src/hci/keymap/keymap_nl.c +++ b/src/hci/keymap/keymap_nl.c @@ -12,11 +12,13 @@ FILE_LICENCE ( PUBLIC_DOMAIN ); /** "nl" keyboard mapping */ struct key_mapping nl_mapping[] __keymap = { + { 0x1c, 0x3c }, /* 0x1c => '<' */ + { 0x1d, 0x1c }, /* 0x1d => 0x1c */ + { 0x1e, 0x36 }, /* 0x1e => '6' */ { 0x26, 0x5f }, /* '&' => '_' */ { 0x28, 0x29 }, /* '(' => ')' */ { 0x29, 0x27 }, /* ')' => '\'' */ { 0x2a, 0x28 }, /* '*' => '(' */ - { 0x2b, 0x7e }, /* '+' => '~' */ { 0x2d, 0x2f }, /* '-' => '/' */ { 0x2f, 0x2d }, /* '/' => '-' */ { 0x3b, 0x2b }, /* ';' => '+' */ diff --git a/src/hci/keymap/keymap_no-latin1.c b/src/hci/keymap/keymap_no-latin1.c index 8c3e81b31..655e4cef7 100644 --- a/src/hci/keymap/keymap_no-latin1.c +++ b/src/hci/keymap/keymap_no-latin1.c @@ -12,6 +12,7 @@ FILE_LICENCE ( PUBLIC_DOMAIN ); /** "no-latin1" keyboard mapping */ struct key_mapping no_latin1_mapping[] __keymap = { + { 0x1d, 0x1e }, /* 0x1d => 0x1e */ { 0x26, 0x2f }, /* '&' => '/' */ { 0x28, 0x29 }, /* '(' => ')' */ { 0x29, 0x3d }, /* ')' => '=' */ diff --git a/src/hci/keymap/keymap_no.c b/src/hci/keymap/keymap_no.c index 45cf9e847..7a2df7c5a 100644 --- a/src/hci/keymap/keymap_no.c +++ b/src/hci/keymap/keymap_no.c @@ -12,94 +12,22 @@ FILE_LICENCE ( PUBLIC_DOMAIN ); /** "no" keyboard mapping */ struct key_mapping no_mapping[] __keymap = { - { 0x02, 0x18 }, /* Ctrl-B => Ctrl-X */ - { 0x03, 0x0a }, /* Ctrl-C => Ctrl-J */ - { 0x04, 0x05 }, /* Ctrl-D => Ctrl-E */ - { 0x06, 0x15 }, /* Ctrl-F => Ctrl-U */ - { 0x07, 0x09 }, /* Ctrl-G => Ctrl-I */ - { 0x08, 0x04 }, /* Ctrl-H => Ctrl-D */ - { 0x0a, 0x08 }, /* Ctrl-J => Ctrl-H */ - { 0x0b, 0x14 }, /* Ctrl-K => Ctrl-T */ - { 0x0c, 0x0e }, /* Ctrl-L => Ctrl-N */ - { 0x0e, 0x02 }, /* Ctrl-N => Ctrl-B */ - { 0x0f, 0x12 }, /* Ctrl-O => Ctrl-R */ - { 0x10, 0x0c }, /* Ctrl-P => Ctrl-L */ - { 0x12, 0x10 }, /* Ctrl-R => Ctrl-P */ - { 0x13, 0x0f }, /* Ctrl-S => Ctrl-O */ - { 0x14, 0x19 }, /* Ctrl-T => Ctrl-Y */ - { 0x15, 0x07 }, /* Ctrl-U => Ctrl-G */ - { 0x16, 0x0b }, /* Ctrl-V => Ctrl-K */ - { 0x18, 0x11 }, /* Ctrl-X => Ctrl-Q */ - { 0x19, 0x06 }, /* Ctrl-Y => Ctrl-F */ - { 0x22, 0x5f }, /* '"' => '_' */ + { 0x1c, 0x27 }, /* 0x1c => '\'' */ + { 0x1e, 0x36 }, /* 0x1e => '6' */ { 0x26, 0x2f }, /* '&' => '/' */ - { 0x27, 0x2d }, /* '\'' => '-' */ { 0x28, 0x29 }, /* '(' => ')' */ { 0x29, 0x3d }, /* ')' => '=' */ { 0x2a, 0x28 }, /* '*' => '(' */ - { 0x2b, 0x60 }, /* '+' => '`' */ - { 0x2c, 0x77 }, /* ',' => 'w' */ { 0x2d, 0x2b }, /* '-' => '+' */ - { 0x2e, 0x76 }, /* '.' => 'v' */ - { 0x2f, 0x7a }, /* '/' => 'z' */ - { 0x3a, 0x53 }, /* ':' => 'S' */ - { 0x3b, 0x73 }, /* ';' => 's' */ - { 0x3c, 0x57 }, /* '<' => 'W' */ + { 0x2f, 0x2d }, /* '/' => '-' */ + { 0x3c, 0x3b }, /* '<' => ';' */ { 0x3d, 0x5c }, /* '=' => '\\' */ - { 0x3e, 0x56 }, /* '>' => 'V' */ - { 0x3f, 0x5a }, /* '?' => 'Z' */ + { 0x3e, 0x3a }, /* '>' => ':' */ + { 0x3f, 0x5f }, /* '?' => '_' */ { 0x40, 0x22 }, /* '@' => '"' */ - { 0x42, 0x58 }, /* 'B' => 'X' */ - { 0x43, 0x4a }, /* 'C' => 'J' */ - { 0x44, 0x45 }, /* 'D' => 'E' */ - { 0x45, 0x3a }, /* 'E' => ':' */ - { 0x46, 0x55 }, /* 'F' => 'U' */ - { 0x47, 0x49 }, /* 'G' => 'I' */ - { 0x48, 0x44 }, /* 'H' => 'D' */ - { 0x49, 0x43 }, /* 'I' => 'C' */ - { 0x4a, 0x48 }, /* 'J' => 'H' */ - { 0x4b, 0x54 }, /* 'K' => 'T' */ - { 0x4c, 0x4e }, /* 'L' => 'N' */ - { 0x4e, 0x42 }, /* 'N' => 'B' */ - { 0x4f, 0x52 }, /* 'O' => 'R' */ - { 0x50, 0x4c }, /* 'P' => 'L' */ - { 0x52, 0x50 }, /* 'R' => 'P' */ - { 0x53, 0x4f }, /* 'S' => 'O' */ - { 0x54, 0x59 }, /* 'T' => 'Y' */ - { 0x55, 0x47 }, /* 'U' => 'G' */ - { 0x56, 0x4b }, /* 'V' => 'K' */ - { 0x57, 0x3b }, /* 'W' => ';' */ - { 0x58, 0x51 }, /* 'X' => 'Q' */ - { 0x59, 0x46 }, /* 'Y' => 'F' */ - { 0x5b, 0x27 }, /* '[' => '\'' */ - { 0x5c, 0x3c }, /* '\\' => '<' */ - { 0x5d, 0x7e }, /* ']' => '~' */ + { 0x5c, 0x27 }, /* '\\' => '\'' */ { 0x5e, 0x26 }, /* '^' => '&' */ { 0x5f, 0x3f }, /* '_' => '?' */ { 0x60, 0x7c }, /* '`' => '|' */ - { 0x62, 0x78 }, /* 'b' => 'x' */ - { 0x63, 0x6a }, /* 'c' => 'j' */ - { 0x64, 0x65 }, /* 'd' => 'e' */ - { 0x65, 0x2e }, /* 'e' => '.' */ - { 0x66, 0x75 }, /* 'f' => 'u' */ - { 0x67, 0x69 }, /* 'g' => 'i' */ - { 0x68, 0x64 }, /* 'h' => 'd' */ - { 0x69, 0x63 }, /* 'i' => 'c' */ - { 0x6a, 0x68 }, /* 'j' => 'h' */ - { 0x6b, 0x74 }, /* 'k' => 't' */ - { 0x6c, 0x6e }, /* 'l' => 'n' */ - { 0x6e, 0x62 }, /* 'n' => 'b' */ - { 0x6f, 0x72 }, /* 'o' => 'r' */ - { 0x70, 0x6c }, /* 'p' => 'l' */ - { 0x72, 0x70 }, /* 'r' => 'p' */ - { 0x73, 0x6f }, /* 's' => 'o' */ - { 0x74, 0x79 }, /* 't' => 'y' */ - { 0x75, 0x67 }, /* 'u' => 'g' */ - { 0x76, 0x6b }, /* 'v' => 'k' */ - { 0x77, 0x2c }, /* 'w' => ',' */ - { 0x78, 0x71 }, /* 'x' => 'q' */ - { 0x79, 0x66 }, /* 'y' => 'f' */ - { 0x7b, 0x2a }, /* '{' => '*' */ - { 0x7c, 0x3e }, /* '|' => '>' */ - { 0x7d, 0x5e }, /* '}' => '^' */ + { 0x7c, 0x2a }, /* '|' => '*' */ }; diff --git a/src/hci/keymap/keymap_pt.c b/src/hci/keymap/keymap_pt.c index a8e44b6a3..b993902af 100644 --- a/src/hci/keymap/keymap_pt.c +++ b/src/hci/keymap/keymap_pt.c @@ -12,18 +12,21 @@ FILE_LICENCE ( PUBLIC_DOMAIN ); /** "pt" keyboard mapping */ struct key_mapping pt_mapping[] __keymap = { - { 0x1c, 0x1d }, /* 0x1c => 0x1d */ - { 0x1d, 0x1b }, /* 0x1d => 0x1b */ - { 0x22, 0x5e }, /* '"' => '^' */ - { 0x27, 0x7e }, /* '\'' => '~' */ - { 0x2f, 0x3b }, /* '/' => ';' */ - { 0x3f, 0x3a }, /* '?' => ':' */ - { 0x5b, 0x27 }, /* '[' => '\'' */ - { 0x5c, 0x5d }, /* '\\' => ']' */ - { 0x5d, 0x5b }, /* ']' => '[' */ - { 0x60, 0x27 }, /* '`' => '\'' */ - { 0x7b, 0x60 }, /* '{' => '`' */ - { 0x7c, 0x7d }, /* '|' => '}' */ - { 0x7d, 0x7b }, /* '}' => '{' */ - { 0x7e, 0x22 }, /* '~' => '"' */ + { 0x1e, 0x36 }, /* 0x1e => '6' */ + { 0x26, 0x2f }, /* '&' => '/' */ + { 0x28, 0x29 }, /* '(' => ')' */ + { 0x29, 0x3d }, /* ')' => '=' */ + { 0x2a, 0x28 }, /* '*' => '(' */ + { 0x2d, 0x27 }, /* '-' => '\'' */ + { 0x2f, 0x2d }, /* '/' => '-' */ + { 0x3c, 0x3b }, /* '<' => ';' */ + { 0x3e, 0x3a }, /* '>' => ':' */ + { 0x3f, 0x5f }, /* '?' => '_' */ + { 0x40, 0x22 }, /* '@' => '"' */ + { 0x5b, 0x2b }, /* '[' => '+' */ + { 0x5e, 0x26 }, /* '^' => '&' */ + { 0x5f, 0x3f }, /* '_' => '?' */ + { 0x60, 0x5c }, /* '`' => '\\' */ + { 0x7b, 0x2a }, /* '{' => '*' */ + { 0x7e, 0x7c }, /* '~' => '|' */ }; diff --git a/src/hci/keymap/keymap_ru.c b/src/hci/keymap/keymap_ru.c index 422b6c69f..c120ffd82 100644 --- a/src/hci/keymap/keymap_ru.c +++ b/src/hci/keymap/keymap_ru.c @@ -12,4 +12,5 @@ FILE_LICENCE ( PUBLIC_DOMAIN ); /** "ru" keyboard mapping */ struct key_mapping ru_mapping[] __keymap = { + { 0x0d, 0x0a }, /* Ctrl-M => Ctrl-J */ }; diff --git a/src/hci/keymap/keymap_bg.c b/src/hci/keymap/keymap_sr-latin.c index 62b6baeac..9d76e8a6c 100644 --- a/src/hci/keymap/keymap_bg.c +++ b/src/hci/keymap/keymap_sr-latin.c @@ -1,6 +1,6 @@ /** @file * - * "bg" keyboard mapping + * "sr-latin" keyboard mapping * * This file is automatically generated; do not edit * @@ -10,6 +10,6 @@ FILE_LICENCE ( PUBLIC_DOMAIN ); #include <ipxe/keymap.h> -/** "bg" keyboard mapping */ -struct key_mapping bg_mapping[] __keymap = { +/** "sr-latin" keyboard mapping */ +struct key_mapping sr_latin_mapping[] __keymap = { }; diff --git a/src/hci/keymap/keymap_sr.c b/src/hci/keymap/keymap_sr.c deleted file mode 100644 index 0552f4d90..000000000 --- a/src/hci/keymap/keymap_sr.c +++ /dev/null @@ -1,35 +0,0 @@ -/** @file - * - * "sr" keyboard mapping - * - * This file is automatically generated; do not edit - * - */ - -FILE_LICENCE ( PUBLIC_DOMAIN ); - -#include <ipxe/keymap.h> - -/** "sr" keyboard mapping */ -struct key_mapping sr_mapping[] __keymap = { - { 0x19, 0x1a }, /* Ctrl-Y => Ctrl-Z */ - { 0x1a, 0x19 }, /* Ctrl-Z => Ctrl-Y */ - { 0x26, 0x2f }, /* '&' => '/' */ - { 0x28, 0x29 }, /* '(' => ')' */ - { 0x29, 0x3d }, /* ')' => '=' */ - { 0x2a, 0x28 }, /* '*' => '(' */ - { 0x2b, 0x2a }, /* '+' => '*' */ - { 0x2d, 0x27 }, /* '-' => '\'' */ - { 0x2f, 0x2d }, /* '/' => '-' */ - { 0x3c, 0x3b }, /* '<' => ';' */ - { 0x3d, 0x2b }, /* '=' => '+' */ - { 0x3e, 0x3a }, /* '>' => ':' */ - { 0x3f, 0x5f }, /* '?' => '_' */ - { 0x40, 0x22 }, /* '@' => '"' */ - { 0x59, 0x5a }, /* 'Y' => 'Z' */ - { 0x5a, 0x59 }, /* 'Z' => 'Y' */ - { 0x5e, 0x26 }, /* '^' => '&' */ - { 0x5f, 0x3f }, /* '_' => '?' */ - { 0x79, 0x7a }, /* 'y' => 'z' */ - { 0x7a, 0x79 }, /* 'z' => 'y' */ -}; diff --git a/src/hci/keymap/keymap_th.c b/src/hci/keymap/keymap_th.c deleted file mode 100644 index e8b44d1ed..000000000 --- a/src/hci/keymap/keymap_th.c +++ /dev/null @@ -1,15 +0,0 @@ -/** @file - * - * "th" keyboard mapping - * - * This file is automatically generated; do not edit - * - */ - -FILE_LICENCE ( PUBLIC_DOMAIN ); - -#include <ipxe/keymap.h> - -/** "th" keyboard mapping */ -struct key_mapping th_mapping[] __keymap = { -}; diff --git a/src/hci/keymap/keymap_wo.c b/src/hci/keymap/keymap_wo.c deleted file mode 100644 index b45357612..000000000 --- a/src/hci/keymap/keymap_wo.c +++ /dev/null @@ -1,55 +0,0 @@ -/** @file - * - * "wo" keyboard mapping - * - * This file is automatically generated; do not edit - * - */ - -FILE_LICENCE ( PUBLIC_DOMAIN ); - -#include <ipxe/keymap.h> - -/** "wo" keyboard mapping */ -struct key_mapping wo_mapping[] __keymap = { - { 0x01, 0x11 }, /* Ctrl-A => Ctrl-Q */ - { 0x11, 0x01 }, /* Ctrl-Q => Ctrl-A */ - { 0x17, 0x1a }, /* Ctrl-W => Ctrl-Z */ - { 0x1a, 0x17 }, /* Ctrl-Z => Ctrl-W */ - { 0x21, 0x31 }, /* '!' => '1' */ - { 0x23, 0x33 }, /* '#' => '3' */ - { 0x24, 0x34 }, /* '$' => '4' */ - { 0x25, 0x35 }, /* '%' => '5' */ - { 0x26, 0x37 }, /* '&' => '7' */ - { 0x28, 0x39 }, /* '(' => '9' */ - { 0x29, 0x30 }, /* ')' => '0' */ - { 0x2a, 0x38 }, /* '*' => '8' */ - { 0x2c, 0x3b }, /* ',' => ';' */ - { 0x2d, 0x29 }, /* '-' => ')' */ - { 0x2e, 0x3a }, /* '.' => ':' */ - { 0x2f, 0x21 }, /* '/' => '!' */ - { 0x31, 0x26 }, /* '1' => '&' */ - { 0x33, 0x22 }, /* '3' => '"' */ - { 0x34, 0x27 }, /* '4' => '\'' */ - { 0x35, 0x28 }, /* '5' => '(' */ - { 0x36, 0x2d }, /* '6' => '-' */ - { 0x38, 0x5f }, /* '8' => '_' */ - { 0x3a, 0x4d }, /* ':' => 'M' */ - { 0x3b, 0x6d }, /* ';' => 'm' */ - { 0x3c, 0x2e }, /* '<' => '.' */ - { 0x3e, 0x2f }, /* '>' => '/' */ - { 0x40, 0x32 }, /* '@' => '2' */ - { 0x41, 0x51 }, /* 'A' => 'Q' */ - { 0x4d, 0x3f }, /* 'M' => '?' */ - { 0x51, 0x41 }, /* 'Q' => 'A' */ - { 0x57, 0x5a }, /* 'W' => 'Z' */ - { 0x5a, 0x57 }, /* 'Z' => 'W' */ - { 0x5d, 0x24 }, /* ']' => '$' */ - { 0x5e, 0x36 }, /* '^' => '6' */ - { 0x61, 0x71 }, /* 'a' => 'q' */ - { 0x6d, 0x2c }, /* 'm' => ',' */ - { 0x71, 0x61 }, /* 'q' => 'a' */ - { 0x77, 0x7a }, /* 'w' => 'z' */ - { 0x7a, 0x77 }, /* 'z' => 'w' */ - { 0x7e, 0x25 }, /* '~' => '%' */ -}; diff --git a/src/util/genkeymap.pl b/src/util/genkeymap.pl deleted file mode 100755 index 7a5024bf8..000000000 --- a/src/util/genkeymap.pl +++ /dev/null @@ -1,238 +0,0 @@ -#!/usr/bin/perl -w -# -# Copyright (C) 2011 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. - -=head1 NAME - -genkeymap.pl - -=head1 SYNOPSIS - -genkeymap.pl [options] <keymap name> - -Options: - - -f,--from=<name> Set BIOS keymap name (default "us") - -h,--help Display brief help message - -v,--verbose Increase verbosity - -q,--quiet Decrease verbosity - -=cut - -# With reference to: -# -# http://gunnarwrobel.de/wiki/Linux-and-the-keyboard.html - -use Getopt::Long; -use Pod::Usage; -use strict; -use warnings; - -use constant BIOS_KEYMAP => "us"; -use constant BKEYMAP_MAGIC => "bkeymap"; -use constant MAX_NR_KEYMAPS => 256; -use constant NR_KEYS => 128; -use constant KG_SHIFT => 0; -use constant KG_ALTGR => 1; -use constant KG_CTRL => 2; -use constant KG_ALT => 3; -use constant KG_SHIFTL => 4; -use constant KG_KANASHIFT => 4; -use constant KG_SHIFTR => 5; -use constant KG_CTRLL => 6; -use constant KG_CTRLR => 7; -use constant KG_CAPSSHIFT => 8; -use constant KT_LATIN => 0; -use constant KT_FN => 1; -use constant KT_SPEC => 2; -use constant KT_PAD => 3; -use constant KT_DEAD => 4; -use constant KT_CONS => 5; -use constant KT_CUR => 6; -use constant KT_SHIFT => 7; -use constant KT_META => 8; -use constant KT_ASCII => 9; -use constant KT_LOCK => 10; -use constant KT_LETTER => 11; -use constant KT_SLOCK => 12; -use constant KT_SPKUP => 14; - -my $verbosity = 1; -my $from_name = BIOS_KEYMAP; - -# Read named keymaps using "loadkeys -b" -# -sub read_keymaps { - my $name = shift; - my $keymaps = []; - - # Generate binary keymap - open my $pipe, "-|", "loadkeys", "-b", $name - or die "Could not load keymap \"".$name."\": $!\n"; - - # Check magic - read $pipe, my $magic, length BKEYMAP_MAGIC - or die "Could not read from \"".$name."\": $!\n"; - die "Bad magic value from \"".$name."\"\n" - unless $magic eq BKEYMAP_MAGIC; - - # Read list of included keymaps - read $pipe, my $included, MAX_NR_KEYMAPS - or die "Could not read from \"".$name."\": $!\n"; - my @included = unpack ( "C*", $included ); - die "Missing or truncated keymap list from \"".$name."\"\n" - unless @included == MAX_NR_KEYMAPS; - - # Read each keymap in turn - for ( my $keymap = 0 ; $keymap < MAX_NR_KEYMAPS ; $keymap++ ) { - if ( $included[$keymap] ) { - read $pipe, my $keysyms, ( NR_KEYS * 2 ) - or die "Could not read from \"".$name."\": $!\n"; - my @keysyms = unpack ( "S*", $keysyms ); - die "Missing or truncated keymap ".$keymap." from \"".$name."\"\n" - unless @keysyms == NR_KEYS; - push @$keymaps, \@keysyms; - } else { - push @$keymaps, undef; - } - } - - close $pipe; - return $keymaps; -} - -# Translate keysym value to ASCII -# -sub keysym_to_ascii { - my $keysym = shift; - - # Non-existent keysyms have no ASCII equivalent - return unless $keysym; - - # Sanity check - if ( $keysym & 0xf000 ) { - warn "Unexpected keysym ".sprintf ( "0x%04x", $keysym )."\n"; - return; - } - - # Extract type and value - my $type = ( $keysym >> 8 ); - my $value = ( $keysym & 0xff ); - - # Non-simple types have no ASCII equivalent - return unless ( ( $type == KT_LATIN ) || ( $type == KT_ASCII ) || - ( $type == KT_LETTER ) ); - - # High-bit-set characters cannot be generated on a US keyboard - return if $value & 0x80; - - return $value; -} - -# Translate ASCII to descriptive name -# -sub ascii_to_name { - my $ascii = shift; - - if ( $ascii == 0x5c ) { - return "'\\\\'"; - } elsif ( $ascii == 0x27 ) { - return "'\\\''"; - } elsif ( ( $ascii >= 0x20 ) && ( $ascii <= 0x7e ) ) { - return sprintf ( "'%c'", $ascii ); - } elsif ( $ascii <= 0x1a ) { - return sprintf ( "Ctrl-%c", ( 0x40 + $ascii ) ); - } else { - return sprintf ( "0x%02x", $ascii ); - } -} - -# Produce translation table between two keymaps -# -sub translate_keymaps { - my $from = shift; - my $to = shift; - my $map = {}; - - foreach my $keymap ( 0, 1 << KG_SHIFT, 1 << KG_CTRL ) { - for ( my $keycode = 0 ; $keycode < NR_KEYS ; $keycode++ ) { - my $from_ascii = keysym_to_ascii ( $from->[$keymap]->[$keycode] ) - or next; - my $to_ascii = keysym_to_ascii ( $to->[$keymap]->[$keycode] ) - or next; - my $new_map = ( ! exists $map->{$from_ascii} ); - my $update_map = - ( $new_map || ( $keycode < $map->{$from_ascii}->{keycode} ) ); - if ( ( $verbosity > 1 ) && - ( ( $from_ascii != $to_ascii ) || - ( $update_map && ! $new_map ) ) ) { - printf STDERR "In keymap %d: %s => %s%s\n", $keymap, - ascii_to_name ( $from_ascii ), ascii_to_name ( $to_ascii ), - ( $update_map ? ( $new_map ? "" : " (override)" ) - : " (ignored)" ); - } - if ( $update_map ) { - $map->{$from_ascii} = { - to_ascii => $to_ascii, - keycode => $keycode, - }; - } - } - } - return { map { $_ => $map->{$_}->{to_ascii} } keys %$map }; -} - -# Parse command-line options -Getopt::Long::Configure ( 'bundling', 'auto_abbrev' ); -GetOptions ( - 'verbose|v+' => sub { $verbosity++; }, - 'quiet|q+' => sub { $verbosity--; }, - 'from|f=s' => sub { shift; $from_name = shift; }, - 'help|h' => sub { pod2usage ( 1 ); }, -) or die "Could not parse command-line options\n"; -pod2usage ( 1 ) unless @ARGV == 1; -my $to_name = shift; - -# Read and translate keymaps -my $from = read_keymaps ( $from_name ); -my $to = read_keymaps ( $to_name ); -my $map = translate_keymaps ( $from, $to ); - -# Generate output -( my $to_name_c = $to_name ) =~ s/\W/_/g; -printf "/** \@file\n"; -printf " *\n"; -printf " * \"".$to_name."\" keyboard mapping\n"; -printf " *\n"; -printf " * This file is automatically generated; do not edit\n"; -printf " *\n"; -printf " */\n"; -printf "\n"; -printf "FILE_LICENCE ( PUBLIC_DOMAIN );\n"; -printf "\n"; -printf "#include <ipxe/keymap.h>\n"; -printf "\n"; -printf "/** \"".$to_name."\" keyboard mapping */\n"; -printf "struct key_mapping ".$to_name_c."_mapping[] __keymap = {\n"; -foreach my $from_sym ( sort { $a <=> $b } keys %$map ) { - my $to_sym = $map->{$from_sym}; - next if $from_sym == $to_sym; - printf "\t{ 0x%02x, 0x%02x },\t/* %s => %s */\n", $from_sym, $to_sym, - ascii_to_name ( $from_sym ), ascii_to_name ( $to_sym ); -} -printf "};\n"; diff --git a/src/util/genkeymap.py b/src/util/genkeymap.py new file mode 100755 index 000000000..1bb494f83 --- /dev/null +++ b/src/util/genkeymap.py @@ -0,0 +1,346 @@ +#!/usr/bin/env python3 +# +# 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. + +"""Generate iPXE keymaps""" + +from __future__ import annotations + +import argparse +from collections import UserDict +from collections.abc import Sequence, Mapping, MutableMapping +from dataclasses import dataclass +from enum import Flag, IntEnum +import re +import subprocess +from struct import Struct +import textwrap +from typing import ClassVar, Optional + + +class KeyType(IntEnum): + """Key types""" + + LATIN = 0 + FN = 1 + SPEC = 2 + PAD = 3 + DEAD = 4 + CONS = 5 + CUR = 6 + SHIFT = 7 + META = 8 + ASCII = 9 + LOCK = 10 + LETTER = 11 + SLOCK = 12 + DEAD2 = 13 + BRL = 14 + UNKNOWN = 0xf0 + + +class KeyModifiers(Flag): + """Key modifiers""" + + NONE = 0 + SHIFT = 1 + ALTGR = 2 + CTRL = 4 + ALT = 8 + SHIFTL = 16 + SHIFTR = 32 + CTRLL = 64 + CTRLR = 128 + + @property + def complexity(self) -> int: + """Get complexity value of applied modifiers""" + if self == self.NONE: + return 0 + if self == self.SHIFT: + return 1 + if self == self.CTRL: + return 2 + return 3 + bin(self.value).count('1') + + +@dataclass +class Key: + """A single key definition""" + + keycode: int + """Opaque keycode""" + + keysym: int + """Key symbol""" + + modifiers: KeyModifiers + """Applied modifiers""" + + ASCII_TYPES: ClassVar[set[KeyType]] = {KeyType.LATIN, KeyType.ASCII, + KeyType.LETTER} + """Key types with direct ASCII values""" + + @property + def keytype(self) -> Optional[KeyType]: + """Key type""" + try: + return KeyType(self.keysym >> 8) + except ValueError: + return None + + @property + def value(self) -> int: + """Key value""" + return self.keysym & 0xff + + @property + def ascii(self) -> Optional[str]: + """ASCII character""" + if self.keytype in self.ASCII_TYPES: + value = self.value + char = chr(value) + if value and char.isascii(): + return char + return None + + +class KeyMapping(UserDict[KeyModifiers, Sequence[Key]]): + """A keyboard mapping""" + + BKEYMAP_MAGIC: ClassVar[bytes] = b'bkeymap' + """Magic signature for output produced by 'loadkeys -b'""" + + MAX_NR_KEYMAPS: ClassVar[int] = 256 + """Maximum number of keymaps produced by 'loadkeys -b'""" + + NR_KEYS: ClassVar[int] = 128 + """Number of keys in each keymap produced by 'loadkeys -b'""" + + KEY_BACKSPACE: ClassVar[int] = 14 + """Key code for backspace + + Keyboard maps seem to somewhat arbitrarily pick an interpretation + for the backspace key and its various modifiers, according to the + personal preference of the keyboard map transcriber. + """ + + KEY_NON_US: ClassVar[int] = 86 + """Key code 86 + + Key code 86 is somewhat bizarre. It doesn't physically exist on + most US keyboards. The database used by "loadkeys" defines it as + "<>", while most other databases either define it as a duplicate + "\\|" or omit it entirely. + """ + + FIXUPS: ClassVar[Mapping[str, Mapping[KeyModifiers, + Sequence[tuple[int, int]]]]] = { + 'us': { + # Redefine erroneous key 86 as generating "\\|" + KeyModifiers.NONE: [(KEY_NON_US, ord('\\'))], + KeyModifiers.SHIFT: [(KEY_NON_US, ord('|'))], + # Treat Ctrl-Backspace as producing Backspace rather than Ctrl-H + KeyModifiers.CTRL: [(KEY_BACKSPACE, 0x7f)], + }, + } + """Fixups for erroneous keymappings produced by 'loadkeys -b'""" + + @property + def unshifted(self): + """Basic unshifted key mapping""" + return self[KeyModifiers.NONE] + + @property + def shifted(self): + """Basic shifted key mapping""" + return self[KeyModifiers.SHIFT] + + @classmethod + def load(cls, name: str) -> KeyMapping: + """Load keymap using 'loadkeys -b'""" + bkeymap = subprocess.check_output(["loadkeys", "-u", "-b", name]) + if not bkeymap.startswith(cls.BKEYMAP_MAGIC): + raise ValueError("Invalid bkeymap magic signature") + bkeymap = bkeymap[len(cls.BKEYMAP_MAGIC):] + included = bkeymap[:cls.MAX_NR_KEYMAPS] + if len(included) != cls.MAX_NR_KEYMAPS: + raise ValueError("Invalid bkeymap inclusion list") + keymaps = bkeymap[cls.MAX_NR_KEYMAPS:] + keys = {} + for modifiers in map(KeyModifiers, range(cls.MAX_NR_KEYMAPS)): + if included[modifiers.value]: + fmt = Struct('<%dH' % cls.NR_KEYS) + keymap = keymaps[:fmt.size] + if len(keymap) != fmt.size: + raise ValueError("Invalid bkeymap map %#x" % + modifiers.value) + keys[modifiers] = [ + Key(modifiers=modifiers, keycode=keycode, keysym=keysym) + for keycode, keysym in enumerate(fmt.unpack(keymap)) + ] + keymaps = keymaps[len(keymap):] + if keymaps: + raise ValueError("Trailing bkeymap data") + for modifiers, fixups in cls.FIXUPS.get(name, {}).items(): + for keycode, keysym in fixups: + keys[modifiers][keycode] = Key(modifiers=modifiers, + keycode=keycode, keysym=keysym) + return cls(keys) + + @property + def inverse(self) -> MutableMapping[str, Key]: + """Construct inverse mapping from ASCII value to key""" + return { + key.ascii: key + # Give priority to simplest modifier for a given ASCII code + for modifiers in sorted(self.keys(), reverse=True, + key=lambda x: (x.complexity, x.value)) + # Give priority to lowest keycode for a given ASCII code + for key in reversed(self[modifiers]) + # Ignore keys with no ASCII value + if key.ascii + } + + +class BiosKeyMapping(KeyMapping): + """Keyboard mapping as used by the BIOS""" + + @property + def inverse(self) -> MutableMapping[str, Key]: + inverse = super().inverse + assert len(inverse) == 0x7f + assert all(x.modifiers in {KeyModifiers.NONE, KeyModifiers.SHIFT, + KeyModifiers.CTRL} + for x in inverse.values()) + return inverse + + +@dataclass +class KeyRemapping: + """A keyboard remapping""" + + name: str + """Mapping name""" + + source: KeyMapping + """Source keyboard mapping""" + + target: KeyMapping + """Target keyboard mapping""" + + @property + def ascii(self) -> MutableMapping[str, str]: + """Remapped ASCII key table""" + # Construct raw mapping from source ASCII to target ASCII + 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 + table = {source: target for source, target in raw.items() + if target + and ord(source) != 0x7f + and ord(target) != 0x7f + and ord(source) != ord(target)} + # Recursively delete any mappings that would produce + # unreachable alphanumerics (e.g. the "il" keymap, which maps + # away the whole lower-case alphabet) + while True: + unreachable = set(table.keys()) - set(table.values()) + delete = {x for x in unreachable if x.isascii() and x.isalnum()} + if not delete: + break + table = {k: v for k, v in table.items() if k not in delete} + # Sanity check: ensure that all numerics are reachable using + # the same shift state + digits = '1234567890' + unshifted = ''.join(table.get(x, x) for x in '1234567890') + shifted = ''.join(table.get(x, x) for x in '!@#$%^&*()') + if digits not in (shifted, unshifted): + raise ValueError("Inconsistent numeric remapping %s / %s" % + (unshifted, shifted)) + return dict(sorted(table.items())) + + @property + def cname(self) -> str: + """C variable name""" + return re.sub(r'\W', '_', self.name) + "_mapping" + + @staticmethod + def ascii_name(char: str) -> str: + """ASCII character name""" + if char == '\\': + name = "'\\\\'" + elif char == '\'': + name = "'\\\''" + elif char.isprintable(): + name = "'%s'" % char + elif ord(char) <= 0x1a: + name = "Ctrl-%c" % (ord(char) + 0x40) + else: + name = "0x%02x" % ord(char) + return name + + @property + def code(self) -> str: + """Generated source code""" + code = textwrap.dedent(f""" + /** @file + * + * "{self.name}" keyboard mapping + * + * This file is automatically generated; do not edit + * + */ + + FILE_LICENCE ( PUBLIC_DOMAIN ); + + #include <ipxe/keymap.h> + + /** "{self.name}" keyboard mapping */ + struct key_mapping {self.cname}[] __keymap = {{ + """).lstrip() + ''.join( + '\t{ 0x%02x, 0x%02x },\t/* %s => %s */\n' % ( + ord(source), ord(target), + self.ascii_name(source), self.ascii_name(target) + ) + for source, target in self.ascii.items() + ) + textwrap.dedent(""" + }; + """).strip() + return code + + +if __name__ == '__main__': + + # Parse command-line arguments + parser = argparse.ArgumentParser(description="Generate iPXE keymaps") + parser.add_argument('--verbose', '-v', action='count', default=0, + help="Increase verbosity") + parser.add_argument('layout', help="Target keyboard layout") + args = parser.parse_args() + + # Load source and target keymaps + source = BiosKeyMapping.load('us') + target = KeyMapping.load(args.layout) + + # Construct remapping + remap = KeyRemapping(name=args.layout, source=source, target=target) + + # Output generated code + print(remap.code) |