using HID-Project library

This commit is contained in:
Devaev Maxim 2018-07-11 05:29:30 +00:00
parent 157828997a
commit c6b6e54875
11 changed files with 375 additions and 54 deletions

View File

@ -7,11 +7,15 @@ build:
update:
platformio platform update
install: upload
upload:
platformio run --target upload
serial:
platformio serialports monitor
regen:
python3 genmap.py
clean:
rm -rf .pioenvs .piolibdeps

36
hid/genmap.py Executable file
View File

@ -0,0 +1,36 @@
#!/usr/bin/env python3
import operator
from typing import Tuple
from typing import List
import yaml
# =====
def main() -> None:
keymap: List[Tuple[int, str, str]] = []
with open("keymap.in") as keymap_file:
for row in keymap_file:
if not row.startswith("#"):
parts = row.split()
keymap.append((int(parts[0]), parts[1], parts[2]))
with open("../kvmd/kvmd/data/keymap.yaml", "w") as kvmd_yaml_file:
yaml.dump({
js_key: code
for (code, _, js_key) in sorted(keymap, key=operator.itemgetter(2))
}, kvmd_yaml_file, indent=4, default_flow_style=False)
with open("src/keymap.h", "w") as hid_header_file:
hid_header_file.write("#include <HID-Project.h>\n\n#include \"inline.h\"\n\n\n")
hid_header_file.write("INLINE uint8_t keymap(uint8_t code) {\n\tswitch(code) {\n")
for (code, hid_key, _) in sorted(keymap, key=operator.itemgetter(1)):
hid_header_file.write("\t\tcase %d: return %s;\n" % (code, hid_key))
hid_header_file.write("\t\tdefault: return 0;\n\t}\n}")
if __name__ == "__main__":
main()

107
hid/keymap.in Normal file
View File

@ -0,0 +1,107 @@
# https://github.com/NicoHood/HID/blob/master/src/HID-APIs/ImprovedKeylayouts.h
1 KEY_A KeyA
2 KEY_B KeyB
3 KEY_C KeyC
4 KEY_D KeyD
5 KEY_E KeyE
6 KEY_F KeyF
7 KEY_G KeyG
8 KEY_H KeyH
9 KEY_I KeyI
10 KEY_J KeyJ
11 KEY_K KeyK
12 KEY_L KeyL
13 KEY_M KeyM
14 KEY_N KeyN
15 KEY_O KeyO
16 KEY_P KeyP
17 KEY_Q KeyQ
18 KEY_R KeyR
19 KEY_S KeyS
20 KEY_T KeyT
21 KEY_U KeyU
22 KEY_V KeyV
23 KEY_W KeyW
24 KEY_X KeyX
25 KEY_Y KeyY
26 KEY_Z KeyZ
27 KEY_1 Digit1
28 KEY_2 Digit2
29 KEY_3 Digit3
30 KEY_4 Digit4
31 KEY_5 Digit5
32 KEY_6 Digit6
33 KEY_7 Digit7
34 KEY_8 Digit8
35 KEY_9 Digit9
36 KEY_0 Digit0
37 KEY_ENTER Enter
38 KEY_ESC Escape
39 KEY_BACKSPACE Backspace
40 KEY_TAB Tab
41 KEY_SPACE Space
42 KEY_MINUS Minus
43 KEY_EQUAL Equal
44 KEY_LEFT_BRACE BracketLeft
45 KEY_RIGHT_BRACE BracketRight
46 KEY_BACKSLASH Backslash
47 KEY_SEMICOLON Semicolon
48 KEY_QUOTE Quote
49 KEY_TILDE Backquote
50 KEY_COMMA Comma
51 KEY_PERIOD Period
52 KEY_SLASH Slash
53 KEY_CAPS_LOCK CapsLock
54 KEY_F1 F1
55 KEY_F2 F2
56 KEY_F3 F3
57 KEY_F4 F4
58 KEY_F5 F5
59 KEY_F6 F6
60 KEY_F7 F7
61 KEY_F8 F8
62 KEY_F9 F9
63 KEY_F10 F10
64 KEY_F11 F11
65 KEY_F12 F12
66 KEY_PRINT PrintScreen
# KEY_SCROLL_LOCK
# KEY_PAUSE
67 KEY_INSERT Insert
68 KEY_HOME Home
69 KEY_PAGE_UP PageUp
70 KEY_DELETE Delete
71 KEY_END End
72 KEY_PAGE_DOWN PageDown
73 KEY_RIGHT_ARROW ArrowRight
74 KEY_LEFT_ARROW ArrowLeft
75 KEY_DOWN_ARROW ArrowDown
76 KEY_UP_ARROW ArrowUp
# KEY_NUM_LOCK
# KEYPAD_DIVIDE
# KEYPAD_MULTIPLY
# KEYPAD_SUBTRACT
# KEYPAD_ADD
# KEYPAD_ENTER
# KEYPAD_1
# KEYPAD_2
# KEYPAD_3
# KEYPAD_4
# KEYPAD_5
# KEYPAD_6
# KEYPAD_7
# KEYPAD_8
# KEYPAD_9
# KEYPAD_0
# KEYPAD_DOT
# KEY_NON_US
# KEY_APPLICATION
# KEY_MENU
77 KEY_LEFT_CTRL ControlLeft
78 KEY_LEFT_SHIFT ShiftLeft
79 KEY_LEFT_ALT AltLeft
80 KEY_LEFT_GUI MetaLeft
81 KEY_RIGHT_CTRL ControlRight
82 KEY_RIGHT_SHIFT ShiftRight
83 KEY_RIGHT_ALT AltRight
84 KEY_RIGHT_GUI MetaRight

