fix(openlogi): stabilize bluetooth direct devices - #342
Conversation
Greptile SummaryThis PR stabilizes Bluetooth-direct Logitech device discovery and GUI state. The main changes are:
Confidence Score: 4/5These issues should be fixed before merging.
Files Needing Attention: crates/openlogi-hid/src/inventory/features.rs and crates/openlogi-gui/src/state/devices.rs
|
| Filename | Overview |
|---|---|
| crates/openlogi-core/src/device.rs | Adds a helper for detecting whether model info contains a real model ID. |
| crates/openlogi-hid/src/inventory/features.rs | Adds the direct feature probe path, but kind-only direct devices can still be rejected. |
| crates/openlogi-hid/src/inventory/probe.rs | Keeps cached direct devices alive on no-evidence refreshes. |
| crates/openlogi-gui/src/state/devices.rs | Adds direct placeholder handling, but identical direct devices can still lose offline cards. |
| CHANGELOG.md | Documents the Bluetooth-direct HID and GUI fixes. |
Reviews (2): Last reviewed commit: "fix(openlogi): stabilize bluetooth direc..." | Re-trigger Greptile
https://github.com//issues/336
|
d537bca to
2fd26eb
Compare
| "Root getFeature HiResWheel", | ||
| DIRECT_CAPABILITY_TIMEOUT, | ||
| ) | ||
| .await | ||
| { | ||
| ids.push(HiResWheelFeature::ID); | ||
| let feature = HiResWheelFeature::new(Arc::clone(channel), slot, info.index); |
There was a problem hiding this comment.
When a Bluetooth-direct mouse answers DeviceTypeAndName but the model, battery, and capability root reads time out, this code builds usable button and pointer capabilities from the kind fallback but still leaves direct_peripheral_evidence false. probe_direct then treats the device as non-peripheral. For a first-time or expired-cache device, that path returns Unkeyed, so the mouse never appears even though the probe learned it is a configurable pointer device.
| && record.display_name == identity.display_name | ||
| && record.kind == identity.kind | ||
| && matches!( | ||
| record.route, | ||
| Some(DeviceRoute::Direct { | ||
| vendor_id: live_vid, | ||
| product_id: live_pid, | ||
| }) if live_vid == vendor_id && live_pid == product_id | ||
| ) | ||
| }) |
There was a problem hiding this comment.
Identical devices still shadow
This suppression still matches only display name, kind, VID, and PID. Two identical Bluetooth-direct devices can share all of those fields. If one is online and the other is sleeping with a persisted direct:*:*:unit:* identity that has no model identity, this branch drops the sleeping device's only offline card even though it is a different physical device.


Filter non-identifying direct HID++ model info before it becomes a persistent device identity, and keep Bluetooth-direct offline placeholders on the HID++ self slot instead of slot 0.
Treat no-evidence direct refreshes for cached devices as transient misses so a slow or sleeping BLE device replays last-good inventory instead of being cleared.
Required macOS privacy grants for packaged installs:
Input Monitoring: OpenLogi GUI app bundle at /Applications/OpenLogi.app (binary: /Applications/OpenLogi.app/Contents/MacOS/openlogi-gui).
Input Monitoring: OpenLogi Agent helper bundle at /Applications/OpenLogi.app/Contents/Library/LoginItems/OpenLogiAgent.app (binary: /Applications/OpenLogi.app/Contents/Library/LoginItems/OpenLogiAgent.app/Contents/MacOS/openlogi-agent).
Accessibility: OpenLogi Agent helper bundle at /Applications/OpenLogi.app/Contents/Library/LoginItems/OpenLogiAgent.app (binary: /Applications/OpenLogi.app/Contents/Library/LoginItems/OpenLogiAgent.app/Contents/MacOS/openlogi-agent), because the agent owns the CGEventTap mouse hook.
Remove the temporary async-hid path patch/vendor tree and raw HID transport trace from the final change; the fix now stays inside OpenLogi's probe and GUI state logic.