diff options
author | Maxim Devaev <[email protected]> | 2023-08-03 05:47:27 +0300 |
---|---|---|
committer | Maxim Devaev <[email protected]> | 2023-08-03 05:47:27 +0300 |
commit | c96057772c8d845c90ad7429e51689eeffb63d71 (patch) | |
tree | c376d9715169b9248aa8b7ef70b8a6506297f982 /hid/pico/src/main.c | |
parent | 1a8f98a64f9480c1062225e0fc994ceac4ba346d (diff) |
rp2040 hid
Diffstat (limited to 'hid/pico/src/main.c')
-rw-r--r-- | hid/pico/src/main.c | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/hid/pico/src/main.c b/hid/pico/src/main.c new file mode 100644 index 00000000..69508689 --- /dev/null +++ b/hid/pico/src/main.c @@ -0,0 +1,122 @@ +/***************************************************************************** +# # +# 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 "pico/stdlib.h" +#include "hardware/gpio.h" +#include "hardware/watchdog.h" + +#include "ph_types.h" +#include "ph_tools.h" +#include "ph_outputs.h" +#include "ph_usb.h" +#include "ph_spi.h" +#include "ph_proto.h" +#include "ph_cmds.h" +#include "ph_debug.h" + + +static bool _reset_required = false; + + +static u8 _handle_request(const u8 *data) { // 8 bytes + // FIXME: See kvmd/kvmd#80 + // Should input buffer be cleared in this case? + if (data[0] == PH_PROTO_MAGIC && ph_crc16(data, 6) == ph_merge8_u16(data[6], data[7])) { +# define HANDLE(x_handler, x_reset) { \ + x_handler(data + 2); \ + if (x_reset) { _reset_required = true; } \ + return PH_PROTO_PONG_OK; \ + } + switch (data[1]) { + case PH_PROTO_CMD_PING: return PH_PROTO_PONG_OK; + case PH_PROTO_CMD_SET_KBD: HANDLE(ph_cmd_set_kbd, true); + case PH_PROTO_CMD_SET_MOUSE: HANDLE(ph_cmd_set_mouse, true); + case PH_PROTO_CMD_SET_CONNECTED: return PH_PROTO_PONG_OK; // Arduino AUM + case PH_PROTO_CMD_CLEAR_HID: HANDLE(ph_cmd_send_clear, false); + case PH_PROTO_CMD_KBD_KEY: HANDLE(ph_cmd_kbd_send_key, false); + case PH_PROTO_CMD_MOUSE_BUTTON: HANDLE(ph_cmd_mouse_send_button, false); + case PH_PROTO_CMD_MOUSE_ABS: HANDLE(ph_cmd_mouse_send_abs, false); + case PH_PROTO_CMD_MOUSE_REL: HANDLE(ph_cmd_mouse_send_rel, false); + case PH_PROTO_CMD_MOUSE_WHEEL: HANDLE(ph_cmd_mouse_send_wheel, false); + case PH_PROTO_CMD_REPEAT: return 0; + } +# undef HANDLE + return PH_PROTO_RESP_INVALID_ERROR; + } + return PH_PROTO_RESP_CRC_ERROR; +} + +static void _send_response(u8 code) { + static u8 prev_code = PH_PROTO_RESP_NONE; + if (code == 0) { + code = prev_code; // Repeat the last code + } else { + prev_code = code; + } + + u8 resp[8] = {0}; + resp[0] = PH_PROTO_MAGIC_RESP; + + if (code & PH_PROTO_PONG_OK) { + resp[1] = PH_PROTO_PONG_OK; + if (_reset_required) { + resp[1] |= PH_PROTO_PONG_RESET_REQUIRED; + } + resp[2] = PH_PROTO_OUT1_DYNAMIC; + + resp[1] |= ph_cmd_get_offlines(); + resp[1] |= ph_cmd_kbd_get_leds(); + resp[2] |= ph_g_outputs_active; + resp[3] |= ph_g_outputs_avail; + } else { + resp[1] = code; + } + + ph_split16(ph_crc16(resp, 6), &resp[6], &resp[7]); + + ph_spi_write(resp); + + if (_reset_required) { + watchdog_reboot(0, 0, 100); // Даем немного времени чтобы отправить ответ, а потом ребутимся + } +} + +static void _spi_data_handler(const u8 *data) { + _send_response(_handle_request(data)); +} + + +int main(void) { + ph_debug_init(false); // No UART + ph_outputs_init(); + ph_usb_init(); + ph_spi_init(_spi_data_handler); + + while (true) { + ph_usb_task(); + if (!_reset_required) { + ph_spi_task(); + ph_debug_act_pulse(50); + } + } + return 0; +} |