linux_input/
input_sys.rs

1#[derive(Clone, PartialEq, Eq, Debug)]
2#[repr(C)]
3pub struct RawDeviceId {
4    pub bus: u16,
5    pub vendor: u16,
6    pub product: u16,
7    pub version: u16
8}
9
10#[derive(Clone, PartialEq, Eq, Debug)]
11#[repr(C)]
12pub struct RawAbsInfo {
13    /// Latest reported value for the axis.
14    pub value: i32,
15    /// Minimum value for the axis.
16    pub minimum: i32,
17    /// Maximum value for the axis.
18    pub maximum: i32,
19    /// Threshold for noise filtering.
20    pub noise_threshold: i32,
21    /// Deadzone.
22    pub deadzone: i32,
23    /// Resolution of the reported values.
24    pub resolution: i32
25}
26
27#[derive(Copy, Clone, PartialEq, Eq, Debug)]
28#[repr(C)]
29pub struct RawForceFeedbackTrigger {
30    pub button: u16,
31    pub interval: u16
32}
33
34#[derive(Copy, Clone, PartialEq, Eq, Debug)]
35#[repr(C)]
36pub struct RawForceFeedbackReplay {
37    pub length: u16,
38    pub delay: u16
39}
40
41#[derive(Copy, Clone, PartialEq, Eq, Debug)]
42#[repr(C)]
43pub struct RawForceFeedbackEnvelope {
44    pub attack_length: u16,
45    pub attack_level: u16,
46    pub fade_length: u16,
47    pub fade_level: u16
48}
49
50#[derive(Copy, Clone, PartialEq, Eq, Debug)]
51#[repr(C)]
52pub struct RawForceFeedbackConstantEffect {
53    pub level: u16,
54    pub envelope: RawForceFeedbackEnvelope
55}
56
57#[derive(Copy, Clone, PartialEq, Eq, Debug)]
58#[repr(C)]
59pub struct RawForceFeedbackRampEffect {
60    pub start_level: i16,
61    pub end_level: u16,
62    pub envelope: RawForceFeedbackEnvelope
63}
64
65#[derive(Copy, Clone, PartialEq, Eq, Debug)]
66#[repr(C)]
67pub struct RawForceFeedbackPeriodicEffect {
68    pub waveform: u16,
69    pub period: u16,
70    pub magnitude: i16,
71    pub offset: i16,
72    pub phase: u16,
73    pub envelope: RawForceFeedbackEnvelope,
74
75    pub custom_length: u32,
76    pub custom_data: *mut i16
77}
78
79#[derive(Copy, Clone, PartialEq, Eq, Debug)]
80#[repr(C)]
81pub struct RawForceFeedbackConditionEffect {
82    pub right_saturation: u16,
83    pub left_saturation: u16,
84    pub right_coefficient: i16,
85    pub left_coefficient: i16,
86    pub deadband: u16,
87    pub center: i16
88}
89
90#[derive(Copy, Clone, PartialEq, Eq, Debug)]
91#[repr(C)]
92pub struct RawForceFeedbackRumbleEffect {
93    pub strong_magnitude: u16,
94    pub weak_magnitude: u16
95}
96
97#[repr(C)]
98#[derive(Copy, Clone)]
99pub union RawForceFeedbackBody {
100    pub constant: RawForceFeedbackConstantEffect,
101    pub ramp: RawForceFeedbackRampEffect,
102    pub periodic: RawForceFeedbackPeriodicEffect,
103    pub condition: [RawForceFeedbackConditionEffect; 2],
104    pub rumble: RawForceFeedbackRumbleEffect
105}
106
107#[derive(Copy, Clone)]
108#[repr(C)]
109pub struct RawForceFeedbackEffect {
110    pub kind: u16,
111    pub id: i16,
112    pub direction: u16,
113    pub trigger: RawForceFeedbackTrigger,
114    pub replay: RawForceFeedbackReplay,
115    pub body: RawForceFeedbackBody
116}
117
118pub const FF_RUMBLE: u16 = 0x50;
119#[allow(dead_code)]
120pub const FF_PERIODIC: u16 = 0x51;
121#[allow(dead_code)]
122pub const FF_CONSTANT: u16 = 0x52;
123#[allow(dead_code)]
124pub const FF_SPRING: u16 = 0x53;
125#[allow(dead_code)]
126pub const FF_FRICTION: u16 = 0x54;
127#[allow(dead_code)]
128pub const FF_DAMPER: u16 = 0x55;
129#[allow(dead_code)]
130pub const FF_INERTIA: u16 = 0x56;
131#[allow(dead_code)]
132pub const FF_RAMP: u16 = 0x57;
133
134pub const FF_GAIN: u16 = 0x60;
135#[allow(dead_code)]
136pub const FF_AUTOCENTER: u16 = 0x61;
137
138#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
139#[repr(C)]
140pub struct Timestamp {
141    pub sec: libc::time_t,
142    pub usec: libc::suseconds_t
143}
144
145impl Timestamp {
146    /// Reads the current timestamp using the CLOCK_MONOTONIC source.
147    pub fn get() -> Result< Self, std::io::Error > {
148        let mut ts = libc::timespec {
149            tv_sec: 0,
150            tv_nsec: 0
151        };
152
153        let result = unsafe {
154            libc::clock_gettime( libc::CLOCK_MONOTONIC, &mut ts )
155        };
156
157        if result < 0 {
158            Err( std::io::Error::last_os_error() )
159        } else {
160            Ok( Timestamp {
161                sec: ts.tv_sec,
162                usec: ts.tv_nsec / 1000
163            })
164        }
165    }
166
167    pub fn as_f64( self ) -> f64 {
168        self.sec as f64 + self.usec as f64 / 1000_000.0
169    }
170}
171
172impl std::ops::Sub for Timestamp {
173    type Output = std::time::Duration;
174    fn sub( self, rhs: Timestamp ) -> Self::Output {
175        std::time::Duration::new( self.sec as _, self.usec as _ ) - std::time::Duration::new( rhs.sec as _, rhs.usec as _ )
176    }
177}
178
179#[derive(Clone, PartialEq, Eq, Default)]
180#[repr(C)]
181pub struct RawInputEvent {
182    pub timestamp: Timestamp,
183    pub kind: u16,
184    pub code: u16,
185    pub value: i32
186}
187
188define_enum! {
189    #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
190    enum EventKind {
191        Other( u16 ),
192        Synchronization     = 0x00,
193        Key                 = 0x01,
194        RelativeAxis        = 0x02,
195        AbsoluteAxis        = 0x03,
196        Misc                = 0x04,
197        Switch              = 0x05,
198        LED                 = 0x11,
199        Sound               = 0x12,
200        AutoRepeat          = 0x14,
201        ForceFeedback       = 0x15,
202        Power               = 0x16,
203        ForceFeedbackStatus = 0x17
204    }
205}
206
207define_enum! {
208    #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
209    enum Key {
210        Other( u16 ),
211        Escape = 1,
212        Digit1 = 2,
213        Digit2 = 3,
214        Digit3 = 4,
215        Digit4 = 5,
216        Digit5 = 6,
217        Digit6 = 7,
218        Digit7 = 8,
219        Digit8 = 9,
220        Digit9 = 10,
221        Digit0 = 11,
222        Minus = 12,
223        Equal = 13,
224        Backspace = 14,
225        Tab = 15,
226        Q = 16,
227        W = 17,
228        E = 18,
229        R = 19,
230        T = 20,
231        Y = 21,
232        U = 22,
233        I = 23,
234        O = 24,
235        P = 25,
236        LeftBrace = 26,
237        RightBrace = 27,
238        Enter = 28,
239        LeftCtrl = 29,
240        A = 30,
241        S = 31,
242        D = 32,
243        F = 33,
244        G = 34,
245        H = 35,
246        J = 36,
247        K = 37,
248        L = 38,
249        Semicolon = 39,
250        Apostrophe = 40,
251        Grave = 41,
252        LeftShift = 42,
253        Backslash = 43,
254        Z = 44,
255        X = 45,
256        C = 46,
257        V = 47,
258        B = 48,
259        N = 49,
260        M = 50,
261        Comma = 51,
262        Dot = 52,
263        Slash = 53,
264        RightShift = 54,
265        KeypadAsterisk = 55,
266        LeftAlt = 56,
267        Space = 57,
268        CapsLock = 58,
269        F1 = 59,
270        F2 = 60,
271        F3 = 61,
272        F4 = 62,
273        F5 = 63,
274        F6 = 64,
275        F7 = 65,
276        F8 = 66,
277        F9 = 67,
278        F10 = 68,
279        NumLock = 69,
280        ScrollLock = 70,
281        Keypad7 = 71,
282        Keypad8 = 72,
283        Keypad9 = 73,
284        KeypadMinus = 74,
285        Keypad4 = 75,
286        Keypad5 = 76,
287        Keypad6 = 77,
288        KeypadPlus = 78,
289        Keypad1 = 79,
290        Keypad2 = 80,
291        Keypad3 = 81,
292        Keypad0 = 82,
293        KeypadDot = 83,
294        F11 = 87,
295        F12 = 88,
296        KeypadEnter = 96,
297        RightCtrl = 97,
298        KeypadSlash = 98,
299        SysRq = 99,
300        RightAlt = 100,
301        Home = 102,
302        Up = 103,
303        PageUp = 104,
304        Left = 105,
305        Right = 106,
306        End = 107,
307        Down = 108,
308        PageDown = 109,
309        Insert = 110,
310        Delete = 111,
311        KeypadEqual = 117,
312        KeypadPlusMinus = 118,
313        Pause = 119,
314        KeypadComma = 121,
315        LeftMeta = 125,
316        RightMeta = 126,
317        MouseLeft = 0x110,
318        MouseRight = 0x111,
319        MouseMiddle = 0x112,
320        MouseExtra1 = 0x113,
321        MouseExtra2 = 0x114,
322        MouseExtra3 = 0x115,
323        MouseExtra4 = 0x116,
324        MouseExtra5 = 0x117,
325
326        // https://www.kernel.org/doc/html/v4.15/input/gamepad.html
327        PadSouth = 0x130,
328        PadEast = 0x131,
329        PadNorth = 0x133,
330        PadWest = 0x134,
331        ShoulderLeft = 0x136,
332        ShoulderRight = 0x137,
333        ShoulderLeftLower = 0x138,
334        ShoulderRightLower = 0x139,
335        Select = 0x13a,
336        Start = 0x13b,
337        HomeButton = 0x13c,
338        StickLeft = 0x13d,
339        StickRight = 0x13e,
340        PadUp = 0x220,
341        PadDown = 0x221,
342        PadLeft = 0x222,
343        PadRight = 0x223,
344
345        ButtonMisc = 0x100,
346        TriggerHappy = 0x2c0
347    }
348}
349
350define_enum! {
351    #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
352    enum RelativeAxis {
353        Other( u16 ),
354        X = 0,
355        Y = 1,
356        Z = 2,
357        RX = 3,
358        RY = 4,
359        RZ = 5,
360        Wheel = 8,
361        WheelHiRes = 11
362    }
363}
364
365define_enum! {
366    #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
367    enum AbsoluteAxis {
368        Other( u16 ),
369        X = 0,
370        Y = 1,
371        Z = 2,
372        RX = 3,
373        RY = 4,
374        RZ = 5,
375        Hat0X = 16,
376        Hat0Y = 17,
377        Hat1X = 18,
378        Hat1Y = 19,
379        Hat2X = 20,
380        Hat2Y = 21,
381        Misc = 40
382    }
383}
384
385define_enum! {
386    // Source: linux/input.h
387    #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
388    enum Bus {
389        Other( u16 ),
390        PCI = 0x01,
391        USB = 0x03,
392        HIL = 0x04,
393        Bluetooth = 0x05,
394        Virtual = 0x06,
395        ISA = 0x10,
396        Host = 0x19
397    }
398}
399
400define_enum! {
401    #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
402    enum ForceFeedback {
403        Other( u16 ),
404        Rumble = 0x50
405    }
406}
407
408ioctl_write_int!( evdev_grab_or_release, b'E', 0x90 );
409ioctl_read!( evdev_get_id, b'E', 0x02, RawDeviceId );
410ioctl_write_ptr!( evdev_set_clock_id, b'E', 0xa0, libc::c_int );
411
412ioctl_write_ptr!( evdev_start_force_feedback, b'E', 0x80, RawForceFeedbackEffect );
413ioctl_write_int!( evdev_stop_force_feedback, b'E', 0x81 );
414ioctl_read!( evdev_get_maximum_simultaneous_force_feedback_effect_count, b'E', 0x84, libc::c_int );
415
416pub unsafe fn evdev_get_event_bits( fd: libc::c_int, kind: EventKind, data: *mut u8, length: usize ) -> nix::Result< libc::c_int > {
417    let result = libc::ioctl( fd, request_code_read!( b'E', 0x20 + kind.raw() as usize, length ), data );
418    nix::errno::Errno::result( result )
419}
420
421pub unsafe fn evdev_get_abs_info( fd: libc::c_int, axis: AbsoluteAxis ) -> nix::Result< RawAbsInfo > {
422    let mut abs_info = std::mem::MaybeUninit::uninit();
423    let result = libc::ioctl( fd, request_code_read!( b'E', 0x40 + axis.raw() as usize, std::mem::size_of::< RawAbsInfo >() ), abs_info.as_mut_ptr() );
424    if result < 0 {
425        return Err( nix::errno::Errno::last().into() );
426    }
427
428    Ok( abs_info.assume_init() )
429}