View File

@ -14,3 +14,6 @@ board = micro
framework = arduino
upload_port = /dev/ttyACM0
monitor_baud = 115200
lib_deps =
HID-Project

1
hid/src/inline.h Normal file
View File

@ -0,0 +1 @@
#define INLINE inline __attribute__((always_inline))

94
hid/src/keymap.h Normal file
View File

@ -0,0 +1,94 @@
#include <HID-Project.h>
#include "inline.h"
INLINE uint8_t keymap(uint8_t code) {
switch(code) {
case 36: return KEY_0;
case 27: return KEY_1;
case 28: return KEY_2;
case 29: return KEY_3;
case 30: return KEY_4;
case 31: return KEY_5;
case 32: return KEY_6;
case 33: return KEY_7;
case 34: return KEY_8;
case 35: return KEY_9;
case 1: return KEY_A;
case 2: return KEY_B;
case 46: return KEY_BACKSLASH;
case 39: return KEY_BACKSPACE;
case 3: return KEY_C;
case 53: return KEY_CAPS_LOCK;
case 50: return KEY_COMMA;
case 4: return KEY_D;
case 70: return KEY_DELETE;
case 75: return KEY_DOWN_ARROW;
case 5: return KEY_E;
case 71: return KEY_END;
case 37: return KEY_ENTER;
case 43: return KEY_EQUAL;
case 38: return KEY_ESC;
case 6: return KEY_F;
case 54: return KEY_F1;
case 63: return KEY_F10;
case 64: return KEY_F11;
case 65: return KEY_F12;
case 55: return KEY_F2;
case 56: return KEY_F3;
case 57: return KEY_F4;
case 58: return KEY_F5;
case 59: return KEY_F6;
case 60: return KEY_F7;
case 61: return KEY_F8;
case 62: return KEY_F9;
case 7: return KEY_G;
case 8: return KEY_H;
case 68: return KEY_HOME;
case 9: return KEY_I;
case 67: return KEY_INSERT;
case 10: return KEY_J;
case 11: return KEY_K;
case 12: return KEY_L;
case 79: return KEY_LEFT_ALT;
case 74: return KEY_LEFT_ARROW;
case 44: return KEY_LEFT_BRACE;
case 77: return KEY_LEFT_CTRL;
case 80: return KEY_LEFT_GUI;
case 78: return KEY_LEFT_SHIFT;
case 13: return KEY_M;
case 42: return KEY_MINUS;
case 14: return KEY_N;
case 15: return KEY_O;
case 16: return KEY_P;
case 72: return KEY_PAGE_DOWN;
case 69: return KEY_PAGE_UP;
case 51: return KEY_PERIOD;
case 66: return KEY_PRINT;
case 17: return KEY_Q;
case 48: return KEY_QUOTE;
case 18: return KEY_R;
case 83: return KEY_RIGHT_ALT;
case 73: return KEY_RIGHT_ARROW;
case 45: return KEY_RIGHT_BRACE;
case 81: return KEY_RIGHT_CTRL;
case 84: return KEY_RIGHT_GUI;
case 82: return KEY_RIGHT_SHIFT;
case 19: return KEY_S;
case 47: return KEY_SEMICOLON;
case 52: return KEY_SLASH;
case 41: return KEY_SPACE;
case 20: return KEY_T;
case 40: return KEY_TAB;
case 49: return KEY_TILDE;
case 21: return KEY_U;
case 76: return KEY_UP_ARROW;
case 22: return KEY_V;
case 23: return KEY_W;
case 24: return KEY_X;
case 25: return KEY_Y;
case 26: return KEY_Z;
default: return 0;
}
}

