m693ctl 1.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- m693ctl-1.3.0/LICENSE +28 -0
- m693ctl-1.3.0/PKG-INFO +371 -0
- m693ctl-1.3.0/README.md +347 -0
- m693ctl-1.3.0/m693/__init__.py +6 -0
- m693ctl-1.3.0/m693/cli.py +690 -0
- m693ctl-1.3.0/m693/device.py +431 -0
- m693ctl-1.3.0/m693/keys.py +415 -0
- m693ctl-1.3.0/m693/lighting.py +321 -0
- m693ctl-1.3.0/m693/macro.py +371 -0
- m693ctl-1.3.0/m693/presets.py +93 -0
- m693ctl-1.3.0/m693/profile.py +539 -0
- m693ctl-1.3.0/m693/stock-profile.bin +0 -0
- m693ctl-1.3.0/m693/transfer.py +103 -0
- m693ctl-1.3.0/m693ctl.egg-info/PKG-INFO +371 -0
- m693ctl-1.3.0/m693ctl.egg-info/SOURCES.txt +53 -0
- m693ctl-1.3.0/m693ctl.egg-info/dependency_links.txt +1 -0
- m693ctl-1.3.0/m693ctl.egg-info/entry_points.txt +5 -0
- m693ctl-1.3.0/m693ctl.egg-info/requires.txt +3 -0
- m693ctl-1.3.0/m693ctl.egg-info/top_level.txt +2 -0
- m693ctl-1.3.0/m693gui/__init__.py +4 -0
- m693ctl-1.3.0/m693gui/app.py +310 -0
- m693ctl-1.3.0/m693gui/artwork.py +45 -0
- m693ctl-1.3.0/m693gui/assets/arrow-down.svg +3 -0
- m693ctl-1.3.0/m693gui/assets/m693.svg +8 -0
- m693ctl-1.3.0/m693gui/assets/theme.qss +237 -0
- m693ctl-1.3.0/m693gui/backend.py +101 -0
- m693ctl-1.3.0/m693gui/library.py +91 -0
- m693ctl-1.3.0/m693gui/model.py +406 -0
- m693ctl-1.3.0/m693gui/tabs/__init__.py +0 -0
- m693ctl-1.3.0/m693gui/tabs/dpi.py +254 -0
- m693ctl-1.3.0/m693gui/tabs/keys.py +388 -0
- m693ctl-1.3.0/m693gui/tabs/lighting.py +456 -0
- m693ctl-1.3.0/m693gui/tabs/macro.py +467 -0
- m693ctl-1.3.0/m693gui/tabs/placeholder.py +72 -0
- m693ctl-1.3.0/m693gui/widgets/__init__.py +0 -0
- m693ctl-1.3.0/m693gui/widgets/chrome.py +185 -0
- m693ctl-1.3.0/m693gui/widgets/controls.py +157 -0
- m693ctl-1.3.0/m693gui/widgets/lighting.py +323 -0
- m693ctl-1.3.0/m693gui/widgets/mouseview.py +136 -0
- m693ctl-1.3.0/m693gui/widgets/recorder.py +134 -0
- m693ctl-1.3.0/m693gui/worker.py +232 -0
- m693ctl-1.3.0/pyproject.toml +59 -0
- m693ctl-1.3.0/setup.cfg +4 -0
- m693ctl-1.3.0/tests/test_battery.py +233 -0
- m693ctl-1.3.0/tests/test_dpi_tab.py +141 -0
- m693ctl-1.3.0/tests/test_inspect_installer.py +91 -0
- m693ctl-1.3.0/tests/test_keys_tab.py +218 -0
- m693ctl-1.3.0/tests/test_lighting_tab.py +193 -0
- m693ctl-1.3.0/tests/test_macro_tab.py +309 -0
- m693ctl-1.3.0/tests/test_model.py +179 -0
- m693ctl-1.3.0/tests/test_pairing_and_cleanup.py +284 -0
- m693ctl-1.3.0/tests/test_retry.py +150 -0
- m693ctl-1.3.0/tests/test_shell.py +196 -0
- m693ctl-1.3.0/tests/test_unknowns.py +128 -0
- m693ctl-1.3.0/tests/test_zones.py +410 -0
m693ctl-1.3.0/LICENSE
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Raj singh chauhan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
The Redragon name, the M693 product artwork, and the contents of the Windows
|
|
26
|
+
installer are the property of their respective owners. None of it is included
|
|
27
|
+
in this repository: tools/extract_assets.py copies the mouse renders out of a
|
|
28
|
+
copy of the installer that you supply yourself.
|
m693ctl-1.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: m693ctl
|
|
3
|
+
Version: 1.3.0
|
|
4
|
+
Summary: Userspace driver and configuration GUI for the Redragon M693-RGB mouse
|
|
5
|
+
Author: Raj Singh Chauhan
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/rajchauhan28/redragon-mouse-linux
|
|
8
|
+
Project-URL: Repository, https://github.com/rajchauhan28/redragon-mouse-linux
|
|
9
|
+
Project-URL: Issues, https://github.com/rajchauhan28/redragon-mouse-linux/issues
|
|
10
|
+
Project-URL: Protocol, https://github.com/rajchauhan28/redragon-mouse-linux/blob/master/PROTOCOL.md
|
|
11
|
+
Keywords: redragon,m693,gaming-mouse,linux,hidraw,areson,compx,dpi,rgb,wayland
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Environment :: X11 Applications :: Qt
|
|
14
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
15
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Topic :: System :: Hardware :: Hardware Drivers
|
|
18
|
+
Requires-Python: >=3.9
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Provides-Extra: gui
|
|
22
|
+
Requires-Dist: PySide6>=6.5; extra == "gui"
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# m693ctl — Redragon M693-RGB on Linux
|
|
26
|
+
|
|
27
|
+
[](https://github.com/rajchauhan28/redragon-mouse-linux/actions/workflows/ci.yml)
|
|
28
|
+
[](https://github.com/rajchauhan28/redragon-mouse-linux/releases)
|
|
29
|
+
[](https://pypi.org/project/m693ctl/)
|
|
30
|
+
[](https://github.com/rajchauhan28/redragon-mouse-linux/blob/master/LICENSE)
|
|
31
|
+
[-blue)](https://github.com/rajchauhan28/redragon-mouse-linux/blob/master/pyproject.toml)
|
|
32
|
+
|
|
33
|
+
> **Disclaimer:** This project is not from the actual Redragon company. Use it at your own risk. This is an open-source project created only to make life easier for Redragon mouse users on Linux. For other mouse types, I'll be happy to discuss further if anyone with another Redragon mouse is willing to participate in testing.
|
|
34
|
+
|
|
35
|
+
<img width="1860" height="1195" alt="screenshot_20260925_000601" src="https://github.com/user-attachments/assets/1741298d-3df3-442f-bdd2-e0054c6f812c" />
|
|
36
|
+
<img width="1857" height="1191" alt="screenshot_20260925_000611" src="https://github.com/user-attachments/assets/ba84686b-25f2-47a2-9bd8-7f6d23ebc52c" />
|
|
37
|
+
<img width="1860" height="1200" alt="screenshot_20260925_000622" src="https://github.com/user-attachments/assets/7c06d9f3-7f34-440a-b7b5-358986093ff0" />
|
|
38
|
+
<img width="1857" height="1193" alt="screenshot_20260925_000629" src="https://github.com/user-attachments/assets/10156695-a7d2-43c2-a8d6-e6d0e838dafa" />
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
A userspace driver for the Redragon M693-RGB gaming mouse, reimplementing what
|
|
43
|
+
the Windows-only `OemDrv.exe` configuration tool does. No kernel module, no
|
|
44
|
+
Wine — it speaks the vendor HID protocol directly over `hidraw`.
|
|
45
|
+
|
|
46
|
+
See [PROTOCOL.md](https://github.com/rajchauhan28/redragon-mouse-linux/blob/master/PROTOCOL.md) for how the protocol was recovered and what
|
|
47
|
+
every byte of the mouse's configuration memory means.
|
|
48
|
+
|
|
49
|
+
Pure Python 3.9+, no third-party dependencies.
|
|
50
|
+
|
|
51
|
+
## Install
|
|
52
|
+
|
|
53
|
+
On Arch and derivatives (EndeavourOS, CachyOS, Manjaro), build the package — or grab `m693ctl-*.pkg.tar.zst` from [Releases](https://github.com/rajchauhan28/redragon-mouse-linux/releases):
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
makepkg -si # driver, CLI, GUI, udev rule, desktop entry
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`pyside6` is an optional dependency, so `m693ctl` works on a machine without
|
|
60
|
+
Qt; install it if you want `m693-gui`.
|
|
61
|
+
|
|
62
|
+
On Ubuntu, Fedora, Debian, openSUSE, NixOS, or any other distro:
|
|
63
|
+
|
|
64
|
+
```sh
|
|
65
|
+
tools/install.sh # udev rule, input group, desktop entry
|
|
66
|
+
pipx install '.[gui]' # or: pip install --user '.[gui]'
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Or install directly with `pipx` (then drop [`99-redragon-m693.rules`](https://github.com/rajchauhan28/redragon-mouse-linux/blob/master/99-redragon-m693.rules) into `/etc/udev/rules.d/`):
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
pipx install 'm693ctl[gui]' # from PyPI (use plain m693ctl for CLI-only)
|
|
73
|
+
# or latest master from GitHub:
|
|
74
|
+
pipx install 'git+https://github.com/rajchauhan28/redragon-mouse-linux.git#egg=m693ctl[gui]'
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Re-plug the receiver afterwards, then verify with:
|
|
78
|
+
|
|
79
|
+
```sh
|
|
80
|
+
m693ctl list # or ./m693ctl list, straight from a checkout
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
`install.sh` only does three things and prints each of them, so read it first if
|
|
84
|
+
you would rather do them by hand: it copies `99-redragon-m693.rules` into
|
|
85
|
+
`/etc/udev/rules.d/`, adds you to the `input` group, and drops a `.desktop`
|
|
86
|
+
entry and icon under `~/.local/share`.
|
|
87
|
+
|
|
88
|
+
Everything works from a checkout without installing anything — `./m693ctl` and
|
|
89
|
+
`./m693-gui` are runnable in place. The driver and CLI have **no dependencies**;
|
|
90
|
+
PySide6 is needed only for the GUI, which is why it is an extra.
|
|
91
|
+
|
|
92
|
+
## Usage
|
|
93
|
+
|
|
94
|
+
```sh
|
|
95
|
+
./m693ctl info # everything the mouse currently holds
|
|
96
|
+
./m693ctl battery # charge, and whether it is charging
|
|
97
|
+
./m693ctl battery -q # just the number, for a status bar
|
|
98
|
+
./m693ctl pair # re-pair the mouse with its 2.4G USB receiver
|
|
99
|
+
|
|
100
|
+
./m693ctl rate 1000 # polling rate: 125 / 250 / 500 / 1000 Hz
|
|
101
|
+
./m693ctl dpi 800 1600 3200 # replace the DPI stages
|
|
102
|
+
./m693ctl dpi 1600x800 # independent X/Y
|
|
103
|
+
./m693ctl dpi --active 2 # switch to stage 2
|
|
104
|
+
./m693ctl dpi --color 1 00ff00 # stage 1 indicator colour
|
|
105
|
+
|
|
106
|
+
./m693ctl led --mode breathing --brightness 200 --speed 5 --color ff0080
|
|
107
|
+
./m693ctl led --zone wheel --mode steady --color 00ff00 # just the wheel
|
|
108
|
+
./m693ctl led --zone all --mode streaming --speed 8 # both zones
|
|
109
|
+
|
|
110
|
+
./m693ctl preset list # built-in and saved lighting looks
|
|
111
|
+
./m693ctl preset apply Ember
|
|
112
|
+
./m693ctl preset save "my look" # captures every zone as it stands now
|
|
113
|
+
./m693ctl set --debounce 4 --lod 2 --angle-snap off
|
|
114
|
+
./m693ctl set --motion-sync on --ripple off
|
|
115
|
+
./m693ctl set --dormancy 300 # sleep timer, seconds
|
|
116
|
+
|
|
117
|
+
./m693ctl button 5 dpi-loop # remap a button slot
|
|
118
|
+
./m693ctl button 5 mute # any multimedia or web function
|
|
119
|
+
./m693ctl button 5 key:ctrl+shift+t # a keyboard shortcut
|
|
120
|
+
./m693ctl button 5 fire:10,3 # fire key: 10 ms apart, 3 shots
|
|
121
|
+
./m693ctl button 5 dpi-lock:2 # hold at DPI stage 3 while pressed
|
|
122
|
+
./m693ctl button 5 disable
|
|
123
|
+
|
|
124
|
+
./m693ctl export my-profile.json # everything, readable and restorable
|
|
125
|
+
./m693ctl import my-profile.json
|
|
126
|
+
|
|
127
|
+
./m693ctl macro 9 # what a button's macro contains
|
|
128
|
+
./m693ctl macro 9 --load gg.jmm --repeat 1
|
|
129
|
+
./m693ctl macro 9 --clear
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
`button` with an unknown action prints the whole catalogue. Slots are 0-based;
|
|
133
|
+
`info` lists what each currently holds.
|
|
134
|
+
|
|
135
|
+
LED modes: `steady`, `breathing`, `streaming`, `neon`, `single-color-flow`,
|
|
136
|
+
`colorful-breathing`, `off`. The cycling modes (`streaming`, `neon`,
|
|
137
|
+
`colorful-breathing`) ignore the stored colour, so set a static mode as well if
|
|
138
|
+
you want `--color` to be visible.
|
|
139
|
+
|
|
140
|
+
### Back up before experimenting
|
|
141
|
+
|
|
142
|
+
```sh
|
|
143
|
+
./m693ctl dump -o m693-backup.bin # 192 bytes of configuration memory
|
|
144
|
+
./m693ctl restore m693-backup.bin
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
`dump` with no `-o` hex-dumps instead, and `--addr` / `--length` let you look
|
|
148
|
+
anywhere (e.g. `--addr 0x100` for the macro area). `raw` writes arbitrary bytes
|
|
149
|
+
without adding checksums, for protocol work.
|
|
150
|
+
|
|
151
|
+
### Waybar / status-bar battery module
|
|
152
|
+
|
|
153
|
+
Because the mouse does not expose a standard HID Battery Service, UPower and
|
|
154
|
+
desktop applets never list it. Poll `m693ctl --wait 0 battery -q` (`--wait 0`
|
|
155
|
+
exits immediately while the mouse is asleep instead of blocking your bar):
|
|
156
|
+
|
|
157
|
+
```jsonc
|
|
158
|
+
"custom/mouse-battery": {
|
|
159
|
+
"exec": "p=$(m693ctl --wait 0 battery -q 2>/dev/null) && echo \" ${p}%\"",
|
|
160
|
+
"interval": 60,
|
|
161
|
+
"tooltip": false
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Graphical interface
|
|
166
|
+
|
|
167
|
+
```sh
|
|
168
|
+
./m693-gui # against the real mouse
|
|
169
|
+
./m693-gui --fake # simulated mouse, no hardware needed
|
|
170
|
+
./m693-gui --native-decorations # use your WM's title bar
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
It is fully keyboard-drivable, which matters more here than in most settings
|
|
174
|
+
dialogs: this is the window you use when a remap has gone wrong and the mouse
|
|
175
|
+
is the one input device you cannot trust.
|
|
176
|
+
|
|
177
|
+
| Key | Action |
|
|
178
|
+
| --- | --- |
|
|
179
|
+
| `Ctrl+1` … `Ctrl+4` | jump to a section |
|
|
180
|
+
| `Ctrl+Tab` / `Ctrl+Shift+Tab`, or ← → on the nav bar | next/previous section |
|
|
181
|
+
| `Tab` | next control; focus is always visibly ringed |
|
|
182
|
+
| `Ctrl+R` | re-read everything from the mouse |
|
|
183
|
+
| `F5` | wake a sleeping mouse |
|
|
184
|
+
| `Ctrl+E` / `Ctrl+I` | export / import a profile |
|
|
185
|
+
| `Ctrl+W`, `Ctrl+Q` | quit |
|
|
186
|
+
|
|
187
|
+
Optionally pull in the mouse renders used for the button callouts and the
|
|
188
|
+
lighting preview. They are Redragon's artwork and are not shipped with this
|
|
189
|
+
repository, so supply your own copy of the installer:
|
|
190
|
+
|
|
191
|
+
```sh
|
|
192
|
+
tools/extract_assets.py "REDRAGON M693-RGB Setup ….exe"
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
They go into the checkout if you are working in one, otherwise into
|
|
196
|
+
`~/.local/share/m693/device/` — which is where they need to be for an
|
|
197
|
+
installed package, since site-packages belongs to root.
|
|
198
|
+
|
|
199
|
+
**Status: complete.** All four tabs — **Key Settings**, **DPI Settings**,
|
|
200
|
+
**Macro** and **Lighting** — are implemented, and the app is packaged and
|
|
201
|
+
keyboard-navigable. See [PLAN.md](https://github.com/rajchauhan28/redragon-mouse-linux/blob/master/PLAN.md).
|
|
202
|
+
|
|
203
|
+
The Lighting tab has two sync modes, as radio buttons: **Side strips + palm
|
|
204
|
+
logo** leaves the wheel with its own effect and the drop-down picks which zone
|
|
205
|
+
you are editing; **All three zones together** drives the lot from one set of
|
|
206
|
+
controls. There is no third option because the strips and the logo are one
|
|
207
|
+
channel — they are always in step, whichever mode you are in. Presets store every zone's
|
|
208
|
+
effect, colour, brightness and speed under a name in
|
|
209
|
+
`~/.config/m693/presets.json`, shared with `m693ctl preset`. There is no
|
|
210
|
+
programmable effect engine on this mouse and no live-lighting command, so a
|
|
211
|
+
custom animation would mean writing to its configuration flash tens of times a
|
|
212
|
+
second; presets combine the seven firmware effects instead, and cost nothing to
|
|
213
|
+
leave applied.
|
|
214
|
+
|
|
215
|
+
The Macro tab keeps a library in `~/.config/m693/macros.json`, records
|
|
216
|
+
keystrokes with their real timing, and lets you add mouse-button and
|
|
217
|
+
multimedia steps by hand. Macros exported from the Windows tool import
|
|
218
|
+
directly: `.jmm` is a documented format now.
|
|
219
|
+
|
|
220
|
+
Key Settings gives each of the seven buttons the stock tool exposes a full
|
|
221
|
+
function menu — mouse buttons, DPI actions, multimedia and web keys, keyboard
|
|
222
|
+
shortcuts, fire keys, DPI lock — with the numbered callouts landing on the
|
|
223
|
+
leader lines already drawn in Redragon's own render. Profiles export to JSON
|
|
224
|
+
and import back.
|
|
225
|
+
|
|
226
|
+
The DPI sliders snap to the sensor's real ladder — 100 DPI steps to 4000, 200
|
|
227
|
+
above — so the number on screen is always a value the mouse can actually store.
|
|
228
|
+
The stock Windows tool lets you pick values it then silently quantises.
|
|
229
|
+
|
|
230
|
+
Edits never write straight through to the mouse. They mutate an in-memory copy
|
|
231
|
+
of its configuration, and a 250 ms timer merges the changed checksummed groups
|
|
232
|
+
into as few write commands as the protocol allows, on a background thread.
|
|
233
|
+
Dragging a slider therefore costs one write, not one per pixel. If the mouse
|
|
234
|
+
falls asleep mid-edit the changes are held and applied when it wakes.
|
|
235
|
+
|
|
236
|
+
```sh
|
|
237
|
+
python3 tests/test_model.py # no hardware required
|
|
238
|
+
python3 tests/test_dpi_tab.py
|
|
239
|
+
python3 tests/test_lighting_tab.py
|
|
240
|
+
python3 tests/test_keys_tab.py
|
|
241
|
+
python3 tests/test_shell.py
|
|
242
|
+
python3 tests/test_macro_tab.py
|
|
243
|
+
python3 tests/test_unknowns.py
|
|
244
|
+
python3 tests/test_battery.py # protocol half runs without Qt
|
|
245
|
+
python3 tests/test_pairing_and_cleanup.py
|
|
246
|
+
python3 tests/test_inspect_installer.py
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## As a library
|
|
250
|
+
|
|
251
|
+
```python
|
|
252
|
+
from m693 import Device, Profile
|
|
253
|
+
from m693 import profile as P
|
|
254
|
+
|
|
255
|
+
with Device() as dev:
|
|
256
|
+
dev.set_driver_status(True)
|
|
257
|
+
dev.wait_online()
|
|
258
|
+
|
|
259
|
+
prof = Profile.read_from(dev)
|
|
260
|
+
print(prof.polling_rate, prof.dpi_stages, prof.dpi_colors)
|
|
261
|
+
|
|
262
|
+
P.set_dpi_stages(dev, [400, 800, 1600, 3200])
|
|
263
|
+
P.set_led_color(dev, (0xFF, 0x00, 0x80))
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Other wireless Redragon mice (`25a7:faXX`)
|
|
267
|
+
|
|
268
|
+
Many wireless Redragon mice — including the M913 Impact Elite, M810 Pro, M686
|
|
269
|
+
Vampire Elite, M724, and M612 Pro — are built on the same Compx / Areson
|
|
270
|
+
`25a7:faXX` platform and ship the same `OemDrv.exe` + `Cfg.ini` Windows
|
|
271
|
+
configuration tool.
|
|
272
|
+
|
|
273
|
+
If you own another wireless Redragon mouse and want Linux support:
|
|
274
|
+
|
|
275
|
+
1. Check your USB IDs (plug in both the 2.4 GHz receiver and USB-C cable if possible):
|
|
276
|
+
```sh
|
|
277
|
+
lsusb -d 25a7:
|
|
278
|
+
```
|
|
279
|
+
2. Extract its capability table from Redragon's Windows `.exe` installer (no Windows needed, only `innoextract`):
|
|
280
|
+
```sh
|
|
281
|
+
python3 tools/inspect_installer.py "REDRAGON_Mxxx_Setup.exe"
|
|
282
|
+
```
|
|
283
|
+
3. Open a [**Device Support** issue](https://github.com/rajchauhan28/redragon-mouse-linux/issues/new?template=new-mouse-model.yml) with both outputs. Do **not** run write commands against an untested model before backing up its flash.
|
|
284
|
+
|
|
285
|
+
## Notes and caveats
|
|
286
|
+
|
|
287
|
+
* **Changes apply instantly** and persist across re-plugs — the settings live
|
|
288
|
+
in the mouse, not in a background daemon. There is no apply step.
|
|
289
|
+
* **A sleeping mouse ignores configuration commands.** It dozes off within
|
|
290
|
+
about a minute of being left alone. `m693ctl` handles this itself: it waits
|
|
291
|
+
for the mouse indefinitely, resumes a command that was interrupted part-way,
|
|
292
|
+
and says so on stderr while it waits. `--wait SECONDS` puts a limit on that,
|
|
293
|
+
and `--wait 0` fails immediately instead. Only silence is retried — an
|
|
294
|
+
explicit refusal from the device is reported straight away.
|
|
295
|
+
|
|
296
|
+
Re-announcing the driver usually wakes the mouse on its own, so in practice
|
|
297
|
+
the wait is a second or two rather than "until you touch it". Note that the
|
|
298
|
+
2.4 GHz receiver keeps answering status queries even while the mouse is
|
|
299
|
+
asleep, so "the dongle is present" is not the same as "the mouse is
|
|
300
|
+
reachable".
|
|
301
|
+
* **The wireless link is lossy**; every command is retried automatically.
|
|
302
|
+
* **The mouse reports its own charge** over command `0x04`, as a whole
|
|
303
|
+
percentage plus a charging flag — the same `GetPower` the Windows tool's
|
|
304
|
+
battery icon uses. It has to be polled: the mouse pushes no notification
|
|
305
|
+
when the charge changes, and it advertises no HID battery usage, so your
|
|
306
|
+
desktop's power applet will never list it. The GUI polls it about every
|
|
307
|
+
30 seconds and shows it in the status bar.
|
|
308
|
+
* Both the wired product id (`25a7:fa7b`) and the 2.4 GHz receiver
|
|
309
|
+
(`25a7:fa7c`) are recognised, and both have now been exercised.
|
|
310
|
+
**Plugging the cable in switches the mouse to wired mode**: it enumerates in
|
|
311
|
+
its own right as `fa7b` while the receiver stays on the bus with nothing
|
|
312
|
+
linked to it. That idle receiver still answers — it reports the mouse
|
|
313
|
+
offline and hands back the *last battery figure it saw*, which looks exactly
|
|
314
|
+
like a live one. So a directly connected mouse is always preferred, and a
|
|
315
|
+
charge is refused outright unless the link says the mouse is really there.
|
|
316
|
+
* **The mouse holds one macro per button**, not a library — a macro lives at
|
|
317
|
+
the address matching the button it is bound to. The library on disk is ours,
|
|
318
|
+
not the mouse's. Up to 70 steps per macro.
|
|
319
|
+
* Macro recording captures **keystrokes only**. Capturing mouse buttons would
|
|
320
|
+
mean swallowing the clicks you need to stop the recording, so they are added
|
|
321
|
+
from the step list instead — which is also the only way to write a press
|
|
322
|
+
without its release.
|
|
323
|
+
* `0x06`, `0x08`, `0x52`, `0x5E` and `0xA7` are spare: zero, correctly
|
|
324
|
+
checksummed, and never read by the stock tool either.
|
|
325
|
+
* `0xB5` and `0xB7` are real settings the Windows tool can write, but this
|
|
326
|
+
model has never written them — they read `0xFF` and form no valid group — so
|
|
327
|
+
they are left alone rather than guessed at.
|
|
328
|
+
* The mouse lights three places but has only **two** channels: `0xA0` drives
|
|
329
|
+
the side strips *and* the palm logo together, `0x4C` drives the scroll wheel.
|
|
330
|
+
All three are listed separately, because that is how the mouse looks, but
|
|
331
|
+
the strips and the logo are one channel — either entry moves both, and both
|
|
332
|
+
say so. There is no way to split them on this model.
|
|
333
|
+
* The wheel's colour is the **DPI stage colour table**, not a field of its own,
|
|
334
|
+
so giving the wheel a colour overwrites the per-stage colour coding. The CLI
|
|
335
|
+
says so and the GUI asks first.
|
|
336
|
+
* `0x54`–`0x5F` is a second effect block whose colour bytes are ignored; its
|
|
337
|
+
mode byte at `0x58` reaches the wheel, which `0x4C` gates. Nothing exposes it.
|
|
338
|
+
* In the travelling effects the two side strips are **offset in time** — they
|
|
339
|
+
are one LED chain running down one side and back up the other. There is no
|
|
340
|
+
phase or direction control: the stock tool has none, and writing to every
|
|
341
|
+
spare byte in the map changes nothing.
|
|
342
|
+
* The stored **speed byte is a delay** — higher is slower — and the firmware
|
|
343
|
+
accepts the whole byte, well past the stock tool's limit of 10. The 1–10
|
|
344
|
+
slider is mapped onto that full range, so 1 is far slower than the Windows
|
|
345
|
+
tool could go. The two zones do not run at the same rate for the same value.
|
|
346
|
+
* The mouse **silently ignores** any field group whose checksum does not
|
|
347
|
+
validate — the write is acknowledged and reads back, but nothing changes.
|
|
348
|
+
`raw` bypasses checksum handling, so use it deliberately.
|
|
349
|
+
* Verified against firmware `2910-B TX V3 CX52850+P3104`. Other M693 revisions
|
|
350
|
+
very likely share this protocol — it is a common Areson/Compx design — but
|
|
351
|
+
take a backup first.
|
|
352
|
+
|
|
353
|
+
## Layout
|
|
354
|
+
|
|
355
|
+
```
|
|
356
|
+
m693ctl CLI entry point
|
|
357
|
+
m693/device.py discovery, framing, checksums, retries
|
|
358
|
+
m693/profile.py memory map, encoders, DPI tables
|
|
359
|
+
m693/keys.py button catalogue, combo-key records
|
|
360
|
+
m693/transfer.py profile export/import
|
|
361
|
+
m693/macro.py macro records and .jmm files
|
|
362
|
+
m693/cli.py argument parsing and subcommands
|
|
363
|
+
m693/stock-profile.bin factory configuration, for Restore and the simulator
|
|
364
|
+
m693gui/ the Qt front-end (app, model, worker, tabs, widgets)
|
|
365
|
+
99-redragon-m693.rules udev rule for non-root access
|
|
366
|
+
packaging/ .desktop entry
|
|
367
|
+
tools/install.sh udev rule + desktop entry
|
|
368
|
+
tools/extract_assets.py pulls the mouse renders out of the Windows installer
|
|
369
|
+
tools/inspect_installer.py extracts VID/PID, sensor & DPI tables for other models
|
|
370
|
+
PROTOCOL.md the reverse-engineering write-up
|
|
371
|
+
```
|