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, FeatureEndpoint},
11 protocol::v20::Hidpp20Error,
12};
13
14pub struct SmartShiftFeature {
16 endpoint: FeatureEndpoint,
18}
19
20impl CreatableFeature for SmartShiftFeature {
21 const ID: u16 = 0x2110;
22 const STARTING_VERSION: u8 = 0;
23
24 fn new(chan: Arc<HidppChannel>, device_index: u8, feature_index: u8) -> Self {
25 Self {
26 endpoint: FeatureEndpoint::new(chan, device_index, feature_index),
27 }
28 }
29}
30
31impl Feature for SmartShiftFeature {}
32
33impl SmartShiftFeature {
34 pub async fn get_ratchet_control_mode(&self) -> Result<RatchetControlMode, Hidpp20Error> {
40 let payload = self.endpoint.call(0, [0; 3]).await?.extend_payload();
41
42 Ok(RatchetControlMode {
43 wheel_mode: WheelMode::try_from(payload[0])
44 .map_err(|_| Hidpp20Error::UnsupportedResponse)?,
45 auto_disengage: payload[1],
46 auto_disengage_default: payload[2],
47 })
48 }
49
50 pub async fn set_ratchet_control_mode(
63 &self,
64 wheel_mode: Option<WheelMode>,
65 auto_disengage: Option<u8>,
66 auto_disengage_default: Option<u8>,
67 ) -> Result<(), Hidpp20Error> {
68 self.endpoint
69 .call(
70 1,
71 [
72 wheel_mode.map_or(0, u8::from),
73 auto_disengage.unwrap_or(0),
74 auto_disengage_default.unwrap_or(0),
75 ],
76 )
77 .await?;
78
79 Ok(())
80 }
81}
82
83#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
85#[cfg_attr(feature = "serde", derive(serde::Serialize))]
86#[non_exhaustive]
87pub struct RatchetControlMode {
88 pub wheel_mode: WheelMode,
92
93 pub auto_disengage: u8,
98
99 pub auto_disengage_default: u8,
101}
102
103#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, IntoPrimitive, TryFromPrimitive)]
105#[cfg_attr(feature = "serde", derive(serde::Serialize))]
106#[non_exhaustive]
107#[repr(u8)]
108pub enum WheelMode {
109 Freespin = 1,
110 Ratchet = 2,
111}