summaryrefslogtreecommitdiff
path: root/hid
diff options
context:
space:
mode:
authorDevaev Maxim <[email protected]>2020-11-12 21:03:28 +0300
committerDevaev Maxim <[email protected]>2020-11-12 21:03:28 +0300
commit87cc8cf7b0e00f7f0a9badf551067aafad6da4ce (patch)
treecdd802d124236ded6969dc5d80c764deec357e02 /hid
parent79ef26e2f441f6c742a5da78b08ea2d5a4cc6e18 (diff)
parent0984f0cb36c5881669010c62e986cc8bc7fe019a (diff)
Merge branch 'spi'
Diffstat (limited to 'hid')
-rw-r--r--hid/Makefile13
-rw-r--r--hid/avrdude-rpi.conf7
-rw-r--r--hid/avrdude.py54
-rw-r--r--hid/lib/.gitignore0
-rw-r--r--hid/patch.py42
-rw-r--r--hid/patches/serial.patch24
-rw-r--r--hid/platformio.ini163
-rw-r--r--hid/src/inline.h26
-rw-r--r--hid/src/main.cpp228
-rw-r--r--hid/src/proto.h76
-rw-r--r--hid/src/ps2/hid.h8
-rw-r--r--hid/src/ps2/keymap.h4
-rw-r--r--hid/src/ps2/keymap.h.mako8
-rw-r--r--hid/src/usb/hid.h18
-rw-r--r--hid/src/usb/keymap.h4
-rw-r--r--hid/src/usb/keymap.h.mako8
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;
}