0x4600 · crown
控制 MX Master 旋转表冠——查询硬件能力、读写上报模式与棘轮模式,并接收转发的旋转、触摸、手势与按钮事件。
Crown 功能控制 MX Master 系列上的旋转表冠。get_info 返回硬件的
CrownControlCapabilities(按钮、长按、机械棘轮、可配置旋转超时、短长按阈值与双击速度)以及
CrownSensorCapabilities(近接、触摸、单击与双击手势),同时给出每圈的槽位数与棘轮数。
get_mode 与 set_mode 读取和写入当前的 CrownMode:事件是通过原生 HID 通道传送还是转发到
HID++(ReportingMode)、棘轮与自由旋转的选择(RatchetMode),以及三个可配置时间参数——旋转超时、短长按阈值和双击速度,均以 10 ms 为步进。SetCrownMode 的每个字段均以零
/ NoChange 为"保持不变"标记,可在不影响其他参数的情况下单独更新某项设置。
转发模式下,表冠会发出单一的 CrownEvent::Update,其中携带一个 CrownUpdate 快照:
rotation_state/relative_slot_rotation/relative_ratchet_rotation/speed——RotationState阶段、带符号的槽位与棘轮增量,以及当前速度(槽位/秒)。proximity/touch——ActivityState生命周期阶段(Start→Active→Stop)。gesture——CrownGesture:Tap、DoubleTap或None。button——ButtonState:Inactive、Press、ShortPressActive、LongPress、LongPressActive或Release。
规格: Logitech HID++ 2.0 —— 0x4600 crown。用于:
openlogi-hidpp中的类型化包装器。
Function reference
The CrownFeature wrapper (0x4600) exposes:
Methods
| Function | HID++ fn | Signature | Returns |
|---|---|---|---|
get_info | 0 | () | CrownInfo |
get_mode | 1 | () | CrownMode |
set_mode | 2 | (mode: SetCrownMode) | CrownMode |
listen | event | () | Receiver<CrownEvent> |
get_info, get_mode, and set_mode are async and return Result<…, Hidpp20Error>. listen is synchronous and returns an async_channel::Receiver<CrownEvent> directly.
Types
CrownInfo
Crown capabilities and hardware constants returned by get_info.
| Field | Type | Description |
|---|---|---|
controls | CrownControlCapabilities | Control capabilities. |
sensors | CrownSensorCapabilities | Sensor capabilities. |
slots | u16 | Number of slots per revolution. |
ratchets | u16 | Number of ratchets per revolution. |
CrownControlCapabilities
Crown control capabilities, from get_info.
| Flag | Bit/Value | Description |
|---|---|---|
BUTTON | 1 << 0 | The crown has a button. |
BUTTON_LONG_PRESS | 1 << 1 | The button reports long presses. |
MECHANIZED_RATCHET | 1 << 2 | The ratchet is mechanized (no manual control). |
ROTATION_TIMEOUT_CONFIGURABLE | 1 << 3 | The rotation timeout is configurable. |
SHORT_LONG_TIMEOUT_CONFIGURABLE | 1 << 4 | The short-long timeout is configurable. |
DOUBLE_TAP_SPEED_CONFIGURABLE | 1 << 5 | The double-tap speed is configurable. |
CrownSensorCapabilities
Crown sensor capabilities, from get_info.
| Flag | Bit/Value | Description |
|---|---|---|
PROXIMITY | 1 << 0 | The crown has a proximity sensor. |
TOUCH | 1 << 1 | The crown has a touch sensor. |
TAP_GESTURE | 1 << 2 | The crown detects tap gestures. |
DOUBLE_TAP_GESTURE | 1 << 3 | The crown detects double-tap gestures. |
CrownMode
The crown's current mode, returned by get_mode and echoed by set_mode.
| Field | Type | Description |
|---|---|---|
diverting | ReportingMode | How events are reported. |
ratchet_mode | RatchetMode | Ratchet mode. |
rotation_timeout | u8 | Rotation timeout, in 10 ms steps. |
short_long_timeout | u8 | Short-long press timeout, in 10 ms steps. |
double_tap_speed | u8 | Double-tap speed, in 10 ms steps. |
SetCrownMode
Mode settings written by set_mode. Every field uses 0 / ReportingMode::NoChange / RatchetMode::NoChange as a "leave unchanged" sentinel. The rotation timeout is clipped to 0x40.
| Field | Type | Description |
|---|---|---|
diverting | ReportingMode | How events are reported, or ReportingMode::NoChange. |
ratchet_mode | RatchetMode | Ratchet mode, or RatchetMode::NoChange. |
rotation_timeout | u8 | Rotation timeout in 10 ms steps, or 0 to leave unchanged. |
short_long_timeout | u8 | Short-long timeout in 10 ms steps, or 0 to leave unchanged. |
double_tap_speed | u8 | Double-tap speed in 10 ms steps, or 0 to leave unchanged. |
ReportingMode
How crown events are reported.
| Variant | Value | Description |
|---|---|---|
NoChange | 0 | Leave the setting unchanged (write-only sentinel). |
Hid | 1 | Events go to the native HID channel. |
Diverted | 2 | Events are diverted to HID++ (required for CrownEvent). |
RatchetMode
The crown's ratchet mode.
| Variant | Value | Description |
|---|---|---|
NoChange | 0 | Leave the setting unchanged (write-only sentinel). |
Free | 1 | Free-spinning mode. |
Ratchet | 2 | Ratchet (detented) mode. |
RotationState
Rotation phase reported in a CrownUpdate.
| Variant | Value | Description |
|---|---|---|
Inactive | 0 | Not rotating (or not diverted). |
Start | 1 | Rotation started. |
Active | 2 | Rotation ongoing. |
Stop | 3 | Rotation stopped. |
ActivityState
Proximity or touch activity phase reported in a CrownUpdate.
| Variant | Value | Description |
|---|---|---|
Inactive | 0 | Inactive. |
Start | 1 | Started. |
Active | 2 | Ongoing. |
Stop | 3 | Stopped. |
CrownGesture
Touch gesture reported in a CrownUpdate.
| Variant | Value | Description |
|---|---|---|
None | 0 | No gesture. |
Tap | 1 | Single tap. |
DoubleTap | 2 | Double tap. |
ButtonState
Crown button state reported in a CrownUpdate.
| Variant | Value | Description |
|---|---|---|
Inactive | 0 | Inactive (or not diverted). |
Press | 1 | Press started. |
ShortPressActive | 2 | Short press active. |
LongPress | 3 | Long press reached the time threshold. |
LongPressActive | 4 | Long press active. |
Release | 5 | Released. |
Events
CrownFeature implements EmittingFeature<CrownEvent>; call listen() to receive a channel of CrownEvent values. Events are only delivered while the crown is diverted (ReportingMode::Diverted).
CrownEvent
| Variant | Description |
|---|---|
Update(CrownUpdate) | The crown's rotation, proximity, touch, gesture, or button state changed. |
CrownUpdate
Payload of CrownEvent::Update.
| Field | Type | Description |
|---|---|---|
rotation_state | RotationState | Current rotation phase. |
relative_slot_rotation | i8 | Slots rotated since the last event (-127..=127). |
relative_ratchet_rotation | i8 | Ratchets rotated since the last event (-127..=127). |
proximity | ActivityState | Proximity-sensor phase. |
touch | ActivityState | Touch-sensor phase. |
gesture | CrownGesture | Touch gesture detected. |
button | ButtonState | Button state. |
speed | i16 | Crown speed in slots per second (signed). |
Wire format
Getter requests carry a 3-byte zero payload (call). set_mode uses a 16-byte long payload (call_long). All responses are read from the 16-byte extended payload returned by extend_payload(). Events arrive as unsolicited 16-byte messages on function index 0.
get_info (fn 0)
Request: [0x00, 0x00, 0x00]
Response (byte → field):
| Byte | Field | Notes |
|---|---|---|
| 0 | controls | CrownControlCapabilities bitfield |
| 1 | sensors | CrownSensorCapabilities bitfield |
| 2–3 | slots | Big-endian u16 — slots per revolution |
| 4–5 | ratchets | Big-endian u16 — ratchets per revolution |
get_mode (fn 1)
Request: [0x00, 0x00, 0x00]
Response (byte → field):
| Byte | Field | Notes |
|---|---|---|
| 0 | diverting | ReportingMode enum (0=NoChange, 1=Hid, 2=Diverted) |
| 1 | ratchet_mode | RatchetMode enum (0=NoChange, 1=Free, 2=Ratchet) |
| 2 | rotation_timeout | u8, in 10 ms steps |
| 3 | short_long_timeout | u8, in 10 ms steps |
| 4 | double_tap_speed | u8, in 10 ms steps |
set_mode (fn 2)
Request (16-byte long payload — bytes 5–15 are 0x00):
| Byte | Field | Notes |
|---|---|---|
| 0 | diverting | ReportingMode as u8 |
| 1 | ratchet_mode | RatchetMode as u8 |
| 2 | rotation_timeout | u8, in 10 ms steps |
| 3 | short_long_timeout | u8, in 10 ms steps |
| 4 | double_tap_speed | u8, in 10 ms steps |
Response: same layout as get_mode — the device echoes the resulting active mode.
CrownEvent::Update (event fn 0)
Unsolicited event emitted while the crown is diverted:
| Byte | Field | Notes |
|---|---|---|
| 0 | rotation_state | RotationState enum |
| 1 | relative_slot_rotation | i8 — signed slot delta since last event |
| 2 | relative_ratchet_rotation | i8 — signed ratchet delta since last event |
| 3 | proximity | ActivityState enum |
| 4 | touch | ActivityState enum |
| 5 | gesture | CrownGesture enum |
| 6 | button | ButtonState enum |
| 7–13 | (reserved) | not decoded by the driver |
| 14–15 | speed | Big-endian i16 — slots per second |
Usage (Rust)
use hidpp::{
device::Device,
feature::crown::{CrownFeature, ReportingMode, RatchetMode, SetCrownMode},
};
// device: &mut Device, already created via Device::new(channel, index)
device.enumerate_features().await?;
if let Some(feat) = device.get_feature::<CrownFeature>() {
let info = feat.get_info().await?;
println!("slots/rev={}, ratchets/rev={}", info.slots, info.ratchets);
// Divert crown events to HID++ and switch to ratchet mode
let mode = feat.set_mode(SetCrownMode {
diverting: ReportingMode::Diverted,
ratchet_mode: RatchetMode::Ratchet,
rotation_timeout: 0, // leave unchanged
short_long_timeout: 0, // leave unchanged
double_tap_speed: 0, // leave unchanged
}).await?;
println!("active mode: {:?}", mode.diverting);
// Receive crown events
let rx = feat.listen();
while let Ok(event) = rx.recv().await {
println!("{:?}", event);
}
}