Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
gpoulios committed Feb 28, 2023
0 parents commit e994182
Show file tree
Hide file tree
Showing 8 changed files with 596 additions and 0 deletions.
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[workspace]

members = [
"lib", "cli", "gui"
]
82 changes: 82 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# deathadderv2-rgb

Set (a constant) color on the Razer DeathAdder v2. (while practising in rust)

A little utility for those of us that don't want to run 2-3 apps and 6 services (!!) just for keeping this mouse from changing colors like a christmas tree. Personally, I don't care about the auto-switching of profiles that Synapse provides and all the other functionality I can have without running Razer's apps in the background.

Unfortunately, the device does not remember the color and it comes back with the rainbow on power on (either after sleep/hibernation or on boot). Not going to bother making it into a service as the task scheduler suits me just fine (read below if you're interested in maintaining the setting).

## Requirements

Only requirement is to be using the libusb0 driver.

One way to install it is using [Zadig](https://zadig.akeo.ie/). You only need to change the entry "Razer DeathAdder V2 (Interface 3)". Use the spinner to select "libusb-win32 (vX.Y.Z)" and hit "Replace driver". In my case (Win11) it timed out while creating a restore point but it actually installed it.

## Usage

The tool comes in two forms, a console executable that you can use like so:

```
> deathadder-rgb-cli aabbcc
```

and a GUI app that will just pop up a color picker prompt (check the mouse while selecting).

You can use the GUI version with command line arguments too (same usage as above), except a console window will not be allocated (this is intentional).

I have not found a way to retrieve the current color from the device so both apps will save the last sent color to a file under %APPDATA%/deathadder/config/default-config.toml.

### Bonus

It is actually possible to set a different color on the scroll wheel (Synapse doesn't support this at the time of this writing). But there's a catch: most combinations don't work and I don't understand why. For sure it accepts combinations when the RGB components in both colors are the same even if in different order. For instance, the following will work:

```
> deathadder-rgb-cli 1bc c1b
> deathadder-rgb-cli 1155AA AA5511
> deathadder-rgb-cli 10f243 f24310
```

### Task Scheduler: re-applying the setting

The GUI version also supports `--last` as the first argument in which case it sets the last applied color (either from cli or gui). This is useful if you want to schedule a task that does not pop up any windows.

A tested setup is to set a trigger at log on, and for waking up from sleep, a custom trigger on Power-Troubleshooter with event ID 1 and delay 5 seconds. In Action tab use the absolute path to `deathadder-rgb-gui` and in the arguments put `--last`.

## Technical

I captured the USB using UsbPcap while Synapse was sending the color-setting commands (it was a single control transfer-write, multiple times to provide that fade effect) and replaced the RGB values in it. The rest of the packet is identical. Haven't tested in any mouse other than mine; not sure if there's anything device-specific in there that would prevent others from using it.

The USB message header was:

```
Setup Data
bmRequestType: 0x21
bRequest: SET_REPORT (0x09)
wValue: 0x0300
wIndex: 0
wLength: 90
Data Fragment: 001f[...]
```

And this is would be the payload for setting the color to bright white:

```
File: lib/src/lib.rs
[...]
// the start (no idea what they are)
0x00, 0x1f, 0x00, 0x00, 0x00, 0x0b, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01,
// wheel RGB (3B) | body RGB (3B)
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
// the trailer (no idea what they are either)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00
[...]
```

12 changes: 12 additions & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "deathadder-rgb-cli"
version = "0.1.0"
edition = "2021"

[[bin]]
name = "deathadder-rgb-cli"
path = "src/cli.rs"

[dependencies]
libdeathadder = { path = "../lib" }
rgb = "0.8.36"
34 changes: 34 additions & 0 deletions cli/src/cli.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use rgb::RGB8;
use libdeathadder::core::{rgb_from_hex, Config};
use libdeathadder::v2::set_color;

fn main() {
let args: Vec<String> = std::env::args().collect();

let parse_arg = |input: &str| -> RGB8 {
match rgb_from_hex(input) {
Ok(rgb) => rgb,
Err(e) => panic!("argument '{}' should be in the \
form [0x/#]RGB[h] or [0x/#]RRGGBB[h] where R, G, and B are hex \
digits: {}", input, e)
}
};

let (color, wheel_color) = match args.len() {
..=1 => {
match Config::load() {
Some(cfg) => (cfg.color, cfg.wheel_color),
None => panic!("failed to load configuration; please specify \
arguments manually")
}
},
2 => (parse_arg(args[1].as_ref()), None),
3 => (parse_arg(args[1].as_ref()), Some(parse_arg(args[2].as_ref()))),
_ => panic!("usage: {} [(body) color] [wheel color]", args[0])
};

match set_color(color, wheel_color) {
Ok(msg) => println!("{}", msg),
Err(e) => panic!("Failed to set color(s): {}", e)
}
}
22 changes: 22 additions & 0 deletions gui/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[package]
name = "deathadder-rgb-gui"
version = "0.1.0"
edition = "2021"

[[bin]]
name = "deathadder-rgb-gui"
path = "src/gui.rs"

[dependencies]
libdeathadder = { path = "../lib" }
winapi = "0.3.9"
rgb = "0.8.36"

[dependencies.windows]
version = "0.44.0"
features = [
"Win32_Foundation",
"Win32_UI_Controls_Dialogs",
"Win32_UI_WindowsAndMessaging",
"Win32_System_Diagnostics_Debug"
]
Loading

0 comments on commit e994182

Please sign in to comment.