Compare commits

...

13 Commits

7 changed files with 361 additions and 313 deletions

View File

@ -9,6 +9,7 @@ echo "" > UDC
echo "Clean up configs" echo "Clean up configs"
rm configs/c.1/hid.kbd0 rm configs/c.1/hid.kbd0
rm configs/c.1/hid.mouse0 rm configs/c.1/hid.mouse0
rm configs/c.1/hid.mouse1
rm configs/c.1/mass_storage.disk1 rm configs/c.1/mass_storage.disk1
rm configs/c.1/mass_storage.cdrom1 rm configs/c.1/mass_storage.cdrom1
@ -18,6 +19,7 @@ rmdir configs/c.1
echo "Clean up functions" echo "Clean up functions"
rmdir functions/hid.kbd0 rmdir functions/hid.kbd0
rmdir functions/hid.mouse0 rmdir functions/hid.mouse0
rmdir functions/hid.mouse1
rmdir functions/mass_storage.disk1 rmdir functions/mass_storage.disk1
rmdir functions/mass_storage.cdrom1 rmdir functions/mass_storage.cdrom1

View File

@ -5,6 +5,40 @@ gserial=$(awk '/Serial/ { print $3 }' /proc/cpuinfo)
gmanufacturer="Petrkr.NET" gmanufacturer="Petrkr.NET"
gproduct="rPi KVM" gproduct="rPi KVM"
#Mouse 0 relative descriptor
MOUSE0=""
MOUSE0="$MOUSE0\\x05\\x01\\x09\\x02" # Usage generic desktop, Usage mouse
MOUSE0="$MOUSE0\\xa1\\x01\\x09\\x01" # Collection App, Usage Pointer
MOUSE0="$MOUSE0\\xa1\\x00" # Collection Physical
MOUSE0="$MOUSE0\\x05\\x09" # Use Page buttons
MOUSE0="$MOUSE0\\x19\\x01\\x29\\x08\\x15\\x00\\x25\\x01\\x75\\x01\\x95\\x08" # Usage min 1, max 8, logical min 0, max 1, report 8, size 1
MOUSE0="$MOUSE0\\x81\\x02" # Input data, variable, absolute
MOUSE0="$MOUSE0\\x05\\x01" # Usage page generic desktop
MOUSE0="$MOUSE0\\x09\\x30\\x09\\x31\\x09\\x38\\x15\\x81\\x25\\x7f\\x75\\x08\\x95\\x03" # Usage X,Y,Wheel, Log min -127, log max 127, size 8, report 3
MOUSE0="$MOUSE0\\x81\\x02" # Input data, variable, absolute
MOUSE0="$MOUSE0\\xc0" # End collection Physical
MOUSE0="$MOUSE0\\xc0" # End collection Application
#Mouse 1 absolute descriptor
MOUSE1=""
MOUSE1="$MOUSE1\\x05\\x01\\x09\\x02" # Usage generic desktop, Usage mouse
MOUSE1="$MOUSE1\\xa1\\x01\\x09\\x01" # Collection App, Usage Pointer
MOUSE1="$MOUSE1\\xa1\\x00" # Collection Physical
MOUSE1="$MOUSE1\\x05\\x09" # Use Page buttons
MOUSE1="$MOUSE1\\x19\\x01\\x29\\x08\\x15\\x00\\x25\\x01\\x75\\x01\\x95\\x08" # Usage min 1, max 8, logical min 0, max 1, report 8, size 1
MOUSE1="$MOUSE1\\x81\\x02" # Input data, variable, absolute
MOUSE1="$MOUSE1\\x05\\x01" # Usage page generic desktop
MOUSE1="$MOUSE1\\x09\\x30\\x16\\x00\\x00\\x26\\x80\\x07\\x75\\x10\\x95\\x01" # Usage X, Log min 0, log max 1920, size 16, report 1
MOUSE1="$MOUSE1\\x81\\x02" # Input data, variable, absolute
MOUSE1="$MOUSE1\\x05\\x01" # Usage page generic desktop
MOUSE1="$MOUSE1\\x09\\x31\\x16\\x00\\x00\\x26\\x38\\x04\\x75\\x10\\x95\\x01" # Usage Y, Log min 0, log max 1080, size 16, report 1
MOUSE1="$MOUSE1\\x81\\x02" # Input data, variable, absolute
MOUSE1="$MOUSE1\\x05\\x01" # Usage page generic desktop
MOUSE1="$MOUSE1\\x09\\x38\\x15\\x81\\x25\\x7f\\x75\\x08\\x95\\x01" # Usage Wheel, log min -127, max 127, size 8, report 1
MOUSE1="$MOUSE1\\x81\\x06" # Input data, variable, relative
MOUSE1="$MOUSE1\\xc0" # End collection Physical
MOUSE1="$MOUSE1\\xc0" # End collection Application
cd /sys/kernel/config/usb_gadget/ cd /sys/kernel/config/usb_gadget/
mkdir -p $gname mkdir -p $gname
cd $gname cd $gname
@ -22,7 +56,7 @@ echo "$gmanufacturer" > strings/0x409/manufacturer
echo "$gproduct" > strings/0x409/product echo "$gproduct" > strings/0x409/product
mkdir -p configs/c.1/strings/0x409 mkdir -p configs/c.1/strings/0x409
echo "Config: HID KBD" > configs/c.1/strings/0x409/configuration echo "Config: KVM Composite" > configs/c.1/strings/0x409/configuration
echo 250 > configs/c.1/MaxPower echo 250 > configs/c.1/MaxPower
echo "Creating usb devices" echo "Creating usb devices"
@ -34,12 +68,19 @@ echo 1 > functions/hid.kbd0/subclass
echo 8 > functions/hid.kbd0/report_length echo 8 > functions/hid.kbd0/report_length
echo -ne \\x05\\x01\\x09\\x06\\xa1\\x01\\x05\\x07\\x19\\xe0\\x29\\xe7\\x15\\x00\\x25\\x01\\x75\\x01\\x95\\x08\\x81\\x02\\x95\\x01\\x75\\x08\\x81\\x03\\x95\\x05\\x75\\x01\\x05\\x08\\x19\\x01\\x29\\x05\\x91\\x02\\x95\\x01\\x75\\x03\\x91\\x03\\x95\\x06\\x75\\x08\\x15\\x00\\x25\\xff\\x05\\x07\\x19\\x00\\x29\\x65\\x81\\x00\\xc0 > functions/hid.kbd0/report_desc echo -ne \\x05\\x01\\x09\\x06\\xa1\\x01\\x05\\x07\\x19\\xe0\\x29\\xe7\\x15\\x00\\x25\\x01\\x75\\x01\\x95\\x08\\x81\\x02\\x95\\x01\\x75\\x08\\x81\\x03\\x95\\x05\\x75\\x01\\x05\\x08\\x19\\x01\\x29\\x05\\x91\\x02\\x95\\x01\\x75\\x03\\x91\\x03\\x95\\x06\\x75\\x08\\x15\\x00\\x25\\xff\\x05\\x07\\x19\\x00\\x29\\x65\\x81\\x00\\xc0 > functions/hid.kbd0/report_desc
echo " HID Mouse" echo " HID Mouse Relative"
mkdir -p functions/hid.mouse0 mkdir -p functions/hid.mouse0
echo 2 > functions/hid.mouse0/protocol echo 2 > functions/hid.mouse0/protocol
echo 1 > functions/hid.mouse0/subclass echo 1 > functions/hid.mouse0/subclass
echo 8 > functions/hid.mouse0/report_length echo 8 > functions/hid.mouse0/report_length
echo -ne \\x05\\x01\\x09\\x02\\xa1\\x01\\x09\\x01\\xa1\\x00\\x05\\x09\\x19\\x01\\x29\\x08\\x15\\x00\\x25\\x01\\x95\\x08\\x75\\x01\\x81\\x02\\x05\\x01\\x09\\x30\\x09\\x31\\x09\\x38\\x15\\x81\\x25\\x7f\\x75\\x08\\x95\\x03\\x81\\x06\\xc0\\xc0 > functions/hid.mouse0/report_desc echo -ne $MOUSE0 > functions/hid.mouse0/report_desc
echo " HID Mouse Absolute"
mkdir -p functions/hid.mouse1
echo 2 > functions/hid.mouse1/protocol
echo 1 > functions/hid.mouse1/subclass
echo 8 > functions/hid.mouse1/report_length
echo -ne $MOUSE1 > functions/hid.mouse1/report_desc
echo " Mass storage" echo " Mass storage"
@ -54,9 +95,15 @@ echo 1 > functions/mass_storage.cdrom1/lun.0/removable
echo "Activating gadgeds" echo "Activating gadgeds"
ln -s functions/hid.kbd0 configs/c.1/ ln -s functions/hid.kbd0 configs/c.1/
ln -s functions/hid.mouse0 configs/c.1/ ln -s functions/hid.mouse0 configs/c.1/
ln -s functions/hid.mouse1 configs/c.1/
ln -s functions/mass_storage.disk1 configs/c.1/ ln -s functions/mass_storage.disk1 configs/c.1/
ln -s functions/mass_storage.cdrom1 configs/c.1/ ln -s functions/mass_storage.cdrom1 configs/c.1/
echo "Turn on gadget" echo "Turn on gadget"
ls /sys/class/udc > UDC ls /sys/class/udc > UDC
echo "Change permissions"
chgrp input /dev/hidg0; chmod 660 /dev/hidg0
chgrp input /dev/hidg1; chmod 660 /dev/hidg1
chgrp input /dev/hidg2; chmod 660 /dev/hidg2

55
hid_descriptors.txt Normal file
View File

@ -0,0 +1,55 @@
05 01 // Usage page Generic desktop
09 02 // Usage Mouse
a1 01 // Collection Application
09 01 // Usage Pointer
a1 00 // Collection Physical
05 09 // Usage Page Buttons
19 01 // Usage Min 01
29 08 // Usage Max 08
15 00 // Logical min 0
25 01 // Logical max 1
95 08 // Report count 8
75 01 // Report size 1
81 02 // Input Data, Variable, Absolute
05 01 // Usage Page Generic Desktop
09 30 // Usage X
09 31 // Usage Y
15 00 // Logical Min ( 0)
25 FF // Logical Max ( 255)
75 08 // Report size 8
95 02 // Report count 2
81 02 // Input Data, Variable, Absolute
05 01 // Usage Page Generic Desktop
09 38 // Usage Wheel
15 81 // Logical Min (-127)
25 7f // Logical Max ( 127)
75 08 // Report size 8
95 01 // Report count 1
81 06 // Input Data, Variable, Relative
c0 // End collection
c0 // End collection
input bytes (4 bytes)
0 - 0 data / 1 constant
1 - 0 array / 1 variable
2 - 0 absolute / 1 relative
3 - 0 no wrap / 1 wrap
4 - 0 linear / 1 non linear
5 - 0 prefered state / 1 no preferred
6 - 0 no null pos / 1 null state
7 - 0 non volatile / 1 volatile
8 - 0 bit field / 1 buffered bytes
9 - 31 reserved
00000110
|||
||\ --> data
|\--> variable
\--> relative

View File

@ -4,12 +4,10 @@ from flask import render_template
from flask import request from flask import request
import threading import threading
import argparse import argparse
import datetime
import time
import json import json
from hidkeycodes import hidkeycodes from hidkeycodes import hidkeycodes
from jskeycodes import jskeycodes from jskeycodes import jscodehidmap
lock = threading.Lock() lock = threading.Lock()
@ -19,11 +17,15 @@ app = Flask(__name__)
hiddev = None hiddev = None
hidmouse = None hidmouse = None
hidmouseabs = None
def hid_init(): def hid_init():
global hiddev, hidmouse global hiddev, hidmouse, hidmouseabs
hiddev=open('/dev/hidg0', 'rb+') hiddev = open('/dev/hidg0', 'rb+')
hidmouse=open('/dev/hidg1', 'rb+') hidmouse = open('/dev/hidg1', 'rb+')
hidmouseabs = open('/dev/hidg2', 'rb+')
def hid_write(data): def hid_write(data):
if hiddev is None: if hiddev is None:
@ -32,6 +34,7 @@ def hid_write(data):
hiddev.write(data) hiddev.write(data)
hiddev.flush() hiddev.flush()
def hid_mouse_write(btn, x, y, wheel): def hid_mouse_write(btn, x, y, wheel):
if hidmouse is None: if hidmouse is None:
return False return False
@ -46,7 +49,21 @@ def hid_mouse_write(btn, x, y, wheel):
hidmouse.flush() hidmouse.flush()
def send_key(hidkey, shift, alt, ctlr): def hid_mouse_writeabs(btn, x, y, wheel):
if hidmouseabs is None:
return False
data = bytearray(6)
data[0] = btn
data[1:3] = x.to_bytes(2, byteorder='little')
data[3:5] = y.to_bytes(2, byteorder='little')
data[5] = wheel
hidmouseabs.write(data)
hidmouseabs.flush()
def send_key(hidkey, shift, alt, ctlr, mod):
data = bytearray(8) data = bytearray(8)
if shift: if shift:
data[0] += hidkeycodes['KEY_MOD_LSHIFT'] data[0] += hidkeycodes['KEY_MOD_LSHIFT']
@ -55,9 +72,9 @@ def send_key(hidkey, shift, alt, ctlr):
if ctlr: if ctlr:
data[0] += hidkeycodes['KEY_MOD_LCTRL'] data[0] += hidkeycodes['KEY_MOD_LCTRL']
if hidkey == hidkeycodes['KEY_MOD_LMETA'] or hidkey == hidkeycodes['KEY_MOD_RMETA']: if mod and (hidkey == hidkeycodes['KEY_MOD_LMETA'] or hidkey == hidkeycodes['KEY_MOD_RMETA']):
data[0] += hidkey data[0] += hidkey
hidkey=0 hidkey = 0
data[2] = hidkey data[2] = hidkey
@ -69,8 +86,8 @@ def get_hid_by_jscode(rawkeycode):
hidkeycode = None hidkeycode = None
hidkeyname = None hidkeyname = None
if rawkeycode in jskeycodes.values(): if rawkeycode in jscodehidmap:
hidkeyname = list(jskeycodes.keys())[list(jskeycodes.values()).index(rawkeycode)] hidkeyname = jscodehidmap[rawkeycode]
if hidkeyname in hidkeycodes: if hidkeyname in hidkeycodes:
hidkeycode = hidkeycodes[hidkeyname] hidkeycode = hidkeycodes[hidkeyname]
else: else:
@ -80,16 +97,15 @@ def get_hid_by_jscode(rawkeycode):
print ("JS key: {} HID key: {}({})".format(rawkeycode, hidkeyname, hidkeycode)) print ("JS key: {} HID key: {}({})".format(rawkeycode, hidkeyname, hidkeycode))
return hidkeycode return hidkeycode, (hidkeyname is not None and "MOD" in hidkeyname)
@app.route("/") @app.route("/")
def index(): def index():
return render_template("hid.html") return render_template("hid.html")
@app.route("/mouse.html") @app.route("/mouse.html")
def mouseindex(): def mouseindex():
return render_template("mouse.html") return render_template("mouse.html")
@app.route("/hid/mouse", methods=["POST"]) @app.route("/hid/mouse", methods=["POST"])
def mouse(): def mouse():
@ -104,20 +120,36 @@ def mouse():
x = x if x >= 0 else 255-abs(x) x = x if x >= 0 else 255-abs(x)
y = y if y >= 0 else 255-abs(y) y = y if y >= 0 else 255-abs(y)
print ("X: {}, Y: {}".format(x,y)) print("X: {}, Y: {}".format(x, y))
hid_mouse_write(btn, x, y, wheel) hid_mouse_write(btn, x, y, wheel)
return Response("", mimetype = "text/plain") return Response("", mimetype="text/plain")
@app.route("/hid/mouseabs", methods=["POST"])
def mouseabs():
mouseevent = json.loads(request.data)
print(mouseevent)
btn = mouseevent['btn']
x = mouseevent['x']
y = mouseevent['y']
wheel = mouseevent['wheel']
print("X: {}, Y: {}".format(x, y))
hid_mouse_writeabs(btn, x, y, wheel)
return Response("", mimetype="text/plain")
@app.route("/hid/keyboard", methods=["POST"]) @app.route("/hid/keyboard", methods=["POST"])
def keypress(): def keypress():
keyevent = json.loads(request.data) keyevent = json.loads(request.data)
print ("Raw data: {}".format(request.data)) print("Raw data: {}".format(request.data))
rawkeycode = keyevent['code'] rawkeycode = keyevent['code']
hidkeycode = get_hid_by_jscode(rawkeycode) hidkeycode, mod = get_hid_by_jscode(rawkeycode)
if hidkeycode is not None: if hidkeycode is not None:
try: try:
@ -125,11 +157,12 @@ def keypress():
hidkeycode, hidkeycode,
keyevent['shiftKey'], keyevent['shiftKey'],
keyevent['altKey'], keyevent['altKey'],
keyevent['ctrlKey']) keyevent['ctrlKey'],
mod)
except Exception as e: except Exception as e:
print("Error sending HID message", e) print("Error sending HID message", e)
return Response("Press {}".format(hidkeycode), mimetype = "text/plain") return Response("Press {}".format(hidkeycode), mimetype="text/plain")
# check to see if this is the main thread of execution # check to see if this is the main thread of execution
@ -147,11 +180,9 @@ if __name__ == '__main__':
hid_init() hid_init()
app.run(host=args["ip"], port=args["port"], debug=True, app.run(host=args["ip"], port=args["port"], debug=True,
threaded=True, use_reloader=False) threaded=True, use_reloader=False)
# Clean up # Clean up
if hiddev is not None: if hiddev is not None:
print("Closing hid") print("Closing hid")
hiddev.close() hiddev.close()

