hidpp/feature/
vertical_scrolling.rs1use num_enum::TryFromPrimitive;
4use openlogi_hidpp_derive::Feature;
5
6use crate::{feature::FeatureEndpoint, protocol::v20::Hidpp20Error};
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TryFromPrimitive)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize))]
11#[non_exhaustive]
12#[repr(u8)]
13pub enum RollerType {
14 Standard = 0x01,
16 ThreeG = 0x03,
18 MicroRatchet = 0x04,
20 Touchpad = 0x05,
22 TouchpadNaturalDefault = 0x06,
24}
25
26#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
28#[cfg_attr(feature = "serde", derive(serde::Serialize))]
29#[non_exhaustive]
30pub enum ScrollLines {
31 SystemDefault,
33 Lines(u8),
35 Page,
37}
38
39#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
41#[cfg_attr(feature = "serde", derive(serde::Serialize))]
42#[non_exhaustive]
43pub struct RollerInfo {
44 pub roller_type: RollerType,
46 pub ratchets_per_turn: u8,
48 pub scroll_lines: ScrollLines,
50}
51
52#[derive(Clone, Feature)]
54#[creatable(id = 0x2100, version = 0)]
55pub struct VerticalScrollingFeature {
56 endpoint: FeatureEndpoint,
58}
59
60impl VerticalScrollingFeature {
61 pub async fn get_roller_info(&self) -> Result<RollerInfo, Hidpp20Error> {
63 let payload = self.endpoint.call(0, [0; 3]).await?.extend_payload();
64 RollerInfo::from_payload(payload)
65 }
66}
67
68impl RollerInfo {
69 fn from_payload(payload: [u8; 16]) -> Result<Self, Hidpp20Error> {
70 Ok(Self {
71 roller_type: RollerType::try_from(payload[0])
72 .map_err(|_| Hidpp20Error::UnsupportedResponse)?,
73 ratchets_per_turn: payload[1],
74 scroll_lines: ScrollLines::from(payload[2]),
75 })
76 }
77}
78
79impl From<u8> for ScrollLines {
80 fn from(value: u8) -> Self {
81 match value {
82 0x00 => Self::SystemDefault,
83 0xff => Self::Page,
84 lines => Self::Lines(lines),
85 }
86 }
87}
88
89#[cfg(test)]
90#[allow(clippy::unwrap_used, reason = "expect/unwrap are idiomatic in tests")]
91mod tests {
92 use super::{RollerInfo, RollerType, ScrollLines};
93
94 #[test]
95 fn parses_roller_info() {
96 let mut payload = [0; 16];
97 payload[0] = 0x04;
98 payload[1] = 24;
99 payload[2] = 0xff;
100
101 let info = RollerInfo::from_payload(payload).unwrap();
102
103 assert_eq!(info.roller_type, RollerType::MicroRatchet);
104 assert_eq!(info.ratchets_per_turn, 24);
105 assert_eq!(info.scroll_lines, ScrollLines::Page);
106 }
107}