Skip to main content

hidpp/feature/sidetone/
mod.rs

1//! Implements `Sidetone` (feature `0x8300`) for audio devices.
2
3use std::sync::Arc;
4
5use crate::{
6    channel::HidppChannel,
7    feature::{CreatableFeature, Feature, FeatureEndpoint},
8    protocol::v20::Hidpp20Error,
9};
10
11/// Per-channel sidetone mute statuses.
12#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
13#[cfg_attr(feature = "serde", derive(serde::Serialize))]
14#[non_exhaustive]
15pub struct SidetoneMuteStatus {
16    /// Raw mute-status bitmask. A set bit means the channel is muted.
17    pub statuses: u8,
18}
19
20/// Change mask and statuses for sidetone mute settings.
21#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize))]
23pub struct SidetoneMuteChange {
24    /// Channels to update. A set bit means the corresponding status bit applies.
25    pub change_mask: u8,
26    /// Desired mute statuses. A set bit means the channel should be muted.
27    pub statuses: u8,
28}
29
30/// Implements the `Sidetone` / `0x8300` feature.
31#[derive(Clone)]
32pub struct SidetoneFeature {
33    /// The endpoint this feature talks to.
34    endpoint: FeatureEndpoint,
35}
36
37impl CreatableFeature for SidetoneFeature {
38    const ID: u16 = 0x8300;
39    const STARTING_VERSION: u8 = 1;
40
41    fn new(chan: Arc<HidppChannel>, device_index: u8, feature_index: u8) -> Self {
42        Self {
43            endpoint: FeatureEndpoint::new(chan, device_index, feature_index),
44        }
45    }
46}
47
48impl Feature for SidetoneFeature {}
49
50impl SidetoneFeature {
51    /// Retrieves the sidetone level, in the documented `0..=100` range.
52    pub async fn get_sidetone_level(&self) -> Result<u8, Hidpp20Error> {
53        Ok(self.endpoint.call(0, [0; 3]).await?.extend_payload()[0])
54    }
55
56    /// Sets the sidetone level. Devices reject values outside `0..=100`.
57    pub async fn set_sidetone_level(&self, level: u8) -> Result<(), Hidpp20Error> {
58        self.endpoint.call(1, [level, 0, 0]).await?;
59        Ok(())
60    }
61
62    /// Retrieves sidetone mute statuses.
63    pub async fn get_sidetone_mute(&self) -> Result<SidetoneMuteStatus, Hidpp20Error> {
64        Ok(SidetoneMuteStatus {
65            statuses: self.endpoint.call(2, [0; 3]).await?.extend_payload()[0],
66        })
67    }
68
69    /// Updates selected sidetone mute statuses.
70    pub async fn set_sidetone_mute(&self, change: SidetoneMuteChange) -> Result<(), Hidpp20Error> {
71        self.endpoint
72            .call(3, [change.change_mask, change.statuses, 0])
73            .await?;
74        Ok(())
75    }
76}