Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions captures/cosmic-byte-kilonova-3335ic/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Cosmic Byte Kilonova 3335IC (`258a:002f`) captures

A read-only probing session against the Kilonova 3335IC's 2.4 GHz dongle
(SINOWEALTH `258a:002f`, the M690 PRO receiver's product id) with node-hid
under Windows 11. Short commands went to interface 1's feature report 5,
banks to feature report 8 (`Col03` of the vendor collections,
`0xff00:0x01`). No vendor application was involved: nothing here shows a
write, and OpenMouse does not write to this device. The mouse was awake and
linked during the session and its battery read 0x46 (70 %). The dongle
reports no serial number, so the files carry no unit identifier.

| File | What it is |
| --- | --- |
| `probes-receiver.hex` | The whole session: identify (ASCII `"2315"`), link (linked), status (wireless, battery 70 %), the 154-byte settings bank and the 88-byte button bank (payload all zeros). |

Each line is one feature report exactly as node-hid returned it, report id
first: `GET`, then the bytes. Unlike the USBPcap capture folders, nothing is
truncated; the banks end where their content ends (the settings bank ends in
the family's `a5 00` marker), and repeated polls are omitted.

Decoding notes and open questions: `docs/kilonova-3335ic.md`. The driver's
read-only treatment of this device is `src/drivers/redragon/m690-pro-hid.ts`.
5 changes: 5 additions & 0 deletions captures/cosmic-byte-kilonova-3335ic/probes-receiver.hex
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
GET 05 01 32 33 31 35 00 00
GET 05 80 01 01 00 00 00 00
GET 05 90 11 46 00 00 00 00
GET 08 21 00 00 00 00 00 00 64 11 04 36 00 03 00 07 00 0f 00 1f 00 3f 00 9f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff 00 00 00 ff 00 00 00 ff ff ff 00 00 ff ff ff 00 ff 00 00 00 00 00 00 05 43 00 40 00 ff 00 42 07 ff 00 00 00 ff 00 00 00 ff 00 ff ff ff ff 00 fa 00 fa ff ff ff 03 42 40 ff 00 00 00 ff 00 00 00 ff ff ff 00 00 ff ff ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 42 00 ff 00 ff 00 00 42 42 02 ff 00 00 00 00 00 00 ff 00 00 a5 00
GET 08 22 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
100 changes: 100 additions & 0 deletions docs/kilonova-3335ic.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Cosmic Byte Kilonova 3335IC (SiNoWealth `258a:002f` receiver)

Identity: Cosmic Byte Kilonova 3335IC, its 2.4 GHz dongle enumerates as
SINOWEALTH `258a:002f` (the M690 PRO receiver's product id), Windows 11,
probed with node-hid in a scratch script. The wired id of this device (if it
has one and whether it is `258a:002e`) is unknown; every capture below is
through the receiver while the mouse was awake and linked, battery at
70 % as the mouse itself reported it.

The dongle is the first decoded member of the same framing as the Redragon
M690 PRO (`src/redragon/m690-pro.ts`, libratbag's `driver-sinowealth.c`):
short commands on feature report 5, banks on feature report 8, and the
settings bank's `a5 00` end marker. What differs is the footprints inside the
banks, so `@openmouse/protocol/sinowealth` lists it as a profile next to the
M690 PRO's, and the M690 PRO client narrows to read-only for it.

## USB shape

`hidapitester --list-detail` shows one device, two interfaces:

- `MI_00` on interface 0: the mouse itself (usage `0x0001:0x0002`).
- `MI_01` on interface 1: six collections in this order — `Col01` keyboard
(`0x0001:0x0006`), `Col02` consumer (`0x000c:0x0001`),
`Col03`/`Col04`/`Col05` vendor (`0xff00:0x0001`, identical layout to the
M690 PRO command collection: feature report 5, 7 bytes; `Col03` carries
report 8, 519 bytes), and `Col06` (`0xff01:0x0001`).

The report descriptor of each vendor collection is byte-identical to the
M690 PRO's (`06 00 FF 09 01 A1 01 85 05 19 01 29 02 15 00 26 FF 00 75 08
95 07 B1 02 C0`). Col03 answers the bank reads, Col05 accepts and reads the
short commands — the same roles the M690 PRO test fixture records.

## Captures (read-only; feature reports as node-hid returns them, id first)

The session's raw feature reports are in
`captures/cosmic-byte-kilonova-3335ic/probes-receiver.hex`. Summary:

| Command | Answer | Meaning |
| --- | --- | --- |
| `[05 01 00 00 00 00 00 00]` | `[05 01 32 33 31 35 00 00]` | identify: ASCII `"2315"` (M690 PRO: `"2945"`) |
| `[05 80 00 00 00 00 00 00]` | `[05 80 01 01 00 00 00 00]` | link: mouse linked and awake |
| `[05 90 00 00 00 00 00 00]` | `[05 90 11 46 00 00 00 00]` | status: wireless (byte 2 bit 0), battery 0x46 = 70 % |
| `[05 21 00 00 00 00 00 00]` | 154 bytes | settings bank |
| `[05 22 00 00 00 00 00 00]` | 88 bytes | button bank: `08 22` then all zeros |

The settings bank, report id included:

```
08210000000000006411043600030007000f001f003f009f0000000000000000
00000000000000000000000000ff000000ff000000ffffff0000ffffff00ff00
00000000000543004000ff004207ff000000ff000000ff00ffffffff00fa00fa
ffffff034240ff000000ff000000ffffff0000ffffffffff0000000000000000
000000004200ff00ff0000424202ff000000000000ff0000a500
```

## Observed facts

- Bank lengths match the M690 PRO's (154 settings, 88 buttons), byte 8 is
0x64 as on every M690 PRO bank read, and the `a5 00` end marker sits at
152-153.
- The M690 PRO disambiguator holds: byte 9 is 0x11 (the M690 PRO's model
byte is 0x13), and identify answers "2315" against the M690 PRO's "2945".
When OpenMouse connected through Chrome, the same model byte reached the
app (the browser cannot read report 5's short answers, so the bank is the
browser-viable footprint — see `src/drivers/redragon/m690-pro-hid.ts`).
- Byte 10 is 0x04: in the M690 PRO's polling-code map that is 1000 Hz. The
rate was not measured (Windows refuses the input interface while a mouse
session holds it), so nothing decodes it for this device yet.

## Hypotheses (not implemented)

- The bytes after the model byte may follow the M690 PRO's meaning (stage
table at 0x0d, colours at 0x2d, effects at 0x45): byte 11 is 0x36, which
would read as "5 stages, stage 2 active" on the M690 PRO. The stage bytes
that follow (`00 07 00 0f 00 1f 00 3f 00 9f`) do not name that list's
1..24 positions (159, 255 are impossible positions), so the mapping or
the offsets differ. Nothing is decoded and nothing is written until a
toggle-diff capture of the vendor's software says otherwise.
- The zero-payload button bank may keep the M690 PRO's four-byte slot grid
at the factory defaults; configuring the vendor's own settings would show
the slots. Not decoded yet.

## What OpenMouse does with this

`RedragonM690ProHidClient` recognizes `258a:002f` by shape (unchanged), and
its settings-block check now resolves a profile. On a Kilonova 3335IC it
reports the device as "Cosmic Byte Kilonova 3335IC", keeps battery and link
(when the transport can read report 5, it behind OpenMouse Bridge in a
browser), hides the settings grid and refuses every write path, instead of
refusing the device the way it refuses a truly foreign bank.

## What would unlock the rest

- The vendor's settings application captures (toggle each setting once)
to map the stage/DPI table, colours and buttons; same work as the M690
PRO's first pass.
- The cable id (`258a:002e` or another) and one wired session to see whether
the status command answers charge codes like the M690 PRO's cable bank.
- A measurement of the polling rate at each vendor application setting to
pin the byte-10 map.
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@
"types": "./dist/redragon/index.d.ts",
"import": "./dist/redragon/index.js"
},
"./sinowealth": {
"types": "./dist/sinowealth/index.d.ts",
"import": "./dist/sinowealth/index.js"
},
"./drivers": {
"types": "./dist/drivers/index.d.ts",
"import": "./dist/drivers/index.js"
Expand Down
2 changes: 1 addition & 1 deletion src/drivers/mouse-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ export interface MagneticCalibrationProgress {
}

export interface MouseStatus {
brand: "RAWM" | "Motospeed" | "Logitech" | "Pulsar" | "Endgame Gear" | "WLMouse" | "G-Wolves" | "Lamzu" | "CRDRAKO" | "Attack Shark" | "LunaFury" | "Vancer" | "Orbital" | "Razer" | "Teevolution" | "ATK" | "VXE" | "VGN" | "VAXEE" | "Finalmouse" | "Keychron" | "moddoMOUSE" | "Ninjutso" | "Zaunkoenig" | "Fantech" | "Wooting" | "WALLHACK" | "SteelSeries" | "Glorious" | "MCHOSE" | "K-snake" | "Noir Gear" | "Lingbao" | "GearHub" | "AJAZZ" | "Corsair" | "Microsoft" | "Dareu" | "Redragon" | "Incott" | "HyperX" | "ASUS" | "Ryunix" | "Delux" | "GravaStar" | "IPI" | "Rapoo" | "Fater" | "Cooler Master" | "AJAZZ" | "Scyrox";
brand: "RAWM" | "Motospeed" | "Logitech" | "Pulsar" | "Endgame Gear" | "WLMouse" | "G-Wolves" | "Lamzu" | "CRDRAKO" | "Attack Shark" | "LunaFury" | "Vancer" | "Orbital" | "Razer" | "Teevolution" | "ATK" | "VXE" | "VGN" | "VAXEE" | "Finalmouse" | "Keychron" | "moddoMOUSE" | "Ninjutso" | "Zaunkoenig" | "Fantech" | "Wooting" | "WALLHACK" | "SteelSeries" | "Glorious" | "MCHOSE" | "K-snake" | "Noir Gear" | "Lingbao" | "GearHub" | "AJAZZ" | "Corsair" | "Microsoft" | "Cosmic Byte" | "Dareu" | "Redragon" | "Incott" | "HyperX" | "ASUS" | "Ryunix" | "Delux" | "GravaStar" | "IPI" | "Rapoo" | "Fater" | "Cooler Master" | "AJAZZ" | "Scyrox";
name: string;
/** Optional LunaFury controls, populated only after successful device reads. */
lunafury?: import("../lamzu/lunafury.js").LunaFurySettings;
Expand Down
Loading
Loading