Skip to content

Retry device-index resolution when a direct-connect index has no sensor - #34

Open
snekxs wants to merge 1 commit into
mainfrom
fix/direct-connect-sensorless-index
Open

Retry device-index resolution when a direct-connect index has no sensor#34
snekxs wants to merge 1 commit into
mainfrom
fix/direct-connect-sensorless-index

Conversation

@snekxs

@snekxs snekxs commented Aug 24, 2026

Copy link
Copy Markdown
Member

Confirmed on real hardware: a PRO X Superlight reached through its own product id can answer HID++2.0 at DEVICE_INDEX_DIRECT (0xff) with no sensor behind it — a genuine admin/pass-through endpoint — while DEVICE_INDEX_RECEIVER (0x01), the very next candidate, is the mouse itself.

resolveDeviceIndex()'s direct-connect fast path latched onto the first HID++2.0-answering index unconditionally, without the DPI-feature check the receiver-attached path already does, so readStatus() threw NotAMouseError without ever trying the next candidate.

Fix: resolveDeviceIndex() accepts an optional excluded-indices set; readStatus() calls it again, excluding the sensorless index, when its own DPI check comes back empty. The direct-connect fast path itself is unchanged (still no probe on the very first attempt — existing test still passes).

Two new tests: the fallback finding the mouse on the second candidate, and the case where nothing has a sensor anywhere (still NotAMouseError, not the generic 'did not answer' error).

All 524 existing tests pass; tsc --noEmit is clean.

resolveDeviceIndex() trusted the first HID++2.0-answering index
unconditionally for a non-receiver product id, never checking for a
DPI/sensor feature the way the receiver-attached path already does.

Confirmed on real hardware (a PRO X Superlight reached through its own
product id): DEVICE_INDEX_DIRECT (0xff) can be a genuine admin/pass-through
endpoint that answers the root feature query with no sensor behind it,
while DEVICE_INDEX_RECEIVER (0x01) — the very next candidate — is the
mouse itself. The old code latched onto 0xff and readStatus() threw
NotAMouseError without ever trying 0x01.

resolveDeviceIndex() now accepts an optional excluded-indices set (and a
flag carrying forward that something already answered-without-a-sensor,
for an accurate final error message); readStatus() calls it a second time,
excluding the sensorless index, when its own DPI check comes back empty.
The direct-connect fast path (no probe on the very first attempt) is
unchanged and still covered by its existing test.

Two new tests cover the fallback (mouse found on the second candidate) and
the case where nothing has a sensor (still reports NotAMouseError, not the
generic 'did not answer' error, since something did answer).
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.

1 participant