OpenLogi

0x2202 · extendedAdjustableDpi

Extended per-sensor DPI control — independent X/Y resolution, lift-off distance, DPI-status LED, and firmware or host-side calibration.

The modern successor to 0x2201 adjustableDpi, adding independent X/Y DPI, lift-off distance (LOD) control, DPI-status LED management, and a firmware/software calibration flow. Rather than a flat DPI list, supported DPI is described as a mix of DpiRange::Fixed values and DpiRange::Stepped ranges (each with from, to, and step). get_sensor_capabilities reports which optional sub-features a sensor supports via the SensorCapabilities flags.

get_sensor_dpi_parameters / set_sensor_dpi_parameters read and write the active DPI for both axes and the LOD in a single call. show_sensor_dpi_status drives the device's DPI indicator LED. The calibration sub-flow (get_dpi_calibration_infostart_dpi_calibrationset_dpi_calibration) can run on firmware or host. Two unsolicited events are emitted: ParametersChanged fires when the user presses a DPI button, and CalibrationCompleted fires when a calibration finishes or times out.

  • SensorCapabilitiesDPI_Y (independent Y-axis DPI), LOD (lift-off control), CALIBRATION, PROFILE (per-profile DPI lists).
  • LodNotSupported, Low, Medium, High.
  • LedHoldTypeTimerBased, EventBased, SwControlOn, SwControlOff.
  • CalibrationTypeHardware (on-sensor) or Software (host-computed).
  • DpiCalibrationCorrectionAdjust(i16) scales resolution by (1024 + value) / 1024; RevertToOob / RevertToProfile reset to defaults.

Spec: Logitech HID++ 2.0 — x2202 extendedAdjustableDpi. Used by: DPI presets.

Function reference

The ExtendedDpiFeature wrapper (0x2202) exposes:

Methods

FunctionHID++ fnSignatureReturns
get_sensor_count0()u8
get_sensor_capabilities1(sensor_index: u8)SensorCapabilitiesInfo
get_sensor_dpi_ranges2(sensor_index: u8, direction: DpiDirection)Vec<DpiRange>
get_sensor_dpi_list3(sensor_index: u8, direction: DpiDirection)Vec<u16>
get_sensor_lod_list4(sensor_index: u8, dpi_level_count: u8)Vec<Lod>
get_sensor_dpi_parameters5(sensor_index: u8)DpiParameters
set_sensor_dpi_parameters6(sensor_index: u8, params: SetDpiParameters)()
show_sensor_dpi_status7(sensor_index: u8, params: ShowDpiStatus)()
get_dpi_calibration_info8(sensor_index: u8)DpiCalibrationInfo
start_dpi_calibration9(sensor_index: u8, params: StartDpiCalibration)()
set_dpi_calibration10(sensor_index: u8, direction: DpiDirection, correction: DpiCalibrationCorrection)()
listenevent()Receiver<ExtendedDpiEvent>

All async methods return Result<…, Hidpp20Error>; listen is synchronous and returns an async_channel::Receiver<ExtendedDpiEvent> directly.

Types

DpiDirection

The axis a DPI value or calibration applies to.

VariantValueDescription
X0Horizontal (X) axis.
Y1Vertical (Y) axis.

Lod

A sensor's lift-off distance setting: the height above the surface at which the sensor stops tracking motion.

VariantValueDescription
NotSupported0Lift-off distance control is not supported.
Low1Low lift-off distance.
Medium2Medium lift-off distance.
High3High lift-off distance.

LedHoldType

How the device holds the DPI status LED after a show_sensor_dpi_status request.

VariantValueDescription
TimerBased0Turn the LED off once a device-defined timeout elapses.
EventBased1Turn the LED off once a device-defined event completes (e.g. releasing a DPI-shift button).
SwControlOn2Turn the LED on under software control.
SwControlOff3Turn the LED off under software control.

CalibrationType

Where a DPI calibration is computed.

VariantValueDescription
Hardware0Calibration is computed by the sensor firmware / hardware.
Software1Calibration is computed by host software.

SensorCapabilities

Per-sensor capability flags reported by get_sensor_capabilities.

FlagBitDescription
DPI_Y1 << 0The sensor supports an independent Y-axis DPI.
LOD1 << 1The sensor supports lift-off distance control.
CALIBRATION1 << 2The sensor supports DPI calibration.
PROFILE1 << 3The sensor supports DPI profiles.

SensorCapabilitiesInfo

A sensor's capabilities and DPI-level count, returned by get_sensor_capabilities.

FieldTypeDescription
sensor_indexu8Index of the sensor the capabilities belong to.
dpi_level_countu8Number of selectable DPI levels, or 0 if the device does not manage DPI levels.
capabilitiesSensorCapabilitiesSupported capabilities.

DpiRange

One entry of a sensor's supported-DPI description, returned by get_sensor_dpi_ranges. Fixed values and stepped ranges may be mixed; adjacent ranges may share an endpoint.

VariantDescription
Fixed(u16)A single selectable DPI value.
Stepped { from: u16, to: u16, step: u16 }A contiguous range of selectable DPI values from from to to (inclusive) in increments of step.

