1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//! Implements the `SmartShift` feature (ID `0x2110`) that allows controlling a
//! smart shift enhanced scroll wheel.
use std::hash::Hash;
use num_enum::{IntoPrimitive, TryFromPrimitive};
use openlogi_hidpp_derive::Feature;
use crate::{feature::FeatureEndpoint, protocol::v20::Hidpp20Error};
/// Implements the `SmartShift` / `0x2110` feature.
#[derive(Feature)]
#[creatable(id = 0x2110, version = 0)]
pub struct SmartShiftFeature {
/// The endpoint this feature talks to.
endpoint: FeatureEndpoint,
}
impl SmartShiftFeature {
/// Retrieves the current ratchet control mode.
///
/// [`RatchetControlMode::wheel_mode`] will only reflect the value set
/// either by software or the wheel mode button. It will not provide
/// information about whether the wheel is in auto-disengaged mode.
pub async fn get_ratchet_control_mode(&self) -> Result<RatchetControlMode, Hidpp20Error> {
let payload = self.endpoint.call(0, [0; 3]).await?.extend_payload();
Ok(RatchetControlMode {
wheel_mode: WheelMode::try_from(payload[0])
.map_err(|_| Hidpp20Error::UnsupportedResponse)?,
auto_disengage: payload[1],
auto_disengage_default: payload[2],
})
}
/// Sets the ratchet control mode.
///
/// For `auto_disengage` (and `auto_disengage_default` respectively), the
/// values `0x01..=0xfe` correspond to the amount of quarter-turns the wheel
/// has to make per second for the wheel to disengage.
/// `0xff` enables permanent ratchet mode.
///
/// All values are optional and will stay as they are if provided with
/// [`None`].
///
/// For `auto_disengage` and `auto_disengange_default`, `0` will have the
/// same effect as [`None`].
pub async fn set_ratchet_control_mode(
&self,
wheel_mode: Option<WheelMode>,
auto_disengage: Option<u8>,
auto_disengage_default: Option<u8>,
) -> Result<(), Hidpp20Error> {
self.endpoint
.call(
1,
[
wheel_mode.map_or(0, u8::from),
auto_disengage.unwrap_or(0),
auto_disengage_default.unwrap_or(0),
],
)
.await?;
Ok(())
}
}
/// Represents the ratchet control mode of the mouse wheel.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub struct RatchetControlMode {
/// The mode the wheel is currently set to.
///
/// This does not reflect the automatic disengage state.
pub wheel_mode: WheelMode,
/// The amount of quarter-turns per second it takes for the wheel to
/// automatically disengage.
///
/// If this value is `0xff`, the wheel will not disengage automatically.
pub auto_disengage: u8,
/// The default value of [`Self::auto_disengage`].
pub auto_disengage_default: u8,
}
/// Represents the ratchet mode of the scroll wheel.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, IntoPrimitive, TryFromPrimitive)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
#[repr(u8)]
pub enum WheelMode {
/// Free-spin wheel mode.
Freespin = 1,
/// Ratchet wheel mode.
Ratchet = 2,
}