diff options
author | Devaev Maxim <[email protected]> | 2020-11-03 10:15:54 +0300 |
---|---|---|
committer | Devaev Maxim <[email protected]> | 2020-11-11 22:24:25 +0300 |
commit | e07cdd60f393eb17184afe4ea1730f3c5745ea6f (patch) | |
tree | 5751136b75af6dc2433c19e17b9e3739cb7a9d33 /hid/src | |
parent | a3707d047fddd5f0c923422468be29ddb345f989 (diff) |
spi firmware
Diffstat (limited to 'hid/src')
-rw-r--r-- | hid/src/inline.h | 26 | ||||
-rw-r--r-- | hid/src/main.cpp | 212 | ||||
-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 | 4 | ||||
-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 | 4 |
9 files changed, 209 insertions, 147 deletions
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 b4960cb5..0da6884b 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" @@ -35,41 +42,9 @@ // #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 +// -- OR -- +// #define CMD_SPI +#define CMD_TIMEOUT 100000 // ----------------------------------------------------------------------------- @@ -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,12 +69,12 @@ 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]; @@ -119,7 +94,7 @@ INLINE uint8_t cmdMouseButtonEvent(const uint8_t *buffer) { // 2 bytes 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]; @@ -134,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, @@ -149,40 +124,86 @@ 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; +volatile uint8_t spi_in_read = 0; // Вычитанное spiRead() + +volatile uint8_t spi_out[4] = {0}; +volatile uint8_t spi_out_index = 0; -INLINE void recvTimerStop(bool flag) { - Timer1.stop(); - cmd_recv_timed_out = flag; +uint8_t spiAvailable() { + return spi_in_index - spi_in_read; } -INLINE void resetCmdRecvTimeout() { - recvTimerStop(false); - Timer1.initialize(CMD_RECV_TIMEOUT); +uint8_t spiRead() { + uint8_t value = 0; + if (spi_in_read < 8) { + value = spi_in[spi_in_read]; + ++spi_in_read; + } + return value; } -INLINE void sendCmdResponse(uint8_t code=0) { +void spiWrite(const uint8_t *buffer) { + if (spi_out[0] == 0) { + spi_out[3] = buffer[3]; + spi_out[2] = buffer[2]; + spi_out[1] = buffer[1]; + spi_out[0] = buffer[0]; // Меджик разрешает начать ответ + } +} + +void spiReadReset() { + spi_in_index = 0; + spi_in_read = 0; +} + +ISR(SPI_STC_vect) { + if (spi_in_index < 8) { + spi_in[spi_in_index] = SPDR; + ++spi_in_index; + SPDR = 0; + } else if (spi_out[0] && spi_out_index < 4) { + SPDR = spi_out[spi_out_index]; + ++spi_out_index; + if (spi_out_index == 4) { + spiReadReset(); + spi_out[0] = 0; + spi_out_index = 0; + } + } else { + SPDR = 0; + } +} +#endif + + +// ----------------------------------------------------------------------------- +void sendCmdResponse(uint8_t code) { static uint8_t prev_code = PROTO_RESP_NONE; if (code == 0) { code = prev_code; // Repeat the last code @@ -193,16 +214,23 @@ 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); +# elif defined(CMD_SPI) + spiWrite(buffer); +# endif } -void intRecvTimedOut() { - recvTimerStop(true); +bool isCmdTimedOut(unsigned long last) { + unsigned long now = micros(); + return ( + (now >= last && now - last > CMD_TIMEOUT) + || (now < last && ((unsigned long)-1) - last + now > CMD_TIMEOUT) + ); } void setup() { @@ -211,48 +239,44 @@ 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() { + unsigned long last = micros(); uint8_t buffer[8]; - unsigned index = 0; + uint8_t index = 0; 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(); +# elif defined(CMD_SPI) + if (spiAvailable() > 0) { + buffer[index] = spiRead(); +# endif 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 && cmd_recv_timed_out) { + } else if (index > 0 && isCmdTimedOut(last)) { +# ifdef CMD_SERIAL sendCmdResponse(PROTO_RESP_TIMEOUT_ERROR); +# elif defined(CMD_SPI) + spiReadReset(); +# endif index = 0; } } 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 cec7cb8a..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,7 +32,7 @@ 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; 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 8cd94fd9..a93d91a4 100644 --- a/hid/src/usb/keymap.h.mako +++ b/hid/src/usb/keymap.h.mako @@ -24,10 +24,8 @@ #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("mcu_code")): case ${km.mcu_code}: return ${km.arduino_name}; |