Skip to content

fix(hidpp): tell another protocol's reports apart from malformed HID++ - #1373

Open
Chernicharo wants to merge 2 commits into
AprilNEA:masterfrom
Chernicharo:fix/fixture-foreign-reports
Open

fix(hidpp): tell another protocol's reports apart from malformed HID++#1373
Chernicharo wants to merge 2 commits into
AprilNEA:masterfrom
Chernicharo:fix/fixture-foreign-reports

Conversation

@Chernicharo

Copy link
Copy Markdown

Summary

Fixes #1349: openlogi fixture contribute step 2 can never succeed for a Unifying receiver on Linux, because the receiver's node also carries Logitech DJ reports (0x20/0x21) and every one of them was classified as a malformed HID++ report, which rejects the whole cassette.

The channel conflated two different facts: a report carrying a HID++ report ID whose framing is invalid, and a report belonging to another protocol that shares the node. Only the first is malformed HID++. The channel already drops both, so replay never needed the foreign ones.

Changes

  • openlogi-hidpp: add is_hidpp_report_id, and a ChannelObservation::ForeignIncomingReport variant. The read loop now reports a non-HID++ report ID as foreign traffic and keeps MalformedIncomingReport for HID++ IDs that fail parsing. A zero-length read stays malformed.
  • openlogi-hid: unassociated_rejection returns Option<CassetteRejectionReason> and yields None for foreign reports; the cassette builder skips those. Foreign reports never entered the cassette itself, so this changes no privacy or replay guarantee.

Testing

  • cargo test -p openlogi-hidpp / cargo test -p openlogi-hid — 212 and 40 passed. Full tier on Linux x86_64 as well: cargo clippy --workspace --all-targets -- -D warnings, cargo test --workspace --exclude openlogi-desktop --no-fail-fast (1404 passed), and the non-GUI rustdoc gate — all green. macOS/Windows cross-lints not run.
  • cargo clippy -p openlogi-hidpp -p openlogi-hid --all-targets -- -D warnings
  • cargo fmt --all -- --check
  • New coverage: is_hidpp_report_id rejects the DJ report IDs; a wire-captured DJ "device paired" notification no longer rejects a cassette, while the existing malformed-HID++ rejection test still passes.
  • Hardware: on an MX Ergo behind a Unifying receiver on Arch Linux (hid-logitech-dj bound), openlogi fixture contribute step 2 now records all eight cassettes and passes strict verification. The same command rejected every attempt (4/4) before this change.

Fixes #1349

A HID node can carry more than HID++: a Unifying receiver on Linux also
emits Logitech DJ reports (0x20/0x21) on the node HID++ uses. The read
loop classified every non-HID++ report as MalformedIncomingReport, so
the fixture recorder rejected each cassette recorded on such a receiver
and `fixture contribute` could never complete there.

Report a non-HID++ report ID as ForeignIncomingReport instead, keep
MalformedIncomingReport for HID++ report IDs that fail parsing, and let
the cassette builder ignore foreign traffic. Foreign reports never
entered a cassette, so replay and privacy guarantees are unchanged.

Fixes AprilNEA#1349
@greptile-apps

greptile-apps Bot commented Sep 12, 2026

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

The PR appears safe to merge; the prior test-coverage concern is fully addressed and no new actionable issue remains.

Summary

  • Adds explicit HID++ report-ID classification and a foreign-report observation variant.
  • Skips cassette rejection for foreign traffic that never enters replay evidence.
  • Strengthens regression coverage with a valid exchange and complete rejection-set assertions.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Raw incoming HID report] --> B{Report ID is HID++?}
    B -->|No| C[ForeignIncomingReport]
    C --> D[Drop from HID++ processing]
    D --> E[No cassette rejection]
    B -->|Yes| F{HID++ framing parses?}
    F -->|No| G[MalformedIncomingReport]
    G --> H[Reject cassette]
    F -->|Yes| I[Normal HID++ correlation and recording]
Loading

Reviews (2) · Last reviewed commit: "test(hid): prove foreign reports add no ..."

Comment thread crates/openlogi-hid/src/recording/cassette/tests.rs Outdated
The regression only asserted that MalformedIncomingReport was absent, so
misclassifying a DJ report as unmatched HID++ input would still have
passed. Record a committable exchange alongside the foreign report and
assert the whole rejection set instead.
@davidbudnick davidbudnick added type: bug Something is broken or behaves incorrectly area: hidpp HID++ protocol and device feature support platform: all Cross-platform issue labels Sep 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: hidpp HID++ protocol and device feature support platform: all Cross-platform issue type: bug Something is broken or behaves incorrectly

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fixture contribute: step 2 always fails on Unifying receivers on Linux (DJ reports rejected as malformed)

2 participants