Skip to main content

hidpp/feature/rgb_effects/
types.rs

1//! Domain types for the `RgbEffects` feature (`0x8071`).
2
3use num_enum::{FromPrimitive, IntoPrimitive, TryFromPrimitive};
4
5/// Number of effect parameters carried by `setRgbClusterEffect`.
6pub const CLUSTER_EFFECT_PARAM_COUNT: usize = 10;
7/// Number of raw parameters returned for onboard-stored effect info.
8pub const ONBOARD_INFO_PARAM_COUNT: usize = 13;
9/// Number of raw parameters carried by the LED-bin functions.
10pub const LED_BIN_PARAM_COUNT: usize = 8;
11
12/// `0xFF` cluster index — refers to all clusters / the multi-cluster context.
13pub const ALL_CLUSTERS: u8 = 0xff;
14/// `0xFF` effect index — queries the cluster or device level in `getInfo`.
15pub const ALL_EFFECTS: u8 = 0xff;
16
17/// Reads a big-endian `u16` at `offset` of a payload.
18pub(super) fn be16(payload: &[u8; 16], offset: usize) -> u16 {
19    u16::from_be_bytes([payload[offset], payload[offset + 1]])
20}
21
22/// Whether a `manage*` call reads or writes.
23#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, IntoPrimitive)]
24#[repr(u8)]
25pub(super) enum GetOrSet {
26    Get = 0,
27    Set = 1,
28}
29
30/// The kind of slot information requested for an onboard-stored effect.
31#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, IntoPrimitive, TryFromPrimitive)]
32#[cfg_attr(feature = "serde", derive(serde::Serialize))]
33#[non_exhaustive]
34#[repr(u8)]
35pub enum SlotInfoType {
36    /// Slot state (validity, length).
37    SlotState = 0,
38    /// Default playback parameters.
39    Defaults = 1,
40    /// UUID bytes 0..=10.
41    Uuid0To10 = 2,
42    /// UUID bytes 11..=16.
43    Uuid11To16 = 3,
44    /// Effect name characters 0..=10.
45    EffectName0To10 = 4,
46    /// Effect name characters 11..=21.
47    EffectName11To21 = 5,
48    /// Effect name characters 21..=31.
49    EffectName21To31 = 6,
50}
51
52/// An overall RGB power mode.
53#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, IntoPrimitive, TryFromPrimitive)]
54#[cfg_attr(feature = "serde", derive(serde::Serialize))]
55#[non_exhaustive]
56#[repr(u8)]
57pub enum RgbPowerMode {
58    /// Full RGB.
59    FullRgb = 1,
60    /// Power-save.
61    PowerSave = 2,
62    /// Power-off.
63    PowerOff = 3,
64}
65
66/// The power-mode target an effect applies to, packed into `setRgbClusterEffect`.
67#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, IntoPrimitive, TryFromPrimitive)]
68#[cfg_attr(feature = "serde", derive(serde::Serialize))]
69#[non_exhaustive]
70#[repr(u8)]
71pub enum PowerModeTarget {
72    /// Full-power mode.
73    FullPower = 0,
74    /// Power-save mode.
75    PowerSave = 1,
76}
77
78/// Selects which LED bin parameter a LED-bin call addresses.
79#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, IntoPrimitive, TryFromPrimitive)]
80#[cfg_attr(feature = "serde", derive(serde::Serialize))]
81#[non_exhaustive]
82#[repr(u8)]
83pub enum LedBinIndex {
84    /// Bin value: brightness.
85    BinValueBrightness = 0,
86    /// Bin value: color.
87    BinValueColor = 1,
88    /// Calibration factors.
89    CalibrationFactors = 2,
90    /// Brightness.
91    Brightness = 3,
92    /// Colorimetric X.
93    ColorimetricX = 4,
94    /// Colorimetric Y.
95    ColorimetricY = 5,
96}
97
98/// The kind of user-activity event.
99#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, IntoPrimitive, FromPrimitive)]
100#[cfg_attr(feature = "serde", derive(serde::Serialize))]
101#[non_exhaustive]
102#[repr(u8)]
103pub enum ActivityEventType {
104    /// The no-activity timeout was reached.
105    NoActivityTimeoutReached = 0,
106    /// User activity was detected.
107    UserActivityDetected = 1,
108    /// A type this crate does not model; carries the raw byte.
109    #[num_enum(catch_all)]
110    Other(u8),
111}
112
113bitflags::bitflags! {
114    /// Persistence of a cluster effect, packed into the low two bits of the
115    /// `setRgbClusterEffect` flags byte.
116    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
117    #[cfg_attr(feature = "serde", derive(serde::Serialize))]
118    pub struct RgbPersistence: u8 {
119        /// Apply to volatile RAM.
120        const VOLATILE = 1 << 0;
121        /// Store in non-volatile EEPROM.
122        const NON_VOLATILE = 1 << 1;
123    }
124}
125
126bitflags::bitflags! {
127    /// Extended device capabilities from `getInfo` (device mode).
128    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
129    #[cfg_attr(feature = "serde", derive(serde::Serialize))]
130    pub struct RgbExtCapabilities: u16 {
131        /// `getInfo` for stored effects is supported.
132        const GET_ZONE_EFFECT = 1 << 0;
133        /// Setting LED bin info is supported.
134        const SET_LED_BIN_INFO = 1 << 2;
135        /// Only monochrome effects are supported.
136        const MONOCHROME_ONLY = 1 << 3;
137        /// Effect-sync correction / events are *not* supported.
138        const NO_EFFECT_SYNC = 1 << 4;
139        /// The shutdown function is supported.
140        const SHUTDOWN = 1 << 5;
141        /// The cluster-changed event is supported.
142        const CLUSTER_CHANGED_EVENT = 1 << 6;
143    }
144}
145
146bitflags::bitflags! {
147    /// Supported non-volatile capabilities from `getInfo` (device mode).
148    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
149    #[cfg_attr(feature = "serde", derive(serde::Serialize))]
150    pub struct RgbNvCapabilities: u16 {
151        /// Boot-up effect.
152        const BOOT_UP_EFFECT = 1 << 0;
153        /// Demo mode.
154        const DEMO = 1 << 1;
155        /// User demo mode.
156        const USER_DEMO_MODE = 1 << 2;
157        /// Events display.
158        const EVENTS_DISPLAY = 1 << 3;
159        /// Active dimming.
160        const ACTIVE_DIMMING = 1 << 4;
161        /// Ramp down to off.
162        const RAMP_DOWN_TO_OFF = 1 << 5;
163        /// Shutdown effect.
164        const SHUTDOWN_EFFECT = 1 << 6;
165    }
166}
167
168bitflags::bitflags! {
169    /// Software-control flags for `manageSwControl`.
170    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
171    #[cfg_attr(feature = "serde", derive(serde::Serialize))]
172    pub struct SwControlFlags: u8 {
173        /// Software controls all RGB clusters (required before `setRgbClusterEffect`).
174        const ALL_CLUSTERS = 1 << 0;
175        /// Software controls power modes (required before `setRgbPowerMode`).
176        const POWER_MODES = 1 << 1;
177    }
178}
179
180bitflags::bitflags! {
181    /// Event-notification flags for `manageSwControl`.
182    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
183    #[cfg_attr(feature = "serde", derive(serde::Serialize))]
184    pub struct EventsNotificationFlags: u8 {
185        /// Emit effect-sync events.
186        const EFFECTS_SYNC = 1 << 0;
187        /// Emit user-activity events.
188        const USER_ACTIVITY = 1 << 1;
189        /// Emit no-user-activity-timeout events.
190        const NO_USER_ACTIVITY_TIMEOUT = 1 << 2;
191    }
192}
193
194bitflags::bitflags! {
195    /// Display-persistency capabilities of a cluster from `getInfo` (cluster mode).
196    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
197    #[cfg_attr(feature = "serde", derive(serde::Serialize))]
198    pub struct DisplayPersistencyCapabilities: u8 {
199        /// Can persist an "always on" state.
200        const ALWAYS_ON = 1 << 0;
201        /// Can persist an "always off" state.
202        const ALWAYS_OFF = 1 << 1;
203        /// Can persist an "on then off" state.
204        const ON_THEN_OFF = 1 << 2;
205    }
206}
207
208/// Device-level information from
209/// [`get_device_info`](super::RgbEffectsFeature::get_device_info).
210#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
211#[cfg_attr(feature = "serde", derive(serde::Serialize))]
212#[non_exhaustive]
213pub struct RgbDeviceInfo {
214    /// Number of RGB clusters.
215    pub cluster_count: u8,
216    /// Supported non-volatile capabilities.
217    pub nv_capabilities: RgbNvCapabilities,
218    /// Extended capabilities.
219    pub ext_capabilities: RgbExtCapabilities,
220    /// Number of multi-cluster effects.
221    pub multicluster_effect_count: u8,
222}
223
224impl RgbDeviceInfo {
225    pub(super) fn from_payload(payload: &[u8; 16]) -> Self {
226        Self {
227            cluster_count: payload[2],
228            nv_capabilities: RgbNvCapabilities::from_bits_retain(be16(payload, 3)),
229            ext_capabilities: RgbExtCapabilities::from_bits_retain(be16(payload, 5)),
230            multicluster_effect_count: payload[7],
231        }
232    }
233}
234
235/// Cluster-level information from
236/// [`get_cluster_info`](super::RgbEffectsFeature::get_cluster_info).
237#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
238#[cfg_attr(feature = "serde", derive(serde::Serialize))]
239#[non_exhaustive]
240pub struct RgbClusterInfo {
241    /// Index of the cluster.
242    pub cluster_index: u8,
243    /// Physical location of the cluster (raw `locationEffect` value).
244    pub location: u16,
245    /// Number of effects the cluster supports.
246    pub effects_number: u8,
247    /// Display persistency capabilities.
248    pub display_persistency: DisplayPersistencyCapabilities,
249    /// Whether effect persistency to EEPROM is supported.
250    pub effect_persistency: bool,
251    /// Whether multi-LED patterns are supported.
252    pub multiled_pattern: bool,
253}
254
255impl RgbClusterInfo {
256    pub(super) fn from_payload(payload: &[u8; 16]) -> Self {
257        Self {
258            cluster_index: payload[0],
259            location: be16(payload, 2),
260            effects_number: payload[4],
261            display_persistency: DisplayPersistencyCapabilities::from_bits_retain(payload[5]),
262            effect_persistency: payload[6] != 0,
263            multiled_pattern: payload[7] != 0,
264        }
265    }
266}
267
268/// Effect-level information from
269/// [`get_effect_info`](super::RgbEffectsFeature::get_effect_info).
270#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
271#[cfg_attr(feature = "serde", derive(serde::Serialize))]
272#[non_exhaustive]
273pub struct RgbEffectInfo {
274    /// Index of the cluster.
275    pub cluster_index: u8,
276    /// Index of the effect within the cluster.
277    pub cluster_effect_index: u8,
278    /// The effect type identifier (raw `effectID`).
279    pub effect_id: u16,
280    /// Effect capability bitmask (meaning depends on `effect_id`; `0` means
281    /// Raptor-compatibility defaults).
282    pub effect_capabilities: u16,
283    /// Effect period in milliseconds, or `0` when not available.
284    pub effect_period: u16,
285}
286
287impl RgbEffectInfo {
288    pub(super) fn from_payload(payload: &[u8; 16]) -> Self {
289        Self {
290            cluster_index: payload[0],
291            cluster_effect_index: payload[1],
292            effect_id: be16(payload, 2),
293            effect_capabilities: be16(payload, 4),
294            effect_period: be16(payload, 6),
295        }
296    }
297}
298
299/// Software-control state from
300/// [`get_sw_control`](super::RgbEffectsFeature::get_sw_control).
301#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
302#[cfg_attr(feature = "serde", derive(serde::Serialize))]
303#[non_exhaustive]
304pub struct RgbSwControl {
305    /// Software-control flags.
306    pub control: SwControlFlags,
307    /// Event-notification flags.
308    pub events: EventsNotificationFlags,
309}
310
311/// A non-volatile configuration entry from
312/// [`get_nv_config`](super::RgbEffectsFeature::get_nv_config).
313#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
314#[cfg_attr(feature = "serde", derive(serde::Serialize))]
315#[non_exhaustive]
316pub struct RgbNvConfig {
317    /// The capability this entry addresses.
318    pub capability: RgbNvCapabilities,
319    /// The capability state. The meaning varies per capability (commonly
320    /// `0` = no change, `1` = enabled, `2` = disabled).
321    pub state: u8,
322    /// First capability-specific parameter.
323    pub param1: u8,
324    /// Second capability-specific parameter.
325    pub param2: u8,
326}
327
328/// Power-mode configuration from
329/// [`get_power_mode_config`](super::RgbEffectsFeature::get_power_mode_config).
330#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
331#[cfg_attr(feature = "serde", derive(serde::Serialize))]
332#[non_exhaustive]
333pub struct RgbPowerModeConfig {
334    /// Power-mode flags (raw).
335    pub flags: u16,
336    /// No-activity timeout before entering power-save, in seconds.
337    pub no_activity_timeout_to_power_save: u16,
338    /// No-activity timeout before turning off, in seconds.
339    pub no_activity_timeout_to_off: u16,
340}
341
342impl RgbPowerModeConfig {
343    pub(super) fn from_payload(payload: &[u8; 16]) -> Self {
344        Self {
345            flags: be16(payload, 1),
346            no_activity_timeout_to_power_save: be16(payload, 3),
347            no_activity_timeout_to_off: be16(payload, 5),
348        }
349    }
350}