Skip to content

fix(openlogi): stabilize bluetooth direct devices#342

Open
toby1991 wants to merge 1 commit into
AprilNEA:masterfrom
toby1991:codex/stabilize-bluetooth-direct-devices
Open

fix(openlogi): stabilize bluetooth direct devices#342
toby1991 wants to merge 1 commit into
AprilNEA:masterfrom
toby1991:codex/stabilize-bluetooth-direct-devices

Conversation

@toby1991

@toby1991 toby1991 commented Jul 1, 2026

Copy link
Copy Markdown

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.

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.
@greptile-apps

greptile-apps Bot commented Jul 1, 2026

Copy link
Copy Markdown

Greptile Summary

This PR stabilizes Bluetooth-direct Logitech device discovery and GUI state. The main changes are:

  • Timeout-bound optional HID++ reads during direct probing.
  • Filtering of non-identifying direct model info before persistence.
  • Cache replay for transient no-evidence direct refreshes.
  • Slot 0xff offline placeholders for Bluetooth-direct devices.
  • Suppression of stale direct unit:* GUI cards.

Confidence Score: 4/5

The direct self-slot classification path needs a fix before merging.

  • A kind-only Bluetooth-direct device can be rejected even after usable fallback capabilities are computed.
  • Identical direct devices can hide each other's offline placeholders in the GUI.
  • The import and helper signature changes appear consistent with the inspected crate surface.

crates/openlogi-hid/src/inventory/probe.rs and crates/openlogi-gui/src/state/devices.rs

Important Files Changed

Filename Overview
crates/openlogi-core/src/device.rs Adds DeviceModelInfo::has_model_identity() to distinguish real model IDs from empty direct HID++ payloads.
crates/openlogi-gui/src/state.rs Skips persistence for online direct records that lack model identity or a per-unit identifier.
crates/openlogi-gui/src/state/devices.rs Adds stale direct identity suppression and uses slot 0xff for direct offline placeholders.
crates/openlogi-hid/src/inventory/features.rs Adds bounded optional reads and a direct root-probe path with measured direct peripheral evidence.
crates/openlogi-hid/src/inventory/probe.rs Uses direct peripheral evidence for direct probe acceptance and preserves cached devices on transient no-evidence refreshes.

Fix All in Codex Fix All in Claude Code

Reviews (1): Last reviewed commit: "fix(openlogi): stabilize bluetooth direc..." | Re-trigger Greptile

let walk_succeeded = capabilities.is_some();
let caps = capabilities.unwrap_or_default();
let is_peripheral = probe.battery.is_some() || caps.buttons || caps.pointer || caps.lighting;
let is_peripheral = probe.direct_peripheral_evidence;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Kind-Only Direct Devices Disappear

When a Bluetooth-direct mouse answers DeviceTypeAndName but the battery, model, and capability root probes time out, probe_direct_features still builds kind-presumed button and pointer capabilities, but direct_peripheral_evidence stays false. This gate then treats the usable self slot as non-peripheral, so a first probe is rejected as Unkeyed and a cached device disappears after the miss grace instead of staying in the GUI.

Fix in Codex Fix in Claude Code

Comment on lines +190 to +193
record.online
&& record.display_name == identity.display_name
&& record.kind == identity.kind
&& matches!(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Identical Devices Shadow Placeholders

This match suppresses any unit-keyed, non-identifying direct identity when any live direct record has the same display name, kind, VID, and PID. Two identical Logitech devices can share all of those fields, so if one is online and the other is asleep, the sleeping device's only offline placeholder is dropped from the carousel until it probes live again.

Fix in Codex Fix in Claude Code

@toby1991

toby1991 commented Jul 1, 2026

Copy link
Copy Markdown
Author
image image https://github.com//issues/336

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