additional keymapping info; refactoring

This commit is contained in:
Devaev Maxim 2020-05-23 11:57:19 +03:00
parent 17082c916a
commit a795fe5ed6
18 changed files with 573 additions and 764 deletions

View File

@ -130,7 +130,7 @@ run-vnc: testenv
regen: 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 \ docker run --user `id -u`:`id -g` --rm \
--volume `pwd`:/src \ --volume `pwd`:/src \
-it $(TESTENV_IMAGE) bash -c "cd src && ./genmap.py keymap.in $$file.mako $$file"; \ -it $(TESTENV_IMAGE) bash -c "cd src && ./genmap.py keymap.in $$file.mako $$file"; \

View File

@ -35,15 +35,27 @@ import mako.template
# ===== # =====
@dataclasses.dataclass(frozen=True)
class _OtgKey:
code: int
is_modifier: bool
@dataclasses.dataclass(frozen=True)
class _X11Key:
name: str
code: int
shift: bool
@dataclasses.dataclass(frozen=True) @dataclasses.dataclass(frozen=True)
class _KeyMapping: class _KeyMapping:
web_name: str web_name: str
serial_code: int serial_code: int
arduino_name: str arduino_name: str
otg_code: int otg_key: _OtgKey
otg_is_modifier: bool
at1_code: int at1_code: int
x11_codes: Set[int] x11_keys: Set[_X11Key]
def _resolve_keysym(name: str) -> int: def _resolve_keysym(name: str) -> int:
@ -61,15 +73,24 @@ def _read_keymap_in(path: str) -> List[_KeyMapping]:
line = line.strip() line = line.strip()
if len(line) > 0 and not line.startswith("#"): if len(line) > 0 and not line.startswith("#"):
parts = list(map(str.strip, line.split())) 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( keymap.append(_KeyMapping(
web_name=parts[0], web_name=parts[0],
serial_code=int(parts[1]), serial_code=int(parts[1]),
arduino_name=parts[2], arduino_name=parts[2],
otg_code=int(parts[3], 16), otg_key=_OtgKey(otg_code, otg_is_modifier),
otg_is_modifier=(parts[4].lower() == "m"), at1_code=int(parts[4], 16),
at1_code=int(parts[5], 16), x11_keys=x11_keys,
x11_codes=set(map(_resolve_keysym, parts[6].split(","))),
)) ))
return keymap return keymap

182
keymap.in
View File

