diff options
author | Maxim Devaev <[email protected]> | 2021-08-15 17:34:42 +0300 |
---|---|---|
committer | Maxim Devaev <[email protected]> | 2021-08-15 20:16:48 +0300 |
commit | df098bd075e26fb6ecc75b2f7be5923371741677 (patch) | |
tree | 663a4e6a4808ed267e985c5b5d3d18bc4cf1f915 | |
parent | 9afa6efbe4b8ee3186c5d840233c96115363460f (diff) |
win95 runtime switching
-rw-r--r-- | hid/platformio.ini | 4 | ||||
-rw-r--r-- | hid/src/main.cpp | 21 | ||||
-rw-r--r-- | hid/src/proto.h | 18 | ||||
-rw-r--r-- | hid/src/usb/hid.h | 10 | ||||
-rw-r--r-- | kvmd/plugins/hid/_mcu/__init__.py | 17 | ||||
-rw-r--r-- | kvmd/plugins/hid/_mcu/proto.py | 9 | ||||
-rw-r--r-- | kvmd/plugins/hid/otg/__init__.py | 45 | ||||
-rw-r--r-- | kvmd/plugins/hid/otg/events.py | 13 | ||||
-rw-r--r-- | kvmd/plugins/hid/otg/mouse.py | 19 | ||||
-rw-r--r-- | kvmd/validators/hid.py | 2 | ||||
-rw-r--r-- | testenv/v2-hdmi-rpi4.override.yaml | 3 | ||||
-rw-r--r-- | web/share/js/kvm/hid.js | 1 |
12 files changed, 110 insertions, 52 deletions
diff --git a/hid/platformio.ini b/hid/platformio.ini index fa42db0b..a6e27454 100644 --- a/hid/platformio.ini +++ b/hid/platformio.ini @@ -7,7 +7,7 @@ platform = atmelavr board = micro framework = arduino lib_deps = - git+https://github.com/mdevaev/HID#f12b7d633f7437552707d6ccd411204cf36601f2 + git+https://github.com/mdevaev/HID#a8877bc878a1a2f39d993a3defa750b6ec1b2ee0 git+https://github.com/Harvie/ps2dev#v0.0.3 extra_scripts = @@ -25,7 +25,7 @@ build_flags = -DHID_SET_USB_KBD -DHID_SET_USB_MOUSE_ABS # ----- The USB ABS fix for Windows 98 (https://github.com/pikvm/pikvm/issues/159) ----- -# -DHID_USB_ABS_WIN98_FIX +# -DHID_WITH_USB_WIN98 # ----- PS2 keyboard only ----- # -DHID_WITH_PS2 # -DHID_SET_PS2_KBD diff --git a/hid/src/main.cpp b/hid/src/main.cpp index ca00f7dc..10136d54 100644 --- a/hid/src/main.cpp +++ b/hid/src/main.cpp @@ -102,6 +102,8 @@ static void _initOutputs() { outputs |= PROTO::OUTPUTS1::MOUSE::USB_REL; # elif defined(HID_WITH_PS2) && defined(HID_SET_PS2_MOUSE) outputs |= PROTO::OUTPUTS1::MOUSE::PS2; +# elif defined(HID_WITH_USB) && defined(HID_WITH_USB_WIN98) && defined(HID_SET_USB_MOUSE_WIN98) + outputs |= PROTO::OUTPUTS1::MOUSE::USB_WIN98; # endif # ifdef HID_DYNAMIC @@ -122,7 +124,8 @@ static void _initOutputs() { uint8_t mouse = outputs & PROTO::OUTPUTS1::MOUSE::MASK; switch (mouse) { # ifdef HID_WITH_USB - case PROTO::OUTPUTS1::MOUSE::USB_ABS: _usb_mouse_abs = new UsbMouseAbsolute(); break; + case PROTO::OUTPUTS1::MOUSE::USB_ABS: + case PROTO::OUTPUTS1::MOUSE::USB_WIN98: _usb_mouse_abs = new UsbMouseAbsolute(); break; case PROTO::OUTPUTS1::MOUSE::USB_REL: _usb_mouse_rel = new UsbMouseRelative(); break; # endif } @@ -140,7 +143,12 @@ static void _initOutputs() { switch (mouse) { # ifdef HID_WITH_USB - case PROTO::OUTPUTS1::MOUSE::USB_ABS: _usb_mouse_abs->begin(); break; + case PROTO::OUTPUTS1::MOUSE::USB_ABS: +# ifdef HID_WITH_USB_WIN98 + case PROTO::OUTPUTS1::MOUSE::USB_WIN98: +# endif + _usb_mouse_abs->begin(mouse == PROTO::OUTPUTS1::MOUSE::USB_WIN98); + break; case PROTO::OUTPUTS1::MOUSE::USB_REL: _usb_mouse_rel->begin(); break; # endif } @@ -286,7 +294,11 @@ static void _sendResponse(uint8_t code) { } if (_usb_mouse_abs) { response[1] |= _usb_mouse_abs->getOfflineAs(PROTO::PONG::MOUSE_OFFLINE); - response[2] |= PROTO::OUTPUTS1::MOUSE::USB_ABS; + if (_usb_mouse_abs->isWin98FixEnabled()) { + response[2] |= PROTO::OUTPUTS1::MOUSE::USB_WIN98; + } else { + response[2] |= PROTO::OUTPUTS1::MOUSE::USB_ABS; + } } else if (_usb_mouse_rel) { response[1] |= _usb_mouse_rel->getOfflineAs(PROTO::PONG::MOUSE_OFFLINE); response[2] |= PROTO::OUTPUTS1::MOUSE::USB_REL; @@ -299,6 +311,9 @@ static void _sendResponse(uint8_t code) { # endif # ifdef HID_WITH_USB response[3] |= PROTO::OUTPUTS2::HAS_USB; +# ifdef HID_WITH_USB_WIN98 + response[3] |= PROTO::OUTPUTS2::HAS_USB_WIN98; +# endif # endif # ifdef HID_WITH_PS2 response[3] |= PROTO::OUTPUTS2::HAS_PS2; diff --git a/hid/src/proto.h b/hid/src/proto.h index 7a273a30..18124d74 100644 --- a/hid/src/proto.h +++ b/hid/src/proto.h @@ -53,18 +53,20 @@ namespace PROTO { const uint8_t PS2 = 0b00000011; }; namespace MOUSE { - const uint8_t MASK = 0b00111000; - const uint8_t USB_ABS = 0b00001000; - const uint8_t USB_REL = 0b00010000; - const uint8_t PS2 = 0b00011000; + const uint8_t MASK = 0b00111000; + const uint8_t USB_ABS = 0b00001000; + const uint8_t USB_REL = 0b00010000; + const uint8_t PS2 = 0b00011000; + const uint8_t USB_WIN98 = 0b00100000; }; }; namespace OUTPUTS2 { // Complex response - const uint8_t CONNECTABLE = 0b10000000; - const uint8_t CONNECTED = 0b01000000; - const uint8_t HAS_USB = 0b00000001; - const uint8_t HAS_PS2 = 0b00000010; + const uint8_t CONNECTABLE = 0b10000000; + const uint8_t CONNECTED = 0b01000000; + const uint8_t HAS_USB = 0b00000001; + const uint8_t HAS_PS2 = 0b00000010; + const uint8_t HAS_USB_WIN98 = 0b00000100; } namespace CMD { diff --git a/hid/src/usb/hid.h b/hid/src/usb/hid.h index 6c3772f2..13f68cf1 100644 --- a/hid/src/usb/hid.h +++ b/hid/src/usb/hid.h @@ -149,11 +149,13 @@ class UsbMouseAbsolute { public: UsbMouseAbsolute() {} - void begin() { + void begin(bool win98_fix) { _mouse.begin(); -#ifdef HID_USB_ABS_WIN98_FIX - _mouse.setWin98Fix(true); -#endif + _mouse.setWin98FixEnabled(win98_fix); + } + + bool isWin98FixEnabled() { + return _mouse.isWin98FixEnabled(); } void clear() { diff --git a/kvmd/plugins/hid/_mcu/__init__.py b/kvmd/plugins/hid/_mcu/__init__.py index 07aeface..4dfd978a 100644 --- a/kvmd/plugins/hid/_mcu/__init__.py +++ b/kvmd/plugins/hid/_mcu/__init__.py @@ -179,12 +179,21 @@ class BaseMcuHid(BaseHid, multiprocessing.Process): # pylint: disable=too-many- if outputs1 & 0b10000000: # Dynamic if outputs2 & 0b00000001: # USB - keyboard_outputs["available"].extend(["usb", "disabled"]) - mouse_outputs["available"].extend(["usb", "usb_rel", "disabled"]) + keyboard_outputs["available"].append("usb") + mouse_outputs["available"].extend(["usb", "usb_rel"]) + + if outputs2 & 0b00000100: # USB WIN98 + mouse_outputs["available"].append("usb_win98") if outputs2 & 0b00000010: # PS/2 - keyboard_outputs["available"].extend(["ps2", "disabled"]) - mouse_outputs["available"].extend(["ps2", "disabled"]) + keyboard_outputs["available"].append("ps2") + mouse_outputs["available"].append("ps2") + + if keyboard_outputs["available"]: + keyboard_outputs["available"].append("disabled") + + if mouse_outputs["available"]: + mouse_outputs["available"].append("disabled") active_keyboard = get_active_keyboard(outputs1) if active_keyboard in keyboard_outputs["available"]: diff --git a/kvmd/plugins/hid/_mcu/proto.py b/kvmd/plugins/hid/_mcu/proto.py index 16757d7d..a49f2b02 100644 --- a/kvmd/plugins/hid/_mcu/proto.py +++ b/kvmd/plugins/hid/_mcu/proto.py @@ -63,10 +63,11 @@ class SetKeyboardOutputEvent(BaseEvent): # ===== _MOUSE_NAMES_TO_CODES = { - "disabled": 0b00000000, - "usb": 0b00001000, - "usb_rel": 0b00010000, - "ps2": 0b00011000, + "disabled": 0b00000000, + "usb": 0b00001000, + "usb_rel": 0b00010000, + "ps2": 0b00011000, + "usb_win98": 0b00100000, } _MOUSE_CODES_TO_NAMES = tools.swapped_kvs(_MOUSE_NAMES_TO_CODES) diff --git a/kvmd/plugins/hid/otg/__init__.py b/kvmd/plugins/hid/otg/__init__.py index 030c551d..f4df4c63 100644 --- a/kvmd/plugins/hid/otg/__init__.py +++ b/kvmd/plugins/hid/otg/__init__.py @@ -27,7 +27,6 @@ from typing import AsyncGenerator from typing import Optional from typing import Any -from .... import tools from .... import aiomulti from ....yamlconf import Option @@ -59,30 +58,31 @@ class Plugin(BaseHid): # pylint: disable=too-many-instance-attributes self.__udc = UsbDeviceController(udc) + win98_fix = mouse.pop("absolute_win98_fix") common = { "udc": self.__udc, "noop": noop, "notifier": self.__notifier, } - self.__keyboard_proc = KeyboardProcess(**common, **keyboard) self.__mouse_current = self.__mouse_proc = MouseProcess(**common, **mouse) self.__mouse_alt_proc: Optional[MouseProcess] = None - self.__output_to_mouse: Dict[str, MouseProcess] = {} - self.__mouse_to_output: Dict[MouseProcess, str] = {} + self.__mouses: Dict[str, MouseProcess] = {} if mouse_alt["device_path"]: self.__mouse_alt_proc = MouseProcess( absolute=(not mouse["absolute"]), - absolute_win98_fix=mouse["absolute_win98_fix"], **common, **mouse_alt, ) - self.__output_to_mouse = { + self.__mouses = { "usb": (self.__mouse_proc if mouse["absolute"] else self.__mouse_alt_proc), "usb_rel": (self.__mouse_alt_proc if mouse["absolute"] else self.__mouse_proc), } - self.__mouse_to_output = tools.swapped_kvs(self.__output_to_mouse) + if win98_fix: + # На самом деле мультимышка и win95 не зависят друг от друга, + # но так было проще реализовать переключение режимов + self.__mouses["usb_win98"] = self.__mouses["usb"] @classmethod def get_plugin_options(cls) -> Dict: @@ -139,8 +139,8 @@ class Plugin(BaseHid): # pylint: disable=too-many-instance-attributes }, "mouse": { "outputs": { - "available": list(self.__output_to_mouse), - "active": (self.__mouse_to_output[self.__mouse_current] if self.__mouse_alt_proc else ""), + "available": list(self.__mouses), + "active": self.__get_current_mouse_mode(), }, **mouse_state, }, @@ -157,7 +157,9 @@ class Plugin(BaseHid): # pylint: disable=too-many-instance-attributes async def reset(self) -> None: self.__keyboard_proc.send_reset_event() - self.__mouse_current.send_reset_event() + self.__mouse_proc.send_reset_event() + if self.__mouse_alt_proc: + self.__mouse_alt_proc.send_reset_event() async def cleanup(self) -> None: try: @@ -188,12 +190,23 @@ class Plugin(BaseHid): # pylint: disable=too-many-instance-attributes def set_params(self, keyboard_output: Optional[str]=None, mouse_output: Optional[str]=None) -> None: _ = keyboard_output - if mouse_output != self.__mouse_to_output[self.__mouse_current]: - if mouse_output in self.__output_to_mouse: - self.__mouse_current.send_clear_event() - self.__mouse_current = self.__output_to_mouse[mouse_output] - self.__notifier.notify() + if mouse_output in self.__mouses and mouse_output != self.__get_current_mouse_mode(): + self.__mouse_current.send_clear_event() + self.__mouse_current = self.__mouses[mouse_output] + self.__mouse_current.set_win98_fix(mouse_output == "usb_win98") + self.__notifier.notify() def clear_events(self) -> None: self.__keyboard_proc.send_clear_event() - self.__mouse_current.send_clear_event() + self.__mouse_proc.send_clear_event() + if self.__mouse_alt_proc: + self.__mouse_alt_proc.send_clear_event() + + # ===== + + def __get_current_mouse_mode(self) -> str: + if len(self.__mouses) == 0: + return "" + if self.__mouse_current.is_absolute(): + return ("usb_win98" if self.__mouse_current.get_win98_fix() else "usb") + return "usb_rel" diff --git a/kvmd/plugins/hid/otg/events.py b/kvmd/plugins/hid/otg/events.py index 229f4faa..5bbffcd6 100644 --- a/kvmd/plugins/hid/otg/events.py +++ b/kvmd/plugins/hid/otg/events.py @@ -124,14 +124,23 @@ class MouseButtonEvent(BaseEvent): class MouseMoveEvent(BaseEvent): to_x: int to_y: int + win98_fix: bool = False to_fixed_x: int = 0 to_fixed_y: int = 0 def __post_init__(self) -> None: assert MouseRange.MIN <= self.to_x <= MouseRange.MAX assert MouseRange.MIN <= self.to_y <= MouseRange.MAX - object.__setattr__(self, "to_fixed_x", MouseRange.remap(self.to_x, 0, MouseRange.MAX)) - object.__setattr__(self, "to_fixed_y", MouseRange.remap(self.to_y, 0, MouseRange.MAX)) + to_fixed_x = MouseRange.remap(self.to_x, 0, MouseRange.MAX) + to_fixed_y = MouseRange.remap(self.to_y, 0, MouseRange.MAX) + if self.win98_fix: + # https://github.com/pikvm/pikvm/issues/159 + # For some reason, the correct implementation of this fix + # is a shift to the left, and not to the right, as in VirtualBox + to_fixed_x <<= 1 + to_fixed_y <<= 1 + object.__setattr__(self, "to_fixed_x", to_fixed_x) + object.__setattr__(self, "to_fixed_y", to_fixed_y) @dataclasses.dataclass(frozen=True) diff --git a/kvmd/plugins/hid/otg/mouse.py b/kvmd/plugins/hid/otg/mouse.py index 4ede3277..39e9657c 100644 --- a/kvmd/plugins/hid/otg/mouse.py +++ b/kvmd/plugins/hid/otg/mouse.py @@ -42,7 +42,6 @@ from .events import make_mouse_report class MouseProcess(BaseDeviceProcess): def __init__(self, **kwargs: Any) -> None: self.__absolute: bool = kwargs.pop("absolute") - self.__absolute_win98_fix: bool = kwargs.pop("absolute_win98_fix") self.__horizontal_wheel: bool = kwargs.pop("horizontal_wheel") super().__init__( @@ -55,6 +54,16 @@ class MouseProcess(BaseDeviceProcess): self.__pressed_buttons = 0 self.__x = 0 # For absolute self.__y = 0 + self.__win98_fix = False + + def is_absolute(self) -> bool: + return self.__absolute + + def set_win98_fix(self, enabled: bool) -> None: + self.__win98_fix = enabled + + def get_win98_fix(self) -> bool: + return self.__win98_fix def cleanup(self) -> None: self._stop() @@ -82,7 +91,7 @@ class MouseProcess(BaseDeviceProcess): def send_move_event(self, to_x: int, to_y: int) -> None: if self.__absolute: - self._queue_event(MouseMoveEvent(to_x, to_y)) + self._queue_event(MouseMoveEvent(to_x, to_y, self.__win98_fix)) def send_relative_event(self, delta_x: int, delta_y: int) -> None: if not self.__absolute: @@ -144,12 +153,6 @@ class MouseProcess(BaseDeviceProcess): assert relative_event is None move_x = self.__x move_y = self.__y - if self.__absolute_win98_fix: - # https://github.com/pikvm/pikvm/issues/159 - # For some reason, the correct implementation of this fix - # is a shift to the left, and not to the right, as in VirtualBox - move_x <<= 1 - move_y <<= 1 else: assert self.__x == self.__y == 0 if relative_event is not None: diff --git a/kvmd/validators/hid.py b/kvmd/validators/hid.py index 7d942969..b41bd5c8 100644 --- a/kvmd/validators/hid.py +++ b/kvmd/validators/hid.py @@ -37,7 +37,7 @@ def valid_hid_keyboard_output(arg: Any) -> str: def valid_hid_mouse_output(arg: Any) -> str: - return check_string_in_list(arg, "Mouse output", ["usb", "usb_rel", "ps2", "disabled"]) + return check_string_in_list(arg, "Mouse output", ["usb", "usb_win98", "usb_rel", "ps2", "disabled"]) def valid_hid_key(arg: Any) -> str: diff --git a/testenv/v2-hdmi-rpi4.override.yaml b/testenv/v2-hdmi-rpi4.override.yaml index a298af0b..85cbd4f9 100644 --- a/testenv/v2-hdmi-rpi4.override.yaml +++ b/testenv/v2-hdmi-rpi4.override.yaml @@ -10,6 +10,9 @@ kvmd: device: /dev/null mouse: device: /dev/null +# absolute_win98_fix: true +# mouse_alt: +# device: /dev/null noop: true msd: diff --git a/web/share/js/kvm/hid.js b/web/share/js/kvm/hid.js index 017eecba..545a712d 100644 --- a/web/share/js/kvm/hid.js +++ b/web/share/js/kvm/hid.js @@ -133,6 +133,7 @@ export function Hid(__getResolution) { let html = ""; for (let args of [ ["USB", "usb", false], + ["USB Win98", "usb_win98", false], ["USB Relative", "usb_rel", true], ["PS/2", "ps2", true], ["Off", "disabled"], |