input_linux/
kinds.rs

1use std::convert::TryFrom;
2use std::mem::transmute;
3use std::{io, fmt, error};
4use crate::{Key, sys};
5#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7
8/// Indicates that a value or event type code was out of range.
9#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
10pub struct RangeError;
11
12impl From<RangeError> for io::Error {
13    fn from(e: RangeError) -> Self {
14        io::Error::new(io::ErrorKind::InvalidData, e.to_string())
15    }
16}
17
18impl error::Error for RangeError {}
19
20impl fmt::Display for RangeError {
21    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
22        write!(f, "event code out of range")
23    }
24}
25
26/// Device properties and quirks.
27#[repr(u16)]
28#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)]
29#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
30#[allow(missing_docs)]
31pub enum InputProperty {
32    Pointer = sys::INPUT_PROP_POINTER as _,
33    Direct = sys::INPUT_PROP_DIRECT as _,
34    ButtonPad = sys::INPUT_PROP_BUTTONPAD as _,
35    SemiMultiTouch = sys::INPUT_PROP_SEMI_MT as _,
36    TopButtonPad = sys::INPUT_PROP_TOPBUTTONPAD as _,
37    PointingStick = sys::INPUT_PROP_POINTING_STICK as _,
38    Accelerometer = sys::INPUT_PROP_ACCELEROMETER as _,
39    Unknown07,
40    Unknown08,
41    Unknown09,
42    Unknown0A,
43    Unknown0B,
44    Unknown0C,
45    Unknown0D,
46    Unknown0E,
47    Unknown0F,
48    Unknown10,
49    Unknown11,
50    Unknown12,
51    Unknown13,
52    Unknown14,
53    Unknown15,
54    Unknown16,
55    Unknown17,
56    Unknown18,
57    Unknown19,
58    Unknown1A,
59    Unknown1B,
60    Unknown1C,
61    Unknown1D,
62    Unknown1E,
63    Unknown1F,
64}
65
66/// Event types
67#[repr(u16)]
68#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)]
69#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
70#[allow(missing_docs)]
71pub enum EventKind {
72    Synchronize = sys::EV_SYN as _,
73    Key = sys::EV_KEY as _,
74    Relative = sys::EV_REL as _,
75    Absolute = sys::EV_ABS as _,
76    Misc = sys::EV_MSC as _,
77    Switch = sys::EV_SW as _,
78    Unknown6,
79    Unknown7,
80    Unknown8,
81    Unknown9,
82    UnknownA,
83    UnknownB,
84    UnknownC,
85    UnknownD,
86    UnknownE,
87    UnknownF,
88    Unknown10,
89
90    Led = sys::EV_LED as _,
91    Sound = sys::EV_SND as _,
92    Unknown13,
93
94    Autorepeat = sys::EV_REP as _,
95    ForceFeedback = sys::EV_FF as _,
96    Power = sys::EV_PWR as _,
97    ForceFeedbackStatus = sys::EV_FF_STATUS as _,
98    Unknown18,
99    Unknown19,
100    Unknown1A,
101    Unknown1B,
102    Unknown1C,
103    Unknown1D,
104    Unknown1E,
105    Unknown1F,
106
107    UInput = sys::EV_UINPUT as _,
108}
109
110/// UInput feedback events.
111#[repr(u16)]
112#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)]
113#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
114#[allow(missing_docs)]
115pub enum UInputKind {
116    Unknown0 = 0,
117    ForceFeedbackUpload = sys::UI_FF_UPLOAD as _,
118    ForceFeedbackErase = sys::UI_FF_ERASE as _,
119}
120
121/// Synchronization events.
122#[repr(u16)]
123#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)]
124#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
125#[allow(missing_docs)]
126pub enum SynchronizeKind {
127    Report = sys::SYN_REPORT as _,
128    Config = sys::SYN_CONFIG as _,
129    MultitouchReport = sys::SYN_MT_REPORT as _,
130    Dropped = sys::SYN_DROPPED as _,
131    Unknown4,
132    Unknown5,
133    Unknown6,
134    Unknown7,
135    Unknown8,
136    Unknown9,
137    UnknownA,
138    UnknownB,
139    UnknownC,
140    UnknownD,
141    UnknownE,
142    UnknownF,
143}
144
145/// Key event value states.
146#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)]
147#[allow(missing_docs)]
148#[repr(transparent)]
149pub struct KeyState {
150    pub value: i32,
151}
152
153#[allow(missing_docs)]
154impl KeyState {
155    pub const RELEASED: Self = KeyState { value: 0 };
156    pub const PRESSED: Self = KeyState { value: 1 };
157    pub const AUTOREPEAT: Self = KeyState { value: 2 };
158
159    pub const fn is_pressed(&self) -> bool {
160        self.value == 1
161    }
162
163    pub const fn pressed(pressed: bool) -> Self {
164        Self {
165            value: pressed as i32,
166        }
167    }
168}
169
170/// Relative axes.
171#[repr(u16)]
172#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)]
173#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
174#[allow(missing_docs)]
175pub enum RelativeAxis {
176    X = sys::REL_X as _,
177    Y = sys::REL_Y as _,
178    Z = sys::REL_Z as _,
179    RX = sys::REL_RX as _,
180    RY = sys::REL_RY as _,
181    RZ = sys::REL_RZ as _,
182    HorizontalWheel = sys::REL_HWHEEL as _,
183    Dial = sys::REL_DIAL as _,
184    Wheel = sys::REL_WHEEL as _,
185    Misc = sys::REL_MISC as _,
186    Reserved = sys::REL_RESERVED as _,
187    WheelHiRes = sys::REL_WHEEL_HI_RES as _,
188    HorizontalWheelHiRes = sys::REL_HWHEEL_HI_RES as _,
189    UnknownD,
190    UnknownE,
191    UnknownF,
192}
193
194/// Absolute axes.
195#[repr(u16)]
196#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)]
197#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
198#[allow(missing_docs)]
199pub enum AbsoluteAxis {
200    X = sys::ABS_X as _,
201    Y = sys::ABS_Y as _,
202    Z = sys::ABS_Z as _,
203    RX = sys::ABS_RX as _,
204    RY = sys::ABS_RY as _,
205    RZ = sys::ABS_RZ as _,
206    Throttle = sys::ABS_THROTTLE as _,
207    Rudder = sys::ABS_RUDDER as _,
208    Wheel = sys::ABS_WHEEL as _,
209    Gas = sys::ABS_GAS as _,
210    Brake = sys::ABS_BRAKE as _,
211    UnknownB,
212    UnknownC,
213    UnknownD,
214    UnknownE,
215    UnknownF,
216
217    Hat0X = sys::ABS_HAT0X as _,
218    Hat0Y = sys::ABS_HAT0Y as _,
219    Hat1X = sys::ABS_HAT1X as _,
220    Hat1Y = sys::ABS_HAT1Y as _,
221    Hat2X = sys::ABS_HAT2X as _,
222    Hat2Y = sys::ABS_HAT2Y as _,
223    Hat3X = sys::ABS_HAT3X as _,
224    Hat3Y = sys::ABS_HAT3Y as _,
225    Pressure = sys::ABS_PRESSURE as _,
226    Distance = sys::ABS_DISTANCE as _,
227    TiltX = sys::ABS_TILT_X as _,
228    TiltY = sys::ABS_TILT_Y as _,
229    ToolWidth = sys::ABS_TOOL_WIDTH as _,
230    Unknown1D,
231    Unknown1E,
232    Unknown1F,
233
234    Volume = sys::ABS_VOLUME as _,
235    Profile = sys::ABS_PROFILE as _,
236    Unknown22,
237    Unknown23,
238    Unknown24,
239    Unknown25,
240    Unknown26,
241    Unknown27,
242
243    Misc = sys::ABS_MISC as _,
244    Unknown29,
245    Unknown2A,
246    Unknown2B,
247    Unknown2C,
248    Unknown2D,
249    Reserved = sys::ABS_RESERVED as _,
250
251    /// MT slot being modified
252    MultitouchSlot = sys::ABS_MT_SLOT as _,
253    /// Major axis of touching ellipse
254    MultitouchTouchMajor = sys::ABS_MT_TOUCH_MAJOR as _,
255    /// Minor axis (omit if circular)
256    MultitouchTouchMinor = sys::ABS_MT_TOUCH_MINOR as _,
257    /// Major axis of approaching ellipse
258    MultitouchWidthMajor = sys::ABS_MT_WIDTH_MAJOR as _,
259    /// Minor axis (omit if circular)
260    MultitouchWidthMinor = sys::ABS_MT_WIDTH_MINOR as _,
261    /// Ellipse orientation
262    MultitouchOrientation = sys::ABS_MT_ORIENTATION as _,
263    /// Center X touch position
264    MultitouchPositionX = sys::ABS_MT_POSITION_X as _,
265    /// Center Y touch position
266    MultitouchPositionY = sys::ABS_MT_POSITION_Y as _,
267    /// Type of touching device
268    MultitouchToolType = sys::ABS_MT_TOOL_TYPE as _,
269    /// Group a set of packets as a blob
270    MultitouchBlobId = sys::ABS_MT_BLOB_ID as _,
271    /// Unique ID of initiated contact
272    MultitouchTrackingId = sys::ABS_MT_TRACKING_ID as _,
273    /// Pressure on contact area
274    MultitouchPressure = sys::ABS_MT_PRESSURE as _,
275    /// Contact hover distance
276    MultitouchDistance = sys::ABS_MT_DISTANCE as _,
277    /// Center X tool position
278    MultitouchToolX = sys::ABS_MT_TOOL_X as _,
279    /// Center Y tool position
280    MultitouchToolY = sys::ABS_MT_TOOL_Y as _,
281    Unknown3E,
282    Unknown3F,
283}
284
285/// Switch events.
286#[repr(u16)]
287#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)]
288#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
289#[allow(missing_docs)]
290pub enum SwitchKind {
291    /// set = lid shut
292    Lid = sys::SW_LID as _,
293    /// set = tablet mode
294    TabletMode = sys::SW_TABLET_MODE as _,
295    /// set = inserted
296    HeadphoneInsert = sys::SW_HEADPHONE_INSERT as _,
297    /// set = radio enabled
298    RfKillAll = sys::SW_RFKILL_ALL as _,
299    // Radio = sys::SW_RADIO as _ = RfKillAll,
300    /// set = inserted
301    MicrophoneInsert = sys::SW_MICROPHONE_INSERT as _,
302    /// set = plugged into dock
303    Dock = sys::SW_DOCK as _,
304    /// set = inserted
305    LineoutInsert = sys::SW_LINEOUT_INSERT as _,
306    /// set = mechanical switch set
307    JackPhysicalInsert = sys::SW_JACK_PHYSICAL_INSERT as _,
308    /// set = inserted
309    VideoOutInsert = sys::SW_VIDEOOUT_INSERT as _,
310    /// set = lens covered
311    CameraLensCover = sys::SW_CAMERA_LENS_COVER as _,
312    /// set = keypad slide out
313    KeypadSlide = sys::SW_KEYPAD_SLIDE as _,
314    /// set = front proximity sensor active
315    FrontProximity = sys::SW_FRONT_PROXIMITY as _,
316    /// set = rotate locked/disabled
317    RotateLock = sys::SW_ROTATE_LOCK as _,
318    /// set = inserted
319    LineInInsert = sys::SW_LINEIN_INSERT as _,
320    /// set = device disabled
321    MuteDevice = sys::SW_MUTE_DEVICE as _,
322    /// set = pen inserted
323    PenInserted = sys::SW_PEN_INSERTED as _,
324    MachineCover = sys::SW_MACHINE_COVER as _,
325}
326
327/// Miscellaneous events.
328#[repr(u16)]
329#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)]
330#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
331#[allow(missing_docs)]
332pub enum MiscKind {
333    /// Serial number, only exported for tablets ("Transducer Serial Number")
334    Serial = sys::MSC_SERIAL as _,
335    /// Only used by the PowerMate driver, right now.
336    PulseLed = sys::MSC_PULSELED as _,
337    /// Completely unused
338    Gesture = sys::MSC_GESTURE as _,
339    /// "Raw" event, rarely used.
340    Raw = sys::MSC_RAW as _,
341    /// Key scancode
342    Scancode = sys::MSC_SCAN as _,
343    /// Completely unused
344    Timestamp = sys::MSC_TIMESTAMP as _,
345    Unknown6,
346    Unknown7,
347}
348
349/// LEDs.
350#[repr(u16)]
351#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)]
352#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
353#[allow(missing_docs)]
354pub enum LedKind {
355    NumLock = sys::LED_NUML as _,
356    CapsLock = sys::LED_CAPSL as _,
357    ScrollLock = sys::LED_SCROLLL as _,
358    Compose = sys::LED_COMPOSE as _,
359    Kana = sys::LED_KANA as _,
360    Sleep = sys::LED_SLEEP as _,
361    Suspend = sys::LED_SUSPEND as _,
362    Mute = sys::LED_MUTE as _,
363    Misc = sys::LED_MISC as _,
364    Mail = sys::LED_MAIL as _,
365    Charging = sys::LED_CHARGING as _,
366    UnknownB,
367    UnknownC,
368    UnknownD,
369    UnknownE,
370    UnknownF,
371}
372
373/// Autorepeat values.
374#[repr(u16)]
375#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)]
376#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
377#[allow(missing_docs)]
378pub enum AutorepeatKind {
379    Delay = sys::REP_DELAY as _,
380    Period = sys::REP_PERIOD as _,
381}
382
383/// Sounds
384#[repr(u16)]
385#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)]
386#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
387#[allow(missing_docs)]
388pub enum SoundKind {
389    Click = sys::SND_CLICK as _,
390    Bell = sys::SND_BELL as _,
391    Tone = sys::SND_TONE as _,
392    Unknown3,
393    Unknown4,
394    Unknown5,
395    Unknown6,
396    Unknown7,
397}
398
399/// Force feedback events.
400#[repr(u16)]
401#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)]
402#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
403#[allow(missing_docs)]
404pub enum ForceFeedbackKind {
405    Unknown0 = 0,
406    Unknown1,
407    Unknown2,
408    Unknown3,
409    Unknown4,
410    Unknown5,
411    Unknown6,
412    Unknown7,
413    Unknown8,
414    Unknown9,
415    UnknownA,
416    UnknownB,
417    UnknownC,
418    UnknownD,
419    UnknownE,
420    UnknownF,
421    Unknown10,
422    Unknown11,
423    Unknown12,
424    Unknown13,
425    Unknown14,
426    Unknown15,
427    Unknown16,
428    Unknown17,
429    Unknown18,
430    Unknown19,
431    Unknown1A,
432    Unknown1B,
433    Unknown1C,
434    Unknown1D,
435    Unknown1E,
436    Unknown1F,
437    Unknown20,
438    Unknown21,
439    Unknown22,
440    Unknown23,
441    Unknown24,
442    Unknown25,
443    Unknown26,
444    Unknown27,
445    Unknown28,
446    Unknown29,
447    Unknown2A,
448    Unknown2B,
449    Unknown2C,
450    Unknown2D,
451    Unknown2E,
452    Unknown2F,
453    Unknown30,
454    Unknown31,
455    Unknown32,
456    Unknown33,
457    Unknown34,
458    Unknown35,
459    Unknown36,
460    Unknown37,
461    Unknown38,
462    Unknown39,
463    Unknown3A,
464    Unknown3B,
465    Unknown3C,
466    Unknown3D,
467    Unknown3E,
468    Unknown3F,
469    Unknown40,
470    Unknown41,
471    Unknown42,
472    Unknown43,
473    Unknown44,
474    Unknown45,
475    Unknown46,
476    Unknown47,
477    Unknown48,
478    Unknown49,
479    Unknown4A,
480    Unknown4B,
481    Unknown4C,
482    Unknown4D,
483    Unknown4E,
484    Unknown4F,
485    Rumble = sys::FF_RUMBLE as _,
486    Periodic = sys::FF_PERIODIC as _,
487    Constant = sys::FF_CONSTANT as _,
488    Spring = sys::FF_SPRING as _,
489    Friction = sys::FF_FRICTION as _,
490    Damper = sys::FF_DAMPER as _,
491    Inertia = sys::FF_INERTIA as _,
492    Ramp = sys::FF_RAMP as _,
493    Square = sys::FF_SQUARE as _,
494    Triangle = sys::FF_TRIANGLE as _,
495    Sine = sys::FF_SINE as _,
496    SawUp = sys::FF_SAW_UP as _,
497    SawDown = sys::FF_SAW_DOWN as _,
498    Custom = sys::FF_CUSTOM as _,
499    Unknown5E,
500    Unknown5F,
501    Gain = sys::FF_GAIN as _,
502    Autocenter = sys::FF_AUTOCENTER as _,
503    Unknown62,
504    Unknown63,
505    Unknown64,
506    Unknown65,
507    Unknown66,
508    Unknown67,
509    Unknown68,
510    Unknown69,
511    Unknown6A,
512    Unknown6B,
513    Unknown6C,
514    Unknown6D,
515    Unknown6E,
516    Unknown6F,
517    Unknown70,
518    Unknown71,
519    Unknown72,
520    Unknown73,
521    Unknown74,
522    Unknown75,
523    Unknown76,
524    Unknown77,
525    Unknown78,
526    Unknown79,
527    Unknown7A,
528    Unknown7B,
529    Unknown7C,
530    Unknown7D,
531    Unknown7E,
532    Unknown7F,
533}
534
535/// Force feedback status events.
536#[repr(u16)]
537#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)]
538#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
539#[allow(missing_docs)]
540pub enum ForceFeedbackStatusKind {
541    Stopped = sys::FF_STATUS_STOPPED as _,
542    Playing = sys::FF_STATUS_PLAYING as _,
543}
544
545impl_iterable! { InputProperty(0, sys::INPUT_PROP_CNT) }
546
547impl EventKind {
548    /// Instantiate from a type code.
549    pub fn from_type(code: u16) -> Result<Self, RangeError> {
550        const EV_UINPUT: u16 = sys::EV_UINPUT as _;
551
552        match code {
553            0..=0x1f | EV_UINPUT => Ok(unsafe { transmute(code) }),
554            _ => Err(Default::default()),
555        }
556    }
557
558    /// Returns the maximum known number of codes for the current event
559    pub fn count(&self) -> Result<usize, ()> {
560        match *self {
561            EventKind::Synchronize => Ok(SynchronizeKind::COUNT),
562            EventKind::Key => Ok(Key::COUNT),
563            EventKind::Relative => Ok(RelativeAxis::COUNT),
564            EventKind::Absolute => Ok(AbsoluteAxis::COUNT),
565            EventKind::Misc => Ok(MiscKind::COUNT),
566            EventKind::Switch => Ok(SwitchKind::COUNT),
567            EventKind::Led => Ok(LedKind::COUNT),
568            EventKind::Sound => Ok(SoundKind::COUNT),
569            EventKind::Autorepeat => Ok(AutorepeatKind::COUNT),
570            EventKind::ForceFeedback => Ok(ForceFeedbackKind::COUNT),
571            EventKind::ForceFeedbackStatus => Ok(ForceFeedbackStatusKind::COUNT),
572            EventKind::UInput => Ok(UInputKind::COUNT),
573            _ => Err(()),
574        }
575    }
576
577    /// Like [`count`](Self::count) but with an exception for
578    /// [`Synchronize`](Self::Synchronize) representing `EventKind`, matching
579    /// the behaviour of `EVIOCGBIT` and `EVIOCGMASK`. If you're using a
580    /// bitmask you probably want this.
581    pub fn count_bits(&self) -> Result<usize, ()> {
582        match *self {
583            EventKind::Synchronize => Ok(EventKind::COUNT),
584            _ => self.count(),
585        }
586    }
587}
588
589impl TryFrom<u16> for EventKind {
590    type Error = RangeError;
591
592    fn try_from(code: u16) -> Result<Self, Self::Error> {
593        Self::from_type(code)
594    }
595}
596
597impl_iterable! { @nofromcode EventKind(0, sys::EV_CNT) }
598
599impl_iterable! { UInputKind(0, sys::UI_FF_ERASE + 1) }
600
601impl_iterable! { SynchronizeKind(0, sys::SYN_CNT) }
602
603impl From<i32> for KeyState {
604    fn from(key: i32) -> Self {
605        unsafe { transmute(key) }
606    }
607}
608
609impl From<KeyState> for i32 {
610    fn from(k: KeyState) -> Self {
611        k.value
612    }
613}
614
615#[cfg(feature = "serde")]
616mod key_state_serde {
617    use serde::{Deserialize, Deserializer, Serialize, Serializer};
618    use super::KeyState as KeyStateSuper;
619
620    #[derive(Serialize, Deserialize)]
621    #[serde(untagged)]
622    enum KeyState {
623        Released,
624        Pressed,
625        Autorepeat,
626        Unknown(i32),
627    }
628
629    impl From<KeyState> for KeyStateSuper {
630        #[inline(always)]
631        fn from(k: KeyState) -> Self {
632            match k {
633                KeyState::Released => KeyStateSuper::RELEASED,
634                KeyState::Pressed => KeyStateSuper::PRESSED,
635                KeyState::Autorepeat => KeyStateSuper::AUTOREPEAT,
636                KeyState::Unknown(v) => v.into(),
637            }
638        }
639    }
640
641    impl From<KeyStateSuper> for KeyState {
642        #[inline(always)]
643        fn from(k: KeyStateSuper) -> Self {
644            match k {
645                KeyStateSuper::RELEASED => KeyState::Released,
646                KeyStateSuper::PRESSED => KeyState::Pressed,
647                KeyStateSuper::AUTOREPEAT => KeyState::Autorepeat,
648                KeyStateSuper { value } => KeyState::Unknown(value),
649            }
650        }
651    }
652
653    impl<'de> Deserialize<'de> for KeyStateSuper {
654        fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
655            KeyState::deserialize(deserializer).map(From::from)
656        }
657    }
658
659    impl Serialize for KeyStateSuper {
660        fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
661            KeyState::from(*self).serialize(serializer)
662        }
663    }
664}
665
666impl_iterable! { RelativeAxis(0, sys::REL_CNT) }
667
668impl_iterable! { AbsoluteAxis(0, sys::ABS_CNT) }
669
670impl_iterable! { SwitchKind(0, sys::SW_CNT) }
671
672impl_iterable! { MiscKind(0, sys::MSC_CNT) }
673
674impl_iterable! { LedKind(0, sys::LED_CNT) }
675
676impl_iterable! { AutorepeatKind(0, sys::REP_CNT) }
677
678impl_iterable! { SoundKind(0, sys::SND_CNT) }
679
680impl_iterable! { ForceFeedbackKind(0, sys::FF_CNT) }
681
682impl_iterable! { ForceFeedbackStatusKind(0, sys::FF_STATUS_MAX + 1) }