OpenLogi
Features

0x2201 · adjustableDpi

Per-sensor pointer resolution — read the sensor count, enumerate supported DPI values, and read or write the active DPI.

Per-sensor pointer resolution. getSensorCount reports how many sensors the device has; getSensorDpiList returns the supported DPI values (a list or a range with a step); getSensorDpi / setSensorDpi read and write the active DPI.

OpenLogi builds its DPI presets on top of this feature, and exposes Cycle DPI and Set preset as bindable actions.

Spec: Logitech HID++ 2.0 — x2201 adjustableDpi. See also x2202 extendedAdjustableDpi. Used by: DPI presets.

Function reference

The AdjustableDpiFeature wrapper (0x2201) exposes:

Methods

FunctionHID++ fnSignatureReturns
get_sensor_count0()u8
get_sensor_dpi_list1(sensor_index: u8)Vec<u16>
get_sensor_dpi2(sensor_index: u8)u16
set_sensor_dpi3(sensor_index: u8, dpi: u16)()

All methods are async and return Result<…, Hidpp20Error>.

Wire format

All four functions use a 3-byte short request payload and receive a 16-byte long response payload (extend_payload()).

get_sensor_count (fn 0)

Request: [0x00, 0x00, 0x00] (no parameters)

Response (byte → field):

ByteFieldNotes
0sensor_countNumber of sensors on the device

get_sensor_dpi_list (fn 1)

Request: [sensor_index, 0x00, 0x00]

Response (bytes → field): byte 0 is the echoed sensor_index. Bytes 1–15 carry up to seven big-endian u16 values, terminated by 0x0000 (terminator may be absent when values fill the payload).

Each u16 value is either:

  • An explicit DPI value (top 3 bits are not 0b111).
  • A range marker (value >> 13 == 0b111): the low 13 bits are the step (value & 0x1fff). The preceding explicit value is the range start; the next explicit value (bytes offset+2..=offset+3) is the range end. The crate expands the range into individual DPI steps and always includes the end value.
BytesFieldNotes
0echoed sensor_indexSkipped by the crate
1–2, 3–4, …DPI entry (big-endian u16)Explicit value or range marker
next 20x0000Terminator (absent if payload is full)

get_sensor_dpi (fn 2)

Request: [sensor_index, 0x00, 0x00]

Response (bytes → field):

ByteFieldNotes
0echoed sensor_indexIgnored by the crate
1DPI high byteCombined as u16::from_be_bytes([payload[1], payload[2]])
2DPI low byte

set_sensor_dpi (fn 3)

Request: [sensor_index, dpi_hi, dpi_lo]dpi split as dpi.to_be_bytes().

Response: acknowledged; return value is () (response payload ignored).

Usage (Rust)

use hidpp::{device::Device, feature::adjustable_dpi::AdjustableDpiFeature};

// device: &mut Device, already created via Device::new(channel, index)
device.enumerate_features().await?;
if let Some(feat) = device.get_feature::<AdjustableDpiFeature>() {
    let sensor_count = feat.get_sensor_count().await?;
    println!("sensors: {sensor_count}");

    // Query supported DPI values for sensor 0
    let dpi_list = feat.get_sensor_dpi_list(0).await?;
    println!("supported DPI: {dpi_list:?}");

    // Read and then raise the active DPI
    let current = feat.get_sensor_dpi(0).await?;
    println!("current DPI: {current}");
    feat.set_sensor_dpi(0, 1600).await?;
}

On this page