@ -25,97 +25,97 @@
# https://gist.github.com/MightyPork/6da26e382a7ad91b5496ee55fdc73db2 # https://gist.github.com/MightyPork/6da26e382a7ad91b5496ee55fdc73db2
# https://github.com/qemu/keycodemapdb/blob/master/data/keymaps.csv # https://github.com/qemu/keycodemapdb/blob/master/data/keymaps.csv
# ---------------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------------------
# Web | Serial code | Arduino key | OTG code + modifier flag | AT set1 | X11 keysyms # 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 KeyA 1 KEY_A 0x04 0x1e ^XK_A,XK_a
KeyB 2 KEY_B 0x05 - 0x30 XK_B,XK_b KeyB 2 KEY_B 0x05 0x30 ^XK_B,XK_b
KeyC 3 KEY_C 0x06 - 0x2e XK_C,XK_c KeyC 3 KEY_C 0x06 0x2e ^XK_C,XK_c
KeyD 4 KEY_D 0x07 - 0x20 XK_D,XK_d KeyD 4 KEY_D 0x07 0x20 ^XK_D,XK_d
KeyE 5 KEY_E 0x08 - 0x12 XK_E,XK_e KeyE 5 KEY_E 0x08 0x12 ^XK_E,XK_e
KeyF 6 KEY_F 0x09 - 0x21 XK_F,XK_f KeyF 6 KEY_F 0x09 0x21 ^XK_F,XK_f
KeyG 7 KEY_G 0x0a - 0x22 XK_G,XK_g KeyG 7 KEY_G 0x0a 0x22 ^XK_G,XK_g
KeyH 8 KEY_H 0x0b - 0x23 XK_H,XK_h KeyH 8 KEY_H 0x0b 0x23 ^XK_H,XK_h
KeyI 9 KEY_I 0x0c - 0x17 XK_I,XK_i KeyI 9 KEY_I 0x0c 0x17 ^XK_I,XK_i
KeyJ 10 KEY_J 0x0d - 0x24 XK_J,XK_j KeyJ 10 KEY_J 0x0d 0x24 ^XK_J,XK_j
KeyK 11 KEY_K 0x0e - 0x25 XK_K,XK_k KeyK 11 KEY_K 0x0e 0x25 ^XK_K,XK_k
KeyL 12 KEY_L 0x0f - 0x26 XK_L,XK_l KeyL 12 KEY_L 0x0f 0x26 ^XK_L,XK_l
KeyM 13 KEY_M 0x10 - 0x32 XK_M,XK_m KeyM 13 KEY_M 0x10 0x32 ^XK_M,XK_m
KeyN 14 KEY_N 0x11 - 0x31 XK_N,XK_n KeyN 14 KEY_N 0x11 0x31 ^XK_N,XK_n
KeyO 15 KEY_O 0x12 - 0x18 XK_O,XK_o KeyO 15 KEY_O 0x12 0x18 ^XK_O,XK_o
KeyP 16 KEY_P 0x13 - 0x19 XK_P,XK_p KeyP 16 KEY_P 0x13 0x19 ^XK_P,XK_p
KeyQ 17 KEY_Q 0x14 - 0x10 XK_Q,XK_q KeyQ 17 KEY_Q 0x14 0x10 ^XK_Q,XK_q
KeyR 18 KEY_R 0x15 - 0x13 XK_R,XK_r KeyR 18 KEY_R 0x15 0x13 ^XK_R,XK_r
KeyS 19 KEY_S 0x16 - 0x1f XK_S,XK_s KeyS 19 KEY_S 0x16 0x1f ^XK_S,XK_s
KeyT 20 KEY_T 0x17 - 0x14 XK_T,XK_t KeyT 20 KEY_T 0x17 0x14 ^XK_T,XK_t
KeyU 21 KEY_U 0x18 - 0x16 XK_U,XK_u KeyU 21 KEY_U 0x18 0x16 ^XK_U,XK_u
KeyV 22 KEY_V 0x19 - 0x2f XK_V,XK_v KeyV 22 KEY_V 0x19 0x2f ^XK_V,XK_v
KeyW 23 KEY_W 0x1a - 0x11 XK_W,XK_w KeyW 23 KEY_W 0x1a 0x11 ^XK_W,XK_w
KeyX 24 KEY_X 0x1b - 0x2d XK_X,XK_x KeyX 24 KEY_X 0x1b 0x2d ^XK_X,XK_x
KeyY 25 KEY_Y 0x1c - 0x15 XK_Y,XK_y KeyY 25 KEY_Y 0x1c 0x15 ^XK_Y,XK_y
KeyZ 26 KEY_Z 0x1d - 0x2c XK_Z,XK_z KeyZ 26 KEY_Z 0x1d 0x2c ^XK_Z,XK_z
Digit1 27 KEY_1 0x1e - 0x02 XK_1,XK_exclam Digit1 27 KEY_1 0x1e 0x02 XK_1,^XK_exclam
Digit2 28 KEY_2 0x1f - 0x03 XK_2,XK_at Digit2 28 KEY_2 0x1f 0x03 XK_2,^XK_at
Digit3 29 KEY_3 0x20 - 0x04 XK_3,XK_numbersign Digit3 29 KEY_3 0x20 0x04 XK_3,^XK_numbersign
Digit4 30 KEY_4 0x21 - 0x05 XK_4,XK_dollar Digit4 30 KEY_4 0x21 0x05 XK_4,^XK_dollar
Digit5 31 KEY_5 0x22 - 0x06 XK_5,XK_percent Digit5 31 KEY_5 0x22 0x06 XK_5,^XK_percent
Digit6 32 KEY_6 0x23 - 0x07 XK_6,XK_asciicircum Digit6 32 KEY_6 0x23 0x07 XK_6,^XK_asciicircum
Digit7 33 KEY_7 0x24 - 0x08 XK_7,XK_ampersand Digit7 33 KEY_7 0x24 0x08 XK_7,^XK_ampersand
Digit8 34 KEY_8 0x25 - 0x09 XK_8,XK_asterisk Digit8 34 KEY_8 0x25 0x09 XK_8,^XK_asterisk
Digit9 35 KEY_9 0x26 - 0x0a XK_9,XK_parenleft Digit9 35 KEY_9 0x26 0x0a XK_9,^XK_parenleft
Digit0 36 KEY_0 0x27 - 0x0b XK_0,XK_parenright Digit0 36 KEY_0 0x27 0x0b XK_0,^XK_parenright
Enter 37 KEY_ENTER 0x28 - 0x1c XK_Return Enter 37 KEY_ENTER 0x28 0x1c XK_Return
Escape 38 KEY_ESC 0x29 - 0x01 XK_Escape Escape 38 KEY_ESC 0x29 0x01 XK_Escape
Backspace 39 KEY_BACKSPACE 0x2a - 0x0e XK_BackSpace Backspace 39 KEY_BACKSPACE 0x2a 0x0e XK_BackSpace
Tab 40 KEY_TAB 0x2b - 0x0f XK_Tab Tab 40 KEY_TAB 0x2b 0x0f XK_Tab
Space 41 KEY_SPACE 0x2c - 0x39 XK_space Space 41 KEY_SPACE 0x2c 0x39 XK_space
Minus 42 KEY_MINUS 0x2d - 0x0c XK_minus,XK_underscore Minus 42 KEY_MINUS 0x2d 0x0c XK_minus,^XK_underscore
Equal 43 KEY_EQUAL 0x2e - 0x0d XK_equal,XK_plus Equal 43 KEY_EQUAL 0x2e 0x0d XK_equal,^XK_plus
BracketLeft 44 KEY_LEFT_BRACE 0x2f - 0x1a XK_bracketleft,XK_braceleft BracketLeft 44 KEY_LEFT_BRACE 0x2f 0x1a XK_bracketleft,^XK_braceleft
BracketRight 45 KEY_RIGHT_BRACE 0x30 - 0x1b XK_bracketright,XK_braceright BracketRight 45 KEY_RIGHT_BRACE 0x30 0x1b XK_bracketright,^XK_braceright
Backslash 46 KEY_BACKSLASH 0x31 - 0x2b XK_backslash,XK_bar Backslash 46 KEY_BACKSLASH 0x31 0x2b XK_backslash,^XK_bar
Semicolon 47 KEY_SEMICOLON 0x33 - 0x27 XK_semicolon,XK_colon Semicolon 47 KEY_SEMICOLON 0x33 0x27 XK_semicolon,^XK_colon
Quote 48 KEY_QUOTE 0x34 - 0x28 XK_apostrophe,XK_quotedbl Quote 48 KEY_QUOTE 0x34 0x28 XK_apostrophe,^XK_quotedbl
Backquote 49 KEY_TILDE 0x35 - 0x29 XK_grave,XK_asciitilde Backquote 49 KEY_TILDE 0x35 0x29 XK_grave,^XK_asciitilde
Comma 50 KEY_COMMA 0x36 - 0x33 XK_comma,XK_less Comma 50 KEY_COMMA 0x36 0x33 XK_comma,^XK_less
Period 51 KEY_PERIOD 0x37 - 0x34 XK_period,XK_greater Period 51 KEY_PERIOD 0x37 0x34 XK_period,^XK_greater
Slash 52 KEY_SLASH 0x38 - 0x35 XK_slash,XK_question Slash 52 KEY_SLASH 0x38 0x35 XK_slash,^XK_question
CapsLock 53 KEY_CAPS_LOCK 0x39 - 0x3a XK_Caps_Lock CapsLock 53 KEY_CAPS_LOCK 0x39 0x3a XK_Caps_Lock
F1 54 KEY_F1 0x3a - 0x3b XK_F1 F1 54 KEY_F1 0x3a 0x3b XK_F1
F2 55 KEY_F2 0x3b - 0x3c XK_F2 F2 55 KEY_F2 0x3b 0x3c XK_F2
F3 56 KEY_F3 0x3c - 0x3d XK_F3 F3 56 KEY_F3 0x3c 0x3d XK_F3
F4 57 KEY_F4 0x3d - 0x3e XK_F4 F4 57 KEY_F4 0x3d 0x3e XK_F4
F5 58 KEY_F5 0x3e - 0x3f XK_F5 F5 58 KEY_F5 0x3e 0x3f XK_F5
F6 59 KEY_F6 0x3f - 0x40 XK_F6 F6 59 KEY_F6 0x3f 0x40 XK_F6
F7 60 KEY_F7 0x40 - 0x41 XK_F7 F7 60 KEY_F7 0x40 0x41 XK_F7
F8 61 KEY_F8 0x41 - 0x42 XK_F8 F8 61 KEY_F8 0x41 0x42 XK_F8
F9 62 KEY_F9 0x42 - 0x43 XK_F9 F9 62 KEY_F9 0x42 0x43 XK_F9
F10 63 KEY_F10 0x43 - 0x44 XK_F10 F10 63 KEY_F10 0x43 0x44 XK_F10
F11 64 KEY_F11 0x44 - 0x57 XK_F11 F11 64 KEY_F11 0x44 0x57 XK_F11
F12 65 KEY_F12 0x45 - 0x58 XK_F12 F12 65 KEY_F12 0x45 0x58 XK_F12
PrintScreen 66 KEY_PRINT 0x46 - 0x54 XK_Sys_Req PrintScreen 66 KEY_PRINT 0x46 0x54 XK_Sys_Req
Insert 67 KEY_INSERT 0x49 - 0xe052 XK_Insert Insert 67 KEY_INSERT 0x49 0xe052 XK_Insert
Home 68 KEY_HOME 0x4a - 0xe047 XK_Home Home 68 KEY_HOME 0x4a 0xe047 XK_Home
PageUp 69 KEY_PAGE_UP 0x4b - 0xe049 XK_Page_Up PageUp 69 KEY_PAGE_UP 0x4b 0xe049 XK_Page_Up
Delete 70 KEY_DELETE 0x4c - 0xe053 XK_Delete Delete 70 KEY_DELETE 0x4c 0xe053 XK_Delete
End 71 KEY_END 0x4d - 0xe04f XK_End End 71 KEY_END 0x4d 0xe04f XK_End
PageDown 72 KEY_PAGE_DOWN 0x4e - 0xe051 XK_Page_Down PageDown 72 KEY_PAGE_DOWN 0x4e 0xe051 XK_Page_Down
ArrowRight 73 KEY_RIGHT_ARROW 0x4f - 0xe04d XK_Right ArrowRight 73 KEY_RIGHT_ARROW 0x4f 0xe04d XK_Right
ArrowLeft 74 KEY_LEFT_ARROW 0x50 - 0xe04b XK_Left ArrowLeft 74 KEY_LEFT_ARROW 0x50 0xe04b XK_Left
ArrowDown 75 KEY_DOWN_ARROW 0x51 - 0xe050 XK_Down ArrowDown 75 KEY_DOWN_ARROW 0x51 0xe050 XK_Down
ArrowUp 76 KEY_UP_ARROW 0x52 - 0xe048 XK_Up ArrowUp 76 KEY_UP_ARROW 0x52 0xe048 XK_Up
ControlLeft 77 KEY_LEFT_CTRL 0x01 m 0x1d XK_Control_L ControlLeft 77 KEY_LEFT_CTRL ^0x01 0x1d XK_Control_L
ShiftLeft 78 KEY_LEFT_SHIFT 0x02 m 0x2a XK_Shift_L ShiftLeft 78 KEY_LEFT_SHIFT ^0x02 0x2a XK_Shift_L
AltLeft 79 KEY_LEFT_ALT 0x04 m 0x38 XK_Alt_L AltLeft 79 KEY_LEFT_ALT ^0x04 0x38 XK_Alt_L
MetaLeft 80 KEY_LEFT_GUI 0x08 m 0xe05b XK_Meta_L MetaLeft 80 KEY_LEFT_GUI ^0x08 0xe05b XK_Meta_L
ControlRight 81 KEY_RIGHT_CTRL 0x10 m 0xe01d XK_Control_R ControlRight 81 KEY_RIGHT_CTRL ^0x10 0xe01d XK_Control_R
ShiftRight 82 KEY_RIGHT_SHIFT 0x20 m 0x36 XK_Shift_R ShiftRight 82 KEY_RIGHT_SHIFT ^0x20 0x36 XK_Shift_R
AltRight 83 KEY_RIGHT_ALT 0x40 m 0xe038 XK_Alt_R AltRight 83 KEY_RIGHT_ALT ^0x40 0xe038 XK_Alt_R
MetaRight 84 KEY_RIGHT_GUI 0x80 m 0xe05c XK_Meta_R MetaRight 84 KEY_RIGHT_GUI ^0x80 0xe05c XK_Meta_R
Pause 85 KEY_PAUSE 0x48 - 0xe046 XK_Pause Pause 85 KEY_PAUSE 0x48 0xe046 XK_Pause
ScrollLock 86 KEY_SCROLL_LOCK 0x47 - 0x46 XK_Scroll_Lock ScrollLock 86 KEY_SCROLL_LOCK 0x47 0x46 XK_Scroll_Lock
NumLock 87 KEY_NUM_LOCK 0x53 - 0x45 XK_Num_Lock NumLock 87 KEY_NUM_LOCK 0x53 0x45 XK_Num_Lock
ContextMenu 88 KEY_MENU 0x65 - 0xe05d XK_Menu ContextMenu 88 KEY_MENU 0x65 0xe05d XK_Menu
# KEY_NON_US_NUM # KEY_NON_US_NUM
# KEYPAD_DIVIDE # KEYPAD_DIVIDE
# KEYPAD_MULTIPLY # KEYPAD_MULTIPLY

