-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathcli.py
344 lines (294 loc) · 13.2 KB
/
cli.py
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
"""This file provides command-line interface to communicate with mouse."""
import argparse
import configparser
from values import DPI, polling_rate, buttons_codes
from values import hid_mod_buttons, hid_buttons
from values import mod_actions, simple_actions
from values import macros_package_header
from main import M601
parser = argparse.ArgumentParser()
parser.add_argument("-m", "--Mode", help="Switch mouse mode (1-2)")
parser.add_argument("-r", "--Read",
help="Reads current mouse settings into .ini file",
metavar="FILE")
parser.add_argument("--hard_reset",
help="""Writes hard coded reset packages into mouse.
Can help if mouse stopped responding """,
action='store_true')
parser.add_argument("-d", "--Dump",
help="Reads raw mouse settings into file",
metavar="FILE")
parser.add_argument("-w", "--Write",
help="Writes settings from .ini file into mouse",
metavar="FILE")
parser.add_argument("-um", "--upload_macros",
help="Uploads macros from file into mouse",
metavar=("NUMBER","FILE"),
nargs=2)
args = parser.parse_args()
mouse = M601()
if args.Mode:
mouse.change_mode(int(args.Mode))
if args.Dump:
mouse.read_settings()
with open(args.Dump, "w") as f:
f.write(f"{mouse.settings_1} \n{mouse.buttons_1} \n{mouse.settings_2} \n{mouse.buttons_2} \n")
def make_ini(mode):
"""Make .ini file according to a mouse object variables."""
ini = f"""[{mode}]
; This parameter sets the USB polling rate.
; Possible value for this mouse is 125, 250, 500, or 1000 Hz
usb_polling_rate = {polling_rate[mouse.raw_polling_rate - 1]}
; This parameter sets active DPI preset among enabled presets
; Note: This is not a preset number, it is it sequence number between enabled presets.
active_dpi_preset = {mouse.raw_active_dpi_presets >> 4}
; This parameter disables certain DPI presets, in order: 1 2 3 4 5
; where 0 - preset is enabled, 1 - preset is disabled
; for example, if you want to disable 4 and 3 DPI preset:
; disabled_dpi_presets = 00110
; if you want to disable only 1 preset:
; 10000
disabled_dpi_presets = {"{0:b}".format(mouse.raw_disabled_dpi_presets)[3:8][::-1]}
; These parameters are setting certain DPI values for certain DPI presets
; Possible DPI values for this mouse are:
; 500, 800, 1000, 1200, 1600, 2000, 2400, 3000, 3200, 3500, 4000, 4500,
; 5000, 5500, 6000, 7200.
dpi_1 = {DPI[mouse.raw_dpi_values[0] - 1]}
dpi_2 = {DPI[mouse.raw_dpi_values[1] - 1]}
dpi_3 = {DPI[mouse.raw_dpi_values[2] - 1]}
dpi_4 = {DPI[mouse.raw_dpi_values[3] - 1]}
dpi_5 = {DPI[mouse.raw_dpi_values[4] - 1]}
; These parameters are setting certain colors for certain DPI presets
; You will see these colors when switching between presets
; [Red, Green, Blue]
; Possible values are 0-255
dpi_1_color = {mouse.raw_dpi_colors[0:3]}
dpi_2_color = {mouse.raw_dpi_colors[3:6]}
dpi_3_color = {mouse.raw_dpi_colors[6:9]}
dpi_4_color = {mouse.raw_dpi_colors[9:12]}
dpi_5_color = {mouse.raw_dpi_colors[12:15]}
; These parameters are setting certain mouse buttons
; Possible values: left, right, middle, back, forward,
; scroll_up, scroll_down, double_click, triple_click,
; dpi_loop, dpi_up, dpi_down, disable_button, switch_effect, change_mode
; macro_1, macro_2, macro_3, macro_4, macro_5
; You can also bin key combinations, for example:
; ctrl_b
; ctrl_shift_b
; alt_b
; ctrl_alt_b
; super_b
; super_shift_b
; b (simple HID button as a key combination)
button_1 = {list(buttons_codes.keys())[list(buttons_codes.values()).index(list(mouse.button_1))]}
button_2 = {list(buttons_codes.keys())[list(buttons_codes.values()).index(list(mouse.button_2))]}
button_3 = {list(buttons_codes.keys())[list(buttons_codes.values()).index(list(mouse.button_3))]}
button_4 = {list(buttons_codes.keys())[list(buttons_codes.values()).index(list(mouse.button_4))]}
button_5 = {list(buttons_codes.keys())[list(buttons_codes.values()).index(list(mouse.button_5))]}
button_6 = {list(buttons_codes.keys())[list(buttons_codes.values()).index(list(mouse.button_6))]}
button_7 = {list(buttons_codes.keys())[list(buttons_codes.values()).index(list(mouse.button_7))]}
; This parameter sets the current lighting effect:
; 0 = None
; 1 = Colorful Streaming
; 2 = Steady
; 3 = Breathing
; 4 = Tail
; 5 = Neon
; 6 = Colorful Steady
; 7 = Flicker
; 8 = Streaming
; 9 = Wave
lighting_effect = {mouse.raw_current_lighting_effect}
; This parameter sets speed for the "Colorful Streaming" lighting effect
; Possible values are 1-3
colorful_streaming_speed = {mouse.raw_colorful_streaming_speed - 16}
; This parameter sets the direction for the "Colorful Streaming" lighting effect
; 0 = Backward, 1 = Forward
colorful_streaming_direction = {mouse.raw_colorful_streaming_direction}
; This parameter sets brightness for the "Steady" lighting effect
; Possible values are 25, 50, 75 or 100
steady_brightness = {int(mouse.raw_steady_brightness / 16 * 25)}
; This parameter sets color for the "Steady" lighting effect
; [Red, Green, Blue]
; Possible values are 0-255
steady_color = {mouse.raw_steady_color}
; This parameter sets speed for the "Breathing" lighting effect
; Possible values are 1-3
breathing_speed = {mouse.raw_breathing_speed - 48}
; This parameter sets amount of colors for the "Breathing" lighting effect
; Possible values are 1-7
breathing_number_of_colors = {mouse.raw_breathing_number_of_colors}
; These parameters are setting colors for the "Breathing" lighting effect
; [Red, Green, Blue]
; Possible values are 0-255
; Unused colors should be set as [0, 0, 0]
breathing_color_1 = {mouse.raw_breathing_colors[0:3]}
breathing_color_2 = {mouse.raw_breathing_colors[3:6]}
breathing_color_3 = {mouse.raw_breathing_colors[6:9]}
breathing_color_4 = {mouse.raw_breathing_colors[9:12]}
breathing_color_5 = {mouse.raw_breathing_colors[12:15]}
breathing_color_6 = {mouse.raw_breathing_colors[15:18]}
breathing_color_7 = {mouse.raw_breathing_colors[18:21]}
; This parameter sets speed for the "Tail" lighting effect
; Possible values are 1-3
tail_speed = {mouse.raw_tail_speed - 48}
; This parameter sets speed for the "Neon" lighting effect
; Possible values are 1-3
neon_speed = {mouse.raw_neon_speed - 48}
; These parameters are setting colors for certain LEDs in the "Colorful Steady" lighting effect
; [Red, Green, Blue]
; Possible values are 0-255
; You can disable certain LED by set it as [0, 0, 0]
colorful_steady_LED1_color = {mouse.raw_colorful_steady_colors[0:3]}
colorful_steady_LED2_color = {mouse.raw_colorful_steady_colors[3:6]}
colorful_steady_LED3_color = {mouse.raw_colorful_steady_colors[6:9]}
colorful_steady_LED4_color = {mouse.raw_colorful_steady_colors[9:12]}
colorful_steady_LED5_color = {mouse.raw_colorful_steady_colors[12:15]}
; These parameters are setting colors for the "Flicker" lighting effect
; [Red, Green, Blue]
; Possible values are 0-255
flicker_color_1 = {mouse.raw_flicker_colors[0:3]}
flicker_color_2 = {mouse.raw_flicker_colors[3:6]}
; This parameter sets the speed for the "Streaming" lighting effect
; Possible values are 1-3
streaming_speed = {mouse.raw_streaming_speed - 48}
; This parameter sets speed for the "Wave" lighting effect
; Possible values are 1-3
wave_speed = {mouse.raw_wave_speed - 48}
"""
return ini
def define_button_type(button):
if button in hid_buttons.keys():
return "simple"
elif button in hid_mod_buttons.keys():
return "mod"
else :
return "unknown"
def make_macros_package(number, file):
if int(number) not in range(1, 6):
raise ValueError(f"Possible macros numbers are 1-5")
raw_macro = [*macros_package_header]
with open(file, "r") as f:
macros = f.readlines()
actions_counter = 0
for line in macros:
line = line.replace("\n", "")
line = line.split(" ")
action = line[0]
value = line[1]
if (action == "down") or (action == "up"):
button_type = define_button_type(value)
if button_type == "simple":
raw_macro.append(simple_actions[action])
raw_macro.append(0x05)
raw_macro.append(hid_buttons[value])
elif button_type == "mod":
raw_macro.append(mod_actions[action])
raw_macro.append(0x05)
raw_macro.append(hid_mod_buttons[value])
else:
raise ValueError(f"Unknown button '{value}'")
actions_counter += 1
if action == "delay":
delay_high_byte = raw_macro[len(raw_macro) - 3]
full_delay = (delay_high_byte * 0x100) + int(value)
delay_high_byte, delay_low_byte = divmod(full_delay, 0x100)
raw_macro.pop(len(raw_macro) - 2)
raw_macro.pop(len(raw_macro) - 2)
raw_macro.insert(len(raw_macro) - 1, delay_high_byte)
raw_macro.insert(len(raw_macro) - 1, delay_low_byte)
raw_macro[8] = int(number)
raw_macro[10] = actions_counter
if len(raw_macro) > 520:
raise ValueError(f"Too big macros")
raw_macro = [*raw_macro, *[0] * (520 - len(raw_macro))]
return raw_macro
if args.Read:
mouse.read_settings()
mouse.parse_settings(mouse.settings_1)
mouse.parse_buttons(mouse.buttons_1)
with open(f"{args.Read}.ini", "w") as f:
f.write(make_ini("mode_1"))
mouse.parse_settings(mouse.settings_2)
mouse.parse_buttons(mouse.buttons_2)
with open(f"{args.Read}.ini", "a") as f:
f.write(make_ini("mode_2"))
def parse_ini(mode):
"""Parse certain values from .ini file into object."""
mouse.raw_polling_rate = polling_rate.index(int(mode['usb_polling_rate'])) + 1
mouse.raw_active_dpi_presets = int(f"{mode['active_dpi_preset']}{mode['disabled_dpi_presets'].count('0')}", 16)
mouse.raw_disabled_dpi_presets = int(mode['disabled_dpi_presets'][::-1], 2) + 224
for i in range(5):
mouse.raw_dpi_values[i] = DPI.index(int(mode[f'dpi_{i + 1}'])) + 1
dpi_colors = ""
for i in range(5):
dpi_colors += mode[f'dpi_{i + 1}_color']
dpi_colors = dpi_colors.replace("][", ",").replace("[", "").replace("]", "")
dpi_colors = dpi_colors.split(",")
for i in range(15):
mouse.raw_dpi_colors[i] = int(dpi_colors[i])
mouse.raw_current_lighting_effect = int(mode['lighting_effect'])
mouse.raw_colorful_streaming_speed = int(mode['colorful_streaming_speed']) + 16
mouse.raw_colorful_streaming_direction = int(mode['colorful_streaming_direction'])
mouse.raw_steady_brightness = int(int(mode['steady_brightness']) * 16 / 25)
steady_color = mode['steady_color']
steady_color = steady_color.replace("[", "").replace("]", "")
steady_color = steady_color.split(",")
for i in range(3):
mouse.raw_steady_color[i] = int(steady_color[i])
mouse.raw_breathing_speed = int(mode['breathing_speed']) + 48
mouse.raw_breathing_number_of_colors = int(mode['breathing_number_of_colors'])
breathing_colors = ""
for i in range(7):
breathing_colors += mode[f'breathing_color_{i+1}']
breathing_colors = breathing_colors.replace("][", ",").replace("[", "").replace("]", "")
breathing_colors = breathing_colors.split(",")
for i in range(21):
mouse.raw_breathing_colors[i] = int(breathing_colors[i])
mouse.raw_tail_speed = int(mode['tail_speed']) + 48
mouse.raw_neon_speed = int(mode['neon_speed']) + 48
colorful_steady_colors = ""
for i in range(5):
colorful_steady_colors += mode[f'colorful_steady_LED{i + 1}_color']
colorful_steady_colors = colorful_steady_colors.replace("][", ",").replace("[", "").replace("]", "")
colorful_steady_colors = colorful_steady_colors.split(",")
for i in range(15):
mouse.raw_colorful_steady_colors[i] = int(colorful_steady_colors[i])
flicker_colors = ""
for i in range(2):
flicker_colors += mode[f'flicker_color_{i + 1}']
flicker_colors = flicker_colors.replace("][", ",").replace("[", "").replace("]", "")
flicker_colors = flicker_colors.split(",")
for i in range(6):
mouse.raw_flicker_colors[i] = int(flicker_colors[i])
mouse.raw_streaming_speed = int(mode['streaming_speed']) + 48
mouse.raw_wave_speed = int(mode['wave_speed']) + 48
mouse.button_1 = buttons_codes[mode['button_1']]
mouse.button_2 = buttons_codes[mode['button_2']]
mouse.button_3 = buttons_codes[mode['button_3']]
mouse.button_4 = buttons_codes[mode['button_4']]
mouse.button_5 = buttons_codes[mode['button_5']]
mouse.button_6 = buttons_codes[mode['button_6']]
mouse.button_7 = buttons_codes[mode['button_7']]
if args.Write:
mouse.read_settings()
config = configparser.ConfigParser()
config.read(args.Write)
config_1 = config['mode_1']
config_2 = config['mode_2']
mouse.parse_settings(mouse.settings_1)
mouse.parse_buttons(mouse.buttons_1)
parse_ini(config_1)
mouse.make_package()
mouse.write_settings(0x11)
mouse.parse_settings(mouse.settings_2)
mouse.parse_buttons(mouse.buttons_2)
parse_ini(config_2)
mouse.make_package()
mouse.write_settings(0x21)
if args.hard_reset:
mouse.hard_reset()
if args.upload_macros:
macros_package = make_macros_package(args.upload_macros[0],
args.upload_macros[1])
mouse.write_macros(macros_package)