Home Projects Git

rivalcfg contribution: adding support for the Rival 600


rivalcfg is a small CLI utility program by flozz on GitHub that allows you to configure SteelSeries Rival gaming mice on Linux and Windows.
The code is well organized and easy to understand and navigate, so adding support for the Rival 600 was a breeze.

The official configuration program (SteelSeries Engine) is Windows and MacOS only. Luckily, the configuration protocol is easy to reverse engineer. (note: article is in french)

[Update] 13.08.2018
Turns out, the Sensei 310 has a similiar protocol, and someone already made significant progress analysing it.
I could apply their findings, and some of the weird stuff is now demystified. My current understanding of the Rival 600 is as follows:
|---COLORS---(wValue=0x0300 feature)------------------------------------------------------------------------------------------| | | | led_id led_id repeat|triggers points | |cmd--|^^|x?---|y?---|^^|speed| |^^|^^| |^^|color1--|color1--|p1|color2--|p2| |colorN--|pN|color1--|pe| |05:00:id:__:__:__:__:id:ll:hh:... 14 bytes ...:rp:tr:__:__:__:nn:r1:g1:b1:r1:g1:b1:p1:r2:g2:b2:p2:...:rN:gN:bN:pN:r1:g1:b1:pe| where: led_id: the led (0..7) x, y : looks like the x and y coordinates of the LEDs (little endian), maybe for wave effect? speed : cycle time in milliseconds (little endian) repeat: wether the cycle should repeat (0=repeat, 1=don't) triggers: the trigger button mask, selects which buttons trigger new color cycle points: number of points (point = color and cumulative proportion of cycle time) colorX: a color in rr:gg:bb format pX : a (cumulative) time proportion note: the offical tool inserts the first color at the end regardless of user choices (color1). this is to ensure smooth colorshifting when going back to start (repeat mode=on) note: the inserted color gets a time proportion (pe) of: 0xFF - sum(p1, p2,...,pN)
I have implemented the protocol in pull request #60.

Below is the reverse engineering process and older findings.
Using the official tool under a virtual machine, I started sniffing USB packets:
|------------------------------COLORS---(wValue=0x0300 (feature)-----------------------------------------------------------------------------------| WHEEL |cmd0-|zone-------------|cmd1-| |color---| |color---| | #00FFFF -> |05:00:00:55:00:46:00:00:10:27:00:00:00:00:00:00:00:00:00:00:00:00:00:00:01:00:00:00:00:04:00:ff:ff:ff:00:00:00:00:ff:00:54:00:00:ff:54:00:ff:ff:56| #00FF00 -> |05:00:00:55:00:46:00:00:10:27:00:00:00:00:00:00:00:00:00:00:00:00:00:00:01:00:00:00:00:04:00:ff:00:ff:00:00:00:00:ff:00:54:00:00:ff:54:00:ff:00:56| | | | | | | | | | LOGO | | | | | | | | | #FF5200 -> |05:00:01:55:00:0e:01:01:10:27:00:00:00:00:00:00:00:00:00:00:00:00:00:00:01:00:00:00:00:04:ff:52:00:ff:00:00:00:00:ff:00:54:00:00:ff:54:ff:52:00:56| #00FFFF -> |05:00:01:55:00:0e:01:01:10:27:00:00:00:00:00:00:00:00:00:00:00:00:00:00:01:00:00:00:00:04:00:ff:ff:ff:00:00:00:00:ff:00:54:00:00:ff:54:00:ff:ff:56| #00FF00 -> |05:00:01:55:00:0e:01:01:10:27:00:00:00:00:00:00:00:00:00:00:00:00:00:00:01:00:00:00:00:04:00:ff:00:ff:00:00:00:00:ff:00:54:00:00:ff:54:00:ff:00:56| | | | | | | | | | STR_L0..2 | | | | | | | | | #0000FF -> |05:00:02:32:00:91:00:02:10:27:00:00:00:00:00:00:00:00:00:00:00:00:00:00:01:00:00:00:00:04:00:00:ff:ff:00:00:00:00:ff:00:54:00:00:ff:54:00:00:ff:56| -> |05:00:04:2d:00:b4:00:04:10:27:00:00:00:00:00:00:00:00:00:00:00:00:00:00:01:00:00:00:00:04:00:00:ff:ff:00:00:00:00:ff:00:54:00:00:ff:54:00:00:ff:56| -> |05:00:06:19:00:d2:00:06:10:27:00:00:00:00:00:00:00:00:00:00:00:00:00:00:01:00:00:00:00:04:00:00:ff:ff:00:00:00:00:ff:00:54:00:00:ff:54:00:00:ff:56| | | | | | | | | | STR_R0..2 | | | | | | | | | #FF00FF -> |05:00:03:78:00:91:00:03:10:27:00:00:00:00:00:00:00:00:00:00:00:00:00:00:01:00:00:00:00:04:ff:00:ff:ff:00:00:00:00:ff:00:54:00:00:ff:54:ff:00:ff:56| -> |05:00:05:7d:00:b4:00:05:10:27:00:00:00:00:00:00:00:00:00:00:00:00:00:00:01:00:00:00:00:04:ff:00:ff:ff:00:00:00:00:ff:00:54:00:00:ff:54:ff:00:ff:56| -> |05:00:07:91:00:d2:00:07:10:27:00:00:00:00:00:00:00:00:00:00:00:00:00:00:01:00:00:00:00:04:ff:00:ff:ff:00:00:00:00:ff:00:54:00:00:ff:54:ff:00:ff:56|
To the left we have what LED on the mouse we are assigning colors to, and which colors we are assigning to it. We can already see some patterns emerging.
It seems the command is actually split in two fields: cmd0 and cmd1. In between it seems the bytes specify what zone (LED) we are targeting.

When trying out more advanced features of the mouse, like color shifting, we can see even more patterns emerging:
LOGO |cmd0-|zone-------------|cmd1-| solid-|--| len-|--|color---|--clr1--|p1|--clr2--|p2|--clr3--|p3|color---| | R>G>B -> |05:00:01:55:00:0e:01:01:10:27:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:04:ff:00:00:ff:00:00:00:00:ff:00:54:00:00:ff:54:ff:00:00:56| s1 -> |05:00:01:55:00:0e:01:01:10:27:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:04:45:45:45:45:45:45:00:00:ff:00:54:00:00:ff:54:45:45:45:56| s2 -> |05:00:01:55:00:0e:01:01:10:27:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:04:45:45:45:45:45:45:00:00:ff:00:54:00:f9:f9:54:45:45:45:56| s3 -> |05:00:01:55:00:0e:01:01:10:27:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:04:45:45:45:45:45:45:00:22:e9:22:54:00:f9:f9:54:45:45:45:56| s4 -> |05:00:01:55:00:0e:01:01:10:27:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:04:45:45:45:45:45:45:0c:22:e9:22:47:00:f9:f9:54:45:45:45:56| 4pt shft |05:00:01:55:00:0e:01:01:10:27:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:05:ff:00:00:ff:00:00:00:da:25:00:11:00:ff:00:68:00:00:ff:2d:ff:00:00:56| |cmd0-|zone-------------|cmd1-| solid-|--| len-|--|color---|--clr1--|p1|--clr2--|p2|--clr3--|p3|--clr4--|p4|color---| | where the shift patterns are as following: R>G>B: #FF0000 @0% -> #00FF00 @33% -> #0000FF @66% s1: #454545 @0% -> #00FF00 @33% -> #0000FF @66% s2: #454545 @0% -> #00FF00 @33% -> #00F9F9 @66% s3: #454545 @0% -> #22E922 @33% -> #00F9F9 @66% s4: #454545 @5% -> #22E922 @33% -> #00F9F9 @66%
Here we're applying color shifting effects on the logo. The R>G>B pattern is the default pattern, which evenly cycles from Red to Green to Blue, and back to Red.
In other words, the time taken to change from Red to Green is 1/3 of total time, from Green to Blue another 1/3, and finally from Blue to Red the last 1/3.
We can look for this and indeed see the colors used in the shift pattern labeled clr1, clr2, ..., clrn and their portion of time labeled p1, p2, ..., pn

Comparing the tables of solid and shifting colors, we can see a byte labeled solid, which seems to select between solid color and shifting color.
Finally, adding a fourth point in the shift pattern, we can see a field labeled len, which seems to specify the number of points in the shift pattern.

Interestingly, the configuration utility sends a complete RGB color shift command even when only setting a solid color. I started experimenting with custom data packets,
trying to shorten the length of the packets.
Turns out, it is possible to set a solid color using fewer bytes, but you have to break the protocol a little!
BUG OR FEATURE? when sending short datagrams, the mouse appears to ignore the length field, and the color data starts from said field instead: LOGO |cmd0-|zone-------------|cmd1-| solid-|--| len-|--|color---|... <- expected format #0000FF -> |05:00:01:55:00:0e:01:01:10:27:00:00:00:00:00:00:00:00:00:00:00:00:00:00:01:00:00:00:00:00:00:ff| |cmd0-|zone-------------|cmd1-| solid-|--| |color---| <- actual format the above bytes will set the logo color to solid blue.
Either it's a feature, or the len field is not a length field at all...