summaryrefslogtreecommitdiff
path: root/hid/arduino/lib/drivers-stm32
diff options
context:
space:
mode:
Diffstat (limited to 'hid/arduino/lib/drivers-stm32')
-rw-r--r--hid/arduino/lib/drivers-stm32/README.md22
-rw-r--r--hid/arduino/lib/drivers-stm32/backup-register.h53
-rw-r--r--hid/arduino/lib/drivers-stm32/bluepill_sch.pngbin0 -> 179860 bytes
-rw-r--r--hid/arduino/lib/drivers-stm32/board-stm32.h103
-rw-r--r--hid/arduino/lib/drivers-stm32/factory.cpp94
-rw-r--r--hid/arduino/lib/drivers-stm32/usb/hid-wrapper-stm32.h72
-rw-r--r--hid/arduino/lib/drivers-stm32/usb/keyboard-stm32.h92
-rw-r--r--hid/arduino/lib/drivers-stm32/usb/mouse-absolute-stm32.h86
-rw-r--r--hid/arduino/lib/drivers-stm32/usb/mouse-relative-stm32.h86
9 files changed, 608 insertions, 0 deletions
diff --git a/hid/arduino/lib/drivers-stm32/README.md b/hid/arduino/lib/drivers-stm32/README.md
new file mode 100644
index 00000000..93de3312
--- /dev/null
+++ b/hid/arduino/lib/drivers-stm32/README.md
@@ -0,0 +1,22 @@
+This is WIP. Use AVR version as reference.
+
+It was tested with bluepill. Most boards are clones.
+If you have problem with USB please check https://stm32duinoforum.com/forum/wiki_subdomain/index_title_Blue_Pill.html for pull up resistor. If it still does not work check another board or cable.
+
+TODO:
+- [x] Serial communication
+- [x] USB keyboard
+- [x] USB keyboard - add scroll status
+- [x] USB keyboard - key sending
+- [x] USB keyboard - test key mapping
+- [x] Persistent storage
+- [ ] SPI communication
+- [ ] PS2 keyboard
+- [x] USB absolute mouse
+- [x] USB absolute mouse - add whele
+- [x] USB relative mouse
+- [x] USB relative mouse - add whele
+- [ ] USB mouses - up down button
+- [ ] WIN98 USB mouse
+- [x] undefine SERIAL_USB
+- [ ] boot keyboard
diff --git a/hid/arduino/lib/drivers-stm32/backup-register.h b/hid/arduino/lib/drivers-stm32/backup-register.h
new file mode 100644
index 00000000..196e4e1c
--- /dev/null
+++ b/hid/arduino/lib/drivers-stm32/backup-register.h
@@ -0,0 +1,53 @@
+/*****************************************************************************
+# #
+# KVMD - The main PiKVM daemon. #
+# #
+# Copyright (C) 2018-2023 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
+
+
+#include <stm32f1_rtc.h>
+
+#include "storage.h"
+
+
+namespace DRIVERS {
+ struct BackupRegister : public Storage {
+ BackupRegister() : Storage(NON_VOLATILE_STORAGE) {
+ _rtc.enableClockInterface();
+ }
+
+ void readBlock(void *dest, const void *src, size_t size) override {
+ uint8_t *dest_ = reinterpret_cast<uint8_t*>(dest);
+ for(size_t index = 0; index < size; ++index) {
+ dest_[index] = _rtc.getBackupRegister(reinterpret_cast<uintptr_t>(src) + index + 1);
+ }
+ }
+
+ void updateBlock(const void *src, void *dest, size_t size) override {
+ const uint8_t *src_ = reinterpret_cast<const uint8_t*>(src);
+ for(size_t index = 0; index < size; ++index) {
+ _rtc.setBackupRegister(reinterpret_cast<uintptr_t>(dest) + index + 1, src_[index]);
+ }
+ }
+
+ private:
+ STM32F1_RTC _rtc;
+ };
+}
diff --git a/hid/arduino/lib/drivers-stm32/bluepill_sch.png b/hid/arduino/lib/drivers-stm32/bluepill_sch.png
new file mode 100644
index 00000000..956448dd
--- /dev/null
+++ b/hid/arduino/lib/drivers-stm32/bluepill_sch.png
Binary files differ
diff --git a/hid/arduino/lib/drivers-stm32/board-stm32.h b/hid/arduino/lib/drivers-stm32/board-stm32.h
new file mode 100644
index 00000000..1602edaa
--- /dev/null
+++ b/hid/arduino/lib/drivers-stm32/board-stm32.h
@@ -0,0 +1,103 @@
+/*****************************************************************************
+# #
+# KVMD - The main PiKVM daemon. #
+# #
+# Copyright (C) 2018-2023 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
+
+#include "board.h"
+#include <libmaple/iwdg.h>
+
+
+namespace DRIVERS {
+ class BoardStm32 : public Board {
+ public:
+ BoardStm32() : Board(BOARD){
+ //2 sec timeout
+ iwdg_init(IWDG_PRE_16, 0xFFF);
+ pinMode(LED_BUILTIN, OUTPUT);
+ }
+
+ void reset() override {
+ nvic_sys_reset();
+ }
+
+ void periodic() override {
+ iwdg_feed();
+ if (is_micros_timed_out(_prev_ts, 100000)) {
+ switch(_state) {
+ case 0:
+ digitalWrite(LED_BUILTIN, LOW);
+ break;
+ case 2:
+ if(_rx_data) {
+ _rx_data = false;
+ digitalWrite(LED_BUILTIN, LOW);
+ }
+ break;
+ case 4:
+ if(_keyboard_online) {
+ _keyboard_online = false;
+ digitalWrite(LED_BUILTIN, LOW);
+ }
+ break;
+ case 8:
+ if(_mouse_online) {
+ _mouse_online = false;
+ digitalWrite(LED_BUILTIN, LOW);
+ }
+ break;
+ case 1: // heartbeat off
+ case 3: // _rx_data off
+ case 7: // _keyboard_online off
+ case 11: // _mouse_online off
+ digitalWrite(LED_BUILTIN, HIGH);
+ break;
+ case 19:
+ _state = -1;
+ break;
+ }
+ ++_state;
+ _prev_ts = micros();
+ }
+ }
+
+ void updateStatus(status status) override {
+ switch (status) {
+ case RX_DATA:
+ _rx_data = true;
+ break;
+ case KEYBOARD_ONLINE:
+ _keyboard_online = true;
+ break;
+ case MOUSE_ONLINE:
+ _mouse_online = true;
+ break;
+ }
+ }
+
+ private:
+ unsigned long _prev_ts = 0;
+ uint8_t _state = 0;
+ bool _rx_data = false;
+ bool _keyboard_online = false;
+ bool _mouse_online = false;
+ };
+}
diff --git a/hid/arduino/lib/drivers-stm32/factory.cpp b/hid/arduino/lib/drivers-stm32/factory.cpp
new file mode 100644
index 00000000..8f20e0ff
--- /dev/null
+++ b/hid/arduino/lib/drivers-stm32/factory.cpp
@@ -0,0 +1,94 @@
+/*****************************************************************************
+# #
+# KVMD - The main PiKVM daemon. #
+# #
+# Copyright (C) 2018-2023 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/>. #
+# #
+*****************************************************************************/
+
+
+#include "factory.h"
+#include "usb/keyboard-stm32.h"
+#include "usb/hid-wrapper-stm32.h"
+#include "usb/mouse-absolute-stm32.h"
+#include "usb/mouse-relative-stm32.h"
+#include "backup-register.h"
+#include "board-stm32.h"
+#include "serial.h"
+
+#ifndef __STM32F1__
+# error "Only STM32F1 is supported"
+#endif
+#ifdef SERIAL_USB
+# error "Disable random USB enumeration"
+#endif
+
+
+namespace DRIVERS {
+ HidWrapper _hidWrapper;
+
+ Keyboard *Factory::makeKeyboard(type _type) {
+ switch (_type) {
+# ifdef HID_WITH_USB
+ case USB_KEYBOARD:
+ return new UsbKeyboard(_hidWrapper);
+# endif
+ default:
+ return new Keyboard(DUMMY);
+ }
+ }
+
+ Mouse *Factory::makeMouse(type _type) {
+ switch(_type) {
+# ifdef HID_WITH_USB
+ case USB_MOUSE_ABSOLUTE:
+ return new UsbMouseAbsolute(_hidWrapper);
+ case USB_MOUSE_RELATIVE:
+ return new UsbMouseRelative(_hidWrapper);
+# endif
+ default:
+ return new Mouse(DRIVERS::DUMMY);
+ }
+ }
+
+ Storage *Factory::makeStorage(type _type) {
+ switch (_type) {
+# ifdef HID_DYNAMIC
+ case NON_VOLATILE_STORAGE:
+ return new BackupRegister();
+# endif
+ default:
+ return new Storage(DRIVERS::DUMMY);
+ }
+ }
+
+ Board *Factory::makeBoard(type _type) {
+ switch (_type) {
+ case BOARD:
+ return new BoardStm32();
+ default:
+ return new Board(DRIVERS::DUMMY);
+ }
+ }
+
+ Connection *Factory::makeConnection(type _type) {
+# ifdef CMD_SERIAL
+ return new Serial();
+# else
+# error CMD phy is not defined
+# endif
+ }
+}
diff --git a/hid/arduino/lib/drivers-stm32/usb/hid-wrapper-stm32.h b/hid/arduino/lib/drivers-stm32/usb/hid-wrapper-stm32.h
new file mode 100644
index 00000000..62f58213
--- /dev/null
+++ b/hid/arduino/lib/drivers-stm32/usb/hid-wrapper-stm32.h
@@ -0,0 +1,72 @@
+/*****************************************************************************
+# #
+# KVMD - The main PiKVM daemon. #
+# #
+# Copyright (C) 2018-2023 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
+
+#include <USBComposite.h>
+
+
+namespace DRIVERS {
+ class HidWrapper {
+ public:
+ void begin() {
+ if (_init) {
+ return;
+ }
+ _init = true;
+
+ _report_descriptor_length = 0;
+ for (unsigned index = 0; index < _count; ++index) {
+ _report_descriptor_length += _descriptors_size[index];
+ }
+
+ _report_descriptor = new uint8[_report_descriptor_length];
+
+ size_t offset = 0;
+ for (unsigned index = 0; index < _count; ++index) {
+ memcpy(_report_descriptor + offset, _report_descriptors[index], _descriptors_size[index]);
+ offset += _descriptors_size[index];
+ }
+
+ usbHid.begin(_report_descriptor, _report_descriptor_length);
+ }
+
+ void addReportDescriptor(const uint8_t *report_descriptor, uint16_t report_descriptor_length) {
+ _report_descriptors[_count] = report_descriptor;
+ _descriptors_size[_count] = report_descriptor_length;
+ ++_count;
+ }
+
+ USBHID usbHid;
+
+ private:
+ bool _init = false;
+
+ static constexpr uint8_t MAX_USB_DESCRIPTORS = 2;
+ const uint8_t *_report_descriptors[MAX_USB_DESCRIPTORS];
+ uint8_t _descriptors_size[MAX_USB_DESCRIPTORS];
+
+ uint8_t _count = 0;
+ uint8_t *_report_descriptor;
+ uint16_t _report_descriptor_length;
+ };
+}
diff --git a/hid/arduino/lib/drivers-stm32/usb/keyboard-stm32.h b/hid/arduino/lib/drivers-stm32/usb/keyboard-stm32.h
new file mode 100644
index 00000000..22dec04d
--- /dev/null
+++ b/hid/arduino/lib/drivers-stm32/usb/keyboard-stm32.h
@@ -0,0 +1,92 @@
+/*****************************************************************************
+# #
+# KVMD - The main PiKVM daemon. #
+# #
+# Copyright (C) 2018-2023 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
+
+#include <USBComposite.h>
+
+#include "tools.h"
+#include "keyboard.h"
+#include "usb-keymap.h"
+#include "hid-wrapper-stm32.h"
+
+
+namespace DRIVERS {
+ const uint8_t reportDescriptionKeyboard[] = {
+ HID_KEYBOARD_REPORT_DESCRIPTOR(),
+ };
+
+ class UsbKeyboard : public Keyboard {
+ public:
+ UsbKeyboard(HidWrapper& _hidWrapper) : Keyboard(USB_KEYBOARD),
+ _hidWrapper(_hidWrapper), _keyboard(_hidWrapper.usbHid) {
+ _hidWrapper.addReportDescriptor(reportDescriptionKeyboard, sizeof(reportDescriptionKeyboard));
+ }
+
+ void begin() override {
+ _hidWrapper.begin();
+ _keyboard.begin();
+ }
+
+ void clear() override {
+ _keyboard.releaseAll();
+ }
+
+ void sendKey(uint8_t code, bool state) override {
+ uint16_t usb_code = keymapUsb(code);
+ if (usb_code == 0) {
+ return;
+ }
+
+ // 0xE0 is a prefix from HID-Project keytable
+ if (usb_code >= 0xE0 && usb_code <= 0xE7) {
+ usb_code = usb_code - 0xE0 + 0x80;
+ } else {
+ usb_code += KEY_HID_OFFSET;
+ }
+
+ if (state) {
+ _keyboard.press(usb_code);
+ } else {
+ _keyboard.release(usb_code);
+ }
+ }
+
+ bool isOffline() override {
+ return (USBComposite == false);
+ }
+
+ KeyboardLedsState getLeds() override {
+ uint8_t leds = _keyboard.getLEDs();
+ KeyboardLedsState result = {
+ .caps = leds & 0b00000010,
+ .scroll = leds & 0b00000100,
+ .num = leds & 0b00000001,
+ };
+ return result;
+ }
+
+ private:
+ HidWrapper& _hidWrapper;
+ HIDKeyboard _keyboard;
+ };
+}
diff --git a/hid/arduino/lib/drivers-stm32/usb/mouse-absolute-stm32.h b/hid/arduino/lib/drivers-stm32/usb/mouse-absolute-stm32.h
new file mode 100644
index 00000000..65195c78
--- /dev/null
+++ b/hid/arduino/lib/drivers-stm32/usb/mouse-absolute-stm32.h
@@ -0,0 +1,86 @@
+/*****************************************************************************
+# #
+# KVMD - The main PiKVM daemon. #
+# #
+# Copyright (C) 2018-2023 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
+
+#include <USBComposite.h>
+
+#include "mouse.h"
+#include "hid-wrapper-stm32.h"
+
+
+namespace DRIVERS {
+ const uint8_t reportDescriptionMouseAbsolute[] = {
+ HID_ABS_MOUSE_REPORT_DESCRIPTOR()
+ };
+
+ class UsbMouseAbsolute : public Mouse {
+ public:
+ UsbMouseAbsolute(HidWrapper& _hidWrapper) : Mouse(USB_MOUSE_ABSOLUTE),
+ _hidWrapper(_hidWrapper), _mouse(_hidWrapper.usbHid) {
+ _hidWrapper.addReportDescriptor(reportDescriptionMouseAbsolute, sizeof(reportDescriptionMouseAbsolute));
+ }
+
+ void begin() override {
+ _hidWrapper.begin();
+ }
+
+ void clear() override {
+ _mouse.release(0xFF);
+ }
+
+ void sendButtons (
+ bool left_select, bool left_state,
+ bool right_select, bool right_state,
+ bool middle_select, bool middle_state,
+ bool up_select, bool up_state,
+ bool down_select, bool down_state) override {
+
+# define SEND_BUTTON(x_low, x_up) { \
+ if (x_low##_select) { \
+ if (x_low##_state) _mouse.press(MOUSE_##x_up); \
+ else _mouse.release(MOUSE_##x_up); \
+ } \
+ }
+ SEND_BUTTON(left, LEFT);
+ SEND_BUTTON(right, RIGHT);
+ SEND_BUTTON(middle, MIDDLE);
+# undef SEND_BUTTON
+ }
+
+ void sendMove(int x, int y) override {
+ _mouse.move(x, y);
+ }
+
+ void sendWheel(int delta_y) override {
+ _mouse.move(0, 0, delta_y);
+ }
+
+ bool isOffline() override {
+ return (USBComposite == false);
+ }
+
+ private:
+ HidWrapper& _hidWrapper;
+ HIDAbsMouse _mouse;
+ };
+}
diff --git a/hid/arduino/lib/drivers-stm32/usb/mouse-relative-stm32.h b/hid/arduino/lib/drivers-stm32/usb/mouse-relative-stm32.h
new file mode 100644
index 00000000..4524e20b
--- /dev/null
+++ b/hid/arduino/lib/drivers-stm32/usb/mouse-relative-stm32.h
@@ -0,0 +1,86 @@
+/*****************************************************************************
+# #
+# KVMD - The main PiKVM daemon. #
+# #
+# Copyright (C) 2018-2023 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
+
+#include <USBComposite.h>
+
+#include "mouse.h"
+#include "hid-wrapper-stm32.h"
+
+
+namespace DRIVERS {
+ const uint8_t reportDescriptionMouseRelative[] = {
+ HID_MOUSE_REPORT_DESCRIPTOR()
+ };
+
+ class UsbMouseRelative : public Mouse {
+ public:
+ UsbMouseRelative(HidWrapper& _hidWrapper) : Mouse(USB_MOUSE_RELATIVE),
+ _hidWrapper(_hidWrapper), _mouse(_hidWrapper.usbHid) {
+ _hidWrapper.addReportDescriptor(reportDescriptionMouseRelative, sizeof(reportDescriptionMouseRelative));
+ }
+
+ void begin() override {
+ _hidWrapper.begin();
+ }
+
+ void clear() override {
+ _mouse.release(0xFF);
+ }
+
+ void sendButtons (
+ bool left_select, bool left_state,
+ bool right_select, bool right_state,
+ bool middle_select, bool middle_state,
+ bool up_select, bool up_state,
+ bool down_select, bool down_state) override {
+
+# define SEND_BUTTON(x_low, x_up) { \
+ if (x_low##_select) { \
+ if (x_low##_state) _mouse.press(MOUSE_##x_up); \
+ else _mouse.release(MOUSE_##x_up); \
+ } \
+ }
+ SEND_BUTTON(left, LEFT);
+ SEND_BUTTON(right, RIGHT);
+ SEND_BUTTON(middle, MIDDLE);
+# undef SEND_BUTTON
+ }
+
+ void sendRelative(int x, int y) override {
+ _mouse.move(x, y);
+ }
+
+ void sendWheel(int delta_y) override {
+ _mouse.move(0, 0, delta_y);
+ }
+
+ bool isOffline() override {
+ return (USBComposite == false);
+ }
+
+ private:
+ HidWrapper& _hidWrapper;
+ HIDMouse _mouse;
+ };
+}