OpenLogi

0x2202 · extendedAdjustableDpi

扩展的按传感器 DPI 控制——X/Y 分辨率、离地距离、DPI 状态 LED 控制和校准。

0x2202 按传感器控制 DPI 参数。它在 0x2201 adjustableDpi 的基础上,增加可选的 X/Y DPI、离地距离(LOD)、DPI 状态 LED 控制、配置文件和校准。

**规格:**Logitech HID++ 2.0 —— x2202 extendedAdjustableDpi。**交叉核对:**Logi Options+ 2.8(静态分析)、Solaar。用于:DPI。

函数参考

ExtendedDpiFeature 是 OpenLogi 对 0x2202 的封装。异步方法返回 Result<T, Hidpp20Error>。listen 是同步方法,并返回 async_channel::Receiver<ExtendedDpiEvent>。

方法

函数HID++ fn签名返回值
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>

类型

DpiDirection

变体值说明
X0水平轴。
Y1垂直轴。

Lod

LOD 是传感器停止追踪移动时,相对表面的高度。

变体值说明
NotSupported0传感器不支持 LOD 控制。
Low1低离地距离。
Medium2中离地距离。
High3高离地距离。

LedHoldType

变体值说明
TimerBased0在设备定义的超时后关闭 LED。
EventBased1在设备定义的事件后关闭 LED。
SwControlOn2由软件控制打开 LED。
SwControlOff3由软件控制关闭 LED。

CalibrationType

变体值说明
Hardware0传感器固件执行校准计算。
Software1主机软件执行校准计算。

SensorCapabilities

字段位说明
DPI_Y1 << 0传感器支持独立的 Y 轴 DPI。
LOD1 << 1传感器支持 LOD 控制。
CALIBRATION1 << 2传感器支持校准。
PROFILE1 << 3传感器支持 DPI 配置文件。

get_sensor_capabilities 会保留未知能力位。SetDpiParameters::for_sensor 只使用 DPI_Y 和 LOD 来准备写入。

SensorCapabilitiesInfo

字段类型说明
sensor_indexu8回复中的传感器索引。
dpi_level_countu8可选 DPI 等级数量。0 表示设备不管理 DPI 等级。
capabilitiesSensorCapabilities该传感器的能力位。

DpiRange

变体说明
Fixed(u16)一个可选 DPI 值。
Stepped带公开 from: u16、to: u16 和 step: u16 字段的闭区间 DPI 范围。

相邻的步进范围可以共享一个端点。

DpiParameters

字段类型说明
sensor_indexu8传感器索引。
dpi_xu16当前 X 轴 DPI。
default_dpi_xu16默认 X 轴 DPI。
dpi_yu16当前 Y 轴 DPI。没有 DPI_Y 时为 0。
default_dpi_yu16默认 Y 轴 DPI。没有 DPI_Y 时为 0。
lodLod当前离地距离。

SetDpiParameters

字段类型说明
dpi_xu16新的 X 轴 DPI。协议范围为 1..=57343。
dpi_yu16新的 Y 轴 DPI。没有 DPI_Y 时为 0。
lodLod新的离地距离。

SetDpiParameters::for_sensor(capabilities, dpi_x, dpi_y, lod) 仅在存在 DPI_Y 时发送 Y 值,并仅在存在 LOD 时发送 LOD。原始 setter 不检查能力或 DPI 范围。

ShowDpiStatus

字段类型说明
dpi_levelu8要显示的等级。协议范围为 1..=dpi_level_count。
led_hold_typeLedHoldTypeLED 的保持方式。
button_numu8触发变更的 HID 按钮号。从 1 开始。

DpiCalibrationInfo

字段类型说明
sensor_indexu8传感器索引。
mouse_widthu8设备宽度,单位为毫米。
mouse_lengthu16设备长度,单位为毫米。
calib_dpi_xu16校准使用的 X 轴 DPI。
calib_dpi_yu16校准使用的 Y 轴 DPI。没有 DPI_Y 时为 0。

StartDpiCalibration

字段类型说明
directionDpiDirection要校准的轴。
expected_countu16预期移动像素数。软件校准会忽略该值。
calib_typeCalibrationType校准执行位置。
start_timeoutu8开始超时,单位为秒。协议允许的最大值为 60。
hw_process_timeoutu8硬件处理超时,单位为秒。协议允许的最大值为 60。
sw_process_timeoutu8软件处理超时,单位为秒。协议允许的最大值为 60。

DpiCalibrationCorrection

变体说明
Adjust(i16)按 (1024 + value) / 1024 缩放分辨率。有效值为 -1023 至 1023。
RevertToOob恢复出厂配置文件设置。线值为 0x0000。
RevertToProfile恢复当前配置文件设置。线值为 0x8000。

Adjust(0) 与 RevertToOob 使用相同的线值。超出范围的调整会返回 Hidpp20Error::Feature(ErrorType::InvalidArgument)。

事件

ExtendedDpiFeature 实现了 EmittingFeature<ExtendedDpiEvent>。设备发送主动报告前,调用 listen()。

