Skip to main content

hidpp/feature/
feature_set.rs

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