diff options
author | Devaev Maxim <[email protected]> | 2020-05-23 11:57:19 +0300 |
---|---|---|
committer | Devaev Maxim <[email protected]> | 2020-05-23 11:57:19 +0300 |
commit | a795fe5ed63b960cbf24c9130ed37f9f7f33280c (patch) | |
tree | 51b884539614ed380cb19cd60e4dae7c8baab090 | |
parent | 17082c916a1d80d92bb5a51fed67f030f605f804 (diff) |
additional keymapping info; refactoring
-rw-r--r-- | Makefile | 2 | ||||
-rwxr-xr-x | genmap.py | 37 | ||||
-rw-r--r-- | keymap.in | 182 | ||||
-rw-r--r-- | kvmd/apps/kvmd/api/hid.py | 4 | ||||
-rw-r--r-- | kvmd/apps/vnc/__init__.py | 3 | ||||
-rw-r--r-- | kvmd/keyboard/__init__.py | 20 | ||||
-rw-r--r-- | kvmd/keyboard/keysym.py (renamed from kvmd/apps/vnc/keysym.py) | 11 | ||||
-rw-r--r-- | kvmd/keyboard/mappings.py | 373 | ||||
-rw-r--r-- | kvmd/keyboard/mappings.py.mako (renamed from kvmd/keymap.py.mako) | 16 | ||||
-rw-r--r-- | kvmd/keyboard/printer.py (renamed from kvmd/keyprint.py) | 8 | ||||
-rw-r--r-- | kvmd/keymap.py | 632 | ||||
-rw-r--r-- | kvmd/plugins/hid/otg/keyboard.py | 13 | ||||
-rw-r--r-- | kvmd/plugins/hid/serial.py | 7 | ||||
-rw-r--r-- | kvmd/validators/kvm.py | 4 | ||||
-rwxr-xr-x | setup.py | 1 | ||||
-rw-r--r-- | testenv/tests/keyboard/__init__.py | 20 | ||||
-rw-r--r-- | testenv/tests/keyboard/test_keymap.py (renamed from testenv/tests/test_keymap.py) | 2 | ||||
-rw-r--r-- | testenv/tests/validators/test_kvm.py | 2 |
18 files changed, 573 insertions, 764 deletions
@@ -130,7 +130,7 @@ run-vnc: testenv regen: testenv - for file in kvmd/keymap.py hid/src/keymap.h; do \ + for file in kvmd/keyboard/mappings.py hid/src/keymap.h; do \ docker run --user `id -u`:`id -g` --rm \ --volume `pwd`:/src \ -it $(TESTENV_IMAGE) bash -c "cd src && ./genmap.py keymap.in $$file.mako $$file"; \ @@ -36,14 +36,26 @@ import mako.template # ===== @dataclasses.dataclass(frozen=True) +class _OtgKey: + code: int + is_modifier: bool + + [email protected](frozen=True) +class _X11Key: + name: str + code: int + shift: bool + + [email protected](frozen=True) class _KeyMapping: web_name: str serial_code: int arduino_name: str - otg_code: int - otg_is_modifier: bool + otg_key: _OtgKey at1_code: int - x11_codes: Set[int] + x11_keys: Set[_X11Key] def _resolve_keysym(name: str) -> int: @@ -61,15 +73,24 @@ def _read_keymap_in(path: str) -> List[_KeyMapping]: line = line.strip() if len(line) > 0 and not line.startswith("#"): parts = list(map(str.strip, line.split())) - if len(parts) >= 7: + if len(parts) >= 6: + otg_is_modifier = parts[3].startswith("^") + otg_code = int((parts[3][1:] if otg_is_modifier else parts[3]), 16) + + x11_keys: Set[_X11Key] = set() + for x11_name in parts[5].split(","): + x11_shift = x11_name.startswith("^") + x11_name = (x11_name[1:] if x11_shift else x11_name) + x11_code = _resolve_keysym(x11_name) + x11_keys.add(_X11Key(x11_name, x11_code, x11_shift)) + keymap.append(_KeyMapping( web_name=parts[0], serial_code=int(parts[1]), arduino_name=parts[2], - otg_code=int(parts[3], 16), - otg_is_modifier=(parts[4].lower() == "m"), - at1_code=int(parts[5], 16), - x11_codes=set(map(_resolve_keysym, parts[6].split(","))), + otg_key=_OtgKey(otg_code, otg_is_modifier), + at1_code=int(parts[4], 16), + x11_keys=x11_keys, )) return keymap @@ -25,97 +25,97 @@ # https://gist.github.com/MightyPork/6da26e382a7ad91b5496ee55fdc73db2 # https://github.com/qemu/keycodemapdb/blob/master/data/keymaps.csv -# ---------------------------------------------------------------------------------------------------------------- -# Web | Serial code | Arduino key | OTG code + modifier flag | AT set1 | X11 keysyms -# ---------------------------------------------------------------------------------------------------------------- -KeyA 1 KEY_A 0x04 - 0x1e XK_A,XK_a -KeyB 2 KEY_B 0x05 - 0x30 XK_B,XK_b -KeyC 3 KEY_C 0x06 - 0x2e XK_C,XK_c -KeyD 4 KEY_D 0x07 - 0x20 XK_D,XK_d -KeyE 5 KEY_E 0x08 - 0x12 XK_E,XK_e -KeyF 6 KEY_F 0x09 - 0x21 XK_F,XK_f -KeyG 7 KEY_G 0x0a - 0x22 XK_G,XK_g -KeyH 8 KEY_H 0x0b - 0x23 XK_H,XK_h -KeyI 9 KEY_I 0x0c - 0x17 XK_I,XK_i -KeyJ 10 KEY_J 0x0d - 0x24 XK_J,XK_j -KeyK 11 KEY_K 0x0e - 0x25 XK_K,XK_k -KeyL 12 KEY_L 0x0f - 0x26 XK_L,XK_l -KeyM 13 KEY_M 0x10 - 0x32 XK_M,XK_m -KeyN 14 KEY_N 0x11 - 0x31 XK_N,XK_n -KeyO 15 KEY_O 0x12 - 0x18 XK_O,XK_o -KeyP 16 KEY_P 0x13 - 0x19 XK_P,XK_p -KeyQ 17 KEY_Q 0x14 - 0x10 XK_Q,XK_q -KeyR 18 KEY_R 0x15 - 0x13 XK_R,XK_r -KeyS 19 KEY_S 0x16 - 0x1f XK_S,XK_s -KeyT 20 KEY_T 0x17 - 0x14 XK_T,XK_t -KeyU 21 KEY_U 0x18 - 0x16 XK_U,XK_u -KeyV 22 KEY_V 0x19 - 0x2f XK_V,XK_v -KeyW 23 KEY_W 0x1a - 0x11 XK_W,XK_w -KeyX 24 KEY_X 0x1b - 0x2d XK_X,XK_x -KeyY 25 KEY_Y 0x1c - 0x15 XK_Y,XK_y -KeyZ 26 KEY_Z 0x1d - 0x2c XK_Z,XK_z -Digit1 27 KEY_1 0x1e - 0x02 XK_1,XK_exclam -Digit2 28 KEY_2 0x1f - 0x03 XK_2,XK_at -Digit3 29 KEY_3 0x20 - 0x04 XK_3,XK_numbersign -Digit4 30 KEY_4 0x21 - 0x05 XK_4,XK_dollar -Digit5 31 KEY_5 0x22 - 0x06 XK_5,XK_percent -Digit6 32 KEY_6 0x23 - 0x07 XK_6,XK_asciicircum -Digit7 33 KEY_7 0x24 - 0x08 XK_7,XK_ampersand -Digit8 34 KEY_8 0x25 - 0x09 XK_8,XK_asterisk -Digit9 35 KEY_9 0x26 - 0x0a XK_9,XK_parenleft -Digit0 36 KEY_0 0x27 - 0x0b XK_0,XK_parenright -Enter 37 KEY_ENTER 0x28 - 0x1c XK_Return -Escape 38 KEY_ESC 0x29 - 0x01 XK_Escape -Backspace 39 KEY_BACKSPACE 0x2a - 0x0e XK_BackSpace -Tab 40 KEY_TAB 0x2b - 0x0f XK_Tab -Space 41 KEY_SPACE 0x2c - 0x39 XK_space -Minus 42 KEY_MINUS 0x2d - 0x0c XK_minus,XK_underscore -Equal 43 KEY_EQUAL 0x2e - 0x0d XK_equal,XK_plus -BracketLeft 44 KEY_LEFT_BRACE 0x2f - 0x1a XK_bracketleft,XK_braceleft -BracketRight 45 KEY_RIGHT_BRACE 0x30 - 0x1b XK_bracketright,XK_braceright -Backslash 46 KEY_BACKSLASH 0x31 - 0x2b XK_backslash,XK_bar -Semicolon 47 KEY_SEMICOLON 0x33 - 0x27 XK_semicolon,XK_colon -Quote 48 KEY_QUOTE 0x34 - 0x28 XK_apostrophe,XK_quotedbl -Backquote 49 KEY_TILDE 0x35 - 0x29 XK_grave,XK_asciitilde -Comma 50 KEY_COMMA 0x36 - 0x33 XK_comma,XK_less -Period 51 KEY_PERIOD 0x37 - 0x34 XK_period,XK_greater -Slash 52 KEY_SLASH 0x38 - 0x35 XK_slash,XK_question -CapsLock 53 KEY_CAPS_LOCK 0x39 - 0x3a XK_Caps_Lock -F1 54 KEY_F1 0x3a - 0x3b XK_F1 -F2 55 KEY_F2 0x3b - 0x3c XK_F2 -F3 56 KEY_F3 0x3c - 0x3d XK_F3 -F4 57 KEY_F4 0x3d - 0x3e XK_F4 -F5 58 KEY_F5 0x3e - 0x3f XK_F5 -F6 59 KEY_F6 0x3f - 0x40 XK_F6 -F7 60 KEY_F7 0x40 - 0x41 XK_F7 -F8 61 KEY_F8 0x41 - 0x42 XK_F8 -F9 62 KEY_F9 0x42 - 0x43 XK_F9 -F10 63 KEY_F10 0x43 - 0x44 XK_F10 -F11 64 KEY_F11 0x44 - 0x57 XK_F11 -F12 65 KEY_F12 0x45 - 0x58 XK_F12 -PrintScreen 66 KEY_PRINT 0x46 - 0x54 XK_Sys_Req -Insert 67 KEY_INSERT 0x49 - 0xe052 XK_Insert -Home 68 KEY_HOME 0x4a - 0xe047 XK_Home -PageUp 69 KEY_PAGE_UP 0x4b - 0xe049 XK_Page_Up -Delete 70 KEY_DELETE 0x4c - 0xe053 XK_Delete -End 71 KEY_END 0x4d - 0xe04f XK_End -PageDown 72 KEY_PAGE_DOWN 0x4e - 0xe051 XK_Page_Down -ArrowRight 73 KEY_RIGHT_ARROW 0x4f - 0xe04d XK_Right -ArrowLeft 74 KEY_LEFT_ARROW 0x50 - 0xe04b XK_Left -ArrowDown 75 KEY_DOWN_ARROW 0x51 - 0xe050 XK_Down -ArrowUp 76 KEY_UP_ARROW 0x52 - 0xe048 XK_Up -ControlLeft 77 KEY_LEFT_CTRL 0x01 m 0x1d XK_Control_L -ShiftLeft 78 KEY_LEFT_SHIFT 0x02 m 0x2a XK_Shift_L -AltLeft 79 KEY_LEFT_ALT 0x04 m 0x38 XK_Alt_L -MetaLeft 80 KEY_LEFT_GUI 0x08 m 0xe05b XK_Meta_L -ControlRight 81 KEY_RIGHT_CTRL 0x10 m 0xe01d XK_Control_R -ShiftRight 82 KEY_RIGHT_SHIFT 0x20 m 0x36 XK_Shift_R -AltRight 83 KEY_RIGHT_ALT 0x40 m 0xe038 XK_Alt_R -MetaRight 84 KEY_RIGHT_GUI 0x80 m 0xe05c XK_Meta_R -Pause 85 KEY_PAUSE 0x48 - 0xe046 XK_Pause -ScrollLock 86 KEY_SCROLL_LOCK 0x47 - 0x46 XK_Scroll_Lock -NumLock 87 KEY_NUM_LOCK 0x53 - 0x45 XK_Num_Lock -ContextMenu 88 KEY_MENU 0x65 - 0xe05d XK_Menu +# ----------------------------------------------------------------------------------------------------------------------- +# Web | Serial code | Arduino key | OTG code (^ for mod) | AT set1 | X11 keysyms (^ for shift) +# ----------------------------------------------------------------------------------------------------------------------- +KeyA 1 KEY_A 0x04 0x1e ^XK_A,XK_a +KeyB 2 KEY_B 0x05 0x30 ^XK_B,XK_b +KeyC 3 KEY_C 0x06 0x2e ^XK_C,XK_c +KeyD 4 KEY_D 0x07 0x20 ^XK_D,XK_d +KeyE 5 KEY_E 0x08 0x12 ^XK_E,XK_e +KeyF 6 KEY_F 0x09 0x21 ^XK_F,XK_f +KeyG 7 KEY_G 0x0a 0x22 ^XK_G,XK_g +KeyH 8 KEY_H 0x0b 0x23 ^XK_H,XK_h +KeyI 9 KEY_I 0x0c 0x17 ^XK_I,XK_i +KeyJ 10 KEY_J 0x0d 0x24 ^XK_J,XK_j +KeyK 11 KEY_K 0x0e 0x25 ^XK_K,XK_k +KeyL 12 KEY_L 0x0f 0x26 ^XK_L,XK_l +KeyM 13 KEY_M 0x10 0x32 ^XK_M,XK_m +KeyN 14 KEY_N 0x11 0x31 ^XK_N,XK_n +KeyO 15 KEY_O 0x12 0x18 ^XK_O,XK_o +KeyP 16 KEY_P 0x13 0x19 ^XK_P,XK_p +KeyQ 17 KEY_Q 0x14 0x10 ^XK_Q,XK_q +KeyR 18 KEY_R 0x15 0x13 ^XK_R,XK_r +KeyS 19 KEY_S 0x16 0x1f ^XK_S,XK_s +KeyT 20 KEY_T 0x17 0x14 ^XK_T,XK_t +KeyU 21 KEY_U 0x18 0x16 ^XK_U,XK_u +KeyV 22 KEY_V 0x19 0x2f ^XK_V,XK_v +KeyW 23 KEY_W 0x1a 0x11 ^XK_W,XK_w +KeyX 24 KEY_X 0x1b 0x2d ^XK_X,XK_x +KeyY 25 KEY_Y 0x1c 0x15 ^XK_Y,XK_y +KeyZ 26 KEY_Z 0x1d 0x2c ^XK_Z,XK_z +Digit1 27 KEY_1 0x1e 0x02 XK_1,^XK_exclam +Digit2 28 KEY_2 0x1f 0x03 XK_2,^XK_at +Digit3 29 KEY_3 0x20 0x04 XK_3,^XK_numbersign +Digit4 30 KEY_4 0x21 0x05 XK_4,^XK_dollar +Digit5 31 KEY_5 0x22 0x06 XK_5,^XK_percent +Digit6 32 KEY_6 0x23 0x07 XK_6,^XK_asciicircum +Digit7 33 KEY_7 0x24 0x08 XK_7,^XK_ampersand +Digit8 34 KEY_8 0x25 0x09 XK_8,^XK_asterisk +Digit9 35 KEY_9 0x26 0x0a XK_9,^XK_parenleft +Digit0 36 KEY_0 0x27 0x0b XK_0,^XK_parenright +Enter 37 KEY_ENTER 0x28 0x1c XK_Return +Escape 38 KEY_ESC 0x29 0x01 XK_Escape +Backspace 39 KEY_BACKSPACE 0x2a 0x0e XK_BackSpace +Tab 40 KEY_TAB 0x2b 0x0f XK_Tab +Space 41 KEY_SPACE 0x2c 0x39 XK_space +Minus 42 KEY_MINUS 0x2d 0x0c XK_minus,^XK_underscore +Equal 43 KEY_EQUAL 0x2e 0x0d XK_equal,^XK_plus +BracketLeft 44 KEY_LEFT_BRACE 0x2f 0x1a XK_bracketleft,^XK_braceleft +BracketRight 45 KEY_RIGHT_BRACE 0x30 0x1b XK_bracketright,^XK_braceright +Backslash 46 KEY_BACKSLASH 0x31 0x2b XK_backslash,^XK_bar +Semicolon 47 KEY_SEMICOLON 0x33 0x27 XK_semicolon,^XK_colon +Quote 48 KEY_QUOTE 0x34 0x28 XK_apostrophe,^XK_quotedbl +Backquote 49 KEY_TILDE 0x35 0x29 XK_grave,^XK_asciitilde +Comma 50 KEY_COMMA 0x36 0x33 XK_comma,^XK_less +Period 51 KEY_PERIOD 0x37 0x34 XK_period,^XK_greater +Slash 52 KEY_SLASH 0x38 0x35 XK_slash,^XK_question +CapsLock 53 KEY_CAPS_LOCK 0x39 0x3a XK_Caps_Lock +F1 54 KEY_F1 0x3a 0x3b XK_F1 +F2 55 KEY_F2 0x3b 0x3c XK_F2 +F3 56 KEY_F3 0x3c 0x3d XK_F3 +F4 57 KEY_F4 0x3d 0x3e XK_F4 +F5 58 KEY_F5 0x3e 0x3f XK_F5 +F6 59 KEY_F6 0x3f 0x40 XK_F6 +F7 60 KEY_F7 0x40 0x41 XK_F7 +F8 61 KEY_F8 0x41 0x42 XK_F8 +F9 62 KEY_F9 0x42 0x43 XK_F9 +F10 63 KEY_F10 0x43 0x44 XK_F10 +F11 64 KEY_F11 0x44 0x57 XK_F11 +F12 65 KEY_F12 0x45 0x58 XK_F12 +PrintScreen 66 KEY_PRINT 0x46 0x54 XK_Sys_Req +Insert 67 KEY_INSERT 0x49 0xe052 XK_Insert +Home 68 KEY_HOME 0x4a 0xe047 XK_Home +PageUp 69 KEY_PAGE_UP 0x4b 0xe049 XK_Page_Up +Delete 70 KEY_DELETE 0x4c 0xe053 XK_Delete +End 71 KEY_END 0x4d 0xe04f XK_End +PageDown 72 KEY_PAGE_DOWN 0x4e 0xe051 XK_Page_Down +ArrowRight 73 KEY_RIGHT_ARROW 0x4f 0xe04d XK_Right +ArrowLeft 74 KEY_LEFT_ARROW 0x50 0xe04b XK_Left +ArrowDown 75 KEY_DOWN_ARROW 0x51 0xe050 XK_Down +ArrowUp 76 KEY_UP_ARROW 0x52 0xe048 XK_Up +ControlLeft 77 KEY_LEFT_CTRL ^0x01 0x1d XK_Control_L +ShiftLeft 78 KEY_LEFT_SHIFT ^0x02 0x2a XK_Shift_L +AltLeft 79 KEY_LEFT_ALT ^0x04 0x38 XK_Alt_L +MetaLeft 80 KEY_LEFT_GUI ^0x08 0xe05b XK_Meta_L +ControlRight 81 KEY_RIGHT_CTRL ^0x10 0xe01d XK_Control_R +ShiftRight 82 KEY_RIGHT_SHIFT ^0x20 0x36 XK_Shift_R +AltRight 83 KEY_RIGHT_ALT ^0x40 0xe038 XK_Alt_R +MetaRight 84 KEY_RIGHT_GUI ^0x80 0xe05c XK_Meta_R +Pause 85 KEY_PAUSE 0x48 0xe046 XK_Pause +ScrollLock 86 KEY_SCROLL_LOCK 0x47 0x46 XK_Scroll_Lock +NumLock 87 KEY_NUM_LOCK 0x53 0x45 XK_Num_Lock +ContextMenu 88 KEY_MENU 0x65 0xe05d XK_Menu # KEY_NON_US_NUM # KEYPAD_DIVIDE # KEYPAD_MULTIPLY diff --git a/kvmd/apps/kvmd/api/hid.py b/kvmd/apps/kvmd/api/hid.py index 5283751a..8bdaac59 100644 --- a/kvmd/apps/kvmd/api/hid.py +++ b/kvmd/apps/kvmd/api/hid.py @@ -38,7 +38,7 @@ from ....validators.kvm import valid_hid_mouse_move from ....validators.kvm import valid_hid_mouse_button from ....validators.kvm import valid_hid_mouse_wheel -from .... import keyprint +from ....keyboard.printer import text_to_web_keys from ..http import exposed_http from ..http import exposed_ws @@ -70,7 +70,7 @@ class HidApi: if limit > 0: text = text[:limit] async with self.__key_lock: - for (key, state) in keyprint.text_to_keys(text): + for (key, state) in text_to_web_keys(text): self.__hid.send_key_event(key, state) return make_json_response() diff --git a/kvmd/apps/vnc/__init__.py b/kvmd/apps/vnc/__init__.py index ef0f0c03..92fb073b 100644 --- a/kvmd/apps/vnc/__init__.py +++ b/kvmd/apps/vnc/__init__.py @@ -23,6 +23,8 @@ from typing import List from typing import Optional +from ...keyboard.keysym import build_symmap + from ...clients.kvmd import KvmdClient from ...clients.streamer import StreamerClient @@ -32,7 +34,6 @@ from .. import init from .vncauth import VncAuthManager from .server import VncServer -from .keysym import build_symmap # ===== diff --git a/kvmd/keyboard/__init__.py b/kvmd/keyboard/__init__.py new file mode 100644 index 00000000..1e91f7fa --- /dev/null +++ b/kvmd/keyboard/__init__.py @@ -0,0 +1,20 @@ +# ========================================================================== # +# # +# KVMD - The main Pi-KVM daemon. # +# # +# Copyright (C) 2018 Maxim Devaev <[email protected]> # +# # +# 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 3 of the License, or # +# (at your option) 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, see <https://www.gnu.org/licenses/>. # +# # +# ========================================================================== # diff --git a/kvmd/apps/vnc/keysym.py b/kvmd/keyboard/keysym.py index 275eee5e..fbfeb913 100644 --- a/kvmd/apps/vnc/keysym.py +++ b/kvmd/keyboard/keysym.py @@ -27,9 +27,10 @@ from typing import Dict import Xlib.keysymdef -from ...logging import get_logger +from ..logging import get_logger -from ... import keymap +from .mappings import X11_TO_AT1 +from .mappings import AT1_TO_WEB # ===== @@ -37,11 +38,11 @@ def build_symmap(path: str) -> Dict[int, str]: # https://github.com/qemu/qemu/blob/95a9457fd44ad97c518858a4e1586a5498f9773c/ui/keymaps.c symmap: Dict[int, str] = {} - for (x11_code, at1_code) in keymap.X11_TO_AT1.items(): - symmap[x11_code] = keymap.AT1_TO_WEB[at1_code] + for (x11_code, at1_key) in X11_TO_AT1.items(): + symmap[x11_code] = AT1_TO_WEB[at1_key.code] for (x11_code, at1_code) in _read_keyboard_layout(path).items(): - if (web_name := keymap.AT1_TO_WEB.get(at1_code)) is not None: + if (web_name := AT1_TO_WEB.get(at1_code)) is not None: # mypy bug symmap[x11_code] = web_name # type: ignore return symmap diff --git a/kvmd/keyboard/mappings.py b/kvmd/keyboard/mappings.py new file mode 100644 index 00000000..6c67dd08 --- /dev/null +++ b/kvmd/keyboard/mappings.py @@ -0,0 +1,373 @@ +# ========================================================================== # +# # +# KVMD - The main Pi-KVM daemon. # +# # +# Copyright (C) 2018 Maxim Devaev <[email protected]> # +# # +# 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 3 of the License, or # +# (at your option) 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, see <https://www.gnu.org/licenses/>. # +# # +# ========================================================================== # + + +import dataclasses + +from typing import Dict + + +# ===== [email protected](frozen=True) +class SerialKey: + code: int + + [email protected](frozen=True) +class OtgKey: + code: int + is_modifier: bool + + [email protected](frozen=True) +class Key: + serial: SerialKey + otg: OtgKey + + +KEYMAP: Dict[str, Key] = { + "KeyA": Key(serial=SerialKey(code=1), otg=OtgKey(code=4, is_modifier=False)), + "KeyB": Key(serial=SerialKey(code=2), otg=OtgKey(code=5, is_modifier=False)), + "KeyC": Key(serial=SerialKey(code=3), otg=OtgKey(code=6, is_modifier=False)), + "KeyD": Key(serial=SerialKey(code=4), otg=OtgKey(code=7, is_modifier=False)), + "KeyE": Key(serial=SerialKey(code=5), otg=OtgKey(code=8, is_modifier=False)), + "KeyF": Key(serial=SerialKey(code=6), otg=OtgKey(code=9, is_modifier=False)), + "KeyG": Key(serial=SerialKey(code=7), otg=OtgKey(code=10, is_modifier=False)), + "KeyH": Key(serial=SerialKey(code=8), otg=OtgKey(code=11, is_modifier=False)), + "KeyI": Key(serial=SerialKey(code=9), otg=OtgKey(code=12, is_modifier=False)), + "KeyJ": Key(serial=SerialKey(code=10), otg=OtgKey(code=13, is_modifier=False)), + "KeyK": Key(serial=SerialKey(code=11), otg=OtgKey(code=14, is_modifier=False)), + "KeyL": Key(serial=SerialKey(code=12), otg=OtgKey(code=15, is_modifier=False)), + "KeyM": Key(serial=SerialKey(code=13), otg=OtgKey(code=16, is_modifier=False)), + "KeyN": Key(serial=SerialKey(code=14), otg=OtgKey(code=17, is_modifier=False)), + "KeyO": Key(serial=SerialKey(code=15), otg=OtgKey(code=18, is_modifier=False)), + "KeyP": Key(serial=SerialKey(code=16), otg=OtgKey(code=19, is_modifier=False)), + "KeyQ": Key(serial=SerialKey(code=17), otg=OtgKey(code=20, is_modifier=False)), + "KeyR": Key(serial=SerialKey(code=18), otg=OtgKey(code=21, is_modifier=False)), + "KeyS": Key(serial=SerialKey(code=19), otg=OtgKey(code=22, is_modifier=False)), + "KeyT": Key(serial=SerialKey(code=20), otg=OtgKey(code=23, is_modifier=False)), + "KeyU": Key(serial=SerialKey(code=21), otg=OtgKey(code=24, is_modifier=False)), + "KeyV": Key(serial=SerialKey(code=22), otg=OtgKey(code=25, is_modifier=False)), + "KeyW": Key(serial=SerialKey(code=23), otg=OtgKey(code=26, is_modifier=False)), + "KeyX": Key(serial=SerialKey(code=24), otg=OtgKey(code=27, is_modifier=False)), + "KeyY": Key(serial=SerialKey(code=25), otg=OtgKey(code=28, is_modifier=False)), + "KeyZ": Key(serial=SerialKey(code=26), otg=OtgKey(code=29, is_modifier=False)), + "Digit1": Key(serial=SerialKey(code=27), otg=OtgKey(code=30, is_modifier=False)), + "Digit2": Key(serial=SerialKey(code=28), otg=OtgKey(code=31, is_modifier=False)), + "Digit3": Key(serial=SerialKey(code=29), otg=OtgKey(code=32, is_modifier=False)), + "Digit4": Key(serial=SerialKey(code=30), otg=OtgKey(code=33, is_modifier=False)), + "Digit5": Key(serial=SerialKey(code=31), otg=OtgKey(code=34, is_modifier=False)), + "Digit6": Key(serial=SerialKey(code=32), otg=OtgKey(code=35, is_modifier=False)), + "Digit7": Key(serial=SerialKey(code=33), otg=OtgKey(code=36, is_modifier=False)), + "Digit8": Key(serial=SerialKey(code=34), otg=OtgKey(code=37, is_modifier=False)), + "Digit9": Key(serial=SerialKey(code=35), otg=OtgKey(code=38, is_modifier=False)), + "Digit0": Key(serial=SerialKey(code=36), otg=OtgKey(code=39, is_modifier=False)), + "Enter": Key(serial=SerialKey(code=37), otg=OtgKey(code=40, is_modifier=False)), + "Escape": Key(serial=SerialKey(code=38), otg=OtgKey(code=41, is_modifier=False)), + "Backspace": Key(serial=SerialKey(code=39), otg=OtgKey(code=42, is_modifier=False)), + "Tab": Key(serial=SerialKey(code=40), otg=OtgKey(code=43, is_modifier=False)), + "Space": Key(serial=SerialKey(code=41), otg=OtgKey(code=44, is_modifier=False)), + "Minus": Key(serial=SerialKey(code=42), otg=OtgKey(code=45, is_modifier=False)), + "Equal": Key(serial=SerialKey(code=43), otg=OtgKey(code=46, is_modifier=False)), + "BracketLeft": Key(serial=SerialKey(code=44), otg=OtgKey(code=47, is_modifier=False)), + "BracketRight": Key(serial=SerialKey(code=45), otg=OtgKey(code=48, is_modifier=False)), + "Backslash": Key(serial=SerialKey(code=46), otg=OtgKey(code=49, is_modifier=False)), + "Semicolon": Key(serial=SerialKey(code=47), otg=OtgKey(code=51, is_modifier=False)), + "Quote": Key(serial=SerialKey(code=48), otg=OtgKey(code=52, is_modifier=False)), + "Backquote": Key(serial=SerialKey(code=49), otg=OtgKey(code=53, is_modifier=False)), + "Comma": Key(serial=SerialKey(code=50), otg=OtgKey(code=54, is_modifier=False)), + "Period": Key(serial=SerialKey(code=51), otg=OtgKey(code=55, is_modifier=False)), + "Slash": Key(serial=SerialKey(code=52), otg=OtgKey(code=56, is_modifier=False)), + "CapsLock": Key(serial=SerialKey(code=53), otg=OtgKey(code=57, is_modifier=False)), + "F1": Key(serial=SerialKey(code=54), otg=OtgKey(code=58, is_modifier=False)), + "F2": Key(serial=SerialKey(code=55), otg=OtgKey(code=59, is_modifier=False)), + "F3": Key(serial=SerialKey(code=56), otg=OtgKey(code=60, is_modifier=False)), + "F4": Key(serial=SerialKey(code=57), otg=OtgKey(code=61, is_modifier=False)), + "F5": Key(serial=SerialKey(code=58), otg=OtgKey(code=62, is_modifier=False)), + "F6": Key(serial=SerialKey(code=59), otg=OtgKey(code=63, is_modifier=False)), + "F7": Key(serial=SerialKey(code=60), otg=OtgKey(code=64, is_modifier=False)), + "F8": Key(serial=SerialKey(code=61), otg=OtgKey(code=65, is_modifier=False)), + "F9": Key(serial=SerialKey(code=62), otg=OtgKey(code=66, is_modifier=False)), + "F10": Key(serial=SerialKey(code=63), otg=OtgKey(code=67, is_modifier=False)), + "F11": Key(serial=SerialKey(code=64), otg=OtgKey(code=68, is_modifier=False)), + "F12": Key(serial=SerialKey(code=65), otg=OtgKey(code=69, is_modifier=False)), + "PrintScreen": Key(serial=SerialKey(code=66), otg=OtgKey(code=70, is_modifier=False)), + "Insert": Key(serial=SerialKey(code=67), otg=OtgKey(code=73, is_modifier=False)), + "Home": Key(serial=SerialKey(code=68), otg=OtgKey(code=74, is_modifier=False)), + "PageUp": Key(serial=SerialKey(code=69), otg=OtgKey(code=75, is_modifier=False)), + "Delete": Key(serial=SerialKey(code=70), otg=OtgKey(code=76, is_modifier=False)), + "End": Key(serial=SerialKey(code=71), otg=OtgKey(code=77, is_modifier=False)), + "PageDown": Key(serial=SerialKey(code=72), otg=OtgKey(code=78, is_modifier=False)), + "ArrowRight": Key(serial=SerialKey(code=73), otg=OtgKey(code=79, is_modifier=False)), + "ArrowLeft": Key(serial=SerialKey(code=74), otg=OtgKey(code=80, is_modifier=False)), + "ArrowDown": Key(serial=SerialKey(code=75), otg=OtgKey(code=81, is_modifier=False)), + "ArrowUp": Key(serial=SerialKey(code=76), otg=OtgKey(code=82, is_modifier=False)), + "ControlLeft": Key(serial=SerialKey(code=77), otg=OtgKey(code=1, is_modifier=True)), + "ShiftLeft": Key(serial=SerialKey(code=78), otg=OtgKey(code=2, is_modifier=True)), + "AltLeft": Key(serial=SerialKey(code=79), otg=OtgKey(code=4, is_modifier=True)), + "MetaLeft": Key(serial=SerialKey(code=80), otg=OtgKey(code=8, is_modifier=True)), + "ControlRight": Key(serial=SerialKey(code=81), otg=OtgKey(code=16, is_modifier=True)), + "ShiftRight": Key(serial=SerialKey(code=82), otg=OtgKey(code=32, is_modifier=True)), + "AltRight": Key(serial=SerialKey(code=83), otg=OtgKey(code=64, is_modifier=True)), + "MetaRight": Key(serial=SerialKey(code=84), otg=OtgKey(code=128, is_modifier=True)), + "Pause": Key(serial=SerialKey(code=85), otg=OtgKey(code=72, is_modifier=False)), + "ScrollLock": Key(serial=SerialKey(code=86), otg=OtgKey(code=71, is_modifier=False)), + "NumLock": Key(serial=SerialKey(code=87), otg=OtgKey(code=83, is_modifier=False)), + "ContextMenu": Key(serial=SerialKey(code=88), otg=OtgKey(code=101, is_modifier=False)), +} + + +# ===== [email protected](frozen=True) +class At1Key: + code: int + shift: bool + + +X11_TO_AT1 = { + 65307: At1Key(code=1, shift=False), # XK_Escape + 33: At1Key(code=2, shift=True), # XK_exclam + 49: At1Key(code=2, shift=False), # XK_1 + 50: At1Key(code=3, shift=False), # XK_2 + 64: At1Key(code=3, shift=True), # XK_at + 35: At1Key(code=4, shift=True), # XK_numbersign + 51: At1Key(code=4, shift=False), # XK_3 + 36: At1Key(code=5, shift=True), # XK_dollar + 52: At1Key(code=5, shift=False), # XK_4 + 37: At1Key(code=6, shift=True), # XK_percent + 53: At1Key(code=6, shift=False), # XK_5 + 54: At1Key(code=7, shift=False), # XK_6 + 94: At1Key(code=7, shift=True), # XK_asciicircum + 38: At1Key(code=8, shift=True), # XK_ampersand + 55: At1Key(code=8, shift=False), # XK_7 + 42: At1Key(code=9, shift=True), # XK_asterisk + 56: At1Key(code=9, shift=False), # XK_8 + 40: At1Key(code=10, shift=True), # XK_parenleft + 57: At1Key(code=10, shift=False), # XK_9 + 41: At1Key(code=11, shift=True), # XK_parenright + 48: At1Key(code=11, shift=False), # XK_0 + 45: At1Key(code=12, shift=False), # XK_minus + 95: At1Key(code=12, shift=True), # XK_underscore + 43: At1Key(code=13, shift=True), # XK_plus + 61: At1Key(code=13, shift=False), # XK_equal + 65288: At1Key(code=14, shift=False), # XK_BackSpace + 65289: At1Key(code=15, shift=False), # XK_Tab + 81: At1Key(code=16, shift=True), # XK_Q + 113: At1Key(code=16, shift=False), # XK_q + 87: At1Key(code=17, shift=True), # XK_W + 119: At1Key(code=17, shift=False), # XK_w + 69: At1Key(code=18, shift=True), # XK_E + 101: At1Key(code=18, shift=False), # XK_e + 82: At1Key(code=19, shift=True), # XK_R + 114: At1Key(code=19, shift=False), # XK_r + 84: At1Key(code=20, shift=True), # XK_T + 116: At1Key(code=20, shift=False), # XK_t + 89: At1Key(code=21, shift=True), # XK_Y + 121: At1Key(code=21, shift=False), # XK_y + 85: At1Key(code=22, shift=True), # XK_U + 117: At1Key(code=22, shift=False), # XK_u + 73: At1Key(code=23, shift=True), # XK_I + 105: At1Key(code=23, shift=False), # XK_i + 79: At1Key(code=24, shift=True), # XK_O + 111: At1Key(code=24, shift=False), # XK_o + 80: At1Key(code=25, shift=True), # XK_P + 112: At1Key(code=25, shift=False), # XK_p + 91: At1Key(code=26, shift=False), # XK_bracketleft + 123: At1Key(code=26, shift=True), # XK_braceleft + 93: At1Key(code=27, shift=False), # XK_bracketright + 125: At1Key(code=27, shift=True), # XK_braceright + 65293: At1Key(code=28, shift=False), # XK_Return + 65507: At1Key(code=29, shift=False), # XK_Control_L + 65: At1Key(code=30, shift=True), # XK_A + 97: At1Key(code=30, shift=False), # XK_a + 83: At1Key(code=31, shift=True), # XK_S + 115: At1Key(code=31, shift=False), # XK_s + 68: At1Key(code=32, shift=True), # XK_D + 100: At1Key(code=32, shift=False), # XK_d + 70: At1Key(code=33, shift=True), # XK_F + 102: At1Key(code=33, shift=False), # XK_f + 71: At1Key(code=34, shift=True), # XK_G + 103: At1Key(code=34, shift=False), # XK_g + 72: At1Key(code=35, shift=True), # XK_H + 104: At1Key(code=35, shift=False), # XK_h + 74: At1Key(code=36, shift=True), # XK_J + 106: At1Key(code=36, shift=False), # XK_j + 75: At1Key(code=37, shift=True), # XK_K + 107: At1Key(code=37, shift=False), # XK_k + 76: At1Key(code=38, shift=True), # XK_L + 108: At1Key(code=38, shift=False), # XK_l + 58: At1Key(code=39, shift=True), # XK_colon + 59: At1Key(code=39, shift=False), # XK_semicolon + 34: At1Key(code=40, shift=True), # XK_quotedbl + 39: At1Key(code=40, shift=False), # XK_apostrophe + 96: At1Key(code=41, shift=False), # XK_grave + 126: At1Key(code=41, shift=True), # XK_asciitilde + 65505: At1Key(code=42, shift=False), # XK_Shift_L + 92: At1Key(code=43, shift=False), # XK_backslash + 124: At1Key(code=43, shift=True), # XK_bar + 90: At1Key(code=44, shift=True), # XK_Z + 122: At1Key(code=44, shift=False), # XK_z + 88: At1Key(code=45, shift=True), # XK_X + 120: At1Key(code=45, shift=False), # XK_x + 67: At1Key(code=46, shift=True), # XK_C + 99: At1Key(code=46, shift=False), # XK_c + 86: At1Key(code=47, shift=True), # XK_V + 118: At1Key(code=47, shift=False), # XK_v + 66: At1Key(code=48, shift=True), # XK_B + 98: At1Key(code=48, shift=False), # XK_b + 78: At1Key(code=49, shift=True), # XK_N + 110: At1Key(code=49, shift=False), # XK_n + 77: At1Key(code=50, shift=True), # XK_M + 109: At1Key(code=50, shift=False), # XK_m + 44: At1Key(code=51, shift=False), # XK_comma + 60: At1Key(code=51, shift=True), # XK_less + 46: At1Key(code=52, shift=False), # XK_period + 62: At1Key(code=52, shift=True), # XK_greater + 47: At1Key(code=53, shift=False), # XK_slash + 63: At1Key(code=53, shift=True), # XK_question + 65506: At1Key(code=54, shift=False), # XK_Shift_R + 65513: At1Key(code=56, shift=False), # XK_Alt_L + 32: At1Key(code=57, shift=False), # XK_space + 65509: At1Key(code=58, shift=False), # XK_Caps_Lock + 65470: At1Key(code=59, shift=False), # XK_F1 + 65471: At1Key(code=60, shift=False), # XK_F2 + 65472: At1Key(code=61, shift=False), # XK_F3 + 65473: At1Key(code=62, shift=False), # XK_F4 + 65474: At1Key(code=63, shift=False), # XK_F5 + 65475: At1Key(code=64, shift=False), # XK_F6 + 65476: At1Key(code=65, shift=False), # XK_F7 + 65477: At1Key(code=66, shift=False), # XK_F8 + 65478: At1Key(code=67, shift=False), # XK_F9 + 65479: At1Key(code=68, shift=False), # XK_F10 + 65407: At1Key(code=69, shift=False), # XK_Num_Lock + 65300: At1Key(code=70, shift=False), # XK_Scroll_Lock + 65301: At1Key(code=84, shift=False), # XK_Sys_Req + 65480: At1Key(code=87, shift=False), # XK_F11 + 65481: At1Key(code=88, shift=False), # XK_F12 + 65508: At1Key(code=57373, shift=False), # XK_Control_R + 65514: At1Key(code=57400, shift=False), # XK_Alt_R + 65299: At1Key(code=57414, shift=False), # XK_Pause + 65360: At1Key(code=57415, shift=False), # XK_Home + 65362: At1Key(code=57416, shift=False), # XK_Up + 65365: At1Key(code=57417, shift=False), # XK_Page_Up + 65361: At1Key(code=57419, shift=False), # XK_Left + 65363: At1Key(code=57421, shift=False), # XK_Right + 65367: At1Key(code=57423, shift=False), # XK_End + 65364: At1Key(code=57424, shift=False), # XK_Down + 65366: At1Key(code=57425, shift=False), # XK_Page_Down + 65379: At1Key(code=57426, shift=False), # XK_Insert + 65535: At1Key(code=57427, shift=False), # XK_Delete + 65511: At1Key(code=57435, shift=False), # XK_Meta_L + 65512: At1Key(code=57436, shift=False), # XK_Meta_R + 65383: At1Key(code=57437, shift=False), # XK_Menu +} + + +AT1_TO_WEB = { + 1: "Escape", + 2: "Digit1", + 3: "Digit2", + 4: "Digit3", + 5: "Digit4", + 6: "Digit5", + 7: "Digit6", + 8: "Digit7", + 9: "Digit8", + 10: "Digit9", + 11: "Digit0", + 12: "Minus", + 13: "Equal", + 14: "Backspace", + 15: "Tab", + 16: "KeyQ", + 17: "KeyW", + 18: "KeyE", + 19: "KeyR", + 20: "KeyT", + 21: "KeyY", + 22: "KeyU", + 23: "KeyI", + 24: "KeyO", + 25: "KeyP", + 26: "BracketLeft", + 27: "BracketRight", + 28: "Enter", + 29: "ControlLeft", + 30: "KeyA", + 31: "KeyS", + 32: "KeyD", + 33: "KeyF", + 34: "KeyG", + 35: "KeyH", + 36: "KeyJ", + 37: "KeyK", + 38: "KeyL", + 39: "Semicolon", + 40: "Quote", + 41: "Backquote", + 42: "ShiftLeft", + 43: "Backslash", + 44: "KeyZ", + 45: "KeyX", + 46: "KeyC", + 47: "KeyV", + 48: "KeyB", + 49: "KeyN", + 50: "KeyM", + 51: "Comma", + 52: "Period", + 53: "Slash", + 54: "ShiftRight", + 56: "AltLeft", + 57: "Space", + 58: "CapsLock", + 59: "F1", + 60: "F2", + 61: "F3", + 62: "F4", + 63: "F5", + 64: "F6", + 65: "F7", + 66: "F8", + 67: "F9", + 68: "F10", + 69: "NumLock", + 70: "ScrollLock", + 84: "PrintScreen", + 87: "F11", + 88: "F12", + 57373: "ControlRight", + 57400: "AltRight", + 57414: "Pause", + 57415: "Home", + 57416: "ArrowUp", + 57417: "PageUp", + 57419: "ArrowLeft", + 57421: "ArrowRight", + 57423: "End", + 57424: "ArrowDown", + 57425: "PageDown", + 57426: "Insert", + 57427: "Delete", + 57435: "MetaLeft", + 57436: "MetaRight", + 57437: "ContextMenu", +} diff --git a/kvmd/keymap.py.mako b/kvmd/keyboard/mappings.py.mako index 0f9e7ef0..d2752d2d 100644 --- a/kvmd/keymap.py.mako +++ b/kvmd/keyboard/mappings.py.mako @@ -43,22 +43,24 @@ class Key: otg: OtgKey <%! import operator %> -# ===== KEYMAP: Dict[str, Key] = { % for km in sorted(keymap, key=operator.attrgetter("serial_code")): - "${km.web_name}": Key( - serial=SerialKey(code=${km.serial_code}), - otg=OtgKey(code=${km.otg_code}, is_modifier=${km.otg_is_modifier}), - ), + "${km.web_name}": Key(serial=SerialKey(code=${km.serial_code}), otg=OtgKey(code=${km.otg_key.code}, is_modifier=${km.otg_key.is_modifier})), % endfor } # ===== [email protected](frozen=True) +class At1Key: + code: int + shift: bool + + X11_TO_AT1 = { % for km in sorted(keymap, key=operator.attrgetter("at1_code")): - % for code in sorted(km.x11_codes): - ${code}: ${km.at1_code}, + % for x11_key in sorted(km.x11_keys, key=(lambda key: (key.code, key.shift))): + ${x11_key.code}: At1Key(code=${km.at1_code}, shift=${x11_key.shift}), # ${x11_key.name} % endfor % endfor } diff --git a/kvmd/keyprint.py b/kvmd/keyboard/printer.py index bee7916a..f8086be3 100644 --- a/kvmd/keyprint.py +++ b/kvmd/keyboard/printer.py @@ -25,7 +25,7 @@ import string from typing import Tuple from typing import Generator -from . import keymap +from .mappings import KEYMAP # ===== @@ -47,7 +47,7 @@ _LOWER_CHARS = { **{str(number): f"Digit{number}" for number in range(0, 10)}, **{ch: f"Key{ch.upper()}" for ch in string.ascii_lowercase}, } -assert not set(_LOWER_CHARS.values()).difference(keymap.KEYMAP) +assert not set(_LOWER_CHARS.values()).difference(KEYMAP) _UPPER_CHARS = { "~": "Backquote", @@ -73,11 +73,11 @@ _UPPER_CHARS = { "+": "Equal", **{ch: f"Key{ch}" for ch in string.ascii_uppercase}, } -assert not set(_UPPER_CHARS.values()).difference(keymap.KEYMAP) +assert not set(_UPPER_CHARS.values()).difference(KEYMAP) # ===== -def text_to_keys(text: str, shift_key: str="ShiftLeft") -> Generator[Tuple[str, bool], None, None]: +def text_to_web_keys(text: str, shift_key: str="ShiftLeft") -> Generator[Tuple[str, bool], None, None]: assert shift_key in ["ShiftLeft", "ShiftRight"] shifted = False diff --git a/kvmd/keymap.py b/kvmd/keymap.py deleted file mode 100644 index 6e466f2f..00000000 --- a/kvmd/keymap.py +++ /dev/null @@ -1,632 +0,0 @@ -# ========================================================================== # -# # -# KVMD - The main Pi-KVM daemon. # -# # -# Copyright (C) 2018 Maxim Devaev <[email protected]> # -# # -# 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 3 of the License, or # -# (at your option) 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, see <https://www.gnu.org/licenses/>. # -# # -# ========================================================================== # - - -import dataclasses - -from typing import Dict - - -# ===== [email protected](frozen=True) -class SerialKey: - code: int - - [email protected](frozen=True) -class OtgKey: - code: int - is_modifier: bool - - [email protected](frozen=True) -class Key: - serial: SerialKey - otg: OtgKey - - -# ===== -KEYMAP: Dict[str, Key] = { - "KeyA": Key( - serial=SerialKey(code=1), - otg=OtgKey(code=4, is_modifier=False), - ), - "KeyB": Key( - serial=SerialKey(code=2), - otg=OtgKey(code=5, is_modifier=False), - ), - "KeyC": Key( - serial=SerialKey(code=3), - otg=OtgKey(code=6, is_modifier=False), - ), - "KeyD": Key( - serial=SerialKey(code=4), - otg=OtgKey(code=7, is_modifier=False), - ), - "KeyE": Key( - serial=SerialKey(code=5), - otg=OtgKey(code=8, is_modifier=False), - ), - "KeyF": Key( - serial=SerialKey(code=6), - otg=OtgKey(code=9, is_modifier=False), - ), - "KeyG": Key( - serial=SerialKey(code=7), - otg=OtgKey(code=10, is_modifier=False), - ), - "KeyH": Key( - serial=SerialKey(code=8), - otg=OtgKey(code=11, is_modifier=False), - ), - "KeyI": Key( - serial=SerialKey(code=9), - otg=OtgKey(code=12, is_modifier=False), - ), - "KeyJ": Key( - serial=SerialKey(code=10), - otg=OtgKey(code=13, is_modifier=False), - ), - "KeyK": Key( - serial=SerialKey(code=11), - otg=OtgKey(code=14, is_modifier=False), - ), - "KeyL": Key( - serial=SerialKey(code=12), - otg=OtgKey(code=15, is_modifier=False), - ), - "KeyM": Key( - serial=SerialKey(code=13), - otg=OtgKey(code=16, is_modifier=False), - ), - "KeyN": Key( - serial=SerialKey(code=14), - otg=OtgKey(code=17, is_modifier=False), - ), - "KeyO": Key( - serial=SerialKey(code=15), - otg=OtgKey(code=18, is_modifier=False), - ), - "KeyP": Key( - serial=SerialKey(code=16), - otg=OtgKey(code=19, is_modifier=False), - ), - "KeyQ": Key( - serial=SerialKey(code=17), - otg=OtgKey(code=20, is_modifier=False), - ), - "KeyR": Key( - serial=SerialKey(code=18), - otg=OtgKey(code=21, is_modifier=False), - ), - "KeyS": Key( - serial=SerialKey(code=19), - otg=OtgKey(code=22, is_modifier=False), - ), - "KeyT": Key( - serial=SerialKey(code=20), - otg=OtgKey(code=23, is_modifier=False), - ), - "KeyU": Key( - serial=SerialKey(code=21), - otg=OtgKey(code=24, is_modifier=False), - ), - "KeyV": Key( - serial=SerialKey(code=22), - otg=OtgKey(code=25, is_modifier=False), - ), - "KeyW": Key( - serial=SerialKey(code=23), - otg=OtgKey(code=26, is_modifier=False), - ), - "KeyX": Key( - serial=SerialKey(code=24), - otg=OtgKey(code=27, is_modifier=False), - ), - "KeyY": Key( - serial=SerialKey(code=25), - otg=OtgKey(code=28, is_modifier=False), - ), - "KeyZ": Key( - serial=SerialKey(code=26), - otg=OtgKey(code=29, is_modifier=False), - ), - "Digit1": Key( - serial=SerialKey(code=27), - otg=OtgKey(code=30, is_modifier=False), - ), - "Digit2": Key( - serial=SerialKey(code=28), - otg=OtgKey(code=31, is_modifier=False), - ), - "Digit3": Key( - serial=SerialKey(code=29), - otg=OtgKey(code=32, is_modifier=False), - ), - "Digit4": Key( - serial=SerialKey(code=30), - otg=OtgKey(code=33, is_modifier=False), - ), - "Digit5": Key( - serial=SerialKey(code=31), - otg=OtgKey(code=34, is_modifier=False), - ), - "Digit6": Key( - serial=SerialKey(code=32), - otg=OtgKey(code=35, is_modifier=False), - ), - "Digit7": Key( - serial=SerialKey(code=33), - otg=OtgKey(code=36, is_modifier=False), - ), - "Digit8": Key( - serial=SerialKey(code=34), - otg=OtgKey(code=37, is_modifier=False), - ), - "Digit9": Key( - serial=SerialKey(code=35), - otg=OtgKey(code=38, is_modifier=False), - ), - "Digit0": Key( - serial=SerialKey(code=36), - otg=OtgKey(code=39, is_modifier=False), - ), - "Enter": Key( - serial=SerialKey(code=37), - otg=OtgKey(code=40, is_modifier=False), - ), - "Escape": Key( - serial=SerialKey(code=38), - otg=OtgKey(code=41, is_modifier=False), - ), - "Backspace": Key( - serial=SerialKey(code=39), - otg=OtgKey(code=42, is_modifier=False), - ), - "Tab": Key( - serial=SerialKey(code=40), - otg=OtgKey(code=43, is_modifier=False), - ), - "Space": Key( - serial=SerialKey(code=41), - otg=OtgKey(code=44, is_modifier=False), - ), - "Minus": Key( - serial=SerialKey(code=42), - otg=OtgKey(code=45, is_modifier=False), - ), - "Equal": Key( - serial=SerialKey(code=43), - otg=OtgKey(code=46, is_modifier=False), - ), - "BracketLeft": Key( - serial=SerialKey(code=44), - otg=OtgKey(code=47, is_modifier=False), - ), - "BracketRight": Key( - serial=SerialKey(code=45), - otg=OtgKey(code=48, is_modifier=False), - ), - "Backslash": Key( - serial=SerialKey(code=46), - otg=OtgKey(code=49, is_modifier=False), - ), - "Semicolon": Key( - serial=SerialKey(code=47), - otg=OtgKey(code=51, is_modifier=False), - ), - "Quote": Key( - serial=SerialKey(code=48), - otg=OtgKey(code=52, is_modifier=False), - ), - "Backquote": Key( - serial=SerialKey(code=49), - otg=OtgKey(code=53, is_modifier=False), - ), - "Comma": Key( - serial=SerialKey(code=50), - otg=OtgKey(code=54, is_modifier=False), - ), - "Period": Key( - serial=SerialKey(code=51), - otg=OtgKey(code=55, is_modifier=False), - ), - "Slash": Key( - serial=SerialKey(code=52), - otg=OtgKey(code=56, is_modifier=False), - ), - "CapsLock": Key( - serial=SerialKey(code=53), - otg=OtgKey(code=57, is_modifier=False), - ), - "F1": Key( - serial=SerialKey(code=54), - otg=OtgKey(code=58, is_modifier=False), - ), - "F2": Key( - serial=SerialKey(code=55), - otg=OtgKey(code=59, is_modifier=False), - ), - "F3": Key( - serial=SerialKey(code=56), - otg=OtgKey(code=60, is_modifier=False), - ), - "F4": Key( - serial=SerialKey(code=57), - otg=OtgKey(code=61, is_modifier=False), - ), - "F5": Key( - serial=SerialKey(code=58), - otg=OtgKey(code=62, is_modifier=False), - ), - "F6": Key( - serial=SerialKey(code=59), - otg=OtgKey(code=63, is_modifier=False), - ), - "F7": Key( - serial=SerialKey(code=60), - otg=OtgKey(code=64, is_modifier=False), - ), - "F8": Key( - serial=SerialKey(code=61), - otg=OtgKey(code=65, is_modifier=False), - ), - "F9": Key( - serial=SerialKey(code=62), - otg=OtgKey(code=66, is_modifier=False), - ), - "F10": Key( - serial=SerialKey(code=63), - otg=OtgKey(code=67, is_modifier=False), - ), - "F11": Key( - serial=SerialKey(code=64), - otg=OtgKey(code=68, is_modifier=False), - ), - "F12": Key( - serial=SerialKey(code=65), - otg=OtgKey(code=69, is_modifier=False), - ), - "PrintScreen": Key( - serial=SerialKey(code=66), - otg=OtgKey(code=70, is_modifier=False), - ), - "Insert": Key( - serial=SerialKey(code=67), - otg=OtgKey(code=73, is_modifier=False), - ), - "Home": Key( - serial=SerialKey(code=68), - otg=OtgKey(code=74, is_modifier=False), - ), - "PageUp": Key( - serial=SerialKey(code=69), - otg=OtgKey(code=75, is_modifier=False), - ), - "Delete": Key( - serial=SerialKey(code=70), - otg=OtgKey(code=76, is_modifier=False), - ), - "End": Key( - serial=SerialKey(code=71), - otg=OtgKey(code=77, is_modifier=False), - ), - "PageDown": Key( - serial=SerialKey(code=72), - otg=OtgKey(code=78, is_modifier=False), - ), - "ArrowRight": Key( - serial=SerialKey(code=73), - otg=OtgKey(code=79, is_modifier=False), - ), - "ArrowLeft": Key( - serial=SerialKey(code=74), - otg=OtgKey(code=80, is_modifier=False), - ), - "ArrowDown": Key( - serial=SerialKey(code=75), - otg=OtgKey(code=81, is_modifier=False), - ), - "ArrowUp": Key( - serial=SerialKey(code=76), - otg=OtgKey(code=82, is_modifier=False), - ), - "ControlLeft": Key( - serial=SerialKey(code=77), - otg=OtgKey(code=1, is_modifier=True), - ), - "ShiftLeft": Key( - serial=SerialKey(code=78), - otg=OtgKey(code=2, is_modifier=True), - ), - "AltLeft": Key( - serial=SerialKey(code=79), - otg=OtgKey(code=4, is_modifier=True), - ), - "MetaLeft": Key( - serial=SerialKey(code=80), - otg=OtgKey(code=8, is_modifier=True), - ), - "ControlRight": Key( - serial=SerialKey(code=81), - otg=OtgKey(code=16, is_modifier=True), - ), - "ShiftRight": Key( - serial=SerialKey(code=82), - otg=OtgKey(code=32, is_modifier=True), - ), - "AltRight": Key( - serial=SerialKey(code=83), - otg=OtgKey(code=64, is_modifier=True), - ), - "MetaRight": Key( - serial=SerialKey(code=84), - otg=OtgKey(code=128, is_modifier=True), - ), - "Pause": Key( - serial=SerialKey(code=85), - otg=OtgKey(code=72, is_modifier=False), - ), - "ScrollLock": Key( - serial=SerialKey(code=86), - otg=OtgKey(code=71, is_modifier=False), - ), - "NumLock": Key( - serial=SerialKey(code=87), - otg=OtgKey(code=83, is_modifier=False), - ), - "ContextMenu": Key( - serial=SerialKey(code=88), - otg=OtgKey(code=101, is_modifier=False), - ), -} - - -# ===== -X11_TO_AT1 = { - 65307: 1, - 33: 2, - 49: 2, - 50: 3, - 64: 3, - 35: 4, - 51: 4, - 36: 5, - 52: 5, - 37: 6, - 53: 6, - 54: 7, - 94: 7, - 38: 8, - 55: 8, - 42: 9, - 56: 9, - 40: 10, - 57: 10, - 41: 11, - 48: 11, - 45: 12, - 95: 12, - 43: 13, - 61: 13, - 65288: 14, - 65289: 15, - 81: 16, - 113: 16, - 87: 17, - 119: 17, - 69: 18, - 101: 18, - 82: 19, - 114: 19, - 84: 20, - 116: 20, - 89: 21, - 121: 21, - 85: 22, - 117: 22, - 73: 23, - 105: 23, - 79: 24, - 111: 24, - 80: 25, - 112: 25, - 91: 26, - 123: 26, - 93: 27, - 125: 27, - 65293: 28, - 65507: 29, - 65: 30, - 97: 30, - 83: 31, - 115: 31, - 68: 32, - 100: 32, - 70: 33, - 102: 33, - 71: 34, - 103: 34, - 72: 35, - 104: 35, - 74: 36, - 106: 36, - 75: 37, - 107: 37, - 76: 38, - 108: 38, - 58: 39, - 59: 39, - 34: 40, - 39: 40, - 96: 41, - 126: 41, - 65505: 42, - 92: 43, - 124: 43, - 90: 44, - 122: 44, - 88: 45, - 120: 45, - 67: 46, - 99: 46, - 86: 47, - 118: 47, - 66: 48, - 98: 48, - 78: 49, - 110: 49, - 77: 50, - 109: 50, - 44: 51, - 60: 51, - 46: 52, - 62: 52, - 47: 53, - 63: 53, - 65506: 54, - 65513: 56, - 32: 57, - 65509: 58, - 65470: 59, - 65471: 60, - 65472: 61, - 65473: 62, - 65474: 63, - 65475: 64, - 65476: 65, - 65477: 66, - 65478: 67, - 65479: 68, - 65407: 69, - 65300: 70, - 65301: 84, - 65480: 87, - 65481: 88, - 65508: 57373, - 65514: 57400, - 65299: 57414, - 65360: 57415, - 65362: 57416, - 65365: 57417, - 65361: 57419, - 65363: 57421, - 65367: 57423, - 65364: 57424, - 65366: 57425, - 65379: 57426, - 65535: 57427, - 65511: 57435, - 65512: 57436, - 65383: 57437, -} - - -AT1_TO_WEB = { - 1: "Escape", - 2: "Digit1", - 3: "Digit2", - 4: "Digit3", - 5: "Digit4", - 6: "Digit5", - 7: "Digit6", - 8: "Digit7", - 9: "Digit8", - 10: "Digit9", - 11: "Digit0", - 12: "Minus", - 13: "Equal", - 14: "Backspace", - 15: "Tab", - 16: "KeyQ", - 17: "KeyW", - 18: "KeyE", - 19: "KeyR", - 20: "KeyT", - 21: "KeyY", - 22: "KeyU", - 23: "KeyI", - 24: "KeyO", - 25: "KeyP", - 26: "BracketLeft", - 27: "BracketRight", - 28: "Enter", - 29: "ControlLeft", - 30: "KeyA", - 31: "KeyS", - 32: "KeyD", - 33: "KeyF", - 34: "KeyG", - 35: "KeyH", - 36: "KeyJ", - 37: "KeyK", - 38: "KeyL", - 39: "Semicolon", - 40: "Quote", - 41: "Backquote", - 42: "ShiftLeft", - 43: "Backslash", - 44: "KeyZ", - 45: "KeyX", - 46: "KeyC", - 47: "KeyV", - 48: "KeyB", - 49: "KeyN", - 50: "KeyM", - 51: "Comma", - 52: "Period", - 53: "Slash", - 54: "ShiftRight", - 56: "AltLeft", - 57: "Space", - 58: "CapsLock", - 59: "F1", - 60: "F2", - 61: "F3", - 62: "F4", - 63: "F5", - 64: "F6", - 65: "F7", - 66: "F8", - 67: "F9", - 68: "F10", - 69: "NumLock", - 70: "ScrollLock", - 84: "PrintScreen", - 87: "F11", - 88: "F12", - 57373: "ControlRight", - 57400: "AltRight", - 57414: "Pause", - 57415: "Home", - 57416: "ArrowUp", - 57417: "PageUp", - 57419: "ArrowLeft", - 57421: "ArrowRight", - 57423: "End", - 57424: "ArrowDown", - 57425: "PageDown", - 57426: "Insert", - 57427: "Delete", - 57435: "MetaLeft", - 57436: "MetaRight", - 57437: "ContextMenu", -} diff --git a/kvmd/plugins/hid/otg/keyboard.py b/kvmd/plugins/hid/otg/keyboard.py index cb83232b..63c15889 100644 --- a/kvmd/plugins/hid/otg/keyboard.py +++ b/kvmd/plugins/hid/otg/keyboard.py @@ -29,7 +29,8 @@ from typing import Any from ....logging import get_logger -from .... import keymap +from ....keyboard.mappings import OtgKey +from ....keyboard.mappings import KEYMAP from .device import BaseEvent from .device import BaseDeviceProcess @@ -46,7 +47,7 @@ class _ResetEvent(BaseEvent): @dataclasses.dataclass(frozen=True) class _ModifierEvent(BaseEvent): - modifier: keymap.OtgKey + modifier: OtgKey state: bool def __post_init__(self) -> None: @@ -55,7 +56,7 @@ class _ModifierEvent(BaseEvent): @dataclasses.dataclass(frozen=True) class _KeyEvent(BaseEvent): - key: keymap.OtgKey + key: OtgKey state: bool def __post_init__(self) -> None: @@ -72,8 +73,8 @@ class KeyboardProcess(BaseDeviceProcess): **kwargs, ) - self.__pressed_modifiers: Set[keymap.OtgKey] = set() - self.__pressed_keys: List[Optional[keymap.OtgKey]] = [None] * 6 + self.__pressed_modifiers: Set[OtgKey] = set() + self.__pressed_keys: List[Optional[OtgKey]] = [None] * 6 def cleanup(self) -> None: self._stop() @@ -89,7 +90,7 @@ class KeyboardProcess(BaseDeviceProcess): self._queue_event(_ResetEvent()) def send_key_event(self, key: str, state: bool) -> None: - otg_key = keymap.KEYMAP[key].otg + otg_key = KEYMAP[key].otg if otg_key.is_modifier: self._queue_event(_ModifierEvent(otg_key, state)) else: diff --git a/kvmd/plugins/hid/serial.py b/kvmd/plugins/hid/serial.py index f2ece19d..c41c762c 100644 --- a/kvmd/plugins/hid/serial.py +++ b/kvmd/plugins/hid/serial.py @@ -39,10 +39,11 @@ import setproctitle from ...logging import get_logger +from ...keyboard.mappings import KEYMAP + from ... import aiotools from ... import aiomulti from ... import gpio -from ... import keymap from ...yamlconf import Option @@ -75,10 +76,10 @@ class _KeyEvent(_BaseEvent): state: bool def __post_init__(self) -> None: - assert self.name in keymap.KEYMAP + assert self.name in KEYMAP def make_command(self) -> bytes: - code = keymap.KEYMAP[self.name].serial.code + code = KEYMAP[self.name].serial.code return struct.pack(">BBBxx", 0x11, code, int(self.state)) diff --git a/kvmd/validators/kvm.py b/kvmd/validators/kvm.py index df09d06e..cf63b97e 100644 --- a/kvmd/validators/kvm.py +++ b/kvmd/validators/kvm.py @@ -22,7 +22,7 @@ from typing import Any -from .. import keymap +from ..keyboard.mappings import KEYMAP from . import check_string_in_list @@ -58,7 +58,7 @@ def valid_stream_fps(arg: Any) -> int: # ===== def valid_hid_key(arg: Any) -> str: - return check_string_in_list(arg, "HID key", keymap.KEYMAP, lower=False) + return check_string_in_list(arg, "HID key", KEYMAP, lower=False) def valid_hid_mouse_move(arg: Any) -> int: @@ -79,6 +79,7 @@ def main() -> None: "kvmd", "kvmd.validators", "kvmd.yamlconf", + "kvmd.keyboard", "kvmd.plugins", "kvmd.plugins.auth", "kvmd.plugins.hid", diff --git a/testenv/tests/keyboard/__init__.py b/testenv/tests/keyboard/__init__.py new file mode 100644 index 00000000..1e91f7fa --- /dev/null +++ b/testenv/tests/keyboard/__init__.py @@ -0,0 +1,20 @@ +# ========================================================================== # +# # +# KVMD - The main Pi-KVM daemon. # +# # +# Copyright (C) 2018 Maxim Devaev <[email protected]> # +# # +# 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 3 of the License, or # +# (at your option) 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, see <https://www.gnu.org/licenses/>. # +# # +# ========================================================================== # diff --git a/testenv/tests/test_keymap.py b/testenv/tests/keyboard/test_keymap.py index 4ee603d0..9a397c6e 100644 --- a/testenv/tests/test_keymap.py +++ b/testenv/tests/keyboard/test_keymap.py @@ -22,7 +22,7 @@ import pytest -from kvmd.keymap import KEYMAP +from kvmd.keyboard.mappings import KEYMAP # ===== diff --git a/testenv/tests/validators/test_kvm.py b/testenv/tests/validators/test_kvm.py index 3bcbd0bf..ccafdbce 100644 --- a/testenv/tests/validators/test_kvm.py +++ b/testenv/tests/validators/test_kvm.py @@ -24,7 +24,7 @@ from typing import Any import pytest -from kvmd.keymap import KEYMAP +from kvmd.keyboard.mappings import KEYMAP from kvmd.validators import ValidatorError from kvmd.validators.kvm import valid_atx_power_action |