use std::sync::Arc;
use hidpp::{device::Device, feature::CreatableFeature, feature::feature_set::FeatureSetFeature};
use crate::reprog_controls::{self, CidFlags, CidInfo, ReprogControlsV4};
use crate::route::DeviceRoute;
use crate::write::{HidppOperation, WriteError, classify_hidpp_error, with_route};
#[derive(Debug, Clone, Copy)]
pub struct FeatureEntry {
pub id: u16,
pub version: u8,
}
#[derive(Debug, Clone, Copy)]
pub struct ReprogControlEntry {
pub cid: u16,
pub task_id: u16,
pub flags: CidFlags,
}
impl From<CidInfo> for ReprogControlEntry {
fn from(info: CidInfo) -> Self {
Self {
cid: info.cid.into(),
task_id: info.task_id.0,
flags: info.flags,
}
}
}
pub async fn dump_features(route: &DeviceRoute) -> Result<Vec<FeatureEntry>, WriteError> {
let index = route.device_index();
with_route(route, move |channel| async move {
let mut device = Device::new(Arc::clone(&channel), index)
.await
.map_err(|_| WriteError::DeviceUnreachable { index })?;
let feature_set_info = device
.root()
.get_feature(FeatureSetFeature::ID)
.await
.map_err(|e| {
classify_hidpp_error(e, HidppOperation::DumpFeatures, FeatureSetFeature::ID)
})?
.ok_or(WriteError::FeatureUnsupported {
feature_hex: FeatureSetFeature::ID,
})?;
let feature_set = device.add_feature::<FeatureSetFeature>(feature_set_info.index);
let count = feature_set.count().await.map_err(|e| {
classify_hidpp_error(e, HidppOperation::DumpFeatures, FeatureSetFeature::ID)
})?;
let mut entries = Vec::with_capacity(usize::from(count));
for i in 0..=count {
let info = feature_set.get_feature(i).await.map_err(|e| {
classify_hidpp_error(e, HidppOperation::DumpFeatures, FeatureSetFeature::ID)
})?;
entries.push(FeatureEntry {
id: info.id,
version: info.version,
});
}
Ok(entries)
})
.await
}
pub async fn dump_reprog_controls(
route: &DeviceRoute,
) -> Result<Vec<ReprogControlEntry>, WriteError> {
let index = route.device_index();
with_route(route, move |channel| async move {
let device = Device::new(Arc::clone(&channel), index)
.await
.map_err(|_| WriteError::DeviceUnreachable { index })?;
let info = device
.root()
.get_feature(reprog_controls::FEATURE_ID)
.await
.map_err(|e| {
classify_hidpp_error(e, HidppOperation::DumpFeatures, reprog_controls::FEATURE_ID)
})?
.ok_or(WriteError::FeatureUnsupported {
feature_hex: reprog_controls::FEATURE_ID,
})?;
let rc = ReprogControlsV4::new(Arc::clone(&channel), index, info.index);
let count = rc.get_count().await.map_err(|e| {
classify_hidpp_error(e, HidppOperation::DumpFeatures, reprog_controls::FEATURE_ID)
})?;
let mut entries = Vec::with_capacity(usize::from(count));
for i in 0..count {
let control = rc.get_cid_info(i).await.map_err(|e| {
classify_hidpp_error(e, HidppOperation::DumpFeatures, reprog_controls::FEATURE_ID)
})?;
entries.push(control.into());
}
Ok(entries)
})
.await
}