The device
|
USB id |
Firmware |
Path |
| ATK ZERO, wired |
0x373b:0x1154 |
mouse 3.0.3 |
direct |
| ATK ZERO, 8K receiver |
0x373b:0x1155 |
mouse 3.0.3, receiver 3.0.2 |
via receiver |
Sensor PAW3950 Ultra. Both report cid,mid = 1,1.
Why it is invisible today
SUPPORTED_HID_FILTERS asks ATK for { 0x373b, usagePage 0xff02, usage 2 }, and
AtkHidClient.isSupported requires the same collection. An ATK ZERO exposes no
0xff02 at all. Its collections, read from the device:
0xff00 / 0x0001 feature #3, 63 B
0xff01 / 0x0001 feature #4, 63 B
0xff05 / 0x0001 input #8 + output #8, 63 B <- the config channel
So the mouse never reaches the browser's device picker, and vendor id alone was
never enough to conclude coverage of this family.
The protocol
ATK's current configurator calls the family BITMOUSE. It is unrelated to the
16-byte EEPROM protocol in src/atk/ — 63-byte frames on report 0x08:
request [0] checksum = Σ bytes 1..62 & 0xff
[1] 0x72 [2] paramLen [3] cmdSn [4] target
[5] commandId [6] cmdLen [7..] payload
reply no checksum byte, so fields sit one earlier:
[0] 0x72 [1] status (0xff = error) [2] cmdSn [3] target
[4] commandId [5] payload length [6..] payload
A receiver answers its own commands on target 0 and relays mouse commands on
target 1.
Two firmware behaviours that bit me, both now pinned by tests:
- Replies are not zero-padded. Bytes past the reported length are the
previous exchange's leftovers, e.g. GetDeviceType answering
72 00 3a 00 1a 01 | 03 | ff ff 00 00 00 01 01 01 08 07 04 where only 03
is valid.
- The DPI table's count byte is the table size, not the enabled count. It
reads 8 on a mouse holding two configured stages; empty slots read 0 DPI while
keeping stale colour bytes.
Verified on hardware
Reads on both transports: version, cid/mid, device type, battery, charging
state, config block, DPI stage table.
Writes, each confirmed by reading back and then restored: polling rate
2000 → 1000 Hz, DPI 800 → 1600, debounce 4 → 8 ms, sleep 1800 → 600 s, motion
sync and ripple control on → off.
What I could not establish
- Lift-off distance. The config byte reads 0 on both transports, and the
vendor's own accessors overlap a 16-bit DPI value at +3 with an 8-bit lift-off
byte at +4. I left it unreported rather than guess.
- Angle snapping. A
SetSensorAngle command exists; not exercised.
GetChipId (71) and GetMouseOnlineStatus (35) both answer zero on
hardware that is plainly online.
cmdSn is a constant 0x3a in every reply captured; meaning unknown.
Evidence
Framing, command ids, field offsets and request lengths came from the vendor's
own WebHID configurator (ATK HUB v3.2.21, served publicly from hub.atk.pro),
and every value used was then confirmed against the device. No vendor code is
copied.
The mouseCidMid command (74) is the same identification route as the open
#44, approached from this protocol's side.
Proposed shape, before I open a PR
A codec under src/bitmouse/ (framing, command table, config and DPI decoders,
sensor DPI ranges, product table), a driver at
src/drivers/atk/bitmouse-hid.ts, registry entry, and PID-scoped filters. Only
the two verified products are claimed; the same protocol drives much of the
current ATK/VXE range, but each model wants its own hardware check.
Branch, if it is easier to read than prose:
https://github.com/itsnttt/mouse-protocol/tree/bitmouse-atk-zero
npm run check is clean there (843 tests), and openmouse builds and passes
its 112 tests against the local package. registry.test.ts needed 0xff05
added to USAGE_PAGES, exactly as its own assertion message instructs.
Two things I would rather agree before opening the PR:
- Where the codec belongs. I put it at
src/bitmouse/ on the reading that
this is a shared OEM family like src/compx/, not an ATK-only thing. If you
would rather it live under src/atk/ as a second module, that is an easy
move.
- How far to claim. I scoped the product table to the two ids I own. If you
would prefer the filter to be vendor-wide on 0xff05 and let the driver
sort it out at runtime, say so — I deliberately avoided claiming models I
cannot test.
The device
0x373b:0x11540x373b:0x1155Sensor PAW3950 Ultra. Both report
cid,mid = 1,1.Why it is invisible today
SUPPORTED_HID_FILTERSasks ATK for{ 0x373b, usagePage 0xff02, usage 2 }, andAtkHidClient.isSupportedrequires the same collection. An ATK ZERO exposes no0xff02at all. Its collections, read from the device:So the mouse never reaches the browser's device picker, and vendor id alone was
never enough to conclude coverage of this family.
The protocol
ATK's current configurator calls the family BITMOUSE. It is unrelated to the
16-byte EEPROM protocol in
src/atk/— 63-byte frames on report0x08:A receiver answers its own commands on
target 0and relays mouse commands ontarget 1.Two firmware behaviours that bit me, both now pinned by tests:
previous exchange's leftovers, e.g.
GetDeviceTypeanswering72 00 3a 00 1a 01 | 03 | ff ff 00 00 00 01 01 01 08 07 04where only03is valid.
reads 8 on a mouse holding two configured stages; empty slots read 0 DPI while
keeping stale colour bytes.
Verified on hardware
Reads on both transports: version, cid/mid, device type, battery, charging
state, config block, DPI stage table.
Writes, each confirmed by reading back and then restored: polling rate
2000 → 1000 Hz, DPI 800 → 1600, debounce 4 → 8 ms, sleep 1800 → 600 s, motion
sync and ripple control on → off.
What I could not establish
vendor's own accessors overlap a 16-bit DPI value at +3 with an 8-bit lift-off
byte at +4. I left it unreported rather than guess.
SetSensorAnglecommand exists; not exercised.GetChipId(71) andGetMouseOnlineStatus(35) both answer zero onhardware that is plainly online.
cmdSnis a constant0x3ain every reply captured; meaning unknown.Evidence
Framing, command ids, field offsets and request lengths came from the vendor's
own WebHID configurator (ATK HUB v3.2.21, served publicly from
hub.atk.pro),and every value used was then confirmed against the device. No vendor code is
copied.
The
mouseCidMidcommand (74) is the same identification route as the open#44, approached from this protocol's side.
Proposed shape, before I open a PR
A codec under
src/bitmouse/(framing, command table, config and DPI decoders,sensor DPI ranges, product table), a driver at
src/drivers/atk/bitmouse-hid.ts, registry entry, and PID-scoped filters. Onlythe two verified products are claimed; the same protocol drives much of the
current ATK/VXE range, but each model wants its own hardware check.
Branch, if it is easier to read than prose:
https://github.com/itsnttt/mouse-protocol/tree/bitmouse-atk-zero
npm run checkis clean there (843 tests), andopenmousebuilds and passesits 112 tests against the local package.
registry.test.tsneeded0xff05added to
USAGE_PAGES, exactly as its own assertion message instructs.Two things I would rather agree before opening the PR:
src/bitmouse/on the reading thatthis is a shared OEM family like
src/compx/, not an ATK-only thing. If youwould rather it live under
src/atk/as a second module, that is an easymove.
would prefer the filter to be vendor-wide on
0xff05and let the driversort it out at runtime, say so — I deliberately avoided claiming models I
cannot test.