1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
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)
|