summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDevaev Maxim <[email protected]>2020-05-23 11:57:19 +0300
committerDevaev Maxim <[email protected]>2020-05-23 11:57:19 +0300
commita795fe5ed63b960cbf24c9130ed37f9f7f33280c (patch)
tree51b884539614ed380cb19cd60e4dae7c8baab090
parent17082c916a1d80d92bb5a51fed67f030f605f804 (diff)
additional keymapping info; refactoring
-rw-r--r--Makefile2
-rwxr-xr-xgenmap.py37
-rw-r--r--keymap.in182
-rw-r--r--kvmd/apps/kvmd/api/hid.py4
-rw-r--r--kvmd/apps/vnc/__init__.py3
-rw-r--r--kvmd/keyboard/__init__.py20
-rw-r--r--kvmd/keyboard/keysym.py (renamed from kvmd/apps/vnc/keysym.py)11
-rw-r--r--kvmd/keyboard/mappings.py373
-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.py632
-rw-r--r--kvmd/plugins/hid/otg/keyboard.py13
-rw-r--r--kvmd/plugins/hid/serial.py7
-rw-r--r--kvmd/validators/kvm.py4
-rwxr-xr-xsetup.py1
-rw-r--r--testenv/tests/keyboard/__init__.py20
-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.py2
18 files changed, 573 insertions, 764 deletions
diff --git a/Makefile b/Makefile
index ec5bb303..1d36693a 100644
--- a/Makefile
+++ b/Makefile
@@ -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"; \
diff --git a/genmap.py b/genmap.py
index 4502ce7d..0de7b503 100755
--- a/genmap.py
+++ b/genmap.py
@@ -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
diff --git a/keymap.in b/keymap.in
index 6bec761c..ca885c2d 100644
--- a/keymap.in
+++ b/keymap.in
@@ -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:
diff --git a/setup.py b/setup.py
index eba00e8b..bc632df5 100755
--- a/setup.py
+++ b/setup.py
@@ -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