How OpenLogi Implements Per-Device Scroll Inversion via HID++ 0x2121
OpenLogi toggles scroll-wheel direction per device by detecting the HID++ 0x2121 capability during enumeration and issuing SetFeature commands through the HID layer to set the inversion flag in volatile device memory.
OpenLogi, an open-source alternative to Logitech Options, enables users to invert scroll-wheel direction on individual Logitech mice through the HID++ protocol. This article examines how the Rust-based codebase discovers, stores, and persists the per-device scroll inversion setting using HID++ feature ID 0x2121.
Capability Discovery in the Device Registry
When a Logitech device connects, the device-registry probes the HID++ capabilities reported by the hardware. In crates/openlogi-device/src/inventory/features.rs at line 324, the code checks for the Capabilities::scroll_inversion bit corresponding to feature 0x2121. If the device reports this capability, the DeviceCapabilities struct records scroll_inversion = true, signaling that the hardware supports scroll-direction inversion.
The core abstraction openlogi_core::device::Device stores this flag as a boolean field scroll_inversion: bool at line 114 of crates/openlogi-core/src/device.rs. This centralizes device capability knowledge within the core domain model.
Core State and UI Exposure
The desktop GUI reads the capability flag via current_scroll_inversion_supported() defined in crates/openlogi-desktop/src/state/scroll.rs at line 25. This function queries the underlying Device state to determine whether the "Invert Scroll" toggle should be enabled in the user interface. If the device lacks the 0x2121 feature, the UI disables the toggle and displays the error message pointer.scroll_inversion_unsupported.
Writing the Scroll Inversion Setting to Hardware
HID API Layer
The public API entry point openlogi_hid::set_scroll_inversion in crates/openlogi-hid/src/lib.rs (line 37) accepts a device route and boolean flag, forwarding the request to the device-write module. This abstraction allows the GUI and automation scripts to toggle inversion without directly handling HID++ protocol details.
Device Write Implementation
Within the device layer, the write module constructs a HID++ SetFeature request targeting the 0x2121 feature. The function set_scroll_inversion_on sends this request through the HID++ channel to toggle the inversion flag on the target device. The implementation resides in the device-write subsystem (referenced in crates/openlogi-device/src/write modules), where the raw HID++ packet is assembled and transmitted.
Agent Orchestration
The agent core routes GUI changes to the physical hardware via openlogi_hid::set_scroll_inversion_on at line 381 of crates/openlogi-agent-core/src/hardware.rs. This ensures that user interactions in the desktop application propagate through the entire stack—from UI state to HID API to device-specific write commands—before reaching the mouse firmware.
Persistence Across Reconnections
Because the inversion setting lives only in volatile device memory, OpenLogi reapplies the saved value on each reconnection. The orchestrator monitors device availability and rewrites the stored inversion flag when a device becomes active, ensuring that user preferences survive sleep/wake cycles or USB reconnection events.
Implementation Example
Query device capabilities and toggle scroll inversion using the OpenLogi API:
// Query whether a device supports scroll inversion
let caps = device.capabilities();
if caps.scroll_inversion {
println!("Device can invert scroll direction");
}
// Invert scrolling for a specific route
use openlogi_hid::set_scroll_inversion;
let route = /* DeviceRoute obtained from inventory */;
set_scroll_inversion(&route, true).await?; // true → invert, false → normal
Summary
- Capability Detection: The device registry probes HID++ feature 0x2121 during enumeration at
inventory/features.rs:324, storing the result inDeviceCapabilities. - State Management: The core device model holds the
scroll_inversionflag atcore/device.rs:114, exposed to the UI viacurrent_scroll_inversion_supported(). - Hardware Control: The HID API (
hid/src/lib.rs:37) and agent core (agent-core/src/hardware.rs:381) coordinate to sendSetFeaturecommands that toggle the inversion bit in device memory. - Persistence: The orchestrator reapplies saved inversion settings on every device reconnection to maintain user preferences across sessions.
Frequently Asked Questions
What is HID++ feature 0x2121?
HID++ feature 0x2121 is the "Scroll Inversion" capability in Logitech's HID++ protocol. When a device reports this feature bit during capability discovery, it indicates that the firmware supports reversing scroll-wheel direction via software commands.
Does scroll inversion persist after unplugging the mouse?
No, the inversion setting resides in volatile device memory and resets when the mouse loses power. OpenLogi handles this by detecting reconnections through the orchestrator and automatically reapplying the saved inversion flag to restore the user's preferred scroll direction.
How does OpenLogi handle devices without scroll inversion support?
If the device registry does not detect the 0x2121 capability bit in inventory/features.rs, the core device model sets scroll_inversion = false. The desktop state (desktop/src/state/scroll.rs) then disables the "Invert Scroll" toggle and displays an unsupported error message to prevent invalid configuration attempts.
Can scroll inversion be toggled programmatically via the API?
Yes, developers can call openlogi_hid::set_scroll_inversion with a valid DeviceRoute and boolean value to programmatically control scroll direction. This function is the same entry point used by the GUI and is available to any Rust code linking against the openlogi_hid crate.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →