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}