Skip to content

fix(cli): diag selects a device that exposes the feature under test#150

Open
recchia wants to merge 2 commits into
AprilNEA:masterfrom
recchia:fix/diag-device-picker
Open

fix(cli): diag selects a device that exposes the feature under test#150
recchia wants to merge 2 commits into
AprilNEA:masterfrom
recchia:fix/diag-device-picker

Conversation

@recchia
Copy link
Copy Markdown

@recchia recchia commented Jun 5, 2026

Closes #148 (Finding 2). Builds on the verification in #148.

first_online_device() returned the first online paired device regardless of
kind. With a keyboard + mouse paired over Bluetooth-direct (each enumerates as
its own inventory), a mouse-only diag picks the keyboard and fails:

device: MX Keys (direct 046d:b35b)
Error: device does not expose HID++ feature 0x2201

This replaces it with select_device(query, required_features):

  • diag dpi / diag smartshift now prefer an online device whose HID++ feature
    table advertises the feature under test (0x2201, and 0x2110/0x2111),
    so a paired keyboard is skipped automatically.
  • Adds a --device <name> override (case-insensitive substring match).
  • On no match, the error lists the online devices instead of a generic message.

Non-breaking: existing invocations work unchanged; diag features and
diag lighting are untouched. Verified on Ubuntu 26.04 / Wayland — with both
devices online, diag dpi now targets the MX Master 3S without powering off the
keyboard, and --device master selects it explicitly.

Replaces the single-device picker with one that enumerates all online
devices and selects by optional --device name filter or required HID++
feature presence, avoiding wrong-device errors when a mouse and keyboard
are both paired over Bluetooth-direct.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Jun 5, 2026

Greptile Summary

This PR replaces the single-call first_online_device() helper with online_devices() + select_device(), which probes each device's HID++ feature table so mouse-only diagnostics (dpi, smartshift) automatically skip a paired keyboard that lacks the required feature. A --device <name> substring flag is added to dpi, smartshift, and lighting to allow explicit override.

  • select_device in mod.rs handles three selection tiers: explicit name query, feature-table probe, then first-online fallback. Probe failures are now surfaced via tracing::warn rather than silently swallowed.
  • lighting.rs gets its own --device inline filter (direct-USB path, no feature probe needed).
  • Error messages now list all online devices when selection fails, replacing the generic "no online device" text.

Confidence Score: 5/5

Safe to merge — the new device-selection logic handles all three tiers (explicit query, feature probe, first-online fallback) correctly, probe errors are now logged rather than silently swallowed, and the changes are additive to the CLI surface.

The refactor is well-scoped: online_devices + select_device replace a simple helper cleanly, the feature-probe loop degrades gracefully on transient errors, and the --device flag is wired up consistently across the three affected subcommands. No data is mutated or persisted, so the worst-case outcome of any edge case is a clear error message rather than silent corruption.

No files require special attention.

Important Files Changed

Filename Overview
crates/openlogi-cli/src/cmd/diag/mod.rs Core selection logic rewritten: online_devices() enumerates all online paired devices; select_device() implements query → feature-probe → first-online tiers. Feature-probe errors are now logged via tracing::warn. Logic is sound.
crates/openlogi-cli/src/cmd/diag/dpi.rs Adds --device arg; switches to select_device(args.device.as_deref(), &[0x2201]). Straightforward and correct.
crates/openlogi-cli/src/cmd/diag/smartshift.rs Adds --device arg; switches to select_device(args.device.as_deref(), &[0x2110, 0x2111]). Correctly probes for both SmartShift feature variants.
crates/openlogi-cli/src/cmd/diag/lighting.rs Adds --device filter inline (direct-USB path, no feature probe needed). Name filter applied before route construction; error message stays simple when a query doesn't match.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["select_device(query, required_features)"] --> B["online_devices()"]
    B --> C{query set?}
    C -- yes --> D["Find first device whose name contains query (case-insensitive)"]
    D -- found --> E["Return (route, name)"]
    D -- not found --> F["no_match_err: list online devices + suggest --device"]
    C -- no --> G{required_features non-empty?}
    G -- yes --> H["For each device: dump_features(route)"]
    H -- "Ok(entries): any feature matches" --> E
    H -- "Ok(entries): no match" --> I["Try next device"]
    H -- "Err(e)" --> J["tracing::warn! + try next device"]
    I --> K{More devices?}
    J --> K
    K -- yes --> H
    K -- no / G=no --> L["devices.into_iter().next()"]
    L -- Some --> E
    L -- None --> M["no_match_err: no online device found"]
Loading

Reviews (2): Last reviewed commit: "fix(cli): address greptile review on sel..." | Re-trigger Greptile

Comment thread crates/openlogi-cli/src/cmd/diag/mod.rs
Comment thread crates/openlogi-cli/src/cmd/diag/mod.rs
- Log a tracing::warn when dump_features fails so silent fallthrough to
  the wrong device is visible in the output.
- Add --device <NAME> to `diag lighting` for parity with dpi/smartshift;
  features is intentionally left without it (it already dumps all devices).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.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.

[Bug] Linux: udev rule misses Bluetooth-direct + diag picks wrong device (Phase 0 HID verification)

1 participant