diff options
author | Devaev Maxim <[email protected]> | 2020-11-12 21:03:28 +0300 |
---|---|---|
committer | Devaev Maxim <[email protected]> | 2020-11-12 21:03:28 +0300 |
commit | 87cc8cf7b0e00f7f0a9badf551067aafad6da4ce (patch) | |
tree | cdd802d124236ded6969dc5d80c764deec357e02 /hid | |
parent | 79ef26e2f441f6c742a5da78b08ea2d5a4cc6e18 (diff) | |
parent | 0984f0cb36c5881669010c62e986cc8bc7fe019a (diff) |
Merge branch 'spi'
Diffstat (limited to 'hid')
-rw-r--r-- | hid/Makefile | 13 | ||||
-rw-r--r-- | hid/avrdude-rpi.conf | 7 | ||||
-rw-r--r-- | hid/avrdude.py | 54 | ||||
-rw-r--r-- | hid/lib/.gitignore | 0 | ||||
-rw-r--r-- | hid/patch.py | 42 | ||||
-rw-r--r-- | hid/patches/serial.patch | 24 | ||||
-rw-r--r-- | hid/platformio.ini | 163 | ||||
-rw-r--r-- | hid/src/inline.h | 26 | ||||
-rw-r--r-- | hid/src/main.cpp | 228 | ||||
-rw-r--r-- | hid/src/proto.h | 76 | ||||
-rw-r--r-- | hid/src/ps2/hid.h | 8 | ||||
-rw-r--r-- | hid/src/ps2/keymap.h | 4 | ||||
-rw-r--r-- | hid/src/ps2/keymap.h.mako | 8 | ||||
-rw-r--r-- | hid/src/usb/hid.h | 18 | ||||
-rw-r--r-- | hid/src/usb/keymap.h | 4 | ||||
-rw-r--r-- | hid/src/usb/keymap.h.mako | 8 |
16 files changed, 470 insertions, 213 deletions
diff --git a/hid/Makefile b/hid/Makefile index 0d07db84..81fe129d 100644 --- a/hid/Makefile +++ b/hid/Makefile @@ -4,6 +4,12 @@ ps2: make _build E=ps2 mixed: make _build E=mixed +usb-spi: + make _build E=usb_spi +ps2-spi: + make _build E=ps2_spi +mixed-spi: + make _build E=mixed_spi _build: rm -f .current platformio run --environment $(E) @@ -15,11 +21,18 @@ upload: platformio run --environment $(shell cat .current) --target upload +bootloader-spi: install-bootloader-spi +install-bootloader-spi: upload-bootloader-spi +upload-bootloader-spi: + platformio run --environment bootloader_spi --target bootloader + + update: platformio platform update clean-all: clean + rm -rf .platformio clean: rm -rf .pio .current diff --git a/hid/avrdude-rpi.conf b/hid/avrdude-rpi.conf new file mode 100644 index 00000000..8a6f5460 --- /dev/null +++ b/hid/avrdude-rpi.conf @@ -0,0 +1,7 @@ +programmer + id = "rpi"; + desc = "RPi SPI programmer"; + type = "linuxspi"; + reset = 25; + baudrate = 400000; +; diff --git a/hid/avrdude.py b/hid/avrdude.py new file mode 100644 index 00000000..3ae227f9 --- /dev/null +++ b/hid/avrdude.py @@ -0,0 +1,54 @@ +# https://docs.platformio.org/en/latest/projectconf/advanced_scripting.html + + +from os import rename +from os import symlink +from os.path import exists +from os.path import join + +import platform + +Import("env") + + +# ===== +def _get_tool_path() -> str: + path = env.PioPlatform().get_package_dir("tool-avrdude") + assert exists(path) + return path + + +def _fix_ld_arm() -> None: + tool_path = _get_tool_path() + flag_path = join(tool_path, ".fix-ld-arm.done") + + if not exists(flag_path): + def patch(*_, **__) -> None: + symlink("/usr/lib/libtinfo.so.6", join(tool_path, "libtinfo.so.5")) + open(flag_path, "w").close() + + env.Execute(patch) + + +def _replace_to_system(new_path: str) -> None: + tool_path = _get_tool_path() + flag_path = join(tool_path, ".replace-to-system.done") + + if not exists(flag_path): + def patch(*_, **__) -> None: + old_path = join(tool_path, "avrdude") + bak_path = join(tool_path, "_avrdude_bak") + rename(old_path, bak_path) + symlink(new_path, old_path) + open(flag_path, "w").close() + + env.Execute(patch) + + +# ===== +if "arm" in platform.machine(): + _fix_ld_arm() + +_path = "/usr/bin/avrdude" +if exists(_path): + _replace_to_system(_path) diff --git a/hid/lib/.gitignore b/hid/lib/.gitignore new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/hid/lib/.gitignore diff --git a/hid/patch.py b/hid/patch.py index 100c0d5b..58462bc1 100644 --- a/hid/patch.py +++ b/hid/patch.py @@ -1,20 +1,40 @@ -from os.path import join +# https://docs.platformio.org/en/latest/projectconf/advanced_scripting.html + + from os.path import exists +from os.path import join +from os.path import basename + +from typing import Dict Import("env") # ===== -deps_path = env.get("PROJECT_LIBDEPS_DIR", env.get("PROJECTLIBDEPS_DIR")) -assert deps_path, deps_path -env_path = join(deps_path, env["PIOENV"]) -flag_path = join(env_path, ".patched") +def _get_pkg_path(name: str) -> str: + path = env.PioPlatform().get_package_dir(name) + assert exists(path) + return path -if not exists(flag_path): - env.Execute(f"patch -p1 -d {join(env_path, 'HID-Project')} < {join('patches', 'absmouse.patch')}") - def touch_flag(*_, **__) -> None: - with open(flag_path, "w") as flag_file: - pass +def _get_libs() -> Dict[str, str]: + return { + builder.name: builder.path + for builder in env.GetLibBuilders() + } + + +def _patch(path: str, patch_path: str) -> None: + assert exists(path) + flag_path: str = join(path, f".{basename(patch_path)}.done") + if not exists(flag_path): + env.Execute(f"patch -p1 -d {path} < {patch_path}") + env.Execute(lambda *_, **__: open(flag_path, "w").close()) + + +# ===== +_patch(_get_pkg_path("framework-arduino-avr"), "patches/serial.patch") - env.Execute(touch_flag) +_libs = _get_libs() +if "HID-Project" in _libs: + _patch(_libs["HID-Project"], "patches/absmouse.patch") diff --git a/hid/patches/serial.patch b/hid/patches/serial.patch new file mode 100644 index 00000000..16ba3811 --- /dev/null +++ b/hid/patches/serial.patch @@ -0,0 +1,24 @@ +https://github.com/arduino/Arduino/issues/6387 +--- a/cores/arduino/USBCore.cpp 2019-09-20 15:48:38.000000000 +0300 ++++ b/cores/arduino/USBCore.cpp 2020-11-11 19:56:49.233690476 +0300 +@@ -375,8 +375,10 @@ + { + u8 i = setup.wIndex; + ++#ifndef NO_SERIAL + if (CDC_ACM_INTERFACE == i) + return CDC_Setup(setup); ++#endif + + #ifdef PLUGGABLE_USB_ENABLED + return PluggableUSB().setup(setup); +@@ -466,7 +468,9 @@ + { + u8 interfaces = 0; + ++#ifndef NO_SERIAL + CDC_GetInterface(&interfaces); ++#endif + + #ifdef PLUGGABLE_USB_ENABLED + PluggableUSB().getInterface(&interfaces); diff --git a/hid/platformio.ini b/hid/platformio.ini index c6c7c34b..a24c4aca 100644 --- a/hid/platformio.ini +++ b/hid/platformio.ini @@ -1,59 +1,142 @@ -; PlatformIO Project Configuration File -; -; Build options: build flags, source filter -; Upload options: custom upload port, speed and extra flags -; Library options: dependencies, extra library storages -; Advanced options: extra scripting -; -; Please visit documentation for the other options and examples -; http://docs.platformio.org/page/projectconf.html - -[common] -lib_deps = -build_flags = - -DCMD_SERIAL=Serial1 +# http://docs.platformio.org/page/projectconf.html +[platformio] +core_dir = ./.platformio/ -[env:usb] +[env] platform = atmelavr board = micro framework = arduino -upload_port = /dev/ttyACM0 +extra_scripts = + pre:avrdude.py + post:patch.py +platform_packages = + tool-avrdude + +[_parts_usb_kbd] lib_deps = - ${common.lib_deps} build_flags = - ${common.build_flags} -DHID_USB_KBD + +[_parts_usb_mouse] +lib_deps = +build_flags = -DHID_USB_MOUSE -extra_scripts = post:patch.py -[env:ps2] -platform = atmelavr -board = micro -framework = arduino -upload_port = /dev/ttyACM0 +[_parts_ps2_kbd] lib_deps = - ${common.lib_deps} git+https://github.com/Harvie/ps2dev#v0.0.3 build_flags = - ${common.build_flags} -DHID_PS2_KBD -DPS2_KBD_CLOCK_PIN=7 -DPS2_KBD_DATA_PIN=5 -[env:mixed] -platform = atmelavr -board = micro -framework = arduino -upload_port = /dev/ttyACM0 +[_usb] lib_deps = - ${common.lib_deps} - git+https://github.com/Harvie/ps2dev#v0.0.3 + ${_parts_usb_kbd.lib_deps} +# ${_parts_usb_mouse.lib_deps} build_flags = - ${common.build_flags} - -DHID_PS2_KBD - -DHID_USB_MOUSE - -DPS2_KBD_CLOCK_PIN=7 - -DPS2_KBD_DATA_PIN=5 + ${_parts_usb_kbd.build_flags} + ${_parts_usb_mouse.build_flags} + +[_ps2] +lib_deps = + ${_parts_ps2_kbd.lib_deps} +build_flags = + ${_parts_ps2_kbd.build_flags} + +[_mixed] +lib_deps = + ${_parts_ps2_kbd.lib_deps} + ${_parts_usb_mouse.lib_deps} +build_flags = + ${_parts_ps2_kbd.build_flags} + ${_parts_usb_mouse.build_flags} + + +# ===== Serial ===== +[_cmd_serial] +build_flags = + -DCMD_SERIAL=Serial1 + -DCMD_SERIAL_SPEED=115200 + -DCMD_SERIAL_TIMEOUT=100000 +upload_port = /dev/ttyACM0 + +[env:usb] +extends = + _usb + _cmd_serial +build_flags = + ${_usb.build_flags} + ${_cmd_serial.build_flags} + +[env:ps2] +extends = + _ps2 + _cmd_serial +build_flags = + ${_ps2.build_flags} + ${_cmd_serial.build_flags} + +[env:mixed] +extends = + _mixed + _cmd_serial +build_flags = + ${_mixed.build_flags} + ${_cmd_serial.build_flags} + + +# ===== RPi SPI ===== +[env:bootloader_spi] +upload_protocol = rpi +upload_flags = + -C + +avrdude-rpi.conf + -P + /dev/spidev0.0:/dev/gpiochip0 +extra_scripts = + pre:avrdude.py + +[_cmd_spi] +build_flags = + -DCMD_SPI + -DNO_SERIAL +upload_protocol = custom +upload_flags = + -C + $PROJECT_PACKAGES_DIR/tool-avrdude/avrdude.conf + -C + +avrdude-rpi.conf + -P + /dev/spidev0.0:/dev/gpiochip0 + -c + rpi + -p + $BOARD_MCU +upload_command = avrdude $UPLOAD_FLAGS -U flash:w:$SOURCE:i + +[env:usb_spi] +extends = + _usb + _cmd_spi +build_flags = + ${_usb.build_flags} + ${_cmd_spi.build_flags} + +[env:ps2_spi] +extends = + _ps2 + _cmd_spi +build_flags = + ${_ps2.build_flags} + ${_cmd_spi.build_flags} + +[env:mixed_spi] +extends = + _mixed + _cmd_spi +build_flags = + ${_mixed.build_flags} + ${_cmd_spi.build_flags} diff --git a/hid/src/inline.h b/hid/src/inline.h deleted file mode 100644 index e4204750..00000000 --- a/hid/src/inline.h +++ /dev/null @@ -1,26 +0,0 @@ -/***************************************************************************** -# # -# KVMD - The main Pi-KVM daemon. # -# # -# Copyright (C) 2018 Maxim Devaev <[email protected]> # -# # -# This program is free software: you can redistribute it and/or modify # -# it under the terms of the GNU General Public License as published by # -# the Free Software Foundation, either version 3 of the License, or # -# (at your option) any later version. # -# # -# This program is distributed in the hope that it will be useful, # -# but WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # -# GNU General Public License for more details. # -# # -# You should have received a copy of the GNU General Public License # -# along with this program. If not, see <https://www.gnu.org/licenses/>. # -# # -*****************************************************************************/ - - -#pragma once - - -#define INLINE inline __attribute__((always_inline)) diff --git a/hid/src/main.cpp b/hid/src/main.cpp index cd3c245a..4eeb9838 100644 --- a/hid/src/main.cpp +++ b/hid/src/main.cpp @@ -20,10 +20,17 @@ *****************************************************************************/ +#if !(defined(CMD_SERIAL) || defined(CMD_SPI)) +# error CMD phy is not defined +#endif + + #include <Arduino.h> -#include <TimerOne.h> +#ifdef CMD_SPI +# include <SPI.h> +#endif -#include "inline.h" +#include "proto.h" #if defined(HID_USB_KBD) || defined(HID_USB_MOUSE) # include "usb/hid.h" @@ -33,43 +40,11 @@ #endif -// #define CMD_SERIAL Serial1 -#define CMD_SERIAL_SPEED 115200 -#define CMD_RECV_TIMEOUT 100000 - -#define PROTO_MAGIC 0x33 -#define PROTO_CRC_POLINOM 0xA001 - -#define PROTO_RESP_OK 0x20 -#define PROTO_RESP_NONE 0x24 -#define PROTO_RESP_CRC_ERROR 0x40 -#define PROTO_RESP_INVALID_ERROR 0x45 -#define PROTO_RESP_TIMEOUT_ERROR 0x48 - -#define PROTO_RESP_PONG_PREFIX 0x80 -#define PROTO_RESP_PONG_CAPS 0b00000001 -#define PROTO_RESP_PONG_SCROLL 0b00000010 -#define PROTO_RESP_PONG_NUM 0b00000100 - -#define PROTO_CMD_PING 0x01 -#define PROTO_CMD_REPEAT 0x02 -#define PROTO_CMD_RESET_HID 0x10 -#define PROTO_CMD_KEY_EVENT 0x11 -#define PROTO_CMD_MOUSE_BUTTON_EVENT 0x13 // Legacy sequence -#define PROTO_CMD_MOUSE_MOVE_EVENT 0x12 -#define PROTO_CMD_MOUSE_WHEEL_EVENT 0x14 - -#define PROTO_CMD_MOUSE_BUTTON_LEFT_SELECT 0b10000000 -#define PROTO_CMD_MOUSE_BUTTON_LEFT_STATE 0b00001000 -#define PROTO_CMD_MOUSE_BUTTON_RIGHT_SELECT 0b01000000 -#define PROTO_CMD_MOUSE_BUTTON_RIGHT_STATE 0b00000100 -#define PROTO_CMD_MOUSE_BUTTON_MIDDLE_SELECT 0b00100000 -#define PROTO_CMD_MOUSE_BUTTON_MIDDLE_STATE 0b00000010 - -#define PROTO_CMD_MOUSE_BUTTON_EXTRA_UP_SELECT 0b10000000 -#define PROTO_CMD_MOUSE_BUTTON_EXTRA_UP_STATE 0b00001000 -#define PROTO_CMD_MOUSE_BUTTON_EXTRA_DOWN_SELECT 0b01000000 -#define PROTO_CMD_MOUSE_BUTTON_EXTRA_DOWN_STATE 0b00000100 +// #define CMD_SERIAL Serial1 +// #define CMD_SERIAL_SPEED 115200 +// #define CMD_SERIAL_TIMEOUT 100000 +// -- OR -- +// #define CMD_SPI // ----------------------------------------------------------------------------- @@ -84,7 +59,7 @@ // ----------------------------------------------------------------------------- -INLINE uint8_t cmdResetHid(const uint8_t *buffer) { // 0 bytes +uint8_t cmdResetHid(const uint8_t *buffer) { // 0 bytes # ifdef HID_USB_KBD hid_kbd.reset(); # endif @@ -94,28 +69,32 @@ INLINE uint8_t cmdResetHid(const uint8_t *buffer) { // 0 bytes return PROTO_RESP_OK; } -INLINE uint8_t cmdKeyEvent(const uint8_t *buffer) { // 2 bytes +uint8_t cmdKeyEvent(const uint8_t *buffer) { // 2 bytes hid_kbd.sendKey(buffer[0], buffer[1]); return PROTO_RESP_OK; } -INLINE uint8_t cmdMouseButtonEvent(const uint8_t *buffer) { // 2 bytes +uint8_t cmdMouseButtonEvent(const uint8_t *buffer) { // 2 bytes # ifdef HID_USB_MOUSE uint8_t main_state = buffer[0]; uint8_t extra_state = buffer[1]; +# define MOUSE_PAIR(_state, _button) \ + _state & PROTO_CMD_MOUSE_BUTTON_##_button##_SELECT, \ + _state & PROTO_CMD_MOUSE_BUTTON_##_button##_STATE hid_mouse.sendMouseButtons( - main_state & PROTO_CMD_MOUSE_BUTTON_LEFT_SELECT, main_state & PROTO_CMD_MOUSE_BUTTON_LEFT_STATE, - main_state & PROTO_CMD_MOUSE_BUTTON_RIGHT_SELECT, main_state & PROTO_CMD_MOUSE_BUTTON_RIGHT_STATE, - main_state & PROTO_CMD_MOUSE_BUTTON_MIDDLE_SELECT, main_state & PROTO_CMD_MOUSE_BUTTON_MIDDLE_STATE, - extra_state & PROTO_CMD_MOUSE_BUTTON_EXTRA_UP_SELECT, extra_state & PROTO_CMD_MOUSE_BUTTON_EXTRA_UP_STATE, - extra_state & PROTO_CMD_MOUSE_BUTTON_EXTRA_DOWN_SELECT, extra_state & PROTO_CMD_MOUSE_BUTTON_EXTRA_DOWN_STATE + MOUSE_PAIR(main_state, LEFT), + MOUSE_PAIR(main_state, RIGHT), + MOUSE_PAIR(main_state, MIDDLE), + MOUSE_PAIR(extra_state, EXTRA_UP), + MOUSE_PAIR(extra_state, EXTRA_DOWN) ); +# undef MOUSE_PAIR # endif return PROTO_RESP_OK; } -INLINE uint8_t cmdMouseMoveEvent(const uint8_t *buffer) { // 4 bytes +uint8_t cmdMouseMoveEvent(const uint8_t *buffer) { // 4 bytes # ifdef HID_USB_MOUSE int x = (int)buffer[0] << 8; x |= (int)buffer[1]; @@ -130,14 +109,14 @@ INLINE uint8_t cmdMouseMoveEvent(const uint8_t *buffer) { // 4 bytes return PROTO_RESP_OK; } -INLINE uint8_t cmdMouseWheelEvent(const uint8_t *buffer) { // 2 bytes +uint8_t cmdMouseWheelEvent(const uint8_t *buffer) { // 2 bytes # ifdef HID_USB_MOUSE hid_mouse.sendMouseWheel(buffer[1]); // Y only, X is not supported # endif return PROTO_RESP_OK; } -INLINE uint8_t cmdPongLeds(const uint8_t *buffer) { // 0 bytes +uint8_t cmdPongLeds(const uint8_t *buffer) { // 0 bytes return ((uint8_t) PROTO_RESP_PONG_PREFIX) | hid_kbd.getLedsAs( PROTO_RESP_PONG_CAPS, PROTO_RESP_PONG_SCROLL, @@ -145,40 +124,79 @@ INLINE uint8_t cmdPongLeds(const uint8_t *buffer) { // 0 bytes ); } - -// ----------------------------------------------------------------------------- -INLINE uint16_t makeCrc16(const uint8_t *buffer, unsigned length) { - uint16_t crc = 0xFFFF; - - for (unsigned byte_count = 0; byte_count < length; ++byte_count) { - crc = crc ^ buffer[byte_count]; - for (unsigned bit_count = 0; bit_count < 8; ++bit_count) { - if ((crc & 0x0001) == 0) { - crc = crc >> 1; - } else { - crc = crc >> 1; - crc = crc ^ PROTO_CRC_POLINOM; - } +uint8_t handleCmdBuffer(const uint8_t *buffer) { // 8 bytes + uint16_t crc = (uint16_t)buffer[6] << 8; + crc |= (uint16_t)buffer[7]; + + if (protoCrc16(buffer, 6) == crc) { +# define HANDLE(_handler) { return _handler(buffer + 2); } + switch (buffer[1]) { + case PROTO_CMD_RESET_HID: HANDLE(cmdResetHid); + case PROTO_CMD_KEY_EVENT: HANDLE(cmdKeyEvent); + case PROTO_CMD_MOUSE_BUTTON_EVENT: HANDLE(cmdMouseButtonEvent); + case PROTO_CMD_MOUSE_MOVE_EVENT: HANDLE(cmdMouseMoveEvent); + case PROTO_CMD_MOUSE_WHEEL_EVENT: HANDLE(cmdMouseWheelEvent); + case PROTO_CMD_PING: HANDLE(cmdPongLeds); + case PROTO_CMD_REPEAT: return 0; + default: return PROTO_RESP_INVALID_ERROR; } +# undef HANDLE } - return crc; + return PROTO_RESP_CRC_ERROR; } // ----------------------------------------------------------------------------- -volatile bool cmd_recv_timed_out = false; +#ifdef CMD_SPI +volatile uint8_t spi_in[8] = {0}; +volatile uint8_t spi_in_index = 0; -INLINE void recvTimerStop(bool flag) { - Timer1.stop(); - cmd_recv_timed_out = flag; +volatile uint8_t spi_out[4] = {0}; +volatile uint8_t spi_out_index = 0; + +bool spiReady() { + return (!spi_out[0] && spi_in_index == 8); +} + +void spiWrite(const uint8_t *buffer) { + spi_out[3] = buffer[3]; + spi_out[2] = buffer[2]; + spi_out[1] = buffer[1]; + spi_out[0] = buffer[0]; // Меджик разрешает начать ответ } -INLINE void resetCmdRecvTimeout() { - recvTimerStop(false); - Timer1.initialize(CMD_RECV_TIMEOUT); +ISR(SPI_STC_vect) { + uint8_t in = SPDR; + if (spi_out[0] && spi_out_index < 4) { + SPDR = spi_out[spi_out_index]; + if (!(SPSR & (1 << WCOL))) { + ++spi_out_index; + if (spi_out_index == 4) { + spi_out_index = 0; + spi_in_index = 0; + spi_out[0] = 0; + } + } + } else { + static bool receiving = false; + if (!receiving && in == PROTO_MAGIC) { + receiving = true; + } + if (receiving && spi_in_index < 8) { + spi_in[spi_in_index] = in; + ++spi_in_index; + } + if (spi_in_index == 8) { + receiving = false; + } + SPDR = 0; + } } +#endif -INLINE void sendCmdResponse(uint8_t code=0) { + +// ----------------------------------------------------------------------------- +void sendCmdResponse(uint8_t code) { static uint8_t prev_code = PROTO_RESP_NONE; if (code == 0) { code = prev_code; // Repeat the last code @@ -189,16 +207,15 @@ INLINE void sendCmdResponse(uint8_t code=0) { uint8_t buffer[4]; buffer[0] = PROTO_MAGIC; buffer[1] = code; - uint16_t crc = makeCrc16(buffer, 2); + uint16_t crc = protoCrc16(buffer, 2); buffer[2] = (uint8_t)(crc >> 8); buffer[3] = (uint8_t)(crc & 0xFF); - recvTimerStop(false); +# ifdef CMD_SERIAL CMD_SERIAL.write(buffer, 4); -} - -void intRecvTimedOut() { - recvTimerStop(true); +# elif defined(CMD_SPI) + spiWrite(buffer); +# endif } void setup() { @@ -207,49 +224,50 @@ void setup() { hid_mouse.begin(); # endif - Timer1.attachInterrupt(intRecvTimedOut); +# ifdef CMD_SERIAL CMD_SERIAL.begin(CMD_SERIAL_SPEED); +# elif defined(CMD_SPI) + pinMode(MISO, OUTPUT); + SPCR = (1 << SPE) | (1 << SPIE); // Slave, SPI En, IRQ En +# endif } void loop() { +# ifdef CMD_SERIAL + unsigned long last = micros(); uint8_t buffer[8]; - unsigned index = 0; + uint8_t index = 0; +# endif while (true) { # ifdef HID_PS2_KBD hid_kbd.periodic(); # endif +# ifdef CMD_SERIAL if (CMD_SERIAL.available() > 0) { buffer[index] = (uint8_t)CMD_SERIAL.read(); if (index == 7) { - uint16_t crc = (uint16_t)buffer[6] << 8; - crc |= (uint16_t)buffer[7]; - - if (makeCrc16(buffer, 6) == crc) { -# define HANDLE(_handler) { sendCmdResponse(_handler(buffer + 2)); break; } - switch (buffer[1]) { - case PROTO_CMD_RESET_HID: HANDLE(cmdResetHid); - case PROTO_CMD_KEY_EVENT: HANDLE(cmdKeyEvent); - case PROTO_CMD_MOUSE_BUTTON_EVENT: HANDLE(cmdMouseButtonEvent); - case PROTO_CMD_MOUSE_MOVE_EVENT: HANDLE(cmdMouseMoveEvent); - case PROTO_CMD_MOUSE_WHEEL_EVENT: HANDLE(cmdMouseWheelEvent); - case PROTO_CMD_PING: HANDLE(cmdPongLeds); - case PROTO_CMD_REPEAT: sendCmdResponse(); break; - default: sendCmdResponse(PROTO_RESP_INVALID_ERROR); break; - } -# undef HANDLE - } else { - sendCmdResponse(PROTO_RESP_CRC_ERROR); - } + sendCmdResponse(handleCmdBuffer(buffer)); index = 0; } else { - resetCmdRecvTimeout(); - index += 1; + last = micros(); + ++index; + } + } else if (index > 0) { + unsigned long now = micros(); + if ( + (now >= last && now - last > CMD_SERIAL_TIMEOUT) + || (now < last && ((unsigned long)-1) - last + now > CMD_SERIAL_TIMEOUT) + ) { + sendCmdResponse(PROTO_RESP_TIMEOUT_ERROR); + index = 0; } - } else if (index > 0 && cmd_recv_timed_out) { - sendCmdResponse(PROTO_RESP_TIMEOUT_ERROR); - index = 0; } +# elif defined(CMD_SPI) + if (spiReady()) { + sendCmdResponse(handleCmdBuffer(spi_in)); + } +# endif } } diff --git a/hid/src/proto.h b/hid/src/proto.h new file mode 100644 index 00000000..36502d4f --- /dev/null +++ b/hid/src/proto.h @@ -0,0 +1,76 @@ +/***************************************************************************** +# # +# KVMD - The main Pi-KVM daemon. # +# # +# Copyright (C) 2018 Maxim Devaev <[email protected]> # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see <https://www.gnu.org/licenses/>. # +# # +*****************************************************************************/ + + +#pragma once + + +#define PROTO_MAGIC 0x33 +#define PROTO_CRC_POLINOM 0xA001 + +#define PROTO_RESP_OK 0x20 +#define PROTO_RESP_NONE 0x24 +#define PROTO_RESP_CRC_ERROR 0x40 +#define PROTO_RESP_INVALID_ERROR 0x45 +#define PROTO_RESP_TIMEOUT_ERROR 0x48 + +#define PROTO_RESP_PONG_PREFIX 0x80 +#define PROTO_RESP_PONG_CAPS 0b00000001 +#define PROTO_RESP_PONG_SCROLL 0b00000010 +#define PROTO_RESP_PONG_NUM 0b00000100 + +#define PROTO_CMD_PING 0x01 +#define PROTO_CMD_REPEAT 0x02 +#define PROTO_CMD_RESET_HID 0x10 +#define PROTO_CMD_KEY_EVENT 0x11 +#define PROTO_CMD_MOUSE_BUTTON_EVENT 0x13 // Legacy sequence +#define PROTO_CMD_MOUSE_MOVE_EVENT 0x12 +#define PROTO_CMD_MOUSE_WHEEL_EVENT 0x14 + +#define PROTO_CMD_MOUSE_BUTTON_LEFT_SELECT 0b10000000 +#define PROTO_CMD_MOUSE_BUTTON_LEFT_STATE 0b00001000 +#define PROTO_CMD_MOUSE_BUTTON_RIGHT_SELECT 0b01000000 +#define PROTO_CMD_MOUSE_BUTTON_RIGHT_STATE 0b00000100 +#define PROTO_CMD_MOUSE_BUTTON_MIDDLE_SELECT 0b00100000 +#define PROTO_CMD_MOUSE_BUTTON_MIDDLE_STATE 0b00000010 + +#define PROTO_CMD_MOUSE_BUTTON_EXTRA_UP_SELECT 0b10000000 +#define PROTO_CMD_MOUSE_BUTTON_EXTRA_UP_STATE 0b00001000 +#define PROTO_CMD_MOUSE_BUTTON_EXTRA_DOWN_SELECT 0b01000000 +#define PROTO_CMD_MOUSE_BUTTON_EXTRA_DOWN_STATE 0b00000100 + + +uint16_t protoCrc16(const uint8_t *buffer, unsigned length) { + uint16_t crc = 0xFFFF; + + for (unsigned byte_count = 0; byte_count < length; ++byte_count) { + crc = crc ^ buffer[byte_count]; + for (unsigned bit_count = 0; bit_count < 8; ++bit_count) { + if ((crc & 0x0001) == 0) { + crc = crc >> 1; + } else { + crc = crc >> 1; + crc = crc ^ PROTO_CRC_POLINOM; + } + } + } + return crc; +} diff --git a/hid/src/ps2/hid.h b/hid/src/ps2/hid.h index d12a16e4..eca2bf4b 100644 --- a/hid/src/ps2/hid.h +++ b/hid/src/ps2/hid.h @@ -25,8 +25,6 @@ #include <Arduino.h> #include <ps2dev.h> -#include "../inline.h" - #include "keymap.h" // #define PS2_KBD_CLOCK_PIN 7 @@ -43,11 +41,11 @@ class Ps2HidKeyboard { _dev.keyboard_init(); } - INLINE void periodic() { + void periodic() { _dev.keyboard_handle(&_leds); } - INLINE void sendKey(uint8_t code, bool state) { + void sendKey(uint8_t code, bool state) { Ps2KeyType ps2_type; uint8_t ps2_code; @@ -76,7 +74,7 @@ class Ps2HidKeyboard { } } - INLINE uint8_t getLedsAs(uint8_t caps, uint8_t scroll, uint8_t num) { + uint8_t getLedsAs(uint8_t caps, uint8_t scroll, uint8_t num) { uint8_t result = 0; periodic(); diff --git a/hid/src/ps2/keymap.h b/hid/src/ps2/keymap.h index 2e484cac..933f6ee5 100644 --- a/hid/src/ps2/keymap.h +++ b/hid/src/ps2/keymap.h @@ -22,8 +22,6 @@ #pragma once -#include "../inline.h" - enum Ps2KeyType : uint8_t { PS2_KEY_TYPE_UNKNOWN = 0, @@ -34,7 +32,7 @@ enum Ps2KeyType : uint8_t { }; -INLINE void keymapPs2(uint8_t code, Ps2KeyType *ps2_type, uint8_t *ps2_code) { +void keymapPs2(uint8_t code, Ps2KeyType *ps2_type, uint8_t *ps2_code) { *ps2_type = PS2_KEY_TYPE_UNKNOWN; *ps2_code = 0; diff --git a/hid/src/ps2/keymap.h.mako b/hid/src/ps2/keymap.h.mako index 70da2f36..bedb5fcc 100644 --- a/hid/src/ps2/keymap.h.mako +++ b/hid/src/ps2/keymap.h.mako @@ -22,8 +22,6 @@ #pragma once -#include "../inline.h" - enum Ps2KeyType : uint8_t { PS2_KEY_TYPE_UNKNOWN = 0, @@ -34,13 +32,13 @@ enum Ps2KeyType : uint8_t { }; <%! import operator %> -INLINE void keymapPs2(uint8_t code, Ps2KeyType *ps2_type, uint8_t *ps2_code) { +void keymapPs2(uint8_t code, Ps2KeyType *ps2_type, uint8_t *ps2_code) { *ps2_type = PS2_KEY_TYPE_UNKNOWN; *ps2_code = 0; switch (code) { -% for km in sorted(keymap, key=operator.attrgetter("serial_code")): - case ${km.serial_code}: *ps2_type = PS2_KEY_TYPE_${km.ps2_key.type.upper()}; *ps2_code = ${km.ps2_key.code}; return; // ${km.arduino_name} +% for km in sorted(keymap, key=operator.attrgetter("mcu_code")): + case ${km.mcu_code}: *ps2_type = PS2_KEY_TYPE_${km.ps2_key.type.upper()}; *ps2_code = ${km.ps2_key.code}; return; // ${km.arduino_name} % endfor } } diff --git a/hid/src/usb/hid.h b/hid/src/usb/hid.h index b4523a6b..6b729323 100644 --- a/hid/src/usb/hid.h +++ b/hid/src/usb/hid.h @@ -24,8 +24,6 @@ #include <HID-Project.h> -#include "../inline.h" - #include "keymap.h" @@ -38,11 +36,11 @@ class UsbHidKeyboard { BootKeyboard.begin(); } - INLINE void reset() { + void reset() { BootKeyboard.releaseAll(); } - INLINE void sendKey(uint8_t code, bool state) { + void sendKey(uint8_t code, bool state) { KeyboardKeycode usb_code = keymapUsb(code); if (usb_code != KEY_ERROR_UNDEFINED) { if (state) BootKeyboard.press(usb_code); @@ -50,7 +48,7 @@ class UsbHidKeyboard { } } - INLINE uint8_t getLedsAs(uint8_t caps, uint8_t scroll, uint8_t num) { + uint8_t getLedsAs(uint8_t caps, uint8_t scroll, uint8_t num) { uint8_t leds = BootKeyboard.getLeds(); uint8_t result = 0; @@ -69,11 +67,11 @@ class UsbHidMouse { SingleAbsoluteMouse.begin(); } - INLINE void reset() { + void reset() { SingleAbsoluteMouse.releaseAll(); } - INLINE void sendMouseButtons( + void sendMouseButtons( bool left_select, bool left_state, bool right_select, bool right_state, bool middle_select, bool middle_state, @@ -87,17 +85,17 @@ class UsbHidMouse { if (down_select) _sendMouseButton(MOUSE_NEXT, down_state); } - INLINE void sendMouseMove(int x, int y) { + void sendMouseMove(int x, int y) { SingleAbsoluteMouse.moveTo(x, y); } - INLINE void sendMouseWheel(int delta_y) { + void sendMouseWheel(int delta_y) { // delta_x is not supported by hid-project now SingleAbsoluteMouse.move(0, 0, delta_y); } private: - INLINE void _sendMouseButton(uint8_t button, bool state) { + void _sendMouseButton(uint8_t button, bool state) { if (state) SingleAbsoluteMouse.press(button); else SingleAbsoluteMouse.release(button); } diff --git a/hid/src/usb/keymap.h b/hid/src/usb/keymap.h index 35df2be4..1564b1f0 100644 --- a/hid/src/usb/keymap.h +++ b/hid/src/usb/keymap.h @@ -24,10 +24,8 @@ #include <HID-Project.h> -#include "../inline.h" - -INLINE KeyboardKeycode keymapUsb(uint8_t code) { +KeyboardKeycode keymapUsb(uint8_t code) { switch (code) { case 1: return KEY_A; case 2: return KEY_B; diff --git a/hid/src/usb/keymap.h.mako b/hid/src/usb/keymap.h.mako index 5df3a7f5..a93d91a4 100644 --- a/hid/src/usb/keymap.h.mako +++ b/hid/src/usb/keymap.h.mako @@ -24,13 +24,11 @@ #include <HID-Project.h> -#include "../inline.h" - <%! import operator %> -INLINE KeyboardKeycode keymapUsb(uint8_t code) { +KeyboardKeycode keymapUsb(uint8_t code) { switch (code) { -% for km in sorted(keymap, key=operator.attrgetter("serial_code")): - case ${km.serial_code}: return ${km.arduino_name}; +% for km in sorted(keymap, key=operator.attrgetter("mcu_code")): + case ${km.mcu_code}: return ${km.arduino_name}; % endfor default: return KEY_ERROR_UNDEFINED; } |