From 72025093c5d614ea2e20e9b831217075ae1967e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Krac=C3=ADk?= Date: Sun, 24 May 2020 12:44:34 +0200 Subject: [PATCH] Hid: JS keycode, HID keycode, mapping, sending --- hidinput.py | 83 ++++++++++++----- hidkeycodes.py | 181 ++++++++++++++++++++++++++++++++++++ jskeycodes.py | 243 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 485 insertions(+), 22 deletions(-) create mode 100644 hidkeycodes.py create mode 100644 jskeycodes.py diff --git a/hidinput.py b/hidinput.py index 9b8ccac..76b0a39 100644 --- a/hidinput.py +++ b/hidinput.py @@ -1,10 +1,16 @@ from flask import Response from flask import Flask from flask import render_template +from flask import request import threading import argparse import datetime import time +import json + +from hidkeycodes import hidkeycodes +from jskeycodes import jskeycodes + lock = threading.Lock() @@ -14,10 +20,10 @@ app = Flask(__name__) NULL = chr(0) hiddev = None -def init(): +def hid_init(): hiddev=open('/dev/hidg0', 'rb+') -def hidwrite(data): +def hid_write(data): if hiddev is None: return False @@ -27,12 +33,26 @@ def hidwrite(data): def send_key(hidkey, shift, alt, ctlr, superkey): # TODO handle mod keys - hidwrite(NULL*2+chr(hidkey)+NULL*5) - hidwrite(NULL*8) + hid_write(NULL*2+chr(hidkey)+NULL*5) + hid_write(NULL*8) -def get_hid_by_scancode(scancode): - +def get_hid_by_jscode(rawkeycode): + hidkeycode = None + hidkeyname = None + + if rawkeycode in jskeycodes.values(): + hidkeyname = list(jskeycodes.keys())[list(jskeycodes.values()).index(rawkeycode)] + if hidkeyname in hidkeycodes: + hidkeycode = hidkeycodes[hidkeyname] + else: + print("Code for key {} not found in HID mapping".format(hidkeyname)) + else: + print("Javascript code for key {} not found".format(rawkeycode)) + + print ("JS key: {} HID key: {}({})".format(rawkeycode, hidkeyname, hidkeycode)) + + return hidkeycode @app.route("/") def index(): @@ -41,27 +61,46 @@ def index(): @app.route("/hid/keyboard", methods=["POST"]) def keypress(): - return Response("Stisknuto ", mimetype = "text/plain") + keyevent = json.loads(request.data) + print ("Raw data: {}".format(request.data)) + + rawkeycode = keyevent['code'] + hidkeycode = get_hid_by_jscode(rawkeycode) + + if hidkeycode is not None: + try: + send_key( + hidkeycode, + keyevent['shiftKey'], + keyevent['altKey'], + keyevent['ctrlKey'], + False) + except Exception as e: + print("Error sending HID message", e) + + return Response("Press {}".format(hidkeycode), mimetype = "text/plain") # check to see if this is the main thread of execution if __name__ == '__main__': - # construct the argument parser and parse command line arguments - ap = argparse.ArgumentParser() - ap.add_argument("-i", "--ip", type=str, required=True, - help="ip address of the device") - ap.add_argument("-o", "--port", type=int, required=True, - help="ephemeral port number of the server (1024 to 65535)") - ap.add_argument("-f", "--frame-count", type=int, default=32, - help="# of frames used to construct the background model") - args = vars(ap.parse_args()) + # construct the argument parser and parse command line arguments + ap = argparse.ArgumentParser() + ap.add_argument("-i", "--ip", type=str, required=True, + help="ip address of the device") + ap.add_argument("-o", "--port", type=int, required=True, + help="ephemeral port number of the server (1024 to 65535)") + ap.add_argument("-f", "--frame-count", type=int, default=32, + help="# of frames used to construct the background model") + args = vars(ap.parse_args()) - app.run(host=args["ip"], port=args["port"], debug=True, - threaded=True, use_reloader=False) + hid_init() + + app.run(host=args["ip"], port=args["port"], debug=True, + threaded=True, use_reloader=False) - # Clean up - if hiddev is not None: - print("Closing hid") - hiddev.close() + # Clean up + if hiddev is not None: + print("Closing hid") + hiddev.close() diff --git a/hidkeycodes.py b/hidkeycodes.py new file mode 100644 index 0000000..f804931 --- /dev/null +++ b/hidkeycodes.py @@ -0,0 +1,181 @@ + +hidkeycodes = { + 'KEY_MOD_LCTRL': '0x01', + 'KEY_MOD_LSHIFT': '0x02', + 'KEY_MOD_LALT': '0x04', + 'KEY_MOD_LMETA': '0x08', + 'KEY_MOD_RCTRL': '0x10', + 'KEY_MOD_RSHIFT': '0x20', + 'KEY_MOD_RALT': '0x40', + 'KEY_MOD_RMETA': '0x80', + 'KEY_NONE': '0x00', + 'KEY_ERR_OVF': '0x01', + 'KEY_A': '0x04', + 'KEY_B': '0x05', + 'KEY_C': '0x06', + 'KEY_D': '0x07', + 'KEY_E': '0x08', + 'KEY_F': '0x09', + 'KEY_G': '0x0a', + 'KEY_H': '0x0b', + 'KEY_I': '0x0c', + 'KEY_J': '0x0d', + 'KEY_K': '0x0e', + 'KEY_L': '0x0f', + 'KEY_M': '0x10', + 'KEY_N': '0x11', + 'KEY_O': '0x12', + 'KEY_P': '0x13', + 'KEY_Q': '0x14', + 'KEY_R': '0x15', + 'KEY_S': '0x16', + 'KEY_T': '0x17', + 'KEY_U': '0x18', + 'KEY_V': '0x19', + 'KEY_W': '0x1a', + 'KEY_X': '0x1b', + 'KEY_Y': '0x1c', + 'KEY_Z': '0x1d', + 'KEY_1': '0x1e', + 'KEY_2': '0x1f', + 'KEY_3': '0x20', + 'KEY_4': '0x21', + 'KEY_5': '0x22', + 'KEY_6': '0x23', + 'KEY_7': '0x24', + 'KEY_8': '0x25', + 'KEY_9': '0x26', + 'KEY_0': '0x27', + 'KEY_ENTER': '0x28', + 'KEY_ESC': '0x29', + 'KEY_BACKSPACE': '0x2a', + 'KEY_TAB': '0x2b', + 'KEY_SPACE': '0x2c', + 'KEY_MINUS': '0x2d', + 'KEY_EQUAL': '0x2e', + 'KEY_LEFTBRACE': '0x2f', + 'KEY_RIGHTBRACE': '0x30', + 'KEY_BACKSLASH': '0x31', + 'KEY_HASHTILDE': '0x32', + 'KEY_SEMICOLON': '0x33', + 'KEY_APOSTROPHE': '0x34', + 'KEY_GRAVE': '0x35', + 'KEY_COMMA': '0x36', + 'KEY_DOT': '0x37', + 'KEY_SLASH': '0x38', + 'KEY_CAPSLOCK': '0x39', + 'KEY_F1': '0x3a', + 'KEY_F2': '0x3b', + 'KEY_F3': '0x3c', + 'KEY_F4': '0x3d', + 'KEY_F5': '0x3e', + 'KEY_F6': '0x3f', + 'KEY_F7': '0x40', + 'KEY_F8': '0x41', + 'KEY_F9': '0x42', + 'KEY_F10': '0x43', + 'KEY_F11': '0x44', + 'KEY_F12': '0x45', + 'KEY_SYSRQ': '0x46', + 'KEY_SCROLLLOCK': '0x47', + 'KEY_PAUSE': '0x48', + 'KEY_INSERT': '0x49', + 'KEY_HOME': '0x4a', + 'KEY_PAGEUP': '0x4b', + 'KEY_DELETE': '0x4c', + 'KEY_END': '0x4d', + 'KEY_PAGEDOWN': '0x4e', + 'KEY_RIGHT': '0x4f', + 'KEY_LEFT': '0x50', + 'KEY_DOWN': '0x51', + 'KEY_UP': '0x52', + 'KEY_NUMLOCK': '0x53', + 'KEY_KPSLASH': '0x54', + 'KEY_KPASTERISK': '0x55', + 'KEY_KPMINUS': '0x56', + 'KEY_KPPLUS': '0x57', + 'KEY_KPENTER': '0x58', + 'KEY_KP1': '0x59', + 'KEY_KP2': '0x5a', + 'KEY_KP3': '0x5b', + 'KEY_KP4': '0x5c', + 'KEY_KP5': '0x5d', + 'KEY_KP6': '0x5e', + 'KEY_KP7': '0x5f', + 'KEY_KP8': '0x60', + 'KEY_KP9': '0x61', + 'KEY_KP0': '0x62', + 'KEY_KPDOT': '0x63', + 'KEY_102ND': '0x64', + 'KEY_COMPOSE': '0x65', + 'KEY_POWER': '0x66', + 'KEY_KPEQUAL': '0x67', + 'KEY_F13': '0x68', + 'KEY_F14': '0x69', + 'KEY_F15': '0x6a', + 'KEY_F16': '0x6b', + 'KEY_F17': '0x6c', + 'KEY_F18': '0x6d', + 'KEY_F19': '0x6e', + 'KEY_F20': '0x6f', + 'KEY_F21': '0x70', + 'KEY_F22': '0x71', + 'KEY_F23': '0x72', + 'KEY_F24': '0x73', + 'KEY_OPEN': '0x74', + 'KEY_HELP': '0x75', + 'KEY_PROPS': '0x76', + 'KEY_FRONT': '0x77', + 'KEY_STOP': '0x78', + 'KEY_AGAIN': '0x79', + 'KEY_UNDO': '0x7a', + 'KEY_CUT': '0x7b', + 'KEY_COPY': '0x7c', + 'KEY_PASTE': '0x7d', + 'KEY_FIND': '0x7e', + 'KEY_MUTE': '0x7f', + 'KEY_VOLUMEUP': '0x80', + 'KEY_VOLUMEDOWN': '0x81', + 'KEY_KPCOMMA': '0x85', + 'KEY_RO': '0x87', + 'KEY_KATAKANAHIRAGANA': '0x88', + 'KEY_YEN': '0x89', + 'KEY_HENKAN': '0x8a', + 'KEY_MUHENKAN': '0x8b', + 'KEY_KPJPCOMMA': '0x8c', + 'KEY_HANGEUL': '0x90', + 'KEY_HANJA': '0x91', + 'KEY_KATAKANA': '0x92', + 'KEY_HIRAGANA': '0x93', + 'KEY_ZENKAKUHANKAKU': '0x94', + 'KEY_KPLEFTPAREN': '0xb6', + 'KEY_KPRIGHTPAREN': '0xb7', + 'KEY_LEFTCTRL': '0xe0', + 'KEY_LEFTSHIFT': '0xe1', + 'KEY_LEFTALT': '0xe2', + 'KEY_LEFTWINDOWS': '0xe3', + 'KEY_RIGHTCTRL': '0xe4', + 'KEY_RIGHTSHIFT': '0xe5', + 'KEY_RIGHTALT': '0xe6', + 'KEY_RIGHTMETA': '0xe7', + 'KEY_MEDIA_PLAYPAUSE': '0xe8', + 'KEY_MEDIA_STOPCD': '0xe9', + 'KEY_MEDIA_PREVIOUSSONG': '0xea', + 'KEY_MEDIA_NEXTSONG': '0xeb', + 'KEY_MEDIA_EJECTCD': '0xec', + 'KEY_MEDIA_VOLUMEUP': '0xed', + 'KEY_MEDIA_VOLUMEDOWN': '0xee', + 'KEY_MEDIA_MUTE': '0xef', + 'KEY_MEDIA_WWW': '0xf0', + 'KEY_MEDIA_BACK': '0xf1', + 'KEY_MEDIA_FORWARD': '0xf2', + 'KEY_MEDIA_STOP': '0xf3', + 'KEY_MEDIA_FIND': '0xf4', + 'KEY_MEDIA_SCROLLUP': '0xf5', + 'KEY_MEDIA_SCROLLDOWN': '0xf6', + 'KEY_MEDIA_EDIT': '0xf7', + 'KEY_MEDIA_SLEEP': '0xf8', + 'KEY_MEDIA_COFFEE': '0xf9', + 'KEY_MEDIA_REFRESH': '0xfa', + 'KEY_MEDIA_CALC': '0xfb', + } diff --git a/jskeycodes.py b/jskeycodes.py new file mode 100644 index 0000000..755a35b --- /dev/null +++ b/jskeycodes.py @@ -0,0 +1,243 @@ + +jskeycodes = { + 'KEY_A': 'KeyA', + 'KEY_B': 'KeyB', + 'KEY_C': 'KeyC', + 'KEY_D': 'KeyD', + 'KEY_E': 'KeyE', + 'KEY_F': 'KeyF', + 'KEY_G': 'KeyG', + 'KEY_H': 'KeyH', + 'KEY_I': 'KeyI', + 'KEY_J': 'KeyJ', + 'KEY_K': 'KeyK', + 'KEY_L': 'KeyL', + 'KEY_M': 'KeyM', + 'KEY_N': 'KeyN', + 'KEY_O': 'KeyO', + 'KEY_P': 'KeyP', + 'KEY_Q': 'KeyQ', + 'KEY_R': 'KeyR', + 'KEY_S': 'KeyS', + 'KEY_T': 'KeyT', + 'KEY_U': 'KeyU', + 'KEY_V': 'KeyV', + 'KEY_W': 'KeyW', + 'KEY_X': 'KeyX', + 'KEY_Y': 'KeyY', + 'KEY_Z': 'KeyZ', + + 'KEY_GRAVE': 'Backquote', + + 'KEY_0': 'Digit0', + 'KEY_1': 'Digit1', + 'KEY_2': 'Digit2', + 'KEY_3': 'Digit3', + 'KEY_4': 'Digit4', + 'KEY_5': 'Digit5', + 'KEY_6': 'Digit6', + 'KEY_7': 'Digit7', + 'KEY_8': 'Digit8', + 'KEY_9': 'Digit9', + + 'KEY_MINUS': 'Minus', + 'KEY_EQUAL': 'Equal', + + 'KEY_LEFTBRACE': 'BracketLeft', + 'KEY_RIGHTBRACE': 'BracketRight', + + 'KEY_SEMICOLON': 'Semicolon', + 'KEY_APOSTROPHE': 'Quote', + 'KEY_BACKSLASH': 'Backslash', + + 'KEY_COMMA': 'Comma', + 'KEY_DOT': 'Period', + 'KEY_SLASH': 'Slash', + + 'KEY_102ND': 'IntlBackslash', + + 'KEY_KP0': 'Numpad0', + 'KEY_KP1': 'Numpad1', + 'KEY_KP2': 'Numpad2', + 'KEY_KP3': 'Numpad3', + 'KEY_KP4': 'Numpad4', + 'KEY_KP5': 'Numpad5', + 'KEY_KP6': 'Numpad6', + 'KEY_KP7': 'Numpad7', + 'KEY_KP8': 'Numpad8', + 'KEY_KP9': 'Numpad9', + 'KEY_KPASTERISK': 'NumpadMultiply', + 'KEY_KPPLUS': 'NumpadAdd', + 'KEY_KPMINUS': 'NumpadSubtract', + 'KEY_KPDOT': 'NumpadDecimal', + 'KEY_KPSLASH': 'NumpadDivide', + 'KEY_KPENTER': 'NumpadEnter', + + 'KEY_ESC': 'Escape', + 'KEY_F1': 'F1', + 'KEY_F2': 'F2', + 'KEY_F3': 'F3', + 'KEY_F4': 'F4', + 'KEY_F5': 'F5', + 'KEY_F6': 'F6', + 'KEY_F7': 'F7', + 'KEY_F8': 'F8', + 'KEY_F9': 'F9', + 'KEY_F10': 'F10', + 'KEY_F11': 'F11', + 'KEY_F12': 'F12', + 'KEY_F13': 'F13', + 'KEY_F14': 'F14', + 'KEY_F15': 'F15', + 'KEY_F16': 'F16', + 'KEY_F17': 'F17', + 'KEY_F18': 'F18', + 'KEY_F19': 'F19', + 'KEY_F20': 'F20', + 'KEY_F21': 'F21', + 'KEY_F22': 'F22', + 'KEY_F23': 'F23', + + 'KEY_BACKSPACE': 'Backspace', + 'KEY_SPACE': 'Space', + 'KEY_TAB': 'Tab', + 'KEY_ENTER' : 'Enter', + + 'KEY_PAGEUP': 'PageUp', + 'KEY_PAGEDOWN': 'PageDown', + 'KEY_HOME': 'Home', + 'KEY_END': 'End', + 'KEY_INSERT': 'Insert', + 'KEY_DELETE': 'Delete', + + 'KEY_UP': 'ArrowUp', + 'KEY_DOWN': 'ArrowDown', + 'KEY_LEFT': 'ArrowLeft', + 'KEY_RIGHT': 'ArrowRight', + + 'KEY_NUMLOCK': 'NumLock', + 'KEY_CAPSLOCK': 'CapsLock', + 'KEY_SCROLLLOCK': 'ScrollLock', + + 'KEY_LEFTWINDOWS': 'MetaLeft', + 'KEY_RIGHTMETA': 'ContextMenu', +} + +jskeywhich = { + 'KEY_CANCEL': 3, + 'KEY_BACKSPACE': 8, + 'KEY_TAB': 9, + 'KEY_CLEAR': 12, + 'KEY_ENTER': 13, + 'KEY_...': 14, + 'KEY_SHIFT': 16, + 'KEY_CONTROL': 17, + 'KEY_ALT': 18, + 'KEY_PAUSE': 19, + 'KEY_CAPSLOCK': 20, + 'KEY_ESC': 27, + 'KEY_SPACE': 32, + 'KEY_PAGEUP': 33, + 'KEY_PAGEDOWN': 34, + 'KEY_END': 35, + 'KEY_HOME': 36, + 'KEY_LEFT': 37, + 'KEY_UP': 38, + 'KEY_RIGHT': 39, + 'KEY_DOWN': 40, + 'KEY_PRINTSCREEN': 44, + 'KEY_INSERT': 45, + 'KEY_DELETE': 46, + 'KEY_0': 48, + 'KEY_1': 49, + 'KEY_2': 50, + 'KEY_3': 51, + 'KEY_4': 52, + 'KEY_5': 53, + 'KEY_6': 54, + 'KEY_7': 55, + 'KEY_8': 56, + 'KEY_9': 57, + 'KEY_SEMICOLON': 59, + 'KEY_EQUAL': 61, + 'KEY_A': 65, + 'KEY_B': 66, + 'KEY_C': 67, + 'KEY_D': 68, + 'KEY_E': 69, + 'KEY_F': 70, + 'KEY_G': 71, + 'KEY_H': 72, + 'KEY_I': 73, + 'KEY_J': 74, + 'KEY_K': 75, + 'KEY_L': 76, + 'KEY_M': 77, + 'KEY_N': 78, + 'KEY_O': 79, + 'KEY_P': 80, + 'KEY_Q': 81, + 'KEY_R': 82, + 'KEY_S': 83, + 'KEY_T': 84, + 'KEY_U': 85, + 'KEY_V': 86, + 'KEY_W': 87, + 'KEY_X': 88, + 'KEY_Y': 89, + 'KEY_Z': 90, + 'KEY_CONTEXTMENU': 93, + 'KEY_NP0': 96, + 'KEY_NP1': 97, + 'KEY_NP2': 98, + 'KEY_NP3': 99, + 'KEY_NP4': 100, + 'KEY_NP5': 101, + 'KEY_NP6': 102, + 'KEY_NP7': 103, + 'KEY_NP8': 104, + 'KEY_NP9': 105, + 'KEY_KPASTERISK': 106, + 'KEY_KPPLUS': 107, + 'KEY_SEPARATOR': 108, + 'KEY_KPMINUS': 109, + 'KEY_KPDOT': 110, + 'KEY_KPSLASH': 111, + 'KEY_F1': 112, + 'KEY_F2': 113, + 'KEY_F3': 114, + 'KEY_F4': 115, + 'KEY_F5': 116, + 'KEY_F6': 117, + 'KEY_F7': 118, + 'KEY_F8': 119, + 'KEY_F9': 120, + 'KEY_F10': 121, + 'KEY_F11': 122, + 'KEY_F12': 123, + 'KEY_F13': 124, + 'KEY_F14': 125, + 'KEY_F15': 126, + 'KEY_F16': 127, + 'KEY_F17': 128, + 'KEY_F18': 129, + 'KEY_F19': 130, + 'KEY_F20': 131, + 'KEY_F21': 132, + 'KEY_F22': 133, + 'KEY_F23': 134, + 'KEY_F24': 135, + 'KEY_NUMLOCK': 144, + 'KEY_SCROLLLOCK': 145, + 'KEY_FIND': 170, + 'KEY_COMMA': 188, + 'KEY_MINUS': 189, + 'KEY_DOT': 190, + 'KEY_SLASH': 191, + 'KEY_GRAVE': 192, + 'KEY_LEFTBRACE': 219, + 'KEY_BACKSLASH': 220, + 'KEY_RIGHTBRACE': 221, + 'KEY_APOSTROPHE': 222, + 'KEY_META': 224 +}