# How to Configure DPI Settings for a Logitech Mouse Using OpenLogi

> Learn how to configure Logitech mouse DPI settings with OpenLogi. This guide explains the process using HID++ features and TOML files for persistent customization.

- Repository: [Xuan Zhang/OpenLogi](https://github.com/AprilNEA/OpenLogi)
- Tags: how-to-guide
- Published: 2026-08-29

---

**OpenLogi configures Logitech mouse DPI by querying HID++ AdjustableDpi features (0x2201/0x2202) to build capability lists, applying changes through the `set_dpi` function in [`crates/openlogi-device/src/write/dpi.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-device/src/write/dpi.rs), and persisting settings via TOML configuration files.**

Configuring DPI settings for a Logitech mouse on Linux requires precise HID++ protocol handling that OpenLogi automates through its agent-based architecture. The application discovers your hardware's supported DPI ranges, provides live preview sliders, and persists custom presets across reboots. This guide explains how to configure DPI settings for your Logitech mouse using OpenLogi's desktop interface, command-line tools, and Rust API.

## Understanding OpenLogi's DPI Architecture

OpenLogi treats **DPI** as a first-class data primitive through the `Dpi` type defined in [`crates/openlogi-core/src/hid/dpi.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/hid/dpi.rs). The system couples this with **`DpiCapabilities`** to represent hardware constraints including minimum, maximum, and step values. When you select a device, the agent queries the mouse's HID++ DPI feature—either `0x2201` (AdjustableDpi) or `0x2202` (ExtendedAdjustableDpi)—to construct a complete picture of supported sensitivity levels.

The architecture separates concerns cleanly: the **agent** handles raw HID++ communication while the **desktop UI** manages state and presentation. This design allows both graphical and programmatic configuration using the same underlying device layer.

## Discovering DPI Capabilities

The capability discovery phase runs automatically when connecting a device. The **`get_dpi_info`** function in [`crates/openlogi-device/src/write/dpi.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-device/src/write/dpi.rs) issues HID++ commands to retrieve current settings and supported ranges, returning a `DpiInfo` struct containing both the active DPI and capability constraints.

This discovery process determines:
- The current DPI value stored in the mouse's memory
- Minimum and maximum supported DPI values
- Step increments (if any) enforced by the hardware
- Whether the device supports on-the-fly adjustment

## Configuring DPI via the Desktop UI

### Live Preview and Slider Controls

The desktop application renders DPI controls through the **`DpiPanel`** component in [`crates/openlogi-desktop/src/features/pointer/dpi.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-desktop/src/features/pointer/dpi.rs). When `DpiStatus::Ready` arrives from the agent via IPC, the UI constructs a `SliderState` using **`DpiCapabilities.min()`**, **`max()`**, and **`step_hint()`** values to set appropriate bounds.

Dragging the slider emits `SliderEvent::Change` events that convert raw values to `Dpi` types using **`Dpi::from_rounded`**. The application snaps values to supported hardware steps via **`capabilities.nearest(dpi)`** before updating the `AppState` preview. This ensures you never select an unsupported DPI value that the hardware cannot apply.

### Committing Changes to Hardware

Releasing the slider triggers `SliderEvent::Release`, which calls **`AppState::commit_dpi`**. This marshals a **`Command::SetDpi(route, dpi)`** to the agent, which executes **`set_dpi_on_channel`** in [`crates/openlogi-device/src/write/dpi.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-device/src/write/dpi.rs). The system verifies writes by reading back the current DPI and logging warnings if the device reports discrepancies, ensuring your configuration actually takes effect.

## Managing DPI Presets and Persistence

### Creating Custom Presets

Users can save frequently used DPI values through preset chips in the UI. Clicking a preset chip invokes `commit_dpi` with the stored value, while the "+" chip appends current settings to the configuration via **`config.set_dpi_presets`** in [`crates/openlogi-desktop/src/state/dpi.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-desktop/src/state/dpi.rs).

The **`commit_dpi_presets`** function handles the actual persistence, storing your custom list alongside the current active DPI.

### Configuration File Storage

OpenLogi persists DPI settings in per-device TOML configuration files. The system saves both the current DPI via **`config.set_dpi`** and the preset list. During device reconnection, the agent automatically reapplies saved values, ensuring your mouse maintains its configuration across system restarts without requiring manual reconfiguration.

## Configuring DPI via CLI and Rust API

### Using the Diagnostic CLI

For headless environments or scripting, the `openlogi diag dpi` command in [`crates/openlogi-cli/src/cmd/diag/dpi.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-cli/src/cmd/diag/dpi.rs) queries **`get_dpi_info`** and prints the current DPI value alongside the complete list of hardware-supported ranges. This provides immediate visibility into your mouse's capabilities without launching the graphical interface.

### Programmatic DPI Configuration

Developers can programmatically configure DPI using the device write layer. The following example demonstrates reading capabilities, snapping to the nearest valid DPI, and committing the change:

```rust
use openlogi_core::hid::{Dpi, DpiCapabilities};
use openlogi_device::write::dpi::{set_dpi, get_dpi_info};
use openlogi_device::backend::HidBackend;

async fn set_mouse_dpi(backend: &dyn HidBackend, route: &DeviceRoute, desired: u16) {
    // Convert raw value to internal Dpi type
    let dpi = Dpi::new(desired);
    
    // Query hardware capabilities
    let info = get_dpi_info(backend, route).await.unwrap();
    let caps: &DpiCapabilities = &info.capabilities;
    
    // Snap to nearest supported value
    let target = caps.nearest(dpi);
    
    // Write to device
    set_dpi(backend, route, target).await.unwrap();
}

```

This approach uses the same code paths as the desktop UI, ensuring consistent behavior whether you use the GUI, CLI, or custom scripts.

## Summary

- OpenLogi queries HID++ features `0x2201` or `0x2202` to detect hardware DPI capabilities via **`get_dpi_info`** in [`crates/openlogi-device/src/write/dpi.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-device/src/write/dpi.rs)
- The desktop UI provides live preview sliders that snap to supported values using **`capabilities.nearest()`** to prevent invalid selections
- Changes are committed through **`AppState::commit_dpi`** which sends **`Command::SetDpi`** to the agent for hardware application
- Settings persist in per-device TOML configuration files and automatically reapply on device reconnection via **`config.set_dpi`** and **`config.set_dpi_presets`**
- Use **`openlogi diag dpi`** for CLI diagnostics or the **`set_dpi`** function for programmatic control without the GUI

## Frequently Asked Questions

### Which Logitech mice support DPI configuration through OpenLogi?

OpenLogi supports any Logitech mouse exposing HID++ AdjustableDpi (`0x2201`) or ExtendedAdjustableDpi (`0x2202`) features. The **`get_dpi_info`** function in [`crates/openlogi-device/src/write/dpi.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-device/src/write/dpi.rs) automatically detects these capabilities during device enumeration, presenting appropriate controls only when the hardware supports DPI adjustment.

### Why does the DPI slider snap to specific values?

The UI enforces hardware constraints by calling **`capabilities.nearest(dpi)`** on the `DpiCapabilities` object returned by the agent. This ensures you only select DPI values your specific mouse model actually supports, preventing invalid configurations that the hardware would reject or round unpredictably.

### How do I create persistent DPI presets in OpenLogi?

Click the "+" chip in the `DpiPanel` to add the current DPI to your presets list, which triggers **`commit_dpi_presets`** invoking **`config.set_dpi_presets`** in [`crates/openlogi-desktop/src/state/dpi.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-desktop/src/state/dpi.rs). These values persist across application restarts in the device's TOML configuration file, and you can recall them instantly by clicking preset chips in the UI.

### Can I configure DPI without the graphical interface?

Yes. Use the **`openlogi diag dpi`** command to view current settings and supported ranges, or integrate the Rust API by calling **`set_dpi`** from [`crates/openlogi-device/src/write/dpi.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-device/src/write/dpi.rs) with a valid `Dpi` value and device route. Both methods bypass the GUI while using identical hardware communication protocols.