View File

@ -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_button
from ....validators.kvm import valid_hid_mouse_wheel 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_http
from ..http import exposed_ws from ..http import exposed_ws
@ -70,7 +70,7 @@ class HidApi:
if limit > 0: if limit > 0:
text = text[:limit] text = text[:limit]
async with self.__key_lock: 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) self.__hid.send_key_event(key, state)
return make_json_response() return make_json_response()

View File

@ -23,6 +23,8 @@
from typing import List from typing import List
from typing import Optional from typing import Optional
from ...keyboard.keysym import build_symmap
from ...clients.kvmd import KvmdClient from ...clients.kvmd import KvmdClient
from ...clients.streamer import StreamerClient from ...clients.streamer import StreamerClient
@ -32,7 +34,6 @@ from .. import init
from .vncauth import VncAuthManager from .vncauth import VncAuthManager
from .server import VncServer from .server import VncServer
from .keysym import build_symmap
# ===== # =====

20
kvmd/keyboard/__init__.py Normal file
View File

@ -0,0 +1,20 @@
# ========================================================================== #
# #
# KVMD - The main Pi-KVM daemon. #
# #
# Copyright (C) 2018 Maxim Devaev <mdevaev@gmail.com> #
# #
# 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/>. #
# #
# ========================================================================== #

