diff options
Diffstat (limited to 'kvmd/plugins/hid/ch9329/mouse.py')
-rw-r--r-- | kvmd/plugins/hid/ch9329/mouse.py | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/kvmd/plugins/hid/ch9329/mouse.py b/kvmd/plugins/hid/ch9329/mouse.py new file mode 100644 index 00000000..034aff92 --- /dev/null +++ b/kvmd/plugins/hid/ch9329/mouse.py @@ -0,0 +1,115 @@ +# ========================================================================== # +# # +# KVMD - The main PiKVM daemon. # +# # +# Copyright (C) 2018-2022 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/>. # +# # +# ========================================================================== # + +import math + +from ....mouse import MouseRange + + +class Mouse: # pylint: disable=too-many-instance-attributes + def __init__(self) -> None: + self.__active = "usb" + self.__button = "" + self.__clicked = False + self.__to_x = [0, 0] + self.__to_y = [0, 0] + self.__wheel_y = 0 + self.__delta_x = 0 + self.__delta_y = 0 + + def button(self, button: str, clicked: bool) -> list[int]: + self.__button = button + self.__clicked = clicked + self.__wheel_y = 0 + if self.__active != "usb": + self.__to_x = [0, 0] + self.__to_y = [0, 0] + return self.__absolute() + + def move(self, to_x: int, to_y: int) -> list[int]: + assert MouseRange.MIN <= to_x <= MouseRange.MAX + assert MouseRange.MIN <= to_y <= MouseRange.MAX + self.__to_x = self.__to_fixed(to_x) + self.__to_y = self.__to_fixed(to_y) + self.__wheel_y = 0 + return self.__absolute() + + def wheel(self, delta_x: int, delta_y: int) -> list[int]: + assert -127 <= delta_y <= 127 + _ = delta_x + self.__wheel_y = 1 if delta_y > 0 else 255 + return self.__absolute() + + def relative(self, delta_x: int, delta_y: int) -> list[int]: + assert -127 <= delta_x <= 127 + assert -127 <= delta_y <= 127 + delta_x = math.ceil(delta_x / 3) + delta_y = math.ceil(delta_y / 3) + self.__delta_x = delta_x if delta_x >= 0 else 255 + delta_x + self.__delta_y = delta_y if delta_y >= 0 else 255 + delta_y + return self.__relative() + + def active(self) -> str: + return self.__active + + def set_active(self, name: str) -> None: + self.__active = name + + def __absolute(self) -> list[int]: + code = 0x00 + if self.__clicked: + code = self.__button_code(self.__button) + cmd = [0x00, 0x04, 0x07, 0x02, code, 0x00, 0x00, 0x00, 0x00, 0x00] + if len(self.__to_x) == 2: + cmd[6] = self.__to_x[0] + cmd[5] = self.__to_x[1] + if len(self.__to_y) == 2: + cmd[8] = self.__to_y[0] + cmd[7] = self.__to_y[1] + if self.__wheel_y: + cmd[9] = self.__wheel_y + return cmd + + def __relative(self) -> list[int]: + code = 0x00 + if self.__clicked: + code = self.__button_code(self.__button) + cmd = [0x00, 0x05, 0x05, 0x01, code, self.__delta_x, self.__delta_y, 0x00] + return cmd + + def __button_code(self, name: str) -> int: + code = 0x00 + match name: + case "left": + code = 0x01 + case "right": + code = 0x02 + case "middle": + code = 0x04 + case "up": + code = 0x08 + case "down": + code = 0x10 + return code + + def __to_fixed(self, num: int) -> list[int]: + to_fixed = math.ceil(MouseRange.remap(num, 0, MouseRange.MAX) / 8) + return [to_fixed >> 8, to_fixed & 0xFF] |