hidpp/feature/
dual_platform.rs1use num_enum::{IntoPrimitive, TryFromPrimitive};
9use openlogi_hidpp_derive::Feature;
10
11use crate::{
12 feature::{DecodeEvent, EventSource, FeatureEndpoint},
13 protocol::v20::Hidpp20Error,
14};
15
16#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, IntoPrimitive, TryFromPrimitive)]
21#[cfg_attr(feature = "serde", derive(serde::Serialize))]
22#[non_exhaustive]
23#[repr(u8)]
24pub enum DualPlatformSelection {
25 IosOrMac = 0,
27 AndroidOrWindows = 1,
29}
30
31#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
33#[cfg_attr(feature = "serde", derive(serde::Serialize))]
34#[non_exhaustive]
35pub enum DualPlatformEvent {
36 PlatformChanged(DualPlatformSelection),
38}
39
40#[derive(Feature)]
42#[creatable(id = 0x4530, version = 0)]
43pub struct DualPlatformFeature {
44 endpoint: FeatureEndpoint,
46
47 events: EventSource<DualPlatformEvent>,
49}
50
51impl DecodeEvent for DualPlatformEvent {
52 fn decode(sub_id: u8, payload: &[u8; 16]) -> Option<Self> {
53 if sub_id != 0 {
55 return None;
56 }
57 DualPlatformSelection::try_from(payload[0])
58 .ok()
59 .map(DualPlatformEvent::PlatformChanged)
60 }
61}
62
63impl DualPlatformFeature {
64 pub async fn get_platform(&self) -> Result<DualPlatformSelection, Hidpp20Error> {
66 let payload = self.endpoint.call(1, [0; 3]).await?.extend_payload();
68 DualPlatformSelection::try_from(payload[0]).map_err(|_| Hidpp20Error::UnsupportedResponse)
69 }
70
71 pub async fn set_platform(
75 &self,
76 platform: DualPlatformSelection,
77 ) -> Result<DualPlatformSelection, Hidpp20Error> {
78 let payload = self
79 .endpoint
80 .call(2, [platform.into(), 0, 0])
81 .await?
82 .extend_payload();
83 DualPlatformSelection::try_from(payload[0]).map_err(|_| Hidpp20Error::UnsupportedResponse)
84 }
85}
86
87#[cfg(test)]
88#[allow(clippy::unwrap_used, reason = "expect/unwrap are idiomatic in tests")]
89mod tests {
90 use super::DualPlatformSelection;
91
92 #[test]
93 fn maps_platform_wire_values() {
94 assert_eq!(
95 DualPlatformSelection::try_from(0).unwrap(),
96 DualPlatformSelection::IosOrMac
97 );
98 assert_eq!(
99 DualPlatformSelection::try_from(1).unwrap(),
100 DualPlatformSelection::AndroidOrWindows
101 );
102 DualPlatformSelection::try_from(2).unwrap_err();
103 assert_eq!(u8::from(DualPlatformSelection::AndroidOrWindows), 1);
104 }
105}