Skip to main content

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}