View File

@ -27,9 +27,10 @@ from typing import Dict
import Xlib.keysymdef 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 # https://github.com/qemu/qemu/blob/95a9457fd44ad97c518858a4e1586a5498f9773c/ui/keymaps.c
symmap: Dict[int, str] = {} symmap: Dict[int, str] = {}
for (x11_code, at1_code) in keymap.X11_TO_AT1.items(): for (x11_code, at1_key) in X11_TO_AT1.items():
symmap[x11_code] = keymap.AT1_TO_WEB[at1_code] symmap[x11_code] = AT1_TO_WEB[at1_key.code]
for (x11_code, at1_code) in _read_keyboard_layout(path).items(): 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 # mypy bug
symmap[x11_code] = web_name # type: ignore symmap[x11_code] = web_name # type: ignore
return symmap return symmap

373
kvmd/keyboard/mappings.py Normal file
View File

@ -0,0 +1,373 @@
# ========================================================================== #
# #
# KVMD - The main Pi-KVM daemon. #
# #
# Copyright (C) 2018 Maxim Devaev <mdevaev@gmail.com> #
# #
# 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
# =====
@dataclasses.dataclass(frozen=True)
class SerialKey:
code: int
@dataclasses.dataclass(frozen=True)
class OtgKey:
code: int
is_modifier: bool
@dataclasses.dataclass(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)),
}
# =====
@dataclasses.dataclass(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",
}

