hidpp/feature/smartshift/
mod.rs1use std::{hash::Hash, sync::Arc};
5
6use num_enum::{IntoPrimitive, TryFromPrimitive};
7
8use crate::{
9 channel::HidppChannel,
10 feature::{CreatableFeature, Feature},
11 nibble::U4,
12 protocol::v20::{self, Hidpp20Error},
13};
14
15pub struct SmartShiftFeature {
17 chan: Arc<HidppChannel>,
19
20 device_index: u8,
22
23 feature_index: u8,
25}
26
27impl CreatableFeature for SmartShiftFeature {
28 const ID: u16 = 0x2110;
29 const STARTING_VERSION: u8 = 0;
30
31 fn new(chan: Arc<HidppChannel>, device_index: u8, feature_index: u8) -> Self {
32 Self {
33 chan,
34 device_index,
35 feature_index,
36 }
37 }
38}
39
40impl Feature for SmartShiftFeature {}
41
42impl SmartShiftFeature {
43 pub async fn get_ratchet_control_mode(&self) -> Result<RatchetControlMode, Hidpp20Error> {
49 let response = self
50 .chan
51 .send_v20(v20::Message::Short(
52 v20::MessageHeader {
53 device_index: self.device_index,
54 feature_index: self.feature_index,
55 function_id: U4::from_lo(0),
56 software_id: self.chan.get_sw_id(),
57 },
58 [0x00, 0x00, 0x00],
59 ))
60 .await?;
61
62 let payload = response.extend_payload();
63
64 Ok(RatchetControlMode {
65 wheel_mode: WheelMode::try_from(payload[0])
66 .map_err(|_| Hidpp20Error::UnsupportedResponse)?,
67 auto_disengage: payload[1],
68 auto_disengage_default: payload[2],
69 })
70 }
71
72 pub async fn set_ratchet_control_mode(
85 &self,
86 wheel_mode: Option<WheelMode>,
87 auto_disengage: Option<u8>,
88 auto_disengage_default: Option<u8>,
89 ) -> Result<(), Hidpp20Error> {
90 self.chan
91 .send_v20(v20::Message::Short(
92 v20::MessageHeader {
93 device_index: self.device_index,
94 feature_index: self.feature_index,
95 function_id: U4::from_lo(1),
96 software_id: self.chan.get_sw_id(),
97 },
98 [
99 wheel_mode.map_or(0, u8::from),
100 auto_disengage.unwrap_or(0),
101 auto_disengage_default.unwrap_or(0),
102 ],
103 ))
104 .await?;
105
106 Ok(())
107 }
108}
109
110#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
112#[cfg_attr(feature = "serde", derive(serde::Serialize))]
113#[non_exhaustive]
114pub struct RatchetControlMode {
115 pub wheel_mode: WheelMode,
119
120 pub auto_disengage: u8,
125
126 pub auto_disengage_default: u8,
128}
129
130#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, IntoPrimitive, TryFromPrimitive)]
132#[cfg_attr(feature = "serde", derive(serde::Serialize))]
133#[non_exhaustive]
134#[repr(u8)]
135pub enum WheelMode {
136 Freespin = 1,
137 Ratchet = 2,
138}