summaryrefslogtreecommitdiff
path: root/kvmd/plugins/hid/ch9329/mouse.py
diff options
context:
space:
mode:
Diffstat (limited to 'kvmd/plugins/hid/ch9329/mouse.py')
-rw-r--r--kvmd/plugins/hid/ch9329/mouse.py115
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]