diff options
Diffstat (limited to 'hid/pico/src/ph_outputs.c')
-rw-r--r-- | hid/pico/src/ph_outputs.c | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/hid/pico/src/ph_outputs.c b/hid/pico/src/ph_outputs.c new file mode 100644 index 00000000..40d10983 --- /dev/null +++ b/hid/pico/src/ph_outputs.c @@ -0,0 +1,137 @@ +/* ========================================================================= # +# # +# 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 "ph_outputs.h" + +#include "hardware/gpio.h" +#include "hardware/structs/watchdog.h" + +#include "ph_types.h" +#include "ph_tools.h" +#include "ph_proto.h" + + +#define _PS2_ENABLED_PIN 2 +#define _PS2_SET_KBD_PIN 3 +#define _PS2_SET_MOUSE_PIN 4 + +#define _USB_DISABLED_PIN 6 +#define _USB_ENABLE_W98_PIN 7 +#define _USB_SET_MOUSE_REL_PIN 8 +#define _USB_SET_MOUSE_W98_PIN 9 + + +u8 ph_g_outputs_active = 0; +u8 ph_g_outputs_avail = 0; + + +static int _read_outputs(void); + + +void ph_outputs_init(void) { +# define INIT_SWITCH(x_pin) { gpio_init(x_pin); gpio_set_dir(x_pin, GPIO_IN); gpio_pull_down(x_pin); } + INIT_SWITCH(_PS2_ENABLED_PIN); + INIT_SWITCH(_PS2_SET_KBD_PIN); + INIT_SWITCH(_PS2_SET_MOUSE_PIN); + + INIT_SWITCH(_USB_DISABLED_PIN); + INIT_SWITCH(_USB_ENABLE_W98_PIN); + INIT_SWITCH(_USB_SET_MOUSE_REL_PIN); + INIT_SWITCH(_USB_SET_MOUSE_W98_PIN); +# undef INIT_SWITCH + + const bool o_ps2_enabled = gpio_get(_PS2_ENABLED_PIN); + const bool o_ps2_kbd = gpio_get(_PS2_SET_KBD_PIN); + const bool o_ps2_mouse = gpio_get(_PS2_SET_MOUSE_PIN); + + const bool o_usb_disabled = gpio_get(_USB_DISABLED_PIN); + const bool o_usb_enabled_w98 = gpio_get(_USB_ENABLE_W98_PIN); + const bool o_usb_mouse_rel = gpio_get(_USB_SET_MOUSE_REL_PIN); + const bool o_usb_mouse_w98 = gpio_get(_USB_SET_MOUSE_W98_PIN); + + int outputs = _read_outputs(); + if (outputs < 0) { + outputs = 0; + + if (o_ps2_enabled && o_ps2_kbd) { + outputs |= PH_PROTO_OUT1_KBD_PS2; + } else if (!o_usb_disabled) { + outputs |= PH_PROTO_OUT1_KBD_USB; + } + + if (o_ps2_enabled && o_ps2_mouse) { + outputs |= PH_PROTO_OUT1_MOUSE_PS2; + } else if (!o_usb_disabled) { + if (o_usb_enabled_w98 && o_usb_mouse_w98) { + outputs |= PH_PROTO_OUT1_MOUSE_USB_W98; + } else if (o_usb_mouse_rel) { + outputs |= PH_PROTO_OUT1_MOUSE_USB_REL; + } else { + outputs |= PH_PROTO_OUT1_MOUSE_USB_ABS; + } + } + + ph_outputs_write(0xFF, outputs, true); + } + + if (!o_usb_disabled) { + ph_g_outputs_avail |= PH_PROTO_OUT2_HAS_USB; + if (o_usb_enabled_w98) { + ph_g_outputs_avail |= PH_PROTO_OUT2_HAS_USB_W98; + } + } + if (o_ps2_enabled) { + ph_g_outputs_avail |= PH_PROTO_OUT2_HAS_PS2; + } + + ph_g_outputs_active = outputs & 0xFF; +} + +void ph_outputs_write(u8 mask, u8 outputs, bool force) { + int old = 0; + if (!force) { + old = _read_outputs(); + if (old < 0) { + old = 0; + } + } + u8 data[4] = {0}; + data[0] = PH_PROTO_MAGIC; + data[1] = (old & ~mask) | outputs; + ph_split16(ph_crc16(data, 2), &data[2], &data[3]); + const u32 s0 = ((u32)data[0] << 24) | ((u32)data[1] << 16) | ((u32)data[2] << 8) | (u32)data[3]; + watchdog_hw->scratch[0] = s0; +} + +static int _read_outputs(void) { + const u32 s0 = watchdog_hw->scratch[0]; + const u8 data[4] = { + (s0 >> 24) & 0xFF, + (s0 >> 16) & 0xFF, + (s0 >> 8) & 0xFF, + s0 & 0xFF, + }; + if (data[0] != PH_PROTO_MAGIC || ph_crc16(data, 2) != ph_merge8_u16(data[2], data[3])) { + return -1; + } + return data[1]; +} |