View File

@ -1,35 +1,44 @@
#include <Arduino.h>
#include <Keyboard.h>
#include <HID-Project.h>
#include "inline.h"
#include "keymap.h"
#define CMD_SERIAL Serial1
#define SERIAL_SPEED 115200
#define CMD_SERIAL_SPEED 115200
#define INLINE inline __attribute__((always_inline))
INLINE void cmdResetHid() {
CMD_SERIAL.read(); // unused now
CMD_SERIAL.read(); // unused now
CMD_SERIAL.read(); // unused now
Keyboard.releaseAll();
}
INLINE void cmdKeyEvent() {
uint8_t state = Serial.read();
uint8_t key = Serial.read();
if (state) {
Keyboard.press(key);
} else {
Keyboard.release(key);
uint8_t state = CMD_SERIAL.read();
uint8_t code = keymap(CMD_SERIAL.read());
CMD_SERIAL.read(); // unused now
if (code) {
if (state) {
Keyboard.press(code);
} else {
Keyboard.release(code);
}
}
}
void setup() {
CMD_SERIAL.begin(SERIAL_SPEED);
CMD_SERIAL.begin(CMD_SERIAL_SPEED);
Keyboard.begin();
}
void loop() {
while (true) { // fast
switch (Serial.read()) {
if (CMD_SERIAL.available() >= 4) {
switch ((uint8_t)CMD_SERIAL.read()) {
case 0: cmdResetHid(); break;
case 1: cmdKeyEvent(); break;
default: break;

View File

@ -0,0 +1,84 @@
AltLeft: 79
AltRight: 83
ArrowDown: 75
ArrowLeft: 74
ArrowRight: 73
ArrowUp: 76
Backquote: 49
Backslash: 46
Backspace: 39
BracketLeft: 44
BracketRight: 45
CapsLock: 53
Comma: 50
ControlLeft: 77
ControlRight: 81
Delete: 70
Digit0: 36
Digit1: 27
Digit2: 28
Digit3: 29
Digit4: 30
Digit5: 31
Digit6: 32
Digit7: 33
Digit8: 34
Digit9: 35
End: 71
Enter: 37
Equal: 43
Escape: 38
F1: 54
F10: 63
F11: 64
F12: 65
F2: 55
F3: 56
F4: 57
F5: 58
F6: 59
F7: 60
F8: 61
F9: 62
Home: 68
Insert: 67
KeyA: 1
KeyB: 2
KeyC: 3
KeyD: 4
KeyE: 5
KeyF: 6
KeyG: 7
KeyH: 8
KeyI: 9
KeyJ: 10
KeyK: 11
KeyL: 12
KeyM: 13
KeyN: 14
KeyO: 15
KeyP: 16
KeyQ: 17
KeyR: 18
KeyS: 19
KeyT: 20
KeyU: 21
KeyV: 22
KeyW: 23
KeyX: 24
KeyY: 25
KeyZ: 26
MetaLeft: 80
MetaRight: 84
Minus: 42
PageDown: 72
PageUp: 69
Period: 51
PrintScreen: 66
Quote: 48
Semicolon: 47
ShiftLeft: 78
ShiftRight: 82
Slash: 52
Space: 41
Tab: 40

View File

@ -1,13 +1,14 @@
import re
import asyncio
import multiprocessing
import multiprocessing.queues
import queue
import pkgutil
from typing import Dict
from typing import Set
from typing import NamedTuple
from typing import Union
import yaml
import serial
from .logging import get_logger
@ -16,50 +17,23 @@ from . import gpio
# =====
def _get_keymap() -> Dict[str, int]:
return yaml.load(pkgutil.get_data(__name__, "data/keymap.yaml").decode()) # type: ignore
_KEYMAP = _get_keymap()
def _keymap(key: str) -> bytes:
code = _KEYMAP.get(key)
return (bytes([code]) if code else b"") # type: ignore
class _KeyEvent(NamedTuple):
key: str
state: bool
def _key_to_bytes(key: str) -> bytes:
# https://www.arduino.cc/reference/en/language/functions/usb/keyboard/
# Also locate Keyboard.h
match = re.match(r"(Digit|Key)([0-9A-Z])", key)
code: Union[str, int, None]
if match:
code = match.group(2)
else:
code = { # type: ignore
"Escape": 0xB1, "Backspace": 0xB2,
"Tab": 0xB3, "Enter": 0xB0,
"Insert": 0xD1, "Delete": 0xD4,
"Home": 0xD2, "End": 0xD5,
"PageUp": 0xD3, "PageDown": 0xD6,
"ArrowLeft": 0xD8, "ArrowRight": 0xD7,
"ArrowUp": 0xDA, "ArrowDown": 0xD9,
"CapsLock": 0xC1,
"ShiftLeft": 0x81, "ShiftRight": 0x85,
"ControlLeft": 0x80, "ControlRight": 0x84,
"AltLeft": 0x82, "AltRight": 0x86,
"MetaLeft": 0x83, "MetaRight": 0x87,
"Backquote": "`", "Minus": "-", "Equal": "=", "Space": " ",
"BracketLeft": "[", "BracketRight": "]", "Semicolon": ";", "Quote": "'",
"Comma": ",", "Period": ".", "Slash": "/", "Backslash": "\\",
"F1": 0xC2, "F2": 0xC3, "F3": 0xC4, "F4": 0xC5,
"F5": 0xC6, "F6": 0xC7, "F7": 0xC8, "F8": 0xC9,
"F9": 0xCA, "F10": 0xCB, "F11": 0xCC, "F12": 0xCD,
}.get(key)
if isinstance(code, str):
return bytes(code, encoding="ascii") # type: ignore
elif isinstance(code, int):
return bytes([code])
return b""
class Hid(multiprocessing.Process):
def __init__(
self,
@ -138,14 +112,15 @@ class Hid(multiprocessing.Process):
raise
def __send_key_event(self, tty: serial.Serial, event: _KeyEvent) -> None:
key_bytes = _key_to_bytes(event.key)
key_bytes = _keymap(event.key)
if key_bytes:
assert len(key_bytes) == 1, (event, key_bytes)
tty.write(
b"\01"
+ (b"\01" if event.state else b"\00")
+ key_bytes
+ b"\00"
)
def __send_clear_hid(self, tty: serial.Serial) -> None:
tty.write(b"\00")
tty.write(b"\00\00\00\00")

View File

@ -26,6 +26,10 @@ def main() -> None:
"kvmd.extras.wscli",
],
package_data={
"kvmd": ["data/*.yaml"],
},
entry_points={
"console_scripts": [
"kvmd = kvmd:main",

View File

@ -11,6 +11,10 @@ COPY stages/pikvm/config.txt /boot/
COPY stages/pikvm/sysctl.conf /etc/sysctl.d/99-pikvm.conf
COPY stages/pikvm/udev.rules /etc/udev/rules.d/pikvm.rules
RUN sed -i -e "s/console=ttyAMA0\,115200//g" /boot/cmdline.txt \
&& sed -i -e "s/kgdboc=ttyAMA0\,115200//g" /boo/cmdline.txt
RUN systemctl mask serial-getty@ttyAMA0.service
RUN cp /usr/share/kvmd/configs/nginx/nginx.conf /etc/nginx/
RUN cp /usr/share/kvmd/configs/kvmd/v1.yaml /etc/kvmd.yaml