hidpp/feature/wireless_device_status/
mod.rs1use std::sync::Arc;
5
6use num_enum::{IntoPrimitive, TryFromPrimitive};
7
8use crate::{
9 channel::HidppChannel,
10 event::EventEmitter,
11 feature::{CreatableFeature, EmittingFeature, Feature},
12 nibble,
13 protocol::v20,
14};
15
16pub struct WirelessDeviceStatusFeature {
18 chan: Arc<HidppChannel>,
20
21 emitter: Arc<EventEmitter<WirelessDeviceStatusEvent>>,
23
24 msg_listener_hdl: u32,
28}
29
30impl CreatableFeature for WirelessDeviceStatusFeature {
31 const ID: u16 = 0x1d4b;
32 const STARTING_VERSION: u8 = 0;
33
34 fn new(chan: Arc<HidppChannel>, device_index: u8, feature_index: u8) -> Self {
35 let emitter = Arc::new(EventEmitter::new());
36
37 let hdl = chan.add_msg_listener({
38 let emitter = Arc::clone(&emitter);
39
40 move |raw, matched| {
41 if matched {
42 return;
43 }
44
45 let msg = v20::Message::from(raw);
46
47 let header = msg.header();
48 if header.device_index != device_index
49 || header.feature_index != feature_index
50 || nibble::combine(header.software_id, header.function_id) != 0
51 {
52 return;
53 }
54
55 let payload = msg.extend_payload();
56 let Ok(status) = WirelessDeviceStatus::try_from(payload[0]) else {
57 return;
58 };
59 let Ok(request) = WirelessDeviceStatusRequest::try_from(payload[1]) else {
60 return;
61 };
62 let Ok(reason) = WirelessDeviceStatusReason::try_from(payload[2]) else {
63 return;
64 };
65
66 emitter.emit(WirelessDeviceStatusEvent::StatusBroadcast(
67 WirelessDeviceStatusBroadcast {
68 status,
69 request,
70 reason,
71 },
72 ));
73 }
74 });
75
76 Self {
77 chan,
78 emitter,
79 msg_listener_hdl: hdl,
80 }
81 }
82}
83
84impl Feature for WirelessDeviceStatusFeature {}
85
86impl EmittingFeature<WirelessDeviceStatusEvent> for WirelessDeviceStatusFeature {
87 fn listen(&self) -> async_channel::Receiver<WirelessDeviceStatusEvent> {
88 self.emitter.create_receiver()
89 }
90}
91
92impl Drop for WirelessDeviceStatusFeature {
93 fn drop(&mut self) {
94 self.chan.remove_msg_listener(self.msg_listener_hdl);
95 }
96}
97
98#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
101#[cfg_attr(feature = "serde", derive(serde::Serialize))]
102#[non_exhaustive]
103pub enum WirelessDeviceStatusEvent {
104 StatusBroadcast(WirelessDeviceStatusBroadcast),
108}
109
110#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
113#[cfg_attr(feature = "serde", derive(serde::Serialize))]
114#[non_exhaustive]
115pub struct WirelessDeviceStatusBroadcast {
116 pub status: WirelessDeviceStatus,
118
119 pub request: WirelessDeviceStatusRequest,
121
122 pub reason: WirelessDeviceStatusReason,
124}
125
126#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, IntoPrimitive, TryFromPrimitive)]
129#[cfg_attr(feature = "serde", derive(serde::Serialize))]
130#[non_exhaustive]
131#[repr(u8)]
132pub enum WirelessDeviceStatus {
133 Unknown = 0x00,
134 Reconnection = 0x01,
135}
136
137#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, IntoPrimitive, TryFromPrimitive)]
140#[cfg_attr(feature = "serde", derive(serde::Serialize))]
141#[non_exhaustive]
142#[repr(u8)]
143pub enum WirelessDeviceStatusRequest {
144 NoRequest = 0x00,
145 SoftwareReconfigurationNeeded = 0x01,
146}
147
148#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, IntoPrimitive, TryFromPrimitive)]
151#[cfg_attr(feature = "serde", derive(serde::Serialize))]
152#[non_exhaustive]
153#[repr(u8)]
154pub enum WirelessDeviceStatusReason {
155 Unknown = 0x00,
156 PowerSwitchActivated = 0x01,
157}