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 pub value: i32,
15 pub minimum: i32,
17 pub maximum: i32,
19 pub noise_threshold: i32,
21 pub deadzone: i32,
23 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 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 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 #[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}