DpiParameters

Current and default DPI parameters of a sensor, returned by get_sensor_dpi_parameters. dpi_y and default_dpi_y are 0 when the sensor does not support an independent Y axis.

FieldTypeDescription
sensor_indexu8Index of the sensor.
dpi_xu16Current X-axis DPI.
default_dpi_xu16Default X-axis DPI.
dpi_yu16Current Y-axis DPI, or 0 when unsupported.
default_dpi_yu16Default Y-axis DPI, or 0 when unsupported.
lodLodCurrent lift-off distance.

SetDpiParameters

DPI parameters to apply with set_sensor_dpi_parameters.

FieldTypeDescription
dpi_xu16New X-axis DPI (1..=57343).
dpi_yu16New Y-axis DPI (1..=57343), or 0 when the sensor has no independent Y axis.
lodLodNew lift-off distance.

ShowDpiStatus

Parameters for show_sensor_dpi_status.

FieldTypeDescription
dpi_levelu8DPI level to display (1..=dpi_level_count).
led_hold_typeLedHoldTypeHow the device holds the DPI status LED.
button_numu8HID button number that initiated the DPI change (starts at 1).

DpiCalibrationInfo

Calibration reference information returned by get_dpi_calibration_info.

FieldTypeDescription
sensor_indexu8Index of the sensor.
mouse_widthu8Device width in millimetres.
mouse_lengthu16Device length in millimetres.
calib_dpi_xu16X-axis DPI configured for calibration.
calib_dpi_yu16Y-axis DPI configured for calibration, or 0 when unsupported.

StartDpiCalibration

Parameters for start_dpi_calibration.

FieldTypeDescription
directionDpiDirectionAxis to calibrate.
expected_countu16Expected pixel count for the calibration movement (ignored for CalibrationType::Software).
calib_typeCalibrationTypeWhere the calibration is computed.
start_timeoutu8Timeout in seconds for the calibration to start (<= 60).
hw_process_timeoutu8Timeout in seconds for the hardware calibration process (<= 60).
sw_process_timeoutu8Timeout in seconds for the software calibration process (<= 60).

DpiCalibrationCorrection

A DPI calibration correction to apply with set_dpi_calibration.

VariantDescription
Adjust(i16)Scale the sensor resolution by (1024 + value) / 1024. Valid values are -1023..=1023; 0 reverts to the out-of-box setting.
RevertToOobRevert to the out-of-box (OOB) profile setting (wire value 0x0000).
RevertToProfileRevert to the setting stored in the current profile (wire value 0x8000).

Events

ExtendedDpiFeature implements EmittingFeature<ExtendedDpiEvent>; call listen() to receive a channel of ExtendedDpiEvent values. The enum has two variants:

DpiParametersChanged

Payload of ExtendedDpiEvent::ParametersChanged. Fired when the sensor's DPI parameters change on the device (e.g. via a DPI button).

FieldTypeDescription
sensor_indexu8Index of the sensor whose parameters changed.
dpi_xu16New X-axis DPI.
dpi_yu16New Y-axis DPI, or 0 when the sensor has no independent Y axis.
lodLodNew lift-off distance.

DpiCalibrationCompleted

Payload of ExtendedDpiEvent::CalibrationCompleted. Fired when a DPI calibration finishes or times out.

FieldTypeDescription
sensor_indexu8Index of the sensor.
directionDpiDirectionAxis that was calibrated.
correctioni16Calibration correction value; i16::MIN (0x8000) signals a sensor-level failure (check failed()).
deltai16Perpendicular-axis displacement in pixel counts, useful for judging calibration quality.

Wire format

Most getter requests carry a 3-byte short payload; setter/calibration requests use a 16-byte long payload via call_long. Responses are always read from the 16-byte extended payload returned by extend_payload().

get_sensor_count (fn 0)

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

Response (byte → field):

ByteFieldNotes
0sensor_countNumber of motion sensors on the device.

get_sensor_capabilities (fn 1)

Request: [sensor_index, 0x00, 0x00]

Response (byte → field):

ByteFieldNotes
0sensor_indexEchoed sensor index.
1dpi_level_countSelectable DPI levels; 0 = unmanaged.
2capabilitiesSensorCapabilities bitfield: bit 0 = DPI_Y, bit 1 = LOD, bit 2 = CALIBRATION, bit 3 = PROFILE.

get_sensor_dpi_ranges (fn 2)

Fetches pages until a 0x0000 end-of-list terminator is encountered (up to 16 pages).

Request: [sensor_index, direction, page] where direction: 0 = X, 1 = Y; page starts at 0.

Response (byte → field):

ByteFieldNotes
0echoed sensor_indexValidated before trusting the page.
1echoed direction
2echoed page
3–15range stream bytesBig-endian 16-bit words; top 3 bits 0b111 = hyphen (step); 0x0000 = end-of-list.

get_sensor_dpi_list (fn 3)

Request: [sensor_index, direction, 0x00]

Response (byte → field):

ByteFieldNotes
0echoed sensor_indexSkipped by the parser.
1echoed directionSkipped by the parser.
2–15DPI list wordsBig-endian u16 values; 0x0000 terminates the list.

get_sensor_lod_list (fn 4)

Request: [sensor_index, 0x00, 0x00]

Response (byte → field):

ByteFieldNotes
0echoed sensor_indexSkipped by the parser.
1 … dpi_level_countLOD entriesOne u8 per level: 0 = NotSupported, 1 = Low, 2 = Medium, 3 = High. List length is supplied by the caller as dpi_level_count.

get_sensor_dpi_parameters (fn 5)

Request: [sensor_index, 0x00, 0x00]

Response (byte → field):

ByteFieldNotes
0sensor_index
1–2dpi_xBig-endian u16.
3–4default_dpi_xBig-endian u16.
5–6dpi_yBig-endian u16; 0 when Y-axis DPI is unsupported.
7–8default_dpi_yBig-endian u16; 0 when Y-axis DPI is unsupported.
9lodLod byte: 0–3.

set_sensor_dpi_parameters (fn 6)

Uses a 16-byte long request payload (call_long).

Request bytes 0–5 (remainder zero-padded):

ByteFieldNotes
0sensor_index
1dpi_x high byte
2dpi_x low byte
3dpi_y high byte0 when no independent Y axis.
4dpi_y low byte0 when no independent Y axis.
5lodLod byte: 0–3.

Response: not read (acknowledged by the device's echo).

show_sensor_dpi_status (fn 7)

Uses a 16-byte long request payload (call_long).

Request bytes 0–3 (remainder zero-padded):

ByteFieldNotes
0sensor_index
1dpi_levelLevel to display (1..=dpi_level_count).
2led_hold_type0 = TimerBased, 1 = EventBased, 2 = SwControlOn, 3 = SwControlOff.
3button_numHID button number that triggered the change (starts at 1).

Response: not read.

get_dpi_calibration_info (fn 8)

Request: [sensor_index, 0x00, 0x00]

Response (byte → field):

ByteFieldNotes
0sensor_index
1mouse_widthDevice width in mm.
2–3mouse_lengthDevice length in mm, big-endian u16.
4–5calib_dpi_xX-axis calibration DPI, big-endian u16.
6–7calib_dpi_yY-axis calibration DPI, big-endian u16; 0 when unsupported.

start_dpi_calibration (fn 9)

Uses a 16-byte long request payload (call_long).

Request bytes 0–7 (remainder zero-padded):

ByteFieldNotes
0sensor_index
1direction0 = X, 1 = Y.
2expected_count high byteIgnored for CalibrationType::Software.
3expected_count low byte
4calib_type0 = Hardware, 1 = Software.
5start_timeoutSeconds; <= 60.
6hw_process_timeoutSeconds; <= 60.
7sw_process_timeoutSeconds; <= 60.

Response: not read (result delivered via CalibrationCompleted event).

set_dpi_calibration (fn 10)

Uses a 16-byte long request payload (call_long).

Request bytes 0–3 (remainder zero-padded):

ByteFieldNotes
0sensor_index
1direction0 = X, 1 = Y.
2correction high byteDpiCalibrationCorrection::to_wire(): 0x8000 = RevertToProfile, 0x0000 = RevertToOob, signed value = Adjust.
3correction low byte

Response: not read.

Events

ParametersChanged (sub-id 0)

ByteFieldNotes
0sensor_index
1–2dpi_xBig-endian u16.
3–4dpi_yBig-endian u16; 0 when Y-axis DPI is unsupported.
5lodLod byte: 0–3.

CalibrationCompleted (sub-id 1)

ByteFieldNotes
0sensor_index
1direction0 = X, 1 = Y.
2–3correctionSigned big-endian i16; 0x8000 (i16::MIN) signals sensor-level failure.
4–5deltaSigned big-endian i16; perpendicular-axis pixel displacement.

Usage (Rust)

use hidpp::{
    device::Device,
    feature::{
        extended_dpi::{
            DpiDirection, ExtendedDpiFeature, Lod, SetDpiParameters, StartDpiCalibration,
            CalibrationType,
        },
        EmittingFeature,
    },
};

// device: &mut Device, already created via Device::new(channel, index).await?
device.enumerate_features().await?;
if let Some(feat) = device.get_feature::<ExtendedDpiFeature>() {
    // Query how many sensors the device has.
    let sensor_count = feat.get_sensor_count().await?;

    // Read the current DPI and lift-off distance for sensor 0.
    let params = feat.get_sensor_dpi_parameters(0).await?;
    println!("DPI X={} Y={} LOD={:?}", params.dpi_x, params.dpi_y, params.lod);

    // Set a new DPI (e.g. 1600 dpi on X, linked Y, medium lift-off).
    feat.set_sensor_dpi_parameters(0, SetDpiParameters {
        dpi_x: 1600,
        dpi_y: 0, // linked to X when sensor has no independent Y axis
        lod: Lod::Medium,
    }).await?;

    // Listen for unsolicited DPI-change events.
    let rx = feat.listen();
    while let Ok(event) = rx.recv().await {
        println!("DPI event: {:?}", event);
    }
}

On this page