Skip to content

atk: add wired VXE R1 SE+ support - #53

Open
logm1lo wants to merge 4 commits into
OpenMouse-Project:mainfrom
logm1lo:feat/vxe-r1-se-plus-wired
Open

atk: add wired VXE R1 SE+ support#53
logm1lo wants to merge 4 commits into
OpenMouse-Project:mainfrom
logm1lo:feat/vxe-r1-se-plus-wired

Conversation

@logm1lo

@logm1lo logm1lo commented Sep 5, 2026

Copy link
Copy Markdown

Summary

  • carry forward the sensor-aware ATK identity and PAW3395 work from atk: decode PAW3395 DPI correctly and identify VXE mice by CID/MID #44, with Saketh's original commit retained in this branch history
  • add the PAW3395SE lookup codec and verified CID/MID 2,32 product entry for the VXE R1 SE+
  • claim the wired 0x3554:0xf58f WebHID transport without overlapping the Pulsar fallback
  • preserve current R1 live-setting behavior for polling, LOD, debounce, and angle snapping
  • fail closed before DPI reads/writes when a shared R1 transport does not answer CID/MID
  • decode battery fields only when present in the declared payload and reject invalid angle checksum pairs
  • add a hardware-derived R1 live-write settle so staged multi-setting saves do not overrun the firmware

This supersedes #44 because that branch conflicts with current main and cannot be updated by my account. The original contribution is retained as commit 3152e56 and Saketh is credited as co-author on the follow-up implementation commit.

Hardware verification

Verified on a wired VXE R1 SE+ (0x3554:0xf58f, firmware 3.15, CID/MID 2,32, PAW3395SE):

  • native driver and Chromium WebHID both identify VXE R1 SE+ and read 800 DPI / 1,000 Hz
  • DPI writes/readback pass at 200, 10,000, 10,100, and 18,000 DPI, covering the high-DPI mode transition
  • OpenMouse staged-save UI changed 800 -> 850 -> 800 DPI successfully
  • Motion Sync, ripple control, and sleep timeout changes passed device readback and were restored
  • polling was acknowledged and restored
  • LOD and angle commands completed and were restored; the live row is fire-and-forget and has no reliable independent readback
  • all original mouse settings were restored after testing

Receiver behavior and debounce writes remain explicitly unverified for this SE+ unit.

Validation

  • rebased through current main (c1a4afe)
  • npm run check: 839 tests passed, TypeScript build and package dry-run passed
  • OpenMouse build and 113 tests passed against this package locally
  • git diff --check passed

SakethKanchi and others added 3 commits September 4, 2026 15:21
The ATK driver applied the A9's PAW3950Ultra DPI encoding to every device
behind vendor id 0x373b. ATK HUB Web 3.2.21 branches that decoder per
sensor: PAW3950/PAW3950DM/PAW3395/PAW3395Ultra pack a plain 10-bit count
of 50-DPI steps instead. A PAW3395 stage read with the A9 encoding is a
fifth of the real value.

A receiver's product id cannot say which sensor a mouse has: 0x373b:0x1085
is a generic "Wireless mouse 1k dongle" reused across models, and the R1
alone ships with PAW3311, PAW3395, PAW3395SE, PAW3395Ultra, PAW3950Ultra
and CORE26K. So identify the mouse the way the vendor's own HUB does, with
GetMouseCIDMID (command 0x10), and look the pair up in a catalog that
carries the sensor.

- add per-sensor profiles and the step-50 codec to src/atk
- add src/drivers/atk/products.ts, keyed "<cid>,<mid>"
- pick the DPI encoding, ceiling and DPI ladder from the sensor, for reads
  and writes alike; an unidentified mouse keeps the A9 behaviour, matching
  the HUB's own fallback
- report VXE as its own brand via deviceBrand(), as Lamzu/CRDRAKO already do
- claim VXE's wired transport (0x3554:0xf58f, "Compx VXE R1"), which speaks
  the same 0xff02/report-0x08 channel. Product-id gated: 0x3554 is shared
  with the VGN Dragonfly F2, so the id also joins the Pulsar fallback's
  CLAIMED_VGN_PRODUCT_IDS
- decode the rest of GetBatteryLevel: the reply carries a charge flag and a
  cell voltage next to the percentage, so report batteryState and
  batteryVoltageMv instead of a hardcoded "Unknown"
- treat an unprogrammed angle register as unsupported. It reads 0xff and
  fails the (value, 0x55-value) pair, but decoded as -1 degrees
- retry identification instead of caching a timeout, so a mouse that was
  asleep is not left misnamed and mis-decoded for the session

Sensors whose DPI mapping is a lookup table (PAW3395SE, PAW3315, PAW3311,
PAW3320) are deliberately not implemented; those tables are not captured
here and a guessed step would misreport DPI silently.

Verified on a VXE R1 (CID/MID 2,12, PAW3395, firmware Mouse 3.13) over both
transports: DPI now reads 1600 rather than 320, ceiling 30000 rather than
42000, and the mouse names itself "VXE R1". Battery was captured across a
charge cycle: flag 0 with a steady voltage on battery, flag 1 with the
voltage climbing on the cable. Writes were not exercised.
See docs/atk-testing.md.
Co-authored-by: sakethkanchi <sakethkanchi3@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants