Skip to main content

hidpp/feature/disable_keys/
mod.rs

1//! Implements the `DisableKeys` feature (ID `0x4521`) that disables a fixed set
2//! of lock / system keys.
3//!
4//! For disabling arbitrary keys by HID usage, see
5//! [`DisableKeysByUsage`](super::disable_keys_by_usage) (`0x4522`).
6
7use std::sync::Arc;
8
9use crate::{
10    channel::HidppChannel,
11    feature::{CreatableFeature, Feature, FeatureEndpoint},
12    protocol::v20::Hidpp20Error,
13};
14
15bitflags::bitflags! {
16    /// The set of keys a [`DisableKeysFeature`] device can disable.
17    ///
18    /// Used both for the device's capabilities and for the currently disabled
19    /// keys.
20    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
21    #[cfg_attr(feature = "serde", derive(serde::Serialize))]
22    pub struct DisableableKeys: u8 {
23        /// The Caps Lock key.
24        const CAPS_LOCK = 1 << 0;
25        /// The Num Lock key.
26        const NUM_LOCK = 1 << 1;
27        /// The Scroll Lock key.
28        const SCROLL_LOCK = 1 << 2;
29        /// The Insert key.
30        const INSERT = 1 << 3;
31        /// The Windows / Start key.
32        const WINDOWS = 1 << 4;
33    }
34}
35
36/// Implements the `DisableKeys` / `0x4521` feature.
37#[derive(Clone)]
38pub struct DisableKeysFeature {
39    /// The endpoint this feature talks to.
40    endpoint: FeatureEndpoint,
41}
42
43impl CreatableFeature for DisableKeysFeature {
44    const ID: u16 = 0x4521;
45    const STARTING_VERSION: u8 = 0;
46
47    fn new(chan: Arc<HidppChannel>, device_index: u8, feature_index: u8) -> Self {
48        Self {
49            endpoint: FeatureEndpoint::new(chan, device_index, feature_index),
50        }
51    }
52}
53
54impl Feature for DisableKeysFeature {}
55
56impl DisableKeysFeature {
57    /// Retrieves the set of keys the device allows software to disable.
58    pub async fn get_capabilities(&self) -> Result<DisableableKeys, Hidpp20Error> {
59        let payload = self.endpoint.call(0, [0; 3]).await?.extend_payload();
60        Ok(DisableableKeys::from_bits_retain(payload[0]))
61    }
62
63    /// Retrieves the set of keys currently disabled.
64    pub async fn get_disabled_keys(&self) -> Result<DisableableKeys, Hidpp20Error> {
65        let payload = self.endpoint.call(1, [0; 3]).await?.extend_payload();
66        Ok(DisableableKeys::from_bits_retain(payload[0]))
67    }
68
69    /// Replaces the set of disabled keys and returns the device's echo.
70    ///
71    /// This replaces the whole set, so passing [`DisableableKeys::empty`]
72    /// re-enables every key. The device rejects keys it cannot disable.
73    pub async fn set_disabled_keys(
74        &self,
75        keys: DisableableKeys,
76    ) -> Result<DisableableKeys, Hidpp20Error> {
77        let payload = self
78            .endpoint
79            .call(2, [keys.bits(), 0, 0])
80            .await?
81            .extend_payload();
82        Ok(DisableableKeys::from_bits_retain(payload[0]))
83    }
84}