-
Notifications
You must be signed in to change notification settings - Fork 0
ATK FIERCE X Protocol Notes
This page tracks the current reverse-engineering state for the ATK FIERCE X using ATK V HUB Web at https://hub.atk.pro/.
These notes are based on WebHID captures from the local sniffer in tools/webhid-sniffer-extension.
| Field | Value |
|---|---|
| Product string | ATK Mouse 8K Dongle |
| Vendor ID | 0x373B |
| Product ID | 0x101B |
| WebHID report ID | 8 |
| Frame size | 16 bytes |
| Config usage page | 0xFF02 |
| Config usage | 0x0002 |
ATK uses the same 16-byte payload shape and global checksum rule as the IPI FLY PRO:
byte[0] = (0x4D - sum(byte[2..=15])) & 0xFFMost ATK settings are not IPI-compatible commands. They are block writes where values are stored as value/check pairs:
check = 0x55 - valueThe active DPI stage is stored in the 0x00 block. Bytes 9/10 carry the stage index and check byte.
stage 1: 07 00 00 00 08 20 35 04 51 00 55 00 00 00 00 3f
stage 2: 07 00 00 00 08 20 35 04 51 01 54 00 00 00 00 3f
stage 3: 07 00 00 00 08 20 35 04 51 02 53 00 00 00 00 3f
stage 4: 07 00 00 00 08 20 35 04 51 03 52 00 00 00 00 3fPolling is stored in the same 0x00 block. Bytes 5/6 carry the polling value and check byte.
125 Hz -> 08 4d
250 Hz -> 04 51
500 Hz -> 02 53
1000 Hz -> 01 54
2000 Hz -> 10 45
4000 Hz -> 20 35
8000 Hz -> 40 15Captured with active stage 4:
125 Hz: 07 00 00 00 08 08 4d 04 51 03 52 00 00 00 00 3f
250 Hz: 07 00 00 00 08 04 51 04 51 03 52 00 00 00 00 3f
500 Hz: 07 00 00 00 08 02 53 04 51 03 52 00 00 00 00 3f
1000 Hz: 07 00 00 00 08 01 54 04 51 03 52 00 00 00 00 3f
2000 Hz: 07 00 00 00 08 10 45 04 51 03 52 00 00 00 00 3f
4000 Hz: 07 00 00 00 08 20 35 04 51 03 52 00 00 00 00 3f
8000 Hz: 07 00 00 00 08 40 15 04 51 03 52 00 00 00 00 3fChanging DPI writes four 8-byte blocks. A DPI value group appears to use:
[raw, raw, flags_or_hi, group_check]
group_check = (0x255 - raw - raw - flags_or_hi) & 0xFFLikely encoding:
dpi = (raw + 1) * 10
raw = (dpi / 10) - 1Examples:
0x4f -> 800 DPI
0x59 -> 900 DPI
0x9f -> 1600 DPIMore fixed-value captures are still needed before implementing DPI writes.
off: 07 00 00 4c 08 00 00 80 d5 03 52 00 55 00 00 f3
solid: 07 00 00 4c 08 01 54 80 d5 03 52 01 54 00 00 9e
breathing: 07 00 00 4c 08 02 53 80 d5 03 52 01 54 00 00 9eThe same 0x4C block also carries LED brightness and speed:
brightness min: 07 00 00 4c 08 01 54 10 45 03 52 01 54 00 00 9e
brightness mid: 07 00 00 4c 08 01 54 80 d5 03 52 01 54 00 00 9e
brightness max: 07 00 00 4c 08 01 54 ff 56 03 52 01 54 00 00 9e
speed slow: 07 00 00 4c 08 02 53 ff 56 01 54 01 54 00 00 9e
speed mid: 07 00 00 4c 08 02 53 ff 56 03 52 01 54 00 00 9eField layout:
byte[5] mode: 0=off, 1=solid, 2=breathing
byte[7] brightness raw: 0x10=min, 0x80=middle, 0xff=max
byte[9] speed raw: 0x01=slow, 0x03=middle
byte[11] enable: 0=off, 1=onDebounce is stored in the 0xA9 block. Bytes 5/6 are the debounce value in milliseconds and its check byte.
0 ms -> 00 55
1 ms -> 01 54
2 ms -> 02 53
4 ms -> 04 51
8 ms -> 08 4d
15 ms -> 0f 46
20 ms -> 14 41Sleep is also stored in the 0xA9 block. Bytes 9/10 are the raw timer and check byte.
raw = seconds / 10Confirmed:
30 s -> 03 52
1 min -> 06 4f
2 min -> 0c 49
3 min -> 12 43
5 min -> 1e 37
20 min -> 78 dd
25 min -> 96 bf
30 min -> b4 a1Changing sleep also emits a 0xB5 write with the same timer raw value. Treat this as part of the sleep write sequence until proven otherwise.
All three are in the 0xA9 block and use 00 55 for off, 01 54 for on.
byte[7..8] Motion Sync
byte[11..12] Linear Correction
byte[13..14] Ripple CorrectionExamples:
Motion Sync on: 07 00 00 a9 0a 08 4d 01 54 03 52 00 55 00 55 ea
Linear on: 07 00 00 a9 0a 08 4d 00 55 03 52 01 54 00 55 ea
Ripple on: 07 00 00 a9 0a 08 4d 00 55 03 52 00 55 01 54 eaon: 16 00 00 00 0a 01 00 00 00 00 00 00 00 00 00 2c
off: 16 00 00 00 0a 00 00 00 00 00 00 00 00 00 00 2dThis is separate from DPI preset colors. DPI colors are assigned per DPI preset and still need their own captures.
off: 18 00 00 00 0a 00 ff 00 08 05 09 01 00 00 00 15
color stream: 18 00 00 00 0a 01 ff 00 08 05 09 01 00 00 00 14
single-color breathing: 18 00 00 00 0a 02 ff 00 08 05 09 01 00 00 00 13
single-color solid: 18 00 00 00 0a 03 ff 00 08 05 09 01 00 00 00 12
neon: 18 00 00 00 0a 04 ff 00 08 05 09 01 00 00 00 11
mixed-color breathing: 18 00 00 00 0a 05 ff 00 08 05 09 01 00 00 00 10
colorful solid: 18 00 00 00 0a 06 ff 00 08 05 09 01 00 00 00 0fCaptured brightness, speed and timer fields for single-color breathing
(mode = 0x02):
brightness min: 18 00 00 00 0a 02 ff 00 08 05 00 01 00 00 00 1c
brightness mid: 18 00 00 00 0a 02 ff 00 08 05 05 01 00 00 00 17
brightness max: 18 00 00 00 0a 02 ff 00 08 05 09 01 00 00 00 13
speed slowest: 18 00 00 00 0a 02 ff 00 08 00 09 01 00 00 00 18
speed mid: 18 00 00 00 0a 02 ff 00 08 05 09 01 00 00 00 13
speed max: 18 00 00 00 0a 02 ff 00 08 09 09 01 00 00 00 0f
timer 1 min: 18 00 00 00 0a 02 ff 00 08 09 09 01 00 00 00 0f
timer 5 min: 18 00 00 00 0a 02 ff 00 08 09 09 05 00 00 00 0b
timer 10 min: 18 00 00 00 0a 02 ff 00 08 09 09 0a 00 00 00 06Observed field layout:
byte[5] mode
byte[6] red
byte[7] green
byte[8] blue
byte[9] speed, range 0x00..0x09
byte[10] brightness, range 0x00..0x09
byte[11] timer in minutesCaptured color picker examples:
18 00 00 00 0a 02 12 ff 05 05 09 01 00 00 00 04
18 00 00 00 0a 02 ff 00 0d 05 09 01 00 00 00 0eThis indicates direct RGB bytes:
byte[6..8] = red, green, blueChanging the receiver LED color from red to green and back caused ATK V HUB to
write a color table at addresses 0x2C, 0x34, 0x3C and 0x44. Each block
contains two RGB groups.
Group format:
[red, green, blue, check]
check = (0x255 - red - green - blue) & 0xFFExamples:
red: ff 00 00 56
green: 00 ff 00 56
blue: 00 00 ff 56
magenta: ff 00 ff 57Observed block writes:
07 00 00 2c 08 ff 00 00 56 00 ff 00 56 00 00 68
07 00 00 34 08 00 00 ff 56 04 00 ff 52 00 00 60
07 00 00 3c 08 ff 00 ff 57 ff 00 ff 57 00 00 58
07 00 00 44 08 ff 00 ff 57 ff 00 ff 57 00 00 50Likely slot layout:
0x2C -> color slots 1 and 2
0x34 -> color slots 3 and 4
0x3C -> color slots 5 and 6
0x44 -> color slots 7 and 8Clean one-slot captures are still needed because dragging the color picker emits intermediate colors.
Captured from increase/decrease controls. Byte 5 is the raw value and byte 6 is
0x55 - value.
07 00 00 0a 02 01 54 00 00 00 00 00 00 00 00 e5
07 00 00 0a 02 02 53 00 00 00 00 00 00 00 00 e5
07 00 00 0a 02 03 52 00 00 00 00 00 00 00 00 e5
07 00 00 0a 02 04 51 00 00 00 00 00 00 00 00 e5
07 00 00 0a 02 05 50 00 00 00 00 00 00 00 00 e5
07 00 00 0a 02 06 4f 00 00 00 00 00 00 00 00 e5
07 00 00 0a 02 07 4e 00 00 00 00 00 00 00 00 e5
07 00 00 0a 02 08 4d 00 00 00 00 00 00 00 00 e5
07 00 00 0a 02 09 4c 00 00 00 00 00 00 00 00 e5
07 00 00 0a 02 0a 4b 00 00 00 00 00 00 00 00 e5
07 00 00 0a 02 0b 4a 00 00 00 00 00 00 00 00 e5This is likely the ATK LOD/numeric sensor height control, but the exact UI label/unit still needs confirmation.
- Confirm fixed DPI values for
800,900,1600and1800. - Confirm the exact UI label/unit for the
0x0Anumeric setting. - Capture DPI preset / receiver LED color slots one slot at a time.
- Identify firmware/version reads.
- Capture one simple button remap.