Skip to content

glorious: fix classic-line connection on a real Model O 2 Wired (settings still unsupported) - #104

Merged
snekxs merged 4 commits into
OpenMouse-Project:mainfrom
onyxhq-dev:fix/glorious-classic-report-id
Sep 16, 2026
Merged

snekxs merged 4 commits into
OpenMouse-Project:mainfrom
onyxhq-dev:fix/glorious-classic-report-id

Conversation

@onyxhq-dev

Copy link
Copy Markdown
Contributor

Fixes the connection failure for a real 0x320f:0x823a ("Model O 2 Wired Mouse") - it could not connect at all before this.

Connecting now works. Changing settings does not yet - that part needs more reverse-engineering than this PR does, see below.

Two bugs, found from user-submitted diagnostics:

  1. Connection failure. The driver assumed the config channel is always the unnumbered feature report (id 0), but this unit carries it as numbered report 7. isSupported()/the constructor now discover the real report id from the device's own collections at connect time instead of assuming.

  2. Every write then failed with "Failed to write the feature report." This unit's report 7 declares a 263-byte length, not the 64 bytes every other classic-line device (and the community tools this protocol was ported from) uses. A first attempt resized the payload to fit, which stopped the WebHID error - but a follow-up diagnostic showed the mouse just silently ignores it: no error, but DPI/polling rate never actually change. The 263-byte unit's real byte layout is unknown; guessing at it isn't safe.

So instead: DPI, polling rate, lift-off distance, RGB, and debounce all now refuse cleanly with a "not confirmed on this unit's 263-byte feature report yet" error, the same shape already used for the existing core2 generation gate, rather than silently no-op. vendors.ts's product table is annotated to flag this PID (and its two same-VID siblings) as unconfirmed rather than implying they share the 64-byte protocol.

Getting settings working needs a real USB capture of Glorious's own official software talking to this exact model - nothing we have reverse-engineers a 263-byte report.

@onyxhq-dev
onyxhq-dev force-pushed the fix/glorious-classic-report-id branch from 22640b3 to 48e9af5 Compare September 14, 2026 10:00
…ng 0

A real 0x320f:0x823a (Model O V2 Wired) carried its config channel as
numbered report 7, not the unnumbered report every other classic-family
device uses - isSupported() rejected it outright since the check was
hardcoded to report id 0.

Now discovered per device at connect time and used for every send/
receive call. WebHID takes the report id separately from the payload
bytes, so existing devices (report id 0) are unaffected.
Connecting to the real 0x320f:0x823a unit worked after the report-id fix,
but every write then failed with "Failed to write the feature report.":
its numbered report 7 declares a shorter byte length than the 64-byte
buffer every payload builder in glorious-classic/index.ts assumes, and
WebHID rejects a feature report whose length does not match the device's
own descriptor.

Same fix shape as the report-id discovery: read the declared length off
the same collection at connect time and resize (truncate or zero-pad)
every payload to fit before sending. The actual command bytes are always
well under the shortest length seen in practice, so truncating never
touches meaningful data.
…ad of guessing

A diagnostic showed the previous fix was wrong in a way that looked right:
resizing the driver's 64-byte payload to the real 0x320f:0x823a unit's
263-byte declared report stopped WebHID's write from erroring, but the
mouse silently ignores the zero-padded result - DPI and polling rate
diagnostics confirmed nothing on the mouse actually changes.

Every payload in glorious-classic/index.ts is only reverse-engineered
against the 64-byte case. Guessing a byte layout for 263 bytes and
padding to fit was worse than doing nothing: it looked successful (no
error, state cached as if applied) while doing nothing. Now any report
length other than the confirmed 64 refuses every write with a clear
'not confirmed' error, the same shape already used for the core2
generation, until a real capture of the device's own official software
gives an actual byte layout to build against.
Same VID (gloriousClassicIWired, 0x320f) as three product-table entries
that share the 'core1' generation label with every other 64-byte
classic-line device, despite a real 0x823a unit's feature report
declaring 263 bytes and doing nothing when sent core1's 64-byte
payloads. The label itself isn't what gates writes at runtime -
isConfirmedReportLength() in classic-hid.ts checks the live descriptor -
but leaving 'core1' undocumented here reads as confirmed when it never
was; only VID-proximity reasoning put it there originally.
@onyxhq-dev
onyxhq-dev force-pushed the fix/glorious-classic-report-id branch from 48e9af5 to 7274ac7 Compare September 15, 2026 09:08
@snekxs
snekxs merged commit 92c595d into OpenMouse-Project:main Sep 16, 2026
1 check passed
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