View File

@ -1,245 +1,129 @@
jscodehidmap = {
'KeyA': 'KEY_A',
'KeyB': 'KEY_B',
'KeyC': 'KEY_C',
'KeyD': 'KEY_D',
'KeyE': 'KEY_E',
'KeyF': 'KEY_F',
'KeyG': 'KEY_G',
'KeyH': 'KEY_H',
'KeyI': 'KEY_I',
'KeyJ': 'KEY_J',
'KeyK': 'KEY_K',
'KeyL': 'KEY_L',
'KeyM': 'KEY_M',
'KeyN': 'KEY_N',
'KeyO': 'KEY_O',
'KeyP': 'KEY_P',
'KeyQ': 'KEY_Q',
'KeyR': 'KEY_R',
'KeyS': 'KEY_S',
'KeyT': 'KEY_T',
'KeyU': 'KEY_U',
'KeyV': 'KEY_V',
'KeyW': 'KEY_W',
'KeyX': 'KEY_X',
'KeyY': 'KEY_Y',
'KeyZ': 'KEY_Z',
jskeycodes = { 'Backquote': 'KEY_GRAVE',
'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', 'Digit0': 'KEY_0',
'Digit1': 'KEY_1',
'Digit2': 'KEY_2',
'Digit3': 'KEY_3',
'Digit4': 'KEY_4',
'Digit5': 'KEY_5',
'Digit6': 'KEY_6',
'Digit7': 'KEY_7',
'Digit8': 'KEY_8',
'Digit9': 'KEY_9',
'KEY_0': 'Digit0', 'Minus': 'KEY_MINUS',
'KEY_1': 'Digit1', 'Equal': 'KEY_EQUAL',
'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', 'BracketLeft': 'KEY_LEFTBRACE',
'KEY_EQUAL': 'Equal', 'BracketRight': 'KEY_RIGHTBRACE',
'KEY_LEFTBRACE': 'BracketLeft', 'Semicolon': 'KEY_SEMICOLON',
'KEY_RIGHTBRACE': 'BracketRight', 'Quote': 'KEY_APOSTROPHE',
'Backslash': 'KEY_BACKSLASH',
'KEY_SEMICOLON': 'Semicolon', 'Comma': 'KEY_COMMA',
'KEY_APOSTROPHE': 'Quote', 'Period': 'KEY_DOT',
'KEY_BACKSLASH': 'Backslash', 'Slash': 'KEY_SLASH',
'KEY_COMMA': 'Comma', 'IntlBackslash': 'KEY_102ND',
'KEY_DOT': 'Period',
'KEY_SLASH': 'Slash',
'KEY_102ND': 'IntlBackslash', 'Numpad0': 'KEY_KP0',
'Numpad1': 'KEY_KP1',
'Numpad2': 'KEY_KP2',
'Numpad3': 'KEY_KP3',
'Numpad4': 'KEY_KP4',
'Numpad5': 'KEY_KP5',
'Numpad6': 'KEY_KP6',
'Numpad7': 'KEY_KP7',
'Numpad8': 'KEY_KP8',
'Numpad9': 'KEY_KP9',
'KEY_KP0': 'Numpad0', 'NumpadMultiply': 'KEY_KPASTERISK',
'KEY_KP1': 'Numpad1', 'NumpadAdd': 'KEY_KPPLUS',
'KEY_KP2': 'Numpad2', 'NumpadSubtract': 'KEY_KPMINUS',
'KEY_KP3': 'Numpad3', 'NumpadDecimal': 'KEY_KPDOT',
'KEY_KP4': 'Numpad4', 'NumpadDivide': 'KEY_KPSLASH',
'KEY_KP5': 'Numpad5', 'NumpadEnter': 'KEY_KPENTER',
'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', 'Escape': 'KEY_ESC',
'KEY_F1': 'F1', 'F1': 'KEY_F1',
'KEY_F2': 'F2', 'F2': 'KEY_F2',
'KEY_F3': 'F3', 'F3': 'KEY_F3',
'KEY_F4': 'F4', 'F4': 'KEY_F4',
'KEY_F5': 'F5', 'F5': 'KEY_F5',
'KEY_F6': 'F6', 'F6': 'KEY_F6',
'KEY_F7': 'F7', 'F7': 'KEY_F7',
'KEY_F8': 'F8', 'F8': 'KEY_F8',
'KEY_F9': 'F9', 'F9': 'KEY_F9',
'KEY_F10': 'F10', 'F10': 'KEY_F10',
'KEY_F11': 'F11', 'F11': 'KEY_F11',
'KEY_F12': 'F12', 'F12': 'KEY_F12',
'KEY_F13': 'F13', 'F13': 'KEY_F13',
'KEY_F14': 'F14', 'F14': 'KEY_F14',
'KEY_F15': 'F15', 'F15': 'KEY_F15',
'KEY_F16': 'F16', 'F16': 'KEY_F16',
'KEY_F17': 'F17', 'F17': 'KEY_F17',
'KEY_F18': 'F18', 'F18': 'KEY_F18',
'KEY_F19': 'F19', 'F19': 'KEY_F19',
'KEY_F20': 'F20', 'F20': 'KEY_F20',
'KEY_F21': 'F21', 'F21': 'KEY_F21',
'KEY_F22': 'F22', 'F22': 'KEY_F22',
'KEY_F23': 'F23', 'F23': 'KEY_F23',
'KEY_BACKSPACE': 'Backspace', 'Backspace': 'KEY_BACKSPACE',
'KEY_SPACE': 'Space', 'Space': 'KEY_SPACE',
'KEY_TAB': 'Tab', 'Tab': 'KEY_TAB',
'KEY_ENTER' : 'Enter', 'Enter': 'KEY_ENTER',
'KEY_PAGEUP': 'PageUp', 'PageUp': 'KEY_PAGEUP',
'KEY_PAGEDOWN': 'PageDown', 'PageDown': 'KEY_PAGEDOWN',
'KEY_HOME': 'Home', 'Home': 'KEY_HOME',
'KEY_END': 'End', 'End': 'KEY_END',
'KEY_INSERT': 'Insert', 'Insert': 'KEY_INSERT',
'KEY_DELETE': 'Delete', 'Delete': 'KEY_DELETE',
'KEY_UP': 'ArrowUp', 'ArrowUp': 'KEY_UP',
'KEY_DOWN': 'ArrowDown', 'ArrowDown': 'KEY_DOWN',
'KEY_LEFT': 'ArrowLeft', 'ArrowLeft': 'KEY_LEFT',
'KEY_RIGHT': 'ArrowRight', 'ArrowRight': 'KEY_RIGHT',
'KEY_NUMLOCK': 'NumLock', 'NumLock': 'KEY_NUMLOCK',
'KEY_CAPSLOCK': 'CapsLock', 'CapsLock': 'KEY_CAPSLOCK',
'KEY_SCROLLLOCK': 'ScrollLock', 'ScrollLock': 'KEY_SCROLLLOCK',
'KEY_MOD_LMETA': 'MetaLeft', 'MetaLeft': 'KEY_MOD_LMETA',
'KEY_MOD_RMETA': 'MetaRight', 'MetaRight': 'KEY_MOD_RMETA',
'KEY_COMPOSE': 'ContextMenu', 'OSLeft': 'KEY_MOD_LMETA',
} 'OSRight': 'KEY_MOD_RMETA',
jskeywhich = { 'ContextMenu': 'KEY_COMPOSE'
'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
} }

View File

@ -18,9 +18,37 @@
<input type="button" onclick="sendMouse(0, 0, 10);" value="v" /><br /> <input type="button" onclick="sendMouse(0, 0, 10);" value="v" /><br />
<input type="button" onclick="sendMouse(1, 0, 0);" value="LEFT" /> <input type="button" onclick="sendMouse(1, 0, 0);" value="LEFT" />
<input type="button" onclick="sendMouse(2, 0, 0);" value="RIGHT" /> <input type="button" onclick="sendMouse(2, 0, 0);" value="RIGHT" />
<script> <script>
var btn=0;
var posX=0;
var posY=0;
$(document).ready(function(){
$("canvas").mousedown(function(event){
btn=event.buttons;
handleMouse();
});
$("canvas").mouseup(function(event){
btn=event.buttons;
handleMouse();
});
$("canvas").mousemove(function(event){
// sendMouse(0, event.originalEvent.movementX, event.originalEvent.movementY);
posX=event.offsetX;
posY=event.offsetY;
handleMouse();
});
});
function handleMouse() {
$("span").text(btn +", "+ posX + ", " + posY);
sendMouse(btn, posX, posY);
}
function sendMouse(btn, x, y) { function sendMouse(btn, x, y) {
var obj = { var obj = {
x: x, x: x,
@ -31,7 +59,7 @@ function sendMouse(btn, x, y) {
var ret = $.ajax({ var ret = $.ajax({
type: "POST", type: "POST",
url: "hid/mouse", url: "hid/mouseabs",
data: JSON.stringify(obj), data: JSON.stringify(obj),
contentType: "application/json; charset=utf-8", contentType: "application/json; charset=utf-8",
dataType: "json" dataType: "json"
@ -40,6 +68,8 @@ function sendMouse(btn, x, y) {
}; };
</script> </script>
<span></span><br/><br/>
<canvas width=500 height=500 style="border: 1px solid black" oncontextmenu="return false"></canvas>
<!--<img src="placeholder.png" width=1920 height=1080 onmousemove='console.log("aaa");' />-->
</body> </body>
</html> </html>

View File

@ -4,7 +4,6 @@ from flask import render_template
import threading import threading
import argparse import argparse
import datetime import datetime
import imutils
import time import time
import cv2 import cv2
from hashlib import md5 from hashlib import md5
@ -27,77 +26,77 @@ time.sleep(1.0)
@app.route("/") @app.route("/")
def index(): def index():
# return the rendered template # return the rendered template
return render_template("index.html") return render_template("index.html")
def detect_motion(frameCount): def detect_motion(frameCount):
global vs, outputFrame, lock global vs, outputFrame, lock
lastframe = None lastframe = None
while True: while True:
flag, frame = cap.read() flag, frame = cap.read()
framedig = md5(frame).digest() framedig = md5(frame).digest()
if lastframe == framedig: if lastframe == framedig:
print("Duplicate frame, skipping") print("Duplicate frame, skipping")
continue continue
if not flag: if not flag:
continue continue
lastframe = framedig lastframe = framedig
timestamp = datetime.datetime.now() timestamp = datetime.datetime.now()
cv2.putText(frame, timestamp.strftime( cv2.putText(frame, timestamp.strftime(
"%A %d %B %Y %I:%M:%S%p"), (10, 15), "%A %d %B %Y %I:%M:%S%p"), (10, 15),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 1) cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 1)
with lock:
outputFrame = frame.copy()
with lock:
outputFrame = frame.copy()
def generate(): def generate():
global outputFrame, lock global outputFrame, lock
while True: while True:
with lock: with lock:
if outputFrame is None: if outputFrame is None:
continue continue
(flag, encodedImage) = cv2.imencode(".jpg", outputFrame) (flag, encodedImage) = cv2.imencode(".jpg", outputFrame)
# ensure the frame was successfully encoded # ensure the frame was successfully encoded
if not flag: if not flag:
continue continue
# yield the output frame in the byte format # yield the output frame in the byte format
yield(b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + yield(b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' +
bytearray(encodedImage) + b'\r\n') bytearray(encodedImage) + b'\r\n')
time.sleep(0.2) time.sleep(0.2)
@app.route("/video_feed") @app.route("/video_feed")
def video_feed(): def video_feed():
# return the response generated along with the specific media # return the response generated along with the specific media
# type (mime type) # type (mime type)
return Response(generate(), return Response(generate(),
mimetype = "multipart/x-mixed-replace; boundary=frame") mimetype = "multipart/x-mixed-replace; boundary=frame")
# check to see if this is the main thread of execution # check to see if this is the main thread of execution
if __name__ == '__main__': if __name__ == '__main__':
# construct the argument parser and parse command line arguments # construct the argument parser and parse command line arguments
ap = argparse.ArgumentParser() ap = argparse.ArgumentParser()
ap.add_argument("-i", "--ip", type=str, required=True, ap.add_argument("-i", "--ip", type=str, required=True,
help="ip address of the device") help="ip address of the device")
ap.add_argument("-o", "--port", type=int, required=True, ap.add_argument("-o", "--port", type=int, required=True,
help="ephemeral port number of the server (1024 to 65535)") help="ephemeral port number of the server (1024 to 65535)")
ap.add_argument("-f", "--frame-count", type=int, default=32, ap.add_argument("-f", "--frame-count", type=int, default=32,
help="# of frames used to construct the background model") help="# of frames used to construct the background model")
args = vars(ap.parse_args()) args = vars(ap.parse_args())
# start a thread that will perform motion detection # start a thread that will perform motion detection
t = threading.Thread(target=detect_motion, args=( t = threading.Thread(target=detect_motion, args=(
args["frame_count"],)) args["frame_count"],))
t.daemon = True t.daemon = True
t.start() t.start()
# start the flask app # start the flask app
app.run(host=args["ip"], port=args["port"], debug=True, app.run(host=args["ip"], port=args["port"], debug=True,
threaded=True, use_reloader=False) threaded=True, use_reloader=False)