View File

@ -43,22 +43,24 @@ class Key:
otg: OtgKey otg: OtgKey
<%! import operator %> <%! import operator %>
# =====
KEYMAP: Dict[str, Key] = { KEYMAP: Dict[str, Key] = {
% for km in sorted(keymap, key=operator.attrgetter("serial_code")): % for km in sorted(keymap, key=operator.attrgetter("serial_code")):
"${km.web_name}": Key( "${km.web_name}": Key(serial=SerialKey(code=${km.serial_code}), otg=OtgKey(code=${km.otg_key.code}, is_modifier=${km.otg_key.is_modifier})),
serial=SerialKey(code=${km.serial_code}),
otg=OtgKey(code=${km.otg_code}, is_modifier=${km.otg_is_modifier}),
),
% endfor % endfor
} }
# ===== # =====
@dataclasses.dataclass(frozen=True)
class At1Key:
code: int
shift: bool
X11_TO_AT1 = { X11_TO_AT1 = {
% for km in sorted(keymap, key=operator.attrgetter("at1_code")): % for km in sorted(keymap, key=operator.attrgetter("at1_code")):
% for code in sorted(km.x11_codes): % for x11_key in sorted(km.x11_keys, key=(lambda key: (key.code, key.shift))):
${code}: ${km.at1_code}, ${x11_key.code}: At1Key(code=${km.at1_code}, shift=${x11_key.shift}), # ${x11_key.name}
% endfor % endfor
% endfor % endfor
} }

