1use std::mem::{size_of, size_of_val};
2use nix::{
3 self,
4 sys::ioctl::ioctl_num_type,
5 convert_ioctl_res,
6 ioctl_read, ioctl_read_buf,
7 ioctl_write_ptr, ioctl_write_int,
8 request_code_read, request_code_write,
9};
10use libc::{c_char, c_int, c_uint, clockid_t, ioctl};
11
12pub use libc::{
13 timeval,
14 input_event, input_id, input_absinfo, input_keymap_entry, input_mask,
15 ff_replay, ff_trigger, ff_envelope, ff_effect, ff_constant_effect,
16 ff_ramp_effect, ff_condition_effect, ff_periodic_effect, ff_rumble_effect,
17};
18
19pub const EV_VERSION: c_int = 0x010001;
21
22pub const ID_BUS: usize = 0;
23pub const ID_VENDOR: usize = 1;
24pub const ID_PRODUCT: usize = 2;
25pub const ID_VERSION: usize = 3;
26
27pub const BUS_PCI: u16 = 0x01;
28pub const BUS_ISAPNP: u16 = 0x02;
29pub const BUS_USB: u16 = 0x03;
30pub const BUS_HIL: u16 = 0x04;
31pub const BUS_BLUETOOTH: u16 = 0x05;
32pub const BUS_VIRTUAL: u16 = 0x06;
33
34pub const BUS_ISA: u16 = 0x10;
35pub const BUS_I8042: u16 = 0x11;
36pub const BUS_XTKBD: u16 = 0x12;
37pub const BUS_RS232: u16 = 0x13;
38pub const BUS_GAMEPORT: u16 = 0x14;
39pub const BUS_PARPORT: u16 = 0x15;
40pub const BUS_AMIGA: u16 = 0x16;
41pub const BUS_ADB: u16 = 0x17;
42pub const BUS_I2C: u16 = 0x18;
43pub const BUS_HOST: u16 = 0x19;
44pub const BUS_GSC: u16 = 0x1A;
45pub const BUS_ATARI: u16 = 0x1B;
46pub const BUS_SPI: u16 = 0x1C;
47pub const BUS_RMI: u16 = 0x1D;
48pub const BUS_CEC: u16 = 0x1E;
49pub const BUS_INTEL_ISHTP: u16 = 0x1F;
50pub const BUS_AMD_SFH: u16 = 0x20;
51
52pub const MT_TOOL_FINGER: u16 = 0x00;
53pub const MT_TOOL_PEN: u16 = 0x01;
54pub const MT_TOOL_PALM: u16 = 0x02;
55pub const MT_TOOL_DIAL: u16 = 0x0a;
56pub const MT_TOOL_MAX: u16 = 0x0f;
57
58pub const FF_STATUS_STOPPED: u16 = 0x00;
59pub const FF_STATUS_PLAYING: u16 = 0x01;
60pub const FF_STATUS_MAX: u16 = 0x01;
61
62pub const FF_RUMBLE: u16 = 0x50;
63pub const FF_PERIODIC: u16 = 0x51;
64pub const FF_CONSTANT: u16 = 0x52;
65pub const FF_SPRING: u16 = 0x53;
66pub const FF_FRICTION: u16 = 0x54;
67pub const FF_DAMPER: u16 = 0x55;
68pub const FF_INERTIA: u16 = 0x56;
69pub const FF_RAMP: u16 = 0x57;
70pub const FF_EFFECT_MIN: u16 = FF_RUMBLE;
71pub const FF_EFFECT_MAX: u16 = FF_RAMP;
72
73pub const FF_SQUARE: u16 = 0x58;
74pub const FF_TRIANGLE: u16 = 0x59;
75pub const FF_SINE: u16 = 0x5a;
76pub const FF_SAW_UP: u16 = 0x5b;
77pub const FF_SAW_DOWN: u16 = 0x5c;
78pub const FF_CUSTOM: u16 = 0x5d;
79pub const FF_WAVEFORM_MIN: u16 = FF_SQUARE;
80pub const FF_WAVEFORM_MAX: u16 = FF_CUSTOM;
81
82pub const FF_GAIN: u16 = 0x60;
84pub const FF_AUTOCENTER: u16 = 0x61;
85
86pub const FF_MAX_EFFECTS: u16 = FF_GAIN;
88
89pub const FF_MAX: u16 = 0x7f;
90pub const FF_CNT: u16 = FF_MAX + 1;
91
92#[repr(C)]
93#[derive(Copy, Clone)]
94pub struct ff_effect_union {
95 #[cfg(target_pointer_width = "64")]
96 pub u: [u64; 4],
97 #[cfg(target_pointer_width = "32")]
98 pub u: [u32; 7],
99}
100
101impl<'a> From<&'a ff_effect> for &'a ff_effect_union {
102 fn from(effect: &'a ff_effect) -> Self {
103 unsafe {
104 let raw = &effect.u as *const _ as *const _;
105 &*raw
106 }
107 }
108}
109
110impl<'a> From<&'a mut ff_effect> for &'a mut ff_effect_union {
111 fn from(effect: &'a mut ff_effect) -> Self {
112 unsafe {
113 let raw = &mut effect.u as *mut _ as *mut _;
114 &mut *raw
115 }
116 }
117}
118
119impl ff_effect_union {
120 pub fn constant(&self) -> &ff_constant_effect {
121 unsafe {
122 let raw = &self.u as *const _ as *const _;
123 &*raw
124 }
125 }
126
127 pub fn constant_mut(&mut self) -> &mut ff_constant_effect {
128 unsafe {
129 let raw = &mut self.u as *mut _ as *mut _;
130 &mut *raw
131 }
132 }
133
134 pub fn ramp(&self) -> &ff_ramp_effect {
135 unsafe {
136 let raw = &self.u as *const _ as *const _;
137 &*raw
138 }
139 }
140
141 pub fn ramp_mut(&mut self) -> &mut ff_ramp_effect {
142 unsafe {
143 let raw = &mut self.u as *mut _ as *mut _;
144 &mut *raw
145 }
146 }
147
148 pub fn periodic(&self) -> &ff_periodic_effect {
149 unsafe {
150 let raw = &self.u as *const _ as *const _;
151 &*raw
152 }
153 }
154
155 pub fn periodic_mut(&mut self) -> &mut ff_periodic_effect {
156 unsafe {
157 let raw = &mut self.u as *mut _ as *mut _;
158 &mut *raw
159 }
160 }
161
162 pub fn condition(&self) -> &[ff_condition_effect; 2] {
163 unsafe {
164 let raw = &self.u as *const _ as *const _;
165 &*raw
166 }
167 }
168
169 pub fn condition_mut(&mut self) -> &mut [ff_condition_effect; 2] {
170 unsafe {
171 let raw = &mut self.u as *mut _ as *mut _;
172 &mut *raw
173 }
174 }
175
176 pub fn rumble(&self) -> &ff_rumble_effect {
177 unsafe {
178 let raw = &self.u as *const _ as *const _;
179 &*raw
180 }
181 }
182
183 pub fn rumble_mut(&mut self) -> &mut ff_rumble_effect {
184 unsafe {
185 let raw = &mut self.u as *mut _ as *mut _;
186 &mut *raw
187 }
188 }
189}
190
191#[repr(C)]
192#[derive(Copy, Clone)]
193pub struct repeat_settings {
194 pub delay: c_uint,
195 pub period: c_uint,
196}
197
198#[repr(C)]
199#[derive(Copy, Clone)]
200pub struct input_mt_request_layout<T: ?Sized = [i32]> {
201 pub code: u32,
202 pub values: T,
203}
204
205ioctl_read! {
206 ev_get_version, b'E', 0x01, c_int
208}
209
210ioctl_read! {
211 ev_get_id, b'E', 0x02, input_id
213}
214
215ioctl_read! {
216 ev_get_rep, b'E', 0x03, repeat_settings
218}
219
220ioctl_write_ptr! {
221 ev_set_rep, b'E', 0x03, repeat_settings
223}
224
225ioctl_read! {
226 ev_get_keycode, b'E', 0x04, [c_uint; 2]
228}
229
230ioctl_read! {
231 ev_get_keycode_v2, b'E', 0x04, input_keymap_entry
233}
234
235ioctl_write_ptr! {
236 ev_set_keycode, b'E', 0x04, [c_uint; 2]
238}
239
240ioctl_write_ptr! {
241 ev_set_keycode_v2, b'E', 0x04, input_keymap_entry
243}
244
245ioctl_read_buf! {
246 ev_get_name, b'E', 0x06, c_char
248}
249
250ioctl_read_buf! {
251 ev_get_phys, b'E', 0x07, c_char
253}
254
255ioctl_read_buf! {
256 ev_get_uniq, b'E', 0x08, c_char
258}
259
260ioctl_read_buf! {
261 ev_get_prop, b'E', 0x09, u8
263}
264
265pub unsafe fn ev_get_mtslots(fd: c_int, buf: *mut input_mt_request_layout) -> nix::Result<i32> {
267 convert_ioctl_res!(ioctl(fd, request_code_read!(b'E', 0x0a, size_of_val(&*buf)) as ioctl_num_type, buf))
269}
270
271ioctl_read_buf! {
272 ev_get_key, b'E', 0x18, u8
274}
275
276ioctl_read_buf! {
277 ev_get_led, b'E', 0x19, u8
279}
280
281ioctl_read_buf! {
282 ev_get_snd, b'E', 0x1a, u8
284}
285
286ioctl_read_buf! {
287 ev_get_sw, b'E', 0x1b, u8
289}
290
291pub unsafe fn ev_get_bit(fd: c_int, ev: u32, buf: &mut [u8]) -> nix::Result<i32> {
293 convert_ioctl_res!(ioctl(fd, request_code_read!(b'E', 0x20 + ev, buf.len()) as ioctl_num_type, buf))
294}
295
296pub unsafe fn ev_get_abs(fd: c_int, abs: u32, buf: *mut input_absinfo) -> nix::Result<i32> {
298 convert_ioctl_res!(ioctl(fd, request_code_read!(b'E', 0x40 + abs, size_of::<input_absinfo>()) as ioctl_num_type, buf))
299}
300
301pub unsafe fn ev_set_abs(fd: c_int, abs: u32, buf: *const input_absinfo) -> nix::Result<i32> {
303 convert_ioctl_res!(ioctl(fd, request_code_read!(b'E', 0x40 + abs, size_of::<input_absinfo>()) as ioctl_num_type, buf))
304}
305
306pub unsafe fn ev_send_ff(fd: c_int, buf: *mut ff_effect) -> nix::Result<i32> {
308 convert_ioctl_res!(ioctl(fd, request_code_write!(b'E', 0x80, size_of::<ff_effect>()) as ioctl_num_type, buf))
310}
311
312ioctl_write_int! {
313 ev_erase_ff, b'E', 0x81
315}
316
317ioctl_read! {
318 ev_get_effects, b'E', 0x84, c_int
320}
321
322ioctl_write_int! {
323 ev_grab, b'E', 0x90
325}
326
327ioctl_write_int! {
328 ev_revoke, b'E', 0x91
330}
331
332ioctl_read! {
333 ev_get_mask, b'E', 0x92, input_mask
335}
336
337ioctl_write_ptr! {
338 ev_set_mask, b'E', 0x93, input_mask
340}
341
342ioctl_write_ptr! {
343 ev_set_clockid, b'E', 0xa0, clockid_t
345}