hidpp/feature/touchpad_raw_xy/
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::{DualXyData, TouchPoint, TouchpadRawEvent};
15
16use crate::{
17 channel::{HidppChannel, MessageListenerGuard},
18 event::EventEmitter,
19 feature::{CreatableFeature, EmittingFeature, Feature, FeatureEndpoint, event_payload},
20 protocol::v20::Hidpp20Error,
21};
22
23bitflags::bitflags! {
24 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
30 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
31 pub struct RawReportFlags: u8 {
32 const RAW = 1 << 0;
34 const FORCE_ADD = 1 << 1;
36 const ENHANCED = 1 << 2;
38 const WIDTH_HEIGHT = 1 << 3;
40 const NATIVE_GESTURE = 1 << 4;
42 const MAJOR_MINOR = 1 << 5;
44 const WIDTH_HEIGHT_8BIT = 1 << 6;
46 }
47}
48
49#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, IntoPrimitive, TryFromPrimitive)]
51#[cfg_attr(feature = "serde", derive(serde::Serialize))]
52#[non_exhaustive]
53#[repr(u8)]
54pub enum Origin {
55 LowerLeft = 1,
57 LowerRight = 2,
59 UpperLeft = 3,
61 UpperRight = 4,
63}
64
65#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
68#[cfg_attr(feature = "serde", derive(serde::Serialize))]
69#[non_exhaustive]
70pub struct TouchpadInfo {
71 pub x_size: u16,
73 pub y_size: u16,
75 pub z_data_range: u8,
77 pub area_data_range: u8,
79 pub timestamp_units: u8,
81 pub max_finger_count: u8,
83 pub origin: Origin,
85 pub pen_support: bool,
87 pub raw_report_mapping_version: u8,
89 pub dpi: u16,
91}
92
93impl TouchpadInfo {
94 fn from_payload(payload: &[u8; 16]) -> Result<Self, Hidpp20Error> {
95 Ok(Self {
96 x_size: u16::from_be_bytes([payload[0], payload[1]]),
97 y_size: u16::from_be_bytes([payload[2], payload[3]]),
98 z_data_range: payload[4],
99 area_data_range: payload[5],
100 timestamp_units: payload[6],
101 max_finger_count: payload[7],
102 origin: Origin::try_from(payload[8]).map_err(|_| Hidpp20Error::UnsupportedResponse)?,
103 pen_support: payload[9] != 0,
104 raw_report_mapping_version: payload[12],
105 dpi: u16::from_be_bytes([payload[13], payload[14]]),
106 })
107 }
108}
109
110pub struct TouchpadRawXyFeature {
112 endpoint: FeatureEndpoint,
114
115 emitter: Arc<EventEmitter<TouchpadRawEvent>>,
117
118 _msg_listener: MessageListenerGuard,
120}
121
122impl CreatableFeature for TouchpadRawXyFeature {
123 const ID: u16 = 0x6100;
124 const STARTING_VERSION: u8 = 0;
125
126 fn new(chan: Arc<HidppChannel>, device_index: u8, feature_index: u8) -> Self {
127 let emitter = Arc::new(EventEmitter::new());
128
129 let listener = chan.add_msg_listener_guarded({
130 let emitter = Arc::clone(&emitter);
131
132 move |raw, matched| {
133 let Some((func, payload)) =
134 event_payload(raw, matched, device_index, feature_index)
135 else {
136 return;
137 };
138 if let Some(event) = event::decode_event(func.to_lo(), &payload) {
139 emitter.emit(event);
140 }
141 }
142 });
143
144 Self {
145 endpoint: FeatureEndpoint::new(chan, device_index, feature_index),
146 emitter,
147 _msg_listener: listener,
148 }
149 }
150}
151
152impl Feature for TouchpadRawXyFeature {}
153
154impl EmittingFeature<TouchpadRawEvent> for TouchpadRawXyFeature {
155 fn listen(&self) -> async_channel::Receiver<TouchpadRawEvent> {
156 self.emitter.create_receiver()
157 }
158}
159
160impl TouchpadRawXyFeature {
161 pub async fn get_touchpad_info(&self) -> Result<TouchpadInfo, Hidpp20Error> {
163 let payload = self.endpoint.call(0, [0; 3]).await?.extend_payload();
164 TouchpadInfo::from_payload(&payload)
165 }
166
167 pub async fn get_raw_report_state(&self) -> Result<RawReportFlags, Hidpp20Error> {
169 let payload = self.endpoint.call(1, [0; 3]).await?.extend_payload();
170 Ok(RawReportFlags::from_bits_retain(payload[0]))
171 }
172
173 pub async fn set_raw_report_state(&self, flags: RawReportFlags) -> Result<(), Hidpp20Error> {
177 self.endpoint.call(2, [flags.bits(), 0, 0]).await?;
178 Ok(())
179 }
180}