hidpp/feature/feature_set/mod.rs
1//! Implements the `FeatureSet` feature (ID `0x0001`) that allows enumerating
2//! all the features supported by a device.
3
4use std::sync::Arc;
5
6use crate::{
7 channel::HidppChannel,
8 feature::{CreatableFeature, Feature, FeatureEndpoint, FeatureType},
9 protocol::v20::Hidpp20Error,
10};
11
12/// Implements the `FeatureSet` / `0x0001` feature.
13///
14/// This feature is primarily used to collect all features supported by the
15/// device. To achieve this, call [`Self::count`] to retrieve the amount of
16/// supported features (excluding the root feature). Then call
17/// [`Self::get_feature`] for every `i in 1..=count` (1-based, as accessing the
18/// root feature is not allowed).
19#[derive(Clone)]
20pub struct FeatureSetFeature {
21 /// The endpoint this feature talks to.
22 endpoint: FeatureEndpoint,
23}
24
25impl CreatableFeature for FeatureSetFeature {
26 const ID: u16 = 0x0001;
27 const STARTING_VERSION: u8 = 0;
28
29 fn new(chan: Arc<HidppChannel>, device_index: u8, feature_index: u8) -> Self {
30 Self {
31 endpoint: FeatureEndpoint::new(chan, device_index, feature_index),
32 }
33 }
34}
35
36impl Feature for FeatureSetFeature {}
37
38impl FeatureSetFeature {
39 /// Retrieves the amount of features supported by the device, not including
40 /// the root feature.
41 pub async fn count(&self) -> Result<u8, Hidpp20Error> {
42 Ok(self.endpoint.call(0, [0; 3]).await?.extend_payload()[0])
43 }
44
45 /// Retrieves the information about a specific feature based on its index in
46 /// the feature table.
47 ///
48 /// Feature index `0` for the root feature is not allowed.
49 pub async fn get_feature(&self, index: u8) -> Result<FeatureInformation, Hidpp20Error> {
50 let payload = self
51 .endpoint
52 .call(1, [index, 0x00, 0x00])
53 .await?
54 .extend_payload();
55
56 Ok(FeatureInformation {
57 id: (payload[0] as u16) << 8 | payload[1] as u16,
58 typ: FeatureType::from(payload[2]),
59 version: payload[3],
60 })
61 }
62}
63
64/// Represents information about a specific feature as returned by the
65/// [`FeatureSetFeature::get_feature`] function.
66#[derive(Clone, Copy, Hash, Debug)]
67#[cfg_attr(feature = "serde", derive(serde::Serialize))]
68#[non_exhaustive]
69pub struct FeatureInformation {
70 /// The protocol ID of the feature.
71 pub id: u16,
72
73 /// The type of the feature.
74 pub typ: FeatureType,
75
76 /// The latest supported version of the feature.
77 ///
78 /// Multi-version features are always backwards compatible as long as the
79 /// feature ID does not change, meaning functions implemented for an older
80 /// version of the same feature will behave as expected for every later
81 /// version.
82 ///
83 /// This field was added in feature version 1 and will be `0` for all older
84 /// versions.
85 pub version: u8,
86}