openlogi_hid/write/
diagnostics.rs1use std::sync::Arc;
2
3use hidpp::{device::Device, feature::CreatableFeature, feature::feature_set::FeatureSetFeature};
4
5use crate::reprog_controls::{self, CidFlags, CidInfo, ReprogControlsV4};
6use crate::route::DeviceRoute;
7use crate::write::{HidppOperation, WriteError, classify_hidpp_error, with_route};
8
9#[derive(Debug, Clone, Copy)]
12pub struct FeatureEntry {
13 pub id: u16,
15 pub version: u8,
17}
18
19#[derive(Debug, Clone, Copy)]
23pub struct ReprogControlEntry {
24 pub cid: u16,
26 pub task_id: u16,
28 pub flags: CidFlags,
30}
31
32impl From<CidInfo> for ReprogControlEntry {
33 fn from(info: CidInfo) -> Self {
34 Self {
35 cid: info.cid.into(),
36 task_id: info.task_id.0,
37 flags: info.flags,
38 }
39 }
40}
41
42pub async fn dump_features(route: &DeviceRoute) -> Result<Vec<FeatureEntry>, WriteError> {
47 let index = route.device_index();
48 with_route(route, move |channel| async move {
49 let mut device = Device::new(Arc::clone(&channel), index)
50 .await
51 .map_err(|_| WriteError::DeviceUnreachable { index })?;
52 let feature_set_info = device
56 .root()
57 .get_feature(FeatureSetFeature::ID)
58 .await
59 .map_err(|e| {
60 classify_hidpp_error(e, HidppOperation::DumpFeatures, FeatureSetFeature::ID)
61 })?
62 .ok_or(WriteError::FeatureUnsupported {
63 feature_hex: FeatureSetFeature::ID,
64 })?;
65 let feature_set = device.add_feature::<FeatureSetFeature>(feature_set_info.index);
66 let count = feature_set.count().await.map_err(|e| {
67 classify_hidpp_error(e, HidppOperation::DumpFeatures, FeatureSetFeature::ID)
68 })?;
69 let mut entries = Vec::with_capacity(usize::from(count));
70 for i in 0..=count {
71 let info = feature_set.get_feature(i).await.map_err(|e| {
72 classify_hidpp_error(e, HidppOperation::DumpFeatures, FeatureSetFeature::ID)
73 })?;
74 entries.push(FeatureEntry {
75 id: info.id,
76 version: info.version,
77 });
78 }
79 Ok(entries)
80 })
81 .await
82}
83
84pub async fn dump_reprog_controls(
90 route: &DeviceRoute,
91) -> Result<Vec<ReprogControlEntry>, WriteError> {
92 let index = route.device_index();
93 with_route(route, move |channel| async move {
94 let device = Device::new(Arc::clone(&channel), index)
95 .await
96 .map_err(|_| WriteError::DeviceUnreachable { index })?;
97 let info = device
98 .root()
99 .get_feature(reprog_controls::FEATURE_ID)
100 .await
101 .map_err(|e| {
102 classify_hidpp_error(e, HidppOperation::DumpFeatures, reprog_controls::FEATURE_ID)
103 })?
104 .ok_or(WriteError::FeatureUnsupported {
105 feature_hex: reprog_controls::FEATURE_ID,
106 })?;
107 let rc = ReprogControlsV4::new(Arc::clone(&channel), index, info.index);
108 let count = rc.get_count().await.map_err(|e| {
109 classify_hidpp_error(e, HidppOperation::DumpFeatures, reprog_controls::FEATURE_ID)
110 })?;
111 let mut entries = Vec::with_capacity(usize::from(count));
112 for i in 0..count {
113 let control = rc.get_cid_info(i).await.map_err(|e| {
114 classify_hidpp_error(e, HidppOperation::DumpFeatures, reprog_controls::FEATURE_ID)
115 })?;
116 entries.push(control.into());
117 }
118 Ok(entries)
119 })
120 .await
121}