How to Configure SmartShift with OpenLogi for Logitech Devices: A Complete Guide
OpenLogi configures Logitech SmartShift (free-spin/ratchet wheel modes) through a three-layer architecture that maps TOML configuration values to HID++ protocol commands via Rust structs in openlogi-core/src/hid/smartshift.rs and IPC RPC calls.
OpenLogi is an open-source user-space driver for Logitech HID++ devices that exposes the SmartShift feature—Logitech's proprietary wheel-ratchet toggle mechanism—through a clean configuration interface. Understanding how to configure SmartShift with OpenLogi for Logitech devices requires familiarity with its layered architecture spanning the HID++ driver, core abstraction module, and IPC transport layer.
Understanding the SmartShift Architecture in OpenLogi
SmartShift configuration flows through three distinct layers that bridge raw hardware protocols with user-facing controls:
- HID++ Driver Layer (
openlogi-hidpp): Handles raw byte transmission for SmartShift features0x2110and0x2111 - Core Abstraction Layer (
openlogi-core/src/hid/smartshift.rs): DefinesSmartShiftMode,SmartShiftAutoDisengage, andSmartShiftStatusenums with conversion logic between persisted config and wire format - IPC/CLI Layer (
openlogi-ipc/src/ipc.rs): Exposes async RPC functionsset_smartshiftandread_smartshiftthat forward configuration changes to the agent
The Configuration Data Flow
When OpenLogi initializes, the agent reads ~/.config/openlogi/config.toml, converts WheelMode values into the SmartShiftMode enum through SmartShiftMode::from(crate::config::WheelMode), and writes the status to the device. Changes triggered via CLI or GUI invoke the IPC set_smartshift function, which ultimately calls the low-level HID++ write path write::smartshift::set_smartshift.
Configuring SmartShift via TOML
The persistent configuration resides in ~/.config/openlogi/config.toml under the [smart_shift] section:
[smart_shift]
# Mode can be "free" (free-spin) or "ratchet" (clicky)
mode = "ratchet"
# Auto-disengage threshold (0.25 turn/s steps). 255 = permanent ratchet.
auto_disengage = 30 # 30 × 0.25 turn/s = 7.5 turn/s
# Optional tunable-torque value (only on devices that support it)
tunable_torque = 2
The mode field accepts "free" for continuous scrolling or "ratchet" for stepped clicking. The auto_disengage value represents threshold steps where each step equals 0.25 turns per second; setting this to 255 locks the wheel in permanent ratchet mode regardless of spin speed.
Three Methods to Configure SmartShift
Depending on your integration needs, OpenLogi exposes SmartShift controls through CLI commands, programmatic Rust APIs, or direct configuration file editing.
Using the OpenLogi CLI
The openlogi-cli binary provides subcommands that serialize requests and transmit them via IPC:
# Set SmartShift to ratchet mode with a 30-step threshold (7.5 turn/s)
openlogi-cli set smartshift --mode ratchet --threshold 30
# Query the current SmartShift status
openlogi-cli get smartshift
These commands update the TOML file automatically after successfully writing to the device hardware.
Using the Rust Library
For embedded applications or custom tooling, import the core HID types and device write functions:
use openlogi_core::hid::smartshift::{SmartShiftMode, SmartShiftThreshold};
use openlogi_device::write::{set_smartshift, get_smartshift_status};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Assume `device` is a previously opened HID++ device.
let status = get_smartshift_status(&device).await?;
println!("Current mode: {:?}, threshold: {:?}", status.mode, status.auto_disengage);
// Switch to free-spin with a 20-step threshold.
let new_status = openlogi_core::hid::smartshift::SmartShiftStatus {
mode: SmartShiftMode::Free,
auto_disengage: openlogi_core::hid::smartshift::SmartShiftAutoDisengage::Threshold(
SmartShiftThreshold::try_new(20)?,
),
tunable_torque: status.tunable_torque,
};
set_smartshift(&device, new_status).await?;
Ok(())
}
This approach uses SmartShiftStatus structs defined in crates/openlogi-core/src/hid/smartshift.rs and write helpers in crates/openlogi-device/src/write/smartshift.rs.
Direct Configuration File Editing
Modify ~/.config/openlogi/config.toml directly and restart the OpenLogi agent:
[smart_shift]
mode = "free"
auto_disengage = 20
# tunable_torque omitted → will retain current value
The agent detects configuration changes on startup and applies them through the same conversion logic used by the IPC layer.
The SmartShift Configuration Lifecycle
OpenLogi manages SmartShift state through a five-phase pipeline:
- Read:
openlogi-hidppqueries feature0x2110, andSmartShift::status()returns aSmartShiftStatusstruct - Convert: The raw status transforms into the core
SmartShiftStatustype viaimpl From<crate::config::SmartShift> - Expose: The IPC layer makes the status available through
read_smartshiftfor GUI consumption - Modify: CLI or GUI constructs a new
SmartShiftStatuswith desiredmodeandauto_disengagevalues - Write:
write::smartshift::set_smartshiftserializes the struct back to HID++ wire bytes usingSmartShiftMode::into()andSmartShiftAutoDisengage::into(), then transmits to the device
Protocol Version Safety
Because the IPC serializes SmartShiftMode enums by their numeric index (Free = 0, Ratchet = 1), OpenLogi implements safeguards in openlogi-ipc/tests/wire_format.rs. Any change to the enum order requires a PROTOCOL_VERSION bump to prevent deserialization errors between agent and client components.
Summary
- Configure SmartShift with OpenLogi by editing
~/.config/openlogi/config.tomlor usingopenlogi-cli set smartshiftcommands - Configuration flows through
openlogi-core/src/hid/smartshift.rswhereSmartShiftModeandSmartShiftStatustypes bridge TOML values and HID++ protocol bytes - The
auto_disengagethreshold uses 0.25 turn/s steps; set to255for permanent ratchet mode - Programmatic control requires importing
openlogi_device::write::set_smartshiftand constructingSmartShiftStatusstructs - Wire format tests in
openlogi-ipc/tests/wire_format.rsensure binary compatibility across protocol versions
Frequently Asked Questions
Which Logitech devices support SmartShift configuration through OpenLogi?
OpenLogi supports any Logitech device implementing HID++ features 0x2110 and 0x2111, typically found in MX Master series mice and similar high-end input devices. Check openlogi-device/src/write/smartshift.rs for the specific feature detection logic that validates hardware compatibility before attempting configuration.
What values should I use for the auto_disengage threshold?
The auto_disengage field accepts values 0 to 255, where each unit represents 0.25 turns per second. For example, 30 equals 7.5 turns per second. Setting this to 255 disables automatic mode switching and forces permanent ratchet mode, while lower values trigger free-spin earlier during fast scrolling.
Does changing SmartShift mode require restarting the OpenLogi agent?
Changes made through openlogi-cli or the GUI apply immediately via IPC calls to set_smartshift. However, direct edits to ~/.config/openlogi/config.toml require an agent restart to take effect, as the configuration is read at startup time in openlogi-core initialization routines.
Why does the IPC layer serialize SmartShiftMode as an integer index?
The IPC uses numeric indices (Free = 0, Ratchet = 1) for SmartShiftMode to minimize wire format size and parsing complexity. This design requires strict PROTOCOL_VERSION management in openlogi-ipc/tests/wire_format.rs—altering the enum definition without bumping the protocol version breaks compatibility between the agent and CLI components.
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 →