Skip to content

fix(assets): resolve assets by displayName when no PID matches (MX Master 3S over BTLE)#26

Closed
jcbrizu wants to merge 3 commits into
AprilNEA:masterfrom
jcbrizu:fix/btle-codename-asset-match
Closed

fix(assets): resolve assets by displayName when no PID matches (MX Master 3S over BTLE)#26
jcbrizu wants to merge 3 commits into
AprilNEA:masterfrom
jcbrizu:fix/btle-codename-asset-match

Conversation

@jcbrizu
Copy link
Copy Markdown
Contributor

@jcbrizu jcbrizu commented Jun 1, 2026

Problem

On an MX Master 3S connected through a Logi Bolt receiver, OpenLogi shows no device image — the GUI falls back to the synthetic silhouette and the asset depot is never downloaded (sync: no matching depots for connected devices).

Root cause: over BTLE the device's HID++ DeviceInformation (feature 0x0003) reports model_ids = [0xb034], extended_model_id = 1, i.e. config_key = "1b034". The asset registry, however, keys the MX Master 3S as 2b043 (a different transport's PID). resolve_in_index only matches by PID — strict {ext}{pid} and bare-PID suffix — and the device never reports b043 under any transport, so nothing matches.

Observed with openlogi list on hardware:

slot 2 ● MX Master 3S (mouse, wpid=b034)
        model_ids=[b034,0000,0000] ext=01 transports=btle

Fix

Add a final resolution step that bridges the firmware codename to the registry displayName (exact, case-insensitive). "MX Master 3S" lines up even when no PID does. This generalises to any BTLE-connected device whose live PID is absent from the registry.

The codename is threaded through resolve_in_index, AssetResolver::resolve, and the asset sync path (collect_models now carries (DeviceModelInfo, Option<String>)). PID matching still takes precedence; the name match is a last resort, so existing devices are unaffected.

Verification

  • cargo test -p openlogi-assets -p openlogi-gui — green, including new tests for Index::find_by_display_name and for the codename fallback in resolve_in_index (a BTLE 3S model misses by PID, resolves by codename).
  • On hardware (MX Master 3S / Bolt / macOS 26): the log now shows asset matched via codename↔displayName fallback depot="mx_master_3s", the mx_master_3s depot downloads, and the mouse image renders.

Likely also helps the missing-image symptom reported in #19 / #25.

The asset registry keys the MX Master 3S as `2b043`, but over a BTLE
link the device reports model id `b034` (ext 1) via HID++ feature 0x0003.
Neither the strict `{ext}{pid}` match nor the bare-PID suffix match finds
`2b043`, so the depot never resolves — no device image, no hotspots, just
the synthetic silhouette.

Add a final resolution step that bridges the firmware codename to the
registry `displayName` (exact, case-insensitive): "MX Master 3S" still
lines up when no PID does. This generalises to other BTLE-connected
devices whose live PID is absent from the registry.

The codename is threaded through `resolve_in_index`, `AssetResolver::resolve`
and the asset sync path. Verified on hardware: the `mx_master_3s` depot now
downloads and the mouse image renders.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copy link
Copy Markdown

@pullfrog pullfrog Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — adds a codename ↔ displayName last-resort tier to the asset resolver so an MX Master 3S on BTLE (and similar devices whose live PID isn't in the registry under any transport) still picks up its depot.

  • Add Index::find_by_display_name — exact, case-insensitive lookup over the registry's displayName. Unit tests cover both case-insensitivity and "exact, not substring" (so MX Master 3 cannot bleed into the MX Master 3S depot).
  • Thread codename through AssetResolver::resolve and resolve_in_index — match order documented in the rustdoc as force → strict PID → suffix PID → codename. New module tests demonstrate the bug (PID-only misses BTLE 3S) and the fix (codename bridges to the mx_master_3s depot).
  • Propagate the codename through the sync pathsync::sync now takes &[(DeviceModelInfo, Option<String>)], collect_models pairs model_info with paired.codename, and the GUI render call site passes paired.codename.as_deref() to cache.resolve.

PID matching still takes precedence, the name match runs only after both PID tiers miss, and the codename comes from firmware (Bolt receiver) or a hard-coded synthetic lookup — never from user input — so the new tier doesn't widen the matching surface in a risky way. The fallback chain inside load_files (variant → side_core.pngfront_core.png) already handles the case where a codename-matched depot's manifest.json doesn't have an entry for the device's reported extended_model_id, so a depot hit still renders something.

Pullfrog  | View workflow run | Using Claude Opus𝕏

AprilNEA
AprilNEA previously approved these changes Jun 1, 2026
The master merge brought in DeviceModelInfo::serial_number (added when
DeviceInformation gained the optional serial-number function), but the
btle_3s_model test helper still constructed the struct without it, so the
merged tree failed to compile. Add the missing serial_number: None.
@AprilNEA AprilNEA self-requested a review June 1, 2026 16:10
@AprilNEA
Copy link
Copy Markdown
Owner

AprilNEA commented Jun 1, 2026

Rebased onto master (dropping the merge commit) and landed directly:

  • 7505fa5 — your fix, authored by you
  • f64f40c — a one-line serial_number: None follow-up the btle_3s_model test helper needed after master added that field to DeviceModelInfo (otherwise the merged tree didn't compile)

Thanks @jcbrizu! Closing since the change is now on master.

@AprilNEA AprilNEA closed this Jun 1, 2026
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