DpiParametersChanged

ExtendedDpiEvent::ParametersChanged 报告由设备发起的 DPI 参数变更。

字段类型说明
sensor_indexu8发生变更的传感器。
dpi_xu16新的 X 轴 DPI。
dpi_yu16新的 Y 轴 DPI。没有 DPI_Y 时为 0。
lodOption<Lod>新的 LOD。未知线值会变为 None。

DpiCalibrationCompleted

ExtendedDpiEvent::CalibrationCompleted 报告校准完成或超时。

字段类型说明
sensor_indexu8已校准的传感器。
directionOption<DpiDirection>已校准的轴。未知线值会变为 None。
correctioni16BE 校准值。i16::MIN 表示传感器级失败。
deltai16BE 垂直轴位移,单位为像素。

使用 DpiCalibrationCompleted::failed() 检查 i16::MIN 失败哨兵。

线格式

函数 0~5 和 8 使用 3 字节短请求。函数 6、7、9 和 10 使用 16 字节长请求。OpenLogi 会将长请求中未指定的字节写为零。下面所有多字节字段均采用 BE 字节序。

get_sensor_count(fn 0)

请求:[0x00, 0x00, 0x00]。

字节字段说明
0sensor_count运动传感器数量。
1–15/OpenLogi 忽略这些字节。

get_sensor_capabilities(fn 1)

请求:[sensor_index, 0x00, 0x00]。

字节字段说明
0回显的 sensor_indexOpenLogi 要求该值匹配。不同则返回 Hidpp20Error::UnsupportedResponse。
1dpi_level_count0 表示设备不管理 DPI 等级。
2capabilities位 0~3 分别是 DPI_Y、LOD、CALIBRATION 和 PROFILE。未知位会保留。
3–15/OpenLogi 忽略这些字节。

get_sensor_dpi_ranges(fn 2)

请求:[sensor_index, direction, page]。direction 的 X 为 0,Y 为 1。page 从 0 开始。

字节字段说明
0回显的 sensor_indexOpenLogi 要求该值匹配。
1回显的 directionOpenLogi 要求该值匹配。
2回显的 pageOpenLogi 要求该值匹配。
3–15范围流13 字节的流。一个 BE 字可以跨越分页边界。

字面值的最高 3 位不是 0b111。最高 3 位为 0b111 的字携带相邻字面端点之间的正步长。0x0000 终止完整数据流。OpenLogi 最多读取 16 页,忽略首个终止符之后的字节,并拒绝格式错误或未终止的范围。

get_sensor_dpi_list(fn 3)

请求:[sensor_index, direction, 0x00]。

字节字段说明
0回显的 sensor_indexOpenLogi 要求该值匹配。
1回显的 directionOpenLogi 要求该值匹配。
2–15DPI 字最多 7 个 BE u16 条目。0x0000 终止列表。

此函数仅在具有 SensorCapabilities::PROFILE 时有意义。完整列表可以没有终止符。OpenLogi 会保留列出的顺序和重复值。

get_sensor_lod_list(fn 4)

请求:[sensor_index, 0x00, 0x00]。

字节字段说明
0回显的 sensor_indexOpenLogi 要求该值匹配。
1 起LOD 条目每个 DPI 等级占一个字节。0、1、2、3 分别映射到 Lod。

调用者提供 dpi_level_count,通常来自 fn 1。列表没有终止符。OpenLogi 只读取该数量的条目,并拒绝未知 LOD 或不可能的长度。它会忽略剩余载荷字节。

get_sensor_dpi_parameters(fn 5)

请求:[sensor_index, 0x00, 0x00]。

字节字段说明
0回显的 sensor_indexOpenLogi 要求该值匹配。
1–2dpi_xBE u16。
3–4default_dpi_xBE u16。
5–6dpi_yBE u16。没有 DPI_Y 时为 0。
7–8default_dpi_yBE u16。没有 DPI_Y 时为 0。
9lodLod 值。OpenLogi 会拒绝未知值。
10–15/OpenLogi 忽略这些字节。

OpenLogi 要求此函数使用长回复。短回复会返回 Hidpp20Error::UnsupportedResponse。

set_sensor_dpi_parameters(fn 6)

字节字段说明
0sensor_index目标传感器。
1–2dpi_xBE u16。
3–4dpi_yBE u16。没有 DPI_Y 时,协议要求为零。
5lodLod 值。没有 LOD 时,协议要求为零。
6–15/OpenLogi 写入零。

OpenLogi 要求回复的字节 0 回显 sensor_index。SetDpiParameters::for_sensor 会为不支持的 Y 和 LOD 字段生成必需的零值。

show_sensor_dpi_status(fn 7)

字节字段说明
0sensor_index目标传感器。
1dpi_level要显示的 DPI 等级。
2led_hold_type0~3 分别映射到 LedHoldType。
3button_numHID 按钮号。
4–15/OpenLogi 写入零。

此函数只在主机模式下有效。OpenLogi 要求回复的字节 0 回显 sensor_index。

get_dpi_calibration_info(fn 8)

请求:[sensor_index, 0x00, 0x00]。

字节字段说明
0回显的 sensor_indexOpenLogi 要求该值匹配。
1mouse_width设备宽度,单位为毫米。
2–3mouse_lengthBE u16 设备长度,单位为毫米。
4–5calib_dpi_xBE u16。
6–7calib_dpi_yBE u16。没有 DPI_Y 时为 0。
8–15/OpenLogi 忽略这些字节。

OpenLogi 要求此函数使用长回复。短回复会返回 Hidpp20Error::UnsupportedResponse。

start_dpi_calibration(fn 9)

字节字段说明
0sensor_index目标传感器。
1directionX 为 0,Y 为 1。
2–3expected_countBE u16。软件校准会忽略该值。
4calib_type硬件为 0,软件为 1。
5start_timeout单位为秒。协议允许的最大值为 60。
6hw_process_timeout单位为秒。协议允许的最大值为 60。
7sw_process_timeout单位为秒。协议允许的最大值为 60。
8–15/OpenLogi 写入零。

此函数需要 SensorCapabilities::CALIBRATION。设备通过 CalibrationCompleted 事件报告结果。软件校准随后使用 fn 10 应用校正值。OpenLogi 要求回复的字节 0 回显 sensor_index。

set_dpi_calibration(fn 10)

字节字段说明
0sensor_index目标传感器。
1directionX 为 0,Y 为 1。
2–3correctionBE 有符号 i16。0x0000 为出厂设置。0x8000 为配置文件恢复。
4–15/OpenLogi 写入零。

OpenLogi 会在发送前验证 Adjust 的范围。它要求回复的字节 0 回显 sensor_index。

事件

主动报告使用子 ID 0 或 1。OpenLogi 解码前 6 个载荷字节,并忽略字节 6~15。

ParametersChanged(sub-id 0)

字节字段说明
0sensor_index发生变更的传感器。
1–2dpi_xBE u16。
3–4dpi_yBE u16。没有 DPI_Y 时为 0。
5lodLod 值。未知值会变为 None。

CalibrationCompleted(sub-id 1)

字节字段说明
0sensor_index完成校准的传感器。
1directionX 为 0,Y 为 1。未知值会变为 None。
2–3correctionBE 有符号 i16。0x8000 是失败哨兵。
4–5deltaBE 有符号 i16 垂直轴位移,单位为像素。

未知事件子 ID 不会生成 ExtendedDpiEvent。

OpenLogi 的用法

设备未公开 0x2201 时,设备层才使用 0x2202。它只操作传感器 0。它通过 fn 5 读取 X DPI,并通过 fn 2 读取 X 轴范围。它不使用配置文件列表、LOD 列表、LED 或校准函数。

写入 DPI 前,OpenLogi 会展平设备报告的 X 轴范围。请求值不在该列表中时,它返回 WriteError::DpiUnsupported。它读取传感器能力和当前参数。SetDpiParameters::for_sensor 仅在具有 DPI_Y 时写入等于 X 的 Y 值。它仅在具有 LOD 时保留当前 LOD;否则写入零。fn 6 的确认回复必须回显传感器。

每次确认写入后,OpenLogi 都读取 X DPI,并重试一次。第二次读到不同值时,它返回 WriteError::DpiNotApplied。读取失败不会撤销已确认的写入。桌面端会在异步写入前保存请求,因此被拒绝或未应用的写入可能会保留在桌面端状态中,直到后续实时读取。

从 v0.8.14 起,库存监听器会识别主动 fn 0 DPI 参数广播。它增加设备设置修订号,因此客户端会重新读取权威设置。监听器不会解码事件载荷,也不会持久化设备发起的变更。它会忽略 fn 1 校准完成广播。

传感器设置是易失性的,因此代理会在重连后重新应用保存的 DPI。OpenLogi 退出时不会执行此功能的专用重置。面向用户的控制见 DPI 页面。

Rust 用法

use hidpp::{
    device::Device,
    feature::{
        EmittingFeature,
        extended_dpi::{DpiDirection, ExtendedDpiFeature, SetDpiParameters},
    },
    protocol::v20::Hidpp20Error,
};

async fn inspect_extended_dpi(device: &mut Device) -> Result<(), Hidpp20Error> {
    device.enumerate_features().await?;
    if let Some(feature) = device.get_feature::<ExtendedDpiFeature>() {
        let capabilities = feature.get_sensor_capabilities(0).await?;
        let ranges = feature.get_sensor_dpi_ranges(0, DpiDirection::X).await?;
        let current = feature.get_sensor_dpi_parameters(0).await?;

        println!("X ranges: {ranges:?}");
        let write = SetDpiParameters::for_sensor(
            capabilities.capabilities,
            1600,
            1600,
            current.lod,
        );
        feature.set_sensor_dpi_parameters(0, write).await?;

        let events = feature.listen();
        if let Ok(event) = events.recv().await {
            println!("DPI event: {event:?}");
        }
    }

    Ok(())
}

本页目录