From 0c0d2a1c16f66a4ec8a78d545964fb8cb6490ab3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yaroslav=20de=20la=20Pe=C3=B1a=20Smirnov?= Date: Tue, 9 Mar 2021 02:04:32 +0300 Subject: script to change intellimouse dpi --- dotfiles/.local/bin/intellimouse-classic | 91 ++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100755 dotfiles/.local/bin/intellimouse-classic (limited to 'dotfiles/.local/bin/intellimouse-classic') diff --git a/dotfiles/.local/bin/intellimouse-classic b/dotfiles/.local/bin/intellimouse-classic new file mode 100755 index 0000000..3b320a3 --- /dev/null +++ b/dotfiles/.local/bin/intellimouse-classic @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 +import sys +import usb.core +import usb.util + +# Script to set the DPI of the Microsoft Classic Intellimouse +# Taken from https://gist.github.com/K-Visscher/22561ca69a64339a7383d67db6e79818 + +VID = 0x045E +PID = 0x0823 + +DPI_WRITE_PROPERTY = 0x96 + +WRITE_REPORT_ID = 0x24 +WRITE_REPORT_LENGTH = 0x20 + +INTERFACE = 0x01 + +class IntelliMouse(): + def __init__(self): + self.reattach = False + self.device = usb.core.find(idVendor=VID, idProduct=PID) + if self.device is None: + raise ValueError("couldn't find the intellimouse...") + + def set_configuration(self): + if sys.platform.startswith("linux"): + for config in self.device: + for interface in config: + if self.device.is_kernel_driver_active(interface.bInterfaceNumber): + self.device.detach_kernel_driver(interface.bInterfaceNumber) + self.reattach = True + + self.device.set_configuration() + + def detach(self): + usb.util.dispose_resources(self.device) + if self.reattach: + for config in self.device: + for interface in config: + if not self.device.is_kernel_driver_active(interface.bInterfaceNumber): + self.device.attach_kernel_driver(interface.bInterfaceNumber) + + def __enter__(self): + self.set_configuration() + + def __exit__(self, exc_type, exc_value, exc_traceback): + self.detach() + + def __write_property(self, property, data): + if not isinstance(property, int): + raise TypeError("please make sure to pass a integer for the property argument...") + if not isinstance(data, list) or not all(isinstance(x, int) for x in data): + raise TypeError("please make sure to pass a list of integers for the data argument...") + report = self.__pad_right([WRITE_REPORT_ID, property, len(data)] + data, WRITE_REPORT_LENGTH) + self.device.ctrl_transfer(0x21, 0x09, 0x03 << 8 | WRITE_REPORT_ID, INTERFACE, report) + + + def __pad_right(self, data, until): + if not isinstance(data, list) or not all(isinstance(x, int) for x in data): + raise TypeError("please make sure to pass a list of integers for the data argument...") + if not isinstance(until, int): + raise TypeError("please make sure to pass a integer for the until argument...") + if until <= 0: + raise ValueError("please pass a positive integer for the until argument...") + if len(data) >= until: + return + return data + ((until - len(data)) * [0x00]) + + def set_dpi(self, dpi): + if not isinstance(dpi, int): + raise TypeError("please make sure to pass an integer...") + if dpi % 200 != 0 or not (dpi >= 400 and dpi <= 3200): + raise ValueError("please make sure to pass a valid value (dpi % 200 == 0 and (dpi >= 400 and dpi <= 3200))") + self.__write_property(DPI_WRITE_PROPERTY, [0x00] + list(dpi.to_bytes(2, byteorder="little"))) + +if __name__ == "__main__": + if len(sys.argv) < 2: + sys.stderr.write("Usage: {} [400 — 3200 DPI]\n".format(sys.argv[0])) + sys.exit(1) + try: + dpi = int(sys.argv[1]) + if dpi < 400 or dpi > 3200: + raise ValueError + except ValueError: + sys.stderr.write("DPI value must be a number between 400 and 3200 inclusively") + exit(1) + + mouse = IntelliMouse() + with mouse: + mouse.set_dpi(dpi) -- cgit v1.2.3