How to Set DPI for Logitech Mouse with OpenLogi: A Complete HID++ Protocol Guide
OpenLogi controls Logitech mouse DPI through the HID++ protocol by detecting either feature 0x2201 (AdjustableDpi) or 0x2202 (ExtendedAdjustableDpi), then writing values via the set_dpi() function while verifying the change against supported sensor capabilities.
OpenLogi provides a Rust-based interface for configuring Logitech peripherals at the firmware level. When you need to change your mouse sensitivity programmatically, the library negotiates with the device using Logitech's proprietary HID++ feature set to ensure compatibility across different sensor architectures.
Understanding the HID++ DPI Feature Detection
OpenLogi automatically probes for two distinct DPI management features when initializing a device connection. This detection logic, implemented in crates/openlogi-device/src/write/dpi.rs within the DpiFeature::open method, determines which protocol version your specific mouse model supports.
0x2201 (AdjustableDpi) represents the preferred implementation. This feature exposes DPI values as a flat list where each entry corresponds to a single sensor sensitivity setting. OpenLogi attempts to open this feature first because it offers broader compatibility with existing Logitech hardware.
0x2202 (ExtendedAdjustableDpi) serves as the fallback protocol. This extended feature supports independent X/Y axis DPI configurations and includes lift-off distance parameters. The library only uses this feature when 0x2201 is unavailable on the target device.
The DPI Control Workflow
Once DpiFeature::open establishes the correct feature handle, OpenLogi executes a three-phase workflow to manage sensitivity settings. Each phase maps to specific methods in the DPI module that handle the low-level HID++ communication.
Reading Current DPI Values
The DpiFeature::current_dpi() method retrieves the active sensitivity setting from the device. Depending on which feature was detected during initialization, this calls either get_sensor_dpi (for 0x2201) or get_sensor_dpi_parameters (for 0x2202) to read the hardware registers.
Querying Supported DPI Ranges
Before writing new values, DpiFeature::supported_dpi() obtains the complete list of valid DPI settings for your specific mouse model. For devices using the extended feature (0x2202), this method processes stepped ranges through the expand_dpi_ranges helper function to generate a flattened list of acceptable values.
Writing and Verifying New DPI
The DpiFeature::set_dpi() method handles the actual configuration change through the following sequence:
- Transmits the new DPI value using
set_sensor_dpi(adjustable feature) orset_sensor_dpi_parameters(extended feature) - Immediately reads the DPI back from the device to confirm the write succeeded
- Logs a warning if the reported value differs from the requested value, indicating the device clamped the input to the nearest supported step
Public API Methods
OpenLogi exposes DPI control through two primary async functions that abstract the feature detection and error handling logic.
set_dpi(backend, route, dpi) manages the complete write operation. This function opens a HID++ channel to the specified device, selects the appropriate feature (0x2201 or 0x2202), transmits the new Dpi value, and performs the verification read. The backend parameter implements the HidBackend trait, while route specifies the DeviceRoute targeting your specific mouse.
get_dpi_info(backend, route) returns comprehensive sensor capabilities. This function provides both the current active DPI and a DpiCapabilities structure containing the full vector of supported values, allowing applications to validate user input against hardware limits before attempting writes.
Practical Implementation Examples
You can interact with OpenLogi's DPI control either programmatically through the Rust library or via the bundled command-line interface.
Rust Library Integration
For custom applications or agents, import the DPI module and use the async API directly:
use openlogi_device::write::dpi::{set_dpi, get_dpi_info};
use openlogi_core::hid::dpi::Dpi;
use openlogi_agent_core::backend::HidBackend;
use openlogi_ipc::DeviceRoute;
async fn change_mouse_dpi(
backend: &dyn HidBackend,
route: &DeviceRoute,
new_dpi: u16
) -> Result<(), WriteError> {
// Convert raw value to the library's Dpi type
let dpi = Dpi::new(new_dpi);
// Write the DPI setting
set_dpi(backend, route, dpi).await?;
// Verify capabilities and confirm the change
let info = get_dpi_info(backend, route).await?;
println!("Current DPI: {}, supported values: {:?}",
info.current, info.capabilities.values());
Ok(())
}
The Dpi type constructor in crates/openlogi-core/src/hid/dpi.rs handles validation, while the DpiInfo structure returned by get_dpi_info contains both the current value and the capabilities object.
Command-Line Interface
For end-user workflows, use the openlogi CLI commands without writing Rust code:
# List connected devices to find your mouse index
openlogi list
# Set device 0 to 1200 DPI
openlogi set-dpi --device 0 --value 1200
# Verify the configuration with diagnostic output
openlogi diag dpi --device 0
The set-dpi command in crates/openlogi-cli/src/cmd/mod.rs forwards your request to the set_dpi function, while diag dpi—implemented in crates/openlogi-cli/src/cmd/diag/dpi.rs—demonstrates the full read-write-read round-trip to confirm the device accepted the new sensitivity value.
Summary
- OpenLogi automatically detects DPI features
0x2201(preferred) or0x2202(extended fallback) inopenlogi-device/src/write/dpi.rs - The
DpiFeature::set_dpi()method writes values and verifies the device report matches the requested sensitivity - Use
set_dpi()to change settings andget_dpi_info()to retrieve current values and supported ranges - The CLI provides
openlogi set-dpiandopenlogi diag dpicommands for non-programmatic access - All DPI types (
Dpi,DpiCapabilities,DpiInfo) are defined inopenlogi-core/src/hid/dpi.rs
Frequently Asked Questions
What is the difference between AdjustableDpi and ExtendedAdjustableDpi features?
The 0x2201 (AdjustableDpi) feature provides a simple flat list of DPI values per sensor, while 0x2202 (ExtendedAdjustableDpi) adds independent X/Y axis control and lift-off distance configuration using stepped ranges. OpenLogi attempts to use 0x2201 first for maximum compatibility, falling back to 0x2202 only when necessary.
Why does OpenLogi read the DPI back after writing it?
The library performs a verification read to ensure the hardware actually accepted the requested value. Some Logitech mice automatically clamp out-of-range values to the nearest supported step. If the read-back value differs from the write request, OpenLogi logs a warning indicating the device modified the input to match its supported capabilities.
Can I set different DPI values for X and Y axes?
Only mice exposing the 0x2202 (ExtendedAdjustableDpi) feature support independent X/Y axis configuration. When this feature is active, the set_sensor_dpi_parameters function accepts separate values for horizontal and vertical sensitivity. The standard 0x2201 feature applies a single value to both axes.
What happens if I request a DPI value my mouse doesn't support?
The device firmware will automatically adjust your request to the nearest valid value within its hardware limits. OpenLogi's verification step detects this discrepancy and reports it via logging or CLI output, allowing you to query the exact supported range using get_dpi_info() or openlogi diag dpi before attempting further modifications.
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 →