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
| Function | HID++ fn | Signature | Returns |
|---|---|---|---|
get_pointer_scaling | 0 | () | PointerScaling |
set_pointer_scaling | 1 | (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.
| API | Signature or value | Returns | Description |
|---|---|---|---|
PointerScaling::ONE | 0x0100 | PointerScaling | The unscaled 1× value. |
PointerScaling::from_raw | (raw: u16) | Option<PointerScaling> | Constructs a value when raw is nonzero. |
PointerScaling::raw | (self) | u16 | Returns the raw unsigned 8.8 value. |
PointerScaling::multiplier | (self) | f32 | Returns 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.
| Bytes | Field | Notes |
|---|---|---|
| 0–1 | PointerScaling raw value | Unsigned 8.8 value in BE order. 0x0100 is 1×. |
| 2–15 | Reserved | OpenLogi ignores these bytes. |
set_pointer_scaling (fn 1)
| Request bytes | Field | Notes |
|---|---|---|
| 0–1 | requested raw value | scaling.raw().to_be_bytes() in BE order. |
| 2 | Padding | OpenLogi writes 0x00. |
| Response bytes | Field | Notes |
|---|---|---|
| 0–1 | echoed raw value | Unsigned 8.8 value in BE order. OpenLogi returns it as PointerScaling. |
| 2–15 | Reserved | OpenLogi 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(())
}