Skip to main content

hidpp/feature/rgb_effects/
types.rs

1//! Domain types for the `RgbEffects` feature (`0x8071`).
2
3use num_enum::{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, TryFromPrimitive)]
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}
109
110bitflags::bitflags! {
111    /// Persistence of a cluster effect, packed into the low two bits of the
112    /// `setRgbClusterEffect` flags byte.
113    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
114    #[cfg_attr(feature = "serde", derive(serde::Serialize))]
115    pub struct RgbPersistence: u8 {
116        /// Apply to volatile RAM.
117        const VOLATILE = 1 << 0;
118        /// Store in non-volatile EEPROM.
119        const NON_VOLATILE = 1 << 1;
120    }
121}
122
123bitflags::bitflags! {
124    /// Extended device capabilities from `getInfo` (device mode).
125    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
126    #[cfg_attr(feature = "serde", derive(serde::Serialize))]
127    pub struct RgbExtCapabilities: u16 {
128        /// `getInfo` for stored effects is supported.
129        const GET_ZONE_EFFECT = 1 << 0;
130        /// Setting LED bin info is supported.
131        const SET_LED_BIN_INFO = 1 << 2;
132        /// Only monochrome effects are supported.
133        const MONOCHROME_ONLY = 1 << 3;
134        /// Effect-sync correction / events are *not* supported.
135        const NO_EFFECT_SYNC = 1 << 4;
136        /// The shutdown function is supported.
137        const SHUTDOWN = 1 << 5;
138        /// The cluster-changed event is supported.
139        const CLUSTER_CHANGED_EVENT = 1 << 6;
140    }
141}
142
143bitflags::bitflags! {
144    /// Supported non-volatile capabilities from `getInfo` (device mode).
145    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
146    #[cfg_attr(feature = "serde", derive(serde::Serialize))]
147    pub struct RgbNvCapabilities: u16 {
148        /// Boot-up effect.
149        const BOOT_UP_EFFECT = 1 << 0;
150        /// Demo mode.
151        const DEMO = 1 << 1;
152        /// User demo mode.
153        const USER_DEMO_MODE = 1 << 2;
154        /// Events display.
155        const EVENTS_DISPLAY = 1 << 3;
156        /// Active dimming.
157        const ACTIVE_DIMMING = 1 << 4;
158        /// Ramp down to off.
159        const RAMP_DOWN_TO_OFF = 1 << 5;
160        /// Shutdown effect.
161        const SHUTDOWN_EFFECT = 1 << 6;
162    }
163}
164
165bitflags::bitflags! {
166    /// Software-control flags for `manageSwControl`.
167    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
168    #[cfg_attr(feature = "serde", derive(serde::Serialize))]
169    pub struct SwControlFlags: u8 {
170        /// Software controls all RGB clusters (required before `setRgbClusterEffect`).
171        const ALL_CLUSTERS = 1 << 0;
172        /// Software controls power modes (required before `setRgbPowerMode`).
173        const POWER_MODES = 1 << 1;
174    }
175}
176
177bitflags::bitflags! {
178    /// Event-notification flags for `manageSwControl`.
179    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
180    #[cfg_attr(feature = "serde", derive(serde::Serialize))]
181    pub struct EventsNotificationFlags: u8 {
182        /// Emit effect-sync events.
183        const EFFECTS_SYNC = 1 << 0;
184        /// Emit user-activity events.
185        const USER_ACTIVITY = 1 << 1;
186        /// Emit no-user-activity-timeout events.
187        const NO_USER_ACTIVITY_TIMEOUT = 1 << 2;
188    }
189}
190
191bitflags::bitflags! {
192    /// Display-persistency capabilities of a cluster from `getInfo` (cluster mode).
193    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
194    #[cfg_attr(feature = "serde", derive(serde::Serialize))]
195    pub struct DisplayPersistencyCapabilities: u8 {
196        /// Can persist an "always on" state.
197        const ALWAYS_ON = 1 << 0;
198        /// Can persist an "always off" state.
199        const ALWAYS_OFF = 1 << 1;
200        /// Can persist an "on then off" state.
201        const ON_THEN_OFF = 1 << 2;
202    }
203}
204
205/// Device-level information from
206/// [`get_device_info`](super::RgbEffectsFeature::get_device_info).
207#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
208#[cfg_attr(feature = "serde", derive(serde::Serialize))]
209#[non_exhaustive]
210pub struct RgbDeviceInfo {
211    /// Number of RGB clusters.
212    pub cluster_count: u8,
213    /// Supported non-volatile capabilities.
214    pub nv_capabilities: RgbNvCapabilities,
215    /// Extended capabilities.
216    pub ext_capabilities: RgbExtCapabilities,
217    /// Number of multi-cluster effects.
218    pub multicluster_effect_count: u8,
219}
220
221impl RgbDeviceInfo {
222    pub(super) fn from_payload(payload: &[u8; 16]) -> Self {
223        Self {
224            cluster_count: payload[2],
225            nv_capabilities: RgbNvCapabilities::from_bits_retain(be16(payload, 3)),
226            ext_capabilities: RgbExtCapabilities::from_bits_retain(be16(payload, 5)),
227            multicluster_effect_count: payload[7],
228        }
229    }
230}
231
232/// Cluster-level information from
233/// [`get_cluster_info`](super::RgbEffectsFeature::get_cluster_info).
234#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
235#[cfg_attr(feature = "serde", derive(serde::Serialize))]
236#[non_exhaustive]
237pub struct RgbClusterInfo {
238    /// Index of the cluster.
239    pub cluster_index: u8,
240    /// Physical location of the cluster (raw `locationEffect` value).
241    pub location: u16,
242    /// Number of effects the cluster supports.
243    pub effects_number: u8,
244    /// Display persistency capabilities.
245    pub display_persistency: DisplayPersistencyCapabilities,
246    /// Whether effect persistency to EEPROM is supported.
247    pub effect_persistency: bool,
248    /// Whether multi-LED patterns are supported.
249    pub multiled_pattern: bool,
250}
251
252impl RgbClusterInfo {
253    pub(super) fn from_payload(payload: &[u8; 16]) -> Self {
254        Self {
255            cluster_index: payload[0],
256            location: be16(payload, 2),
257            effects_number: payload[4],
258            display_persistency: DisplayPersistencyCapabilities::from_bits_retain(payload[5]),
259            effect_persistency: payload[6] != 0,
260            multiled_pattern: payload[7] != 0,
261        }
262    }
263}
264
265/// Effect-level information from
266/// [`get_effect_info`](super::RgbEffectsFeature::get_effect_info).
267#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
268#[cfg_attr(feature = "serde", derive(serde::Serialize))]
269#[non_exhaustive]
270pub struct RgbEffectInfo {
271    /// Index of the cluster.
272    pub cluster_index: u8,
273    /// Index of the effect within the cluster.
274    pub cluster_effect_index: u8,
275    /// The effect type identifier (raw `effectID`).
276    pub effect_id: u16,
277    /// Effect capability bitmask (meaning depends on `effect_id`; `0` means
278    /// Raptor-compatibility defaults).
279    pub effect_capabilities: u16,
280    /// Effect period in milliseconds, or `0` when not available.
281    pub effect_period: u16,
282}
283
284impl RgbEffectInfo {
285    pub(super) fn from_payload(payload: &[u8; 16]) -> Self {
286        Self {
287            cluster_index: payload[0],
288            cluster_effect_index: payload[1],
289            effect_id: be16(payload, 2),
290            effect_capabilities: be16(payload, 4),
291            effect_period: be16(payload, 6),
292        }
293    }
294}
295
296/// Software-control state from
297/// [`get_sw_control`](super::RgbEffectsFeature::get_sw_control).
298#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
299#[cfg_attr(feature = "serde", derive(serde::Serialize))]
300#[non_exhaustive]
301pub struct RgbSwControl {
302    /// Software-control flags.
303    pub control: SwControlFlags,
304    /// Event-notification flags.
305    pub events: EventsNotificationFlags,
306}
307
308/// A non-volatile configuration entry from
309/// [`get_nv_config`](super::RgbEffectsFeature::get_nv_config).
310#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
311#[cfg_attr(feature = "serde", derive(serde::Serialize))]
312#[non_exhaustive]
313pub struct RgbNvConfig {
314    /// The capability this entry addresses.
315    pub capability: RgbNvCapabilities,
316    /// The capability state. The meaning varies per capability (commonly
317    /// `0` = no change, `1` = enabled, `2` = disabled).
318    pub state: u8,
319    /// First capability-specific parameter.
320    pub param1: u8,
321    /// Second capability-specific parameter.
322    pub param2: u8,
323}
324
325/// Power-mode configuration from
326/// [`get_power_mode_config`](super::RgbEffectsFeature::get_power_mode_config).
327#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
328#[cfg_attr(feature = "serde", derive(serde::Serialize))]
329#[non_exhaustive]
330pub struct RgbPowerModeConfig {
331    /// Power-mode flags (raw).
332    pub flags: u16,
333    /// No-activity timeout before entering power-save, in seconds.
334    pub no_activity_timeout_to_power_save: u16,
335    /// No-activity timeout before turning off, in seconds.
336    pub no_activity_timeout_to_off: u16,
337}
338
339impl RgbPowerModeConfig {
340    pub(super) fn from_payload(payload: &[u8; 16]) -> Self {
341        Self {
342            flags: be16(payload, 1),
343            no_activity_timeout_to_power_save: be16(payload, 3),
344            no_activity_timeout_to_off: be16(payload, 5),
345        }
346    }
347}