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}