OpenLogi

0x2205 · PointerMotionScaling

Read or write a device-specific pointer-motion multiplier in unsigned 8.8 fixed-point format.

PointerMotionScaling applies a device-specific multiplier to pointer movement. The raw value is unsigned 8.8 fixed point. 0x0100 is 1×, and 0x0180 is 1.5×.

Spec: Logitech HID++ 2.0 — x2205 PointerMotionScaling. Cross-checked: Logi Options+ 2.8 (static analysis). Used by: openlogi diag pointer-speed; Report rate.

Function reference

The PointerMotionScalingFeature wrapper (0x2205, version 0+) reads and writes one scalar value.

Methods

FunctionHID++ fnSignatureReturns
get_pointer_scaling0()PointerScaling
set_pointer_scaling1(scaling: PointerScaling)PointerScaling

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

Types

PointerScaling is a nonzero raw u16. A zero raw value returns None from from_raw and causes a wire reply to fail with Hidpp20Error::UnsupportedResponse.

APISignature or valueReturnsDescription
PointerScaling::ONE0x0100PointerScalingThe unscaled 1× value.
PointerScaling::from_raw(raw: u16)Option<PointerScaling>Constructs a value when raw is nonzero.
PointerScaling::raw(self)u16Returns the raw unsigned 8.8 value.
PointerScaling::multiplier(self)f32Returns raw / 256.0.

Events

PointerMotionScalingFeature exposes no event type.

Wire format

Both functions send a 3-byte short request. OpenLogi reads each reply as a 16-byte extended payload.

get_pointer_scaling (fn 0)

Request: [0x00, 0x00, 0x00]. All three bytes are padding.

BytesFieldNotes
0–1PointerScaling raw valueUnsigned 8.8 value in BE order. 0x0100 is 1×.
2–15ReservedOpenLogi ignores these bytes.

set_pointer_scaling (fn 1)

Request bytesFieldNotes
0–1requested raw valuescaling.raw().to_be_bytes() in BE order.
2PaddingOpenLogi writes 0x00.
Response bytesFieldNotes
0–1echoed raw valueUnsigned 8.8 value in BE order. OpenLogi returns it as PointerScaling.
2–15ReservedOpenLogi ignores these bytes.

How OpenLogi uses it

The device layer opens 0x2205 on the selected route for get_pointer_scaling and set_pointer_scaling. A write has no unrelated fields to preserve. OpenLogi writes the scalar, then performs an independent read and returns that applied value.

openlogi diag pointer-speed is the only product caller in v0.8.15. It reads the original value, skips an equal target, and always attempts a restore before it judges the test write. It verifies that the restored value equals the original value.

The diagnostic accepts every nonzero raw u16. It has no GUI, agent configuration, or IPC setting. The related Report rate page documents this separation.

Open questions

The HID++ specification recommends 0x0010–0x1000 and says firmware clips out-of-range writes. An observed MX Ergo firmware version, MPM06.03_B0022, stored 0x0001 and 0xffff unchanged. OpenLogi therefore does not assume clipping and leaves user-facing bounds to a future product control.

Usage (Rust)

use hidpp::{
    device::Device,
    feature::pointer_motion_scaling::{PointerMotionScalingFeature, PointerScaling},
    protocol::v20::Hidpp20Error,
};

async fn set_scaling(device: &mut Device) -> Result<(), Hidpp20Error> {
    device.enumerate_features().await?;

    if let Some(feature) = device.get_feature::<PointerMotionScalingFeature>() {
        let requested = PointerScaling::from_raw(0x0180).expect("value is nonzero");
        let applied = feature.set_pointer_scaling(requested).await?;
        println!("Applied multiplier: {:.2}×", applied.multiplier());
    }

    Ok(())
}

On this page