hidpp/feature/
extended_report_rate.rs1use num_enum::{IntoPrimitive, TryFromPrimitive};
4use openlogi_hidpp_derive::Feature;
5
6use crate::{feature::FeatureEndpoint, protocol::v20::Hidpp20Error};
7
8bitflags::bitflags! {
9 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
11 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
12 pub struct ExtendedReportRateList: u16 {
13 const HZ_125 = 1 << 0;
15 const HZ_250 = 1 << 1;
17 const HZ_500 = 1 << 2;
19 const HZ_1000 = 1 << 3;
21 const HZ_2000 = 1 << 4;
23 const HZ_4000 = 1 << 5;
25 const HZ_8000 = 1 << 6;
27 }
28}
29
30#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, IntoPrimitive, TryFromPrimitive)]
32#[cfg_attr(feature = "serde", derive(serde::Serialize))]
33#[non_exhaustive]
34#[repr(u8)]
35pub enum ConnectionType {
36 Wired = 0,
38 GamingWireless = 1,
40}
41
42#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, IntoPrimitive, TryFromPrimitive)]
44#[cfg_attr(feature = "serde", derive(serde::Serialize))]
45#[non_exhaustive]
46#[repr(u8)]
47pub enum ExtendedReportRate {
48 Hz125 = 0,
50 Hz250 = 1,
52 Hz500 = 2,
54 Hz1000 = 3,
56 Hz2000 = 4,
58 Hz4000 = 5,
60 Hz8000 = 6,
62}
63
64#[derive(Clone, Feature)]
66#[creatable(id = 0x8061, version = 0)]
67pub struct ExtendedReportRateFeature {
68 endpoint: FeatureEndpoint,
70}
71
72impl ExtendedReportRateFeature {
73 pub async fn get_device_capabilities(
75 &self,
76 connection_type: ConnectionType,
77 ) -> Result<ExtendedReportRateList, Hidpp20Error> {
78 let payload = self
79 .endpoint
80 .call(0, [u8::from(connection_type), 0, 0])
81 .await?
82 .extend_payload();
83 Ok(report_rate_list_from_payload(payload))
84 }
85
86 pub async fn get_actual_report_rate_list(
88 &self,
89 ) -> Result<ExtendedReportRateList, Hidpp20Error> {
90 let payload = self.endpoint.call(1, [0; 3]).await?.extend_payload();
91 Ok(report_rate_list_from_payload(payload))
92 }
93
94 pub async fn get_report_rate(
96 &self,
97 connection_type: ConnectionType,
98 ) -> Result<ExtendedReportRate, Hidpp20Error> {
99 let payload = self
100 .endpoint
101 .call(2, [u8::from(connection_type), 0, 0])
102 .await?
103 .extend_payload();
104 ExtendedReportRate::try_from(payload[0]).map_err(|_| Hidpp20Error::UnsupportedResponse)
105 }
106
107 pub async fn set_report_rate(
109 &self,
110 report_rate: ExtendedReportRate,
111 ) -> Result<(), Hidpp20Error> {
112 self.endpoint.call(3, [u8::from(report_rate), 0, 0]).await?;
113 Ok(())
114 }
115}
116
117fn report_rate_list_from_payload(payload: [u8; 16]) -> ExtendedReportRateList {
118 ExtendedReportRateList::from_bits_retain(u16::from_be_bytes([payload[0], payload[1]]))
119}
120
121#[cfg(test)]
122mod tests {
123 use super::{ExtendedReportRateList, report_rate_list_from_payload};
124
125 #[test]
126 fn parses_report_rate_mask() {
127 let mut payload = [0; 16];
128 payload[1] = 0b0100_1001;
129
130 let rates = report_rate_list_from_payload(payload);
131
132 assert!(rates.contains(ExtendedReportRateList::HZ_125));
133 assert!(rates.contains(ExtendedReportRateList::HZ_1000));
134 assert!(rates.contains(ExtendedReportRateList::HZ_8000));
135 }
136}