hidpp/feature/touch_mouse_raw/
mod.rs1pub mod event;
6
7#[cfg(test)]
8mod tests;
9
10use std::sync::Arc;
11
12use num_enum::{IntoPrimitive, TryFromPrimitive};
13
14pub use event::{TouchMousePoint, TouchMouseRawEvent, TouchMouseStatus};
15
16use crate::{
17 channel::{HidppChannel, MessageListenerGuard},
18 event::EventEmitter,
19 feature::{CreatableFeature, EmittingFeature, Feature, FeatureEndpoint, event_payload},
20 protocol::v20::Hidpp20Error,
21};
22
23#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, IntoPrimitive, TryFromPrimitive)]
25#[cfg_attr(feature = "serde", derive(serde::Serialize))]
26#[non_exhaustive]
27#[repr(u8)]
28pub enum Origin {
29 LowerLeft = 1,
31 LowerRight = 2,
33 UpperLeft = 3,
35 UpperRight = 4,
37}
38
39#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, IntoPrimitive, TryFromPrimitive)]
41#[cfg_attr(feature = "serde", derive(serde::Serialize))]
42#[non_exhaustive]
43#[repr(u8)]
44pub enum RawMode {
45 NativeGestures = 0,
47 RawFiltered = 1,
49 RawUnfilteredAndGestures = 2,
51 RawUnfilteredAlways = 3,
53 RawUnfilteredWithZ = 4,
56}
57
58#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
61#[cfg_attr(feature = "serde", derive(serde::Serialize))]
62#[non_exhaustive]
63pub struct TouchMouseInfo {
64 pub x_max_count: u16,
66 pub y_max_count: u16,
68 pub resolution_dpi: u16,
70 pub origin: Origin,
72 pub max_finger_count: u8,
74 pub width_height_data_range: u8,
76}
77
78impl TouchMouseInfo {
79 fn from_payload(payload: &[u8; 16]) -> Result<Self, Hidpp20Error> {
80 Ok(Self {
81 x_max_count: u16::from_be_bytes([payload[0], payload[1]]),
82 y_max_count: u16::from_be_bytes([payload[2], payload[3]]),
83 resolution_dpi: u16::from_be_bytes([payload[4], payload[5]]),
84 origin: Origin::try_from(payload[6]).map_err(|_| Hidpp20Error::UnsupportedResponse)?,
85 max_finger_count: payload[7],
86 width_height_data_range: payload[8],
87 })
88 }
89}
90
91pub struct TouchMouseRawFeature {
93 endpoint: FeatureEndpoint,
95
96 emitter: Arc<EventEmitter<TouchMouseRawEvent>>,
98
99 _msg_listener: MessageListenerGuard,
101}
102
103impl CreatableFeature for TouchMouseRawFeature {
104 const ID: u16 = 0x6110;
105 const STARTING_VERSION: u8 = 0;
106
107 fn new(chan: Arc<HidppChannel>, device_index: u8, feature_index: u8) -> Self {
108 let emitter = Arc::new(EventEmitter::new());
109
110 let listener = chan.add_msg_listener_guarded({
111 let emitter = Arc::clone(&emitter);
112
113 move |raw, matched| {
114 let Some((func, payload)) =
115 event_payload(raw, matched, device_index, feature_index)
116 else {
117 return;
118 };
119 if let Some(event) = event::decode_event(func.to_lo(), &payload) {
120 emitter.emit(event);
121 }
122 }
123 });
124
125 Self {
126 endpoint: FeatureEndpoint::new(chan, device_index, feature_index),
127 emitter,
128 _msg_listener: listener,
129 }
130 }
131}
132
133impl Feature for TouchMouseRawFeature {}
134
135impl EmittingFeature<TouchMouseRawEvent> for TouchMouseRawFeature {
136 fn listen(&self) -> async_channel::Receiver<TouchMouseRawEvent> {
137 self.emitter.create_receiver()
138 }
139}
140
141impl TouchMouseRawFeature {
142 pub async fn get_touchpad_info(&self) -> Result<TouchMouseInfo, Hidpp20Error> {
144 let payload = self.endpoint.call(0, [0; 3]).await?.extend_payload();
145 TouchMouseInfo::from_payload(&payload)
146 }
147
148 pub async fn get_raw_mode(&self) -> Result<RawMode, Hidpp20Error> {
150 let payload = self.endpoint.call(1, [0; 3]).await?.extend_payload();
151 RawMode::try_from(payload[0]).map_err(|_| Hidpp20Error::UnsupportedResponse)
152 }
153
154 pub async fn set_raw_mode(&self, mode: RawMode) -> Result<(), Hidpp20Error> {
159 self.endpoint.call(2, [mode.into(), 0, 0]).await?;
160 Ok(())
161 }
162}