View File

@ -25,7 +25,7 @@ import string
from typing import Tuple from typing import Tuple
from typing import Generator 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)}, **{str(number): f"Digit{number}" for number in range(0, 10)},
**{ch: f"Key{ch.upper()}" for ch in string.ascii_lowercase}, **{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 = { _UPPER_CHARS = {
"~": "Backquote", "~": "Backquote",
@ -73,11 +73,11 @@ _UPPER_CHARS = {
"+": "Equal", "+": "Equal",
**{ch: f"Key{ch}" for ch in string.ascii_uppercase}, **{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"] assert shift_key in ["ShiftLeft", "ShiftRight"]
shifted = False shifted = False

View File

@ -1,632 +0,0 @@
# ========================================================================== #
# #
# KVMD - The main Pi-KVM daemon. #
# #
# Copyright (C) 2018 Maxim Devaev <mdevaev@gmail.com> #
# #
# 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
# =====
@dataclasses.dataclass(frozen=True)
class SerialKey:
code: int
@dataclasses.dataclass(frozen=True)
class OtgKey:
code: int
is_modifier: bool
@dataclasses.dataclass(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",
}

View File

@ -29,7 +29,8 @@ from typing import Any
from ....logging import get_logger 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 BaseEvent
from .device import BaseDeviceProcess from .device import BaseDeviceProcess
@ -46,7 +47,7 @@ class _ResetEvent(BaseEvent):
@dataclasses.dataclass(frozen=True) @dataclasses.dataclass(frozen=True)
class _ModifierEvent(BaseEvent): class _ModifierEvent(BaseEvent):
modifier: keymap.OtgKey modifier: OtgKey
state: bool state: bool
def __post_init__(self) -> None: def __post_init__(self) -> None:
@ -55,7 +56,7 @@ class _ModifierEvent(BaseEvent):
@dataclasses.dataclass(frozen=True) @dataclasses.dataclass(frozen=True)
class _KeyEvent(BaseEvent): class _KeyEvent(BaseEvent):
key: keymap.OtgKey key: OtgKey
state: bool state: bool
def __post_init__(self) -> None: def __post_init__(self) -> None:
@ -72,8 +73,8 @@ class KeyboardProcess(BaseDeviceProcess):
**kwargs, **kwargs,
) )
self.__pressed_modifiers: Set[keymap.OtgKey] = set() self.__pressed_modifiers: Set[OtgKey] = set()
self.__pressed_keys: List[Optional[keymap.OtgKey]] = [None] * 6 self.__pressed_keys: List[Optional[OtgKey]] = [None] * 6
def cleanup(self) -> None: def cleanup(self) -> None:
self._stop() self._stop()
@ -89,7 +90,7 @@ class KeyboardProcess(BaseDeviceProcess):
self._queue_event(_ResetEvent()) self._queue_event(_ResetEvent())
def send_key_event(self, key: str, state: bool) -> None: 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: if otg_key.is_modifier:
self._queue_event(_ModifierEvent(otg_key, state)) self._queue_event(_ModifierEvent(otg_key, state))
else: else:

View File

@ -39,10 +39,11 @@ import setproctitle
from ...logging import get_logger from ...logging import get_logger
from ...keyboard.mappings import KEYMAP
from ... import aiotools from ... import aiotools
from ... import aiomulti from ... import aiomulti
from ... import gpio from ... import gpio
from ... import keymap
from ...yamlconf import Option from ...yamlconf import Option
@ -75,10 +76,10 @@ class _KeyEvent(_BaseEvent):
state: bool state: bool
def __post_init__(self) -> None: def __post_init__(self) -> None:
assert self.name in keymap.KEYMAP assert self.name in KEYMAP
def make_command(self) -> bytes: 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)) return struct.pack(">BBBxx", 0x11, code, int(self.state))

View File

@ -22,7 +22,7 @@
from typing import Any from typing import Any
from .. import keymap from ..keyboard.mappings import KEYMAP
from . import check_string_in_list from . import check_string_in_list
@ -58,7 +58,7 @@ def valid_stream_fps(arg: Any) -> int:
# ===== # =====
def valid_hid_key(arg: Any) -> str: 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: def valid_hid_mouse_move(arg: Any) -> int:

View File

@ -79,6 +79,7 @@ def main() -> None:
"kvmd", "kvmd",
"kvmd.validators", "kvmd.validators",
"kvmd.yamlconf", "kvmd.yamlconf",
"kvmd.keyboard",
"kvmd.plugins", "kvmd.plugins",
"kvmd.plugins.auth", "kvmd.plugins.auth",
"kvmd.plugins.hid", "kvmd.plugins.hid",

View File

@ -0,0 +1,20 @@
# ========================================================================== #
# #
# KVMD - The main Pi-KVM daemon. #
# #
# Copyright (C) 2018 Maxim Devaev <mdevaev@gmail.com> #
# #
# 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/>. #
# #
# ========================================================================== #

View File

@ -22,7 +22,7 @@
import pytest import pytest
from kvmd.keymap import KEYMAP from kvmd.keyboard.mappings import KEYMAP
# ===== # =====

View File

@ -24,7 +24,7 @@ from typing import Any
import pytest import pytest
from kvmd.keymap import KEYMAP from kvmd.keyboard.mappings import KEYMAP
from kvmd.validators import ValidatorError from kvmd.validators import ValidatorError
from kvmd.validators.kvm import valid_atx_power_action from kvmd.validators.kvm import valid_atx_power_action