OpenLogi

0x4600 · crown

查询和配置旋转表冠,并接收其转向后的转动、传感器、手势和按钮更新。

0x4600 控制受支持 MX Master 设备的旋转表冠。它公开能力和当前模式读取。它可以修改上报方式、棘轮模式和三个时间值。

规格: Logitech HID++ 2.0 —— x4600 crown(v0)。用于: OpenLogi 只提供类型化 openlogi-hidpp 包装器。

函数参考

CrownFeature 实现 feature 版本 0。

方法

函数HID++ fn签名返回值
get_info0()CrownInfo
get_mode1()CrownMode
set_mode2(mode: SetCrownMode)()
listenevent()async_channel::Receiver<CrownEvent>

前三个方法是 async,并返回 Result<…, Hidpp20Error>。listen 是同步方法。

类型

CrownInfo

字段类型说明
controlsCrownControlCapabilities控制能力位。
sensorsCrownSensorCapabilities传感器能力位。
slotsu16每圈的槽位数。
ratchetsu16每圈的棘齿数。

CrownControlCapabilities

字段值说明
BUTTON1 << 0表冠有按钮。
BUTTON_LONG_PRESS1 << 1按钮报告长按。
MECHANIZED_RATCHET1 << 2棘轮是机械式的。
ROTATION_TIMEOUT_CONFIGURABLE1 << 3可以配置转动超时。
SHORT_LONG_TIMEOUT_CONFIGURABLE1 << 4可以配置短按和长按阈值。
DOUBLE_TAP_SPEED_CONFIGURABLE1 << 5可以配置双击速度。

CrownSensorCapabilities

字段值说明
PROXIMITY1 << 0表冠有近接传感器。
TOUCH1 << 1表冠有触摸传感器。
TAP_GESTURE1 << 2表冠识别单击。
DOUBLE_TAP_GESTURE1 << 3表冠识别双击。

CrownMode 和 SetCrownMode

字段CrownMode 类型SetCrownMode 类型说明
divertingReportingModeOption<ReportingMode>事件上报目标。
ratchet_modeRatchetModeOption<RatchetMode>自由或棘轮转动。
rotation_timeoutu8Option<NonZeroU8>以 10 ms 为步进的超时。
short_long_timeoutu8Option<NonZeroU8>以 10 ms 为步进的按压阈值。
double_tap_speedu8Option<NonZeroU8>以 10 ms 为步进的双击速度。

SetCrownMode 中的 None 会写入协议的零保持不变标记。设备会将 rotation_timeout 限制为 0x40。CrownMode 会拒绝该标记和其他未知模式值。

ReportingMode 和 RatchetMode

类型变体值说明
ReportingModeHid1事件发送到原生 HID。
ReportingModeDiverted2事件发送到 HID++。
RatchetModeFree1自由转动。
RatchetModeRatchet2有刻度的转动。

事件

CrownFeature 实现 EmittingFeature<CrownEvent>。它只接受事件子 ID 0。

CrownEvent 和 CrownUpdate

变体或字段类型说明
Update(CrownUpdate)CrownEvent上报转向时的一条表冠更新。
rotation_stateRotationState转动生命周期状态。
relative_slot_rotationi8带符号的槽位增量。
relative_ratchet_rotationi8带符号的棘齿增量。
proximityActivityState近接生命周期状态。
touchActivityState触摸生命周期状态。
gestureCrownGesture触摸手势。
buttonButtonState按钮生命周期状态。
speedi16每秒带符号的槽位数。
类型变体值
RotationStateInactive、Start、Active、Stop、Other(u8)0–3、其他
ActivityStateInactive、Start、Active、Stop、Other(u8)0–3、其他
CrownGestureNone、Tap、DoubleTap、Other(u8)0–2、其他
ButtonStateInactive、Press、ShortPressActive、LongPress、LongPressActive、Release、Other(u8)0–5、其他

事件枚举会将未建模字节保留为 Other(u8)。

线格式

get_info 和 get_mode 发送三个零字节。set_mode 发送 16 字节长负载。OpenLogi 忽略下表未列出的响应字节。

get_info(fn 0)

字节字段备注
0controlsCrownControlCapabilities;未知位会保留。
1sensorsCrownSensorCapabilities;未知位会保留。
2–3slotsu16,BE。
4–5ratchetsu16,BE。
6–15—OpenLogi 忽略这些字节。

get_mode(fn 1)

字节字段备注
0diverting1 = Hid;2 = Diverted。0 和其他值会被拒绝。
1ratchet_mode1 = Free;2 = Ratchet。0 和其他值会被拒绝。
2rotation_timeoutu8,以 10 ms 为步进。
3short_long_timeoutu8,以 10 ms 为步进。
4double_tap_speedu8,以 10 ms 为步进。
5–15—OpenLogi 忽略这些字节。

set_mode(fn 2)

字节字段备注
0divertingSome(Hid) = 1;Some(Diverted) = 2;None = 0。
1ratchet_modeSome(Free) = 1;Some(Ratchet) = 2;None = 0。
2rotation_timeoutNonZeroU8 值,或 None 的 0。
3short_long_timeoutNonZeroU8 值,或 None 的 0。
4double_tap_speedNonZeroU8 值,或 None 的 0。
5–15—OpenLogi 写入 0x00。

协议响应回显请求字节。OpenLogi 不解码该响应。调用 get_mode 可读取结果模式。

CrownEvent::Update 事件(fn 0)

字节字段备注
0rotation_stateRotationState,包括 Other(u8)。
1relative_slot_rotationi8。
2relative_ratchet_rotationi8。
3proximityActivityState,包括 Other(u8)。
4touchActivityState,包括 Other(u8)。
5gestureCrownGesture,包括 Other(u8)。
6buttonButtonState,包括 Other(u8)。
7–13—OpenLogi 忽略这些字节。
14–15speedi16,BE。

OpenLogi 的用法

v0.8.15 的设备层和代理层没有使用 CrownFeature。类型化包装器向库使用者公开此功能。它不执行能力门控、读改写、读回检查或会话恢复。

Rust 用法

use std::num::NonZeroU8;

use hidpp::{
    device::Device,
    feature::{
        EmittingFeature,
        crown::{CrownFeature, RatchetMode, ReportingMode, SetCrownMode},
    },
};

// device: &mut Device, already created via Device::new(channel, index)
device.enumerate_features().await?;
if let Some(feature) = device.get_feature::<CrownFeature>() {
    feature
        .set_mode(SetCrownMode {
            diverting: Some(ReportingMode::Diverted),
            ratchet_mode: Some(RatchetMode::Ratchet),
            rotation_timeout: Some(NonZeroU8::new(10).unwrap()),
            short_long_timeout: None,
            double_tap_speed: None,
        })
        .await?;
    println!("{:?}", feature.get_mode().await?);

    let receiver = feature.listen();
    while let Ok(event) = receiver.recv().await {
        println!("{event:?}");
    }
}

本页目录