Skip to main content

hidpp/feature/
solar_dashboard.rs

1//! Implements the `SolarKeyboardDashboard` feature (ID `0x4301`) for Logitech's
2//! solar keyboards (e.g. the K750): scheduling light-measure reports, overriding
3//! the CheckLight LED, and receiving battery / light broadcast events.
4
5pub mod event;
6
7#[cfg(test)]
8mod tests;
9
10use num_enum::{IntoPrimitive, TryFromPrimitive};
11use openlogi_hidpp_derive::Feature;
12
13pub use event::{SolarEvent, SolarStatus};
14
15use crate::{
16    feature::{EventSource, FeatureEndpoint},
17    protocol::v20::Hidpp20Error,
18};
19
20/// A CheckLight LED color for [`set_led`](SolarDashboardFeature::set_led).
21#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, IntoPrimitive, TryFromPrimitive)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize))]
23#[non_exhaustive]
24#[repr(u8)]
25pub enum LedId {
26    /// All LEDs off.
27    Off = 0,
28    /// Red.
29    Red = 1,
30    /// Orange.
31    Orange = 2,
32    /// Green.
33    Green = 3,
34}
35
36/// Implements the `SolarKeyboardDashboard` / `0x4301` feature.
37#[derive(Feature)]
38#[creatable(id = 0x4301, version = 0)]
39pub struct SolarDashboardFeature {
40    /// The endpoint this feature talks to.
41    endpoint: FeatureEndpoint,
42
43    /// Publishes decoded events to listeners.
44    events: EventSource<SolarEvent>,
45}
46
47impl SolarDashboardFeature {
48    /// Schedules [`SolarEvent::LightMeasure`] reports.
49    ///
50    /// `max_reports` is the number of reports to send and `report_period` their
51    /// spacing in seconds. Passing `0` for either cancels reporting.
52    pub async fn set_light_measure(
53        &self,
54        max_reports: u8,
55        report_period: u8,
56    ) -> Result<(), Hidpp20Error> {
57        self.endpoint
58            .call(0, [max_reports, report_period, 0])
59            .await?;
60        Ok(())
61    }
62
63    /// Lights the CheckLight LED in the given color for a firmware-defined
64    /// duration.
65    ///
66    /// Intended to override the firmware's own CheckLight display in response to a
67    /// [`SolarEvent::CheckLightButton`]; the firmware waits 250 ms before showing
68    /// its own status, so call this within that window.
69    pub async fn set_led(&self, led: LedId) -> Result<(), Hidpp20Error> {
70        self.endpoint.call(1, [led.into(), 0, 0]).await?;
71        Ok(())
72    }
73}