0x2201 · adjustableDpi
按传感器调节指针分辨率——枚举支持的 DPI 值,并读取或写入当前 DPI。
0x2201 按传感器控制一个 DPI 值。它报告传感器数量、支持的 DPI 值和当前 DPI。功能版本 1 还会报告默认 DPI 值。
**规格:**Logitech HID++ 2.0 —— x2201 adjustableDpi。**交叉核对:**Logi Options+ 2.8(静态分析)、Solaar。用于:DPI。
函数参考
AdjustableDpiFeature 是 OpenLogi 对 0x2201 的封装。所有方法都是异步方法,并返回 Result<T, Hidpp20Error>。
方法
| 函数 | HID++ fn | 签名 | 返回值 |
|---|---|---|---|
get_sensor_count | 0 | () | u8 |
get_sensor_dpi_list | 1 | (sensor_index: u8) | Vec<u16> |
get_sensor_dpi | 2 | (sensor_index: u8) | u16 |
set_sensor_dpi | 3 | (sensor_index: u8, dpi: u16) | () |
类型
封装使用 u8 表示传感器索引,使用 u16 表示 DPI。get_sensor_dpi_list 返回按升序排列且不重复的值。
事件
OpenLogi v0.8.15 未定义 0x2201 事件类型。
线格式
函数 0~2 使用 3 字节短载荷。功能版本 0 和 1 的 set_sensor_dpi 也使用此形式。所有多字节 DPI 值均采用 BE 字节序。封装会对回复调用 extend_payload(),因此不要求长回复。
get_sensor_count(fn 0)
请求:[0x00, 0x00, 0x00]。
| 字节 | 字段 | 说明 |
|---|---|---|
| 0 | sensor_count | 运动传感器数量。 |
| 1–15 | / | OpenLogi 忽略这些字节。 |
get_sensor_dpi_list(fn 1)
请求:[sensor_index, 0x00, 0x00]。
| 字节 | 字段 | 说明 |
|---|---|---|
| 0 | 回显的 sensor_index | OpenLogi 要求该值与请求相同。不同则返回 Hidpp20Error::UnsupportedResponse。 |
| 1–14 | DPI 字 | 最多 7 个 BE u16 字,按顺序解码。 |
| 15 | 尾随字节 | 该字节不能构成完整的字。OpenLogi 会忽略它。 |
0x0000 终止列表。完整列表没有终止符。字面 DPI 字的最高 3 位不是 0b111。最高 3 位为 0b111 的字是范围标记。其低 13 位是正步长。
前一个字面值是范围起点。后一个字面值是范围终点。OpenLogi 展开范围,保留不在步长网格上的终点,再排序和去重。起始范围标记、零步长、缺少终点或递减终点都会返回 Hidpp20Error::UnsupportedResponse。
get_sensor_dpi(fn 2)
请求:[sensor_index, 0x00, 0x00]。
| 字节 | 字段 | 说明 |
|---|---|---|
| 0 | 回显的 sensor_index | 协议提供此回显。OpenLogi 在此函数中忽略它。 |
| 1–2 | current_dpi | BE u16。OpenLogi 返回此值。 |
| 3–4 | default_dpi | 功能版本 1 及以后为 BE u16。版本 0 使用零。OpenLogi 忽略这些字节。 |
| 5–15 | / | OpenLogi 忽略这些字节。 |
set_sensor_dpi(fn 3)
| 字节 | 字段 | 说明 |
|---|---|---|
| 0 | sensor_index | 目标传感器。 |
| 1–2 | dpi | BE u16。 |
| 3 | dpi_level | Logi Options+ 2.8 的静态分析表明,此字段存在于功能版本 2 及以后。其含义尚未确认。 |
功能版本低于 2 时,请求在字节 2 后结束。OpenLogi v0.8.15 对所有版本都发送 3 字节形式。它会忽略确认回复的载荷。
OpenLogi 的用法
设备层先解析 0x2201,再解析 0x2202。它只操作传感器 0。设备报告零个传感器时,OpenLogi 会拒绝该设备。对于 0x2201,它读取当前 DPI 和支持的 DPI 列表。
写入前,OpenLogi 检查请求的 DPI 是否完全匹配设备报告的值。否则,它返回 WriteError::DpiUnsupported,且不发送数据包。写入后,它读取 DPI,并重试一次。第二次读到不同值时,它返回 WriteError::DpiNotApplied。读取失败不会撤销已确认的写入。
桌面端会在异步设备写入前保存请求的 DPI。因此,拒绝或未应用的写入可能会让请求值保留在桌面端状态中,直到后续实时读取。传感器设置是易失性的,因此代理会在重连后重新应用保存的 DPI。OpenLogi 退出时不会执行此功能的专用重置。
OpenLogi 不公开 default_dpi 或版本 2 的 dpi_level。面向用户的控制见 DPI 页面。
未确认的细节
Logi Options+ 2.8 会为版本 2 及以后的 0x2201 写入第 4 个 dpi_level 字节。公开规格止于版本 1。静态分析无法确认该字段的含义或硬件支持情况。OpenLogi 对每个版本都发送版本 0/1 形式。
Rust 用法
use hidpp::{
device::Device,
feature::adjustable_dpi::AdjustableDpiFeature,
protocol::v20::Hidpp20Error,
};
async fn set_first_other_dpi(device: &mut Device) -> Result<(), Hidpp20Error> {
device.enumerate_features().await?;
if let Some(feature) = device.get_feature::<AdjustableDpiFeature>() {
let sensor_count = feature.get_sensor_count().await?;
let supported = feature.get_sensor_dpi_list(0).await?;
let current = feature.get_sensor_dpi(0).await?;
println!("sensors: {sensor_count}, current DPI: {current}");
if let Some(&next) = supported.iter().find(|&&dpi| dpi != current) {
feature.set_sensor_dpi(0, next).await?;
}
}
Ok(())
}