How SmartShift Is Configured in OpenLogi: TOML, UI, and HID++ Protocol
SmartShift in OpenLogi is configured through a three-layer architecture: declarative TOML files for static settings, runtime UI/CLI for dynamic changes, and HID++ protocol commands for device communication.
OpenLogi implements Logitech's SmartShift (dynamic ratchet/free-spin wheel mode) as a core device feature in its Rust-based driver stack. This article explains how SmartShift configuration flows from user-facing settings to hardware commands, based on the OpenLogi source code in the AprilNEA/OpenLogi repository.
TOML Configuration File Structure
User-defined SmartShift settings live in config.toml under each device's smartshift table. The example in docs/config.example.toml shows the complete schema:
[devices."receiver:aabbccdd:slot:1".smartshift]
mode = "ratchet" # or "free"
auto_disengage = 16 # threshold (0-255)
tunable_torque = 50 # torque (0-255)
The mode field accepts two string values:
ratchet— stepped scrolling with tactile feedbackfree— smooth spinning with no resistance
auto_disengage controls how long the ratchet mode holds before automatic release (higher values = longer hold). tunable_torque sets the mechanical resistance strength in ratchet mode (higher values = stronger detents). Both are u8 values (0-255 range).
Configuration Parsing and Core Types
The TOML deserializes into internal structures defined in openlogi-core. In crates/openlogi-core/src/hid/smartshift.rs, the SmartShiftStatus struct mirrors both the configuration format and the HID++ wire protocol:
mode→SmartShiftModeenum (RatchetorFree)auto_disengage→SmartShiftAutoDisengage::Threshold(u8)tunable_torque→TunableTorque(u8)
This design ensures zero-copy translation between user configuration and device commands.
Device Write Path: From Status to HID++ Commands
When settings change, openlogi-device translates SmartShiftStatus into hardware commands. The high-level API lives in crates/openlogi-device/src/write/smartshift.rs:
// Key functions in the write module
pub async fn set_smartshift(route: &DeviceRoute, status: SmartShiftStatus) -> Result<(), WriteError>;
pub async fn toggle_smartshift(route: &DeviceRoute) -> Result<SmartShiftMode, WriteError>;
pub async fn set_smartshift_sensitivity(route: &DeviceRoute, threshold: u8, torque: u8) -> Result<(), WriteError>;
These functions open the SmartShift feature from openlogi-hidpp and dispatch the appropriate sub-commands:
set_status— full configuration writetoggle— mode switch onlyset_sensitivity— threshold and torque adjustment
HID++ Protocol Implementation
The wire-format protocol definitions span two feature files in openlogi-hidpp:
| Feature ID | File | Device Support |
|---|---|---|
| 0x2110 | crates/openlogi-hidpp/src/feature/smartshift.rs |
Standard SmartShift devices |
| 0x2111 | crates/openlogi-hidpp/src/feature/smartshift_enhanced.rs |
Newer hardware variants |
The actual I/O dispatch occurs in crates/openlogi-hid/src/host.rs, which exposes async functions that the agent and UI consume:
use openlogi_hid::host::get_smartshift_status;
use openlogi_core::hid::smartshift::SmartShiftStatus;
async fn print_smartshift(route: &DeviceRoute) -> Result<(), WriteError> {
let status: SmartShiftStatus = get_smartshift_status(route).await?;
println!("Mode: {:?}, Auto‑Disengage: {:?}, Torque: {:?}",
status.mode, status.auto_disengage, status.tunable_torque);
Ok(())
}
Runtime UI and IPC Architecture
The openlogi-ui crate communicates with the background agent through tarpc RPC defined in crates/openlogi-ipc/src/ipc.rs:
// RPC methods for SmartShift control
async fn read_smartshift(device_key: String) -> Result<SmartShiftStatus, IpcError>;
async fn set_smartshift(device_key: String, status: SmartShiftStatus) -> Result<(), IpcError>;
The UI workflow:
- Call
read_smartshifton device selection to populate state - Display toggle button and sensitivity slider (localized via
crates/openlogi-ui/locales/*.toml) - Call
set_smartshiftwhen user changes settings
CLI users bypass the UI entirely:
openlogi set_smartshift --device "receiver:aabbccdd:slot:1" --mode free
Configuration Persistence and Hot-Reload
OpenLogi supports live configuration updates:
- File watcher detects
config.tomlchanges - Agent re-parses affected
SmartShiftStatusvalues - New settings push to device via the same write path as UI changes
This unifies declarative (file-based) and imperative (runtime) configuration into a single pipeline.
Summary
- TOML files provide static SmartShift configuration under
[devices."..."].smartshifttables SmartShiftStatusinopenlogi-corebridges user settings and HID++ wire format- Write helpers in
openlogi-device/src/write/smartshift.rstranslate status to device commands - HID++ features 0x2110 and 0x2111 handle protocol-level communication
- tarpc IPC enables UI and CLI to control SmartShift without direct hardware access
- Hot-reload ensures file changes propagate to connected devices immediately
Frequently Asked Questions
What are the valid values for SmartShift mode in OpenLogi?
OpenLogi accepts two string values for the mode field: "ratchet" for stepped scrolling and "free" for smooth spinning. These map to the SmartShiftMode::Ratchet and SmartShiftMode::Free variants in crates/openlogi-core/src/hid/smartshift.rs.
How do I adjust SmartShift sensitivity in OpenLogi?
Use the auto_disengage field (0-255) to control how long ratchet mode holds, and tunable_torque (0-255) to set mechanical resistance. Higher auto_disengage values delay automatic disengagement; higher tunable_torque values create stronger tactile feedback. Both can be set via TOML or adjusted at runtime through the UI slider.
Why does OpenLogi have two HID++ feature IDs for SmartShift?
Feature ID 0x2110 in smartshift.rs supports standard SmartShift hardware, while 0x2111 in smartshift_enhanced.rs handles newer devices with extended capabilities. The openlogi-device crate automatically selects the appropriate feature based on device capability detection.
Can I toggle SmartShift without editing the configuration file?
Yes. The UI toggle button calls toggle_smartshift() via IPC, and the CLI supports openlogi set_smartshift --mode <ratchet|free>. Runtime changes persist only until device disconnect unless you also update config.toml or enable auto-save in UI preferences.
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 →