Skip to main content

hidpp/feature/crown/
event.rs

1//! The event emitted by the `Crown` feature (`0x4600`).
2
3use num_enum::{FromPrimitive, IntoPrimitive};
4
5/// Rotation phase reported in a [`CrownUpdate`].
6#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, IntoPrimitive, FromPrimitive)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize))]
8#[non_exhaustive]
9#[repr(u8)]
10pub enum RotationState {
11    /// Not rotating (or not diverted).
12    Inactive = 0,
13    /// Rotation started.
14    Start = 1,
15    /// Rotation ongoing.
16    Active = 2,
17    /// Rotation stopped.
18    Stop = 3,
19    /// A state this crate does not model; carries the raw byte.
20    #[num_enum(catch_all)]
21    Other(u8),
22}
23
24/// Proximity or touch activity phase reported in a [`CrownUpdate`].
25#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, IntoPrimitive, FromPrimitive)]
26#[cfg_attr(feature = "serde", derive(serde::Serialize))]
27#[non_exhaustive]
28#[repr(u8)]
29pub enum ActivityState {
30    /// Inactive.
31    Inactive = 0,
32    /// Started.
33    Start = 1,
34    /// Ongoing.
35    Active = 2,
36    /// Stopped.
37    Stop = 3,
38    /// A state this crate does not model; carries the raw byte.
39    #[num_enum(catch_all)]
40    Other(u8),
41}
42
43/// Touch gesture reported in a [`CrownUpdate`].
44#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, IntoPrimitive, FromPrimitive)]
45#[cfg_attr(feature = "serde", derive(serde::Serialize))]
46#[non_exhaustive]
47#[repr(u8)]
48pub enum CrownGesture {
49    /// No gesture.
50    None = 0,
51    /// Single tap.
52    Tap = 1,
53    /// Double tap.
54    DoubleTap = 2,
55    /// A gesture this crate does not model; carries the raw byte.
56    #[num_enum(catch_all)]
57    Other(u8),
58}
59
60/// Crown button state reported in a [`CrownUpdate`].
61#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, IntoPrimitive, FromPrimitive)]
62#[cfg_attr(feature = "serde", derive(serde::Serialize))]
63#[non_exhaustive]
64#[repr(u8)]
65pub enum ButtonState {
66    /// Inactive (or not diverted).
67    Inactive = 0,
68    /// Press started.
69    Press = 1,
70    /// Short press active.
71    ShortPressActive = 2,
72    /// Long press reached the time threshold.
73    LongPress = 3,
74    /// Long press active.
75    LongPressActive = 4,
76    /// Released.
77    Release = 5,
78    /// A state this crate does not model; carries the raw byte.
79    #[num_enum(catch_all)]
80    Other(u8),
81}
82
83/// An event emitted by [`CrownFeature`](super::CrownFeature).
84#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
85#[cfg_attr(feature = "serde", derive(serde::Serialize))]
86#[non_exhaustive]
87pub enum CrownEvent {
88    /// The crown's rotation, proximity, touch, gesture or button state changed.
89    ///
90    /// Only reported while the crown is diverted (see
91    /// [`set_mode`](super::CrownFeature::set_mode)).
92    Update(CrownUpdate),
93}
94
95/// Payload of [`CrownEvent::Update`].
96#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
97#[cfg_attr(feature = "serde", derive(serde::Serialize))]
98#[non_exhaustive]
99pub struct CrownUpdate {
100    /// Current rotation phase.
101    pub rotation_state: RotationState,
102    /// Slots rotated since the last event (`-127..=127`).
103    pub relative_slot_rotation: i8,
104    /// Ratchets rotated since the last event (`-127..=127`).
105    pub relative_ratchet_rotation: i8,
106    /// Proximity-sensor phase.
107    pub proximity: ActivityState,
108    /// Touch-sensor phase.
109    pub touch: ActivityState,
110    /// Touch gesture detected.
111    pub gesture: CrownGesture,
112    /// Button state.
113    pub button: ButtonState,
114    /// Crown speed in slots per second (signed).
115    pub speed: i16,
116}
117
118/// Decodes the `0x4600` event payload by its sub-id.
119pub(super) fn decode_event(sub_id: u8, payload: &[u8; 16]) -> Option<CrownEvent> {
120    match sub_id {
121        0 => Some(CrownEvent::Update(CrownUpdate {
122            rotation_state: RotationState::from(payload[0]),
123            relative_slot_rotation: payload[1] as i8,
124            relative_ratchet_rotation: payload[2] as i8,
125            proximity: ActivityState::from(payload[3]),
126            touch: ActivityState::from(payload[4]),
127            gesture: CrownGesture::from(payload[5]),
128            button: ButtonState::from(payload[6]),
129            speed: i16::from_be_bytes([payload[14], payload[15]]),
130        })),
131        _ => None,
132    }
133}