input_linux_sys/
input.rs

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
19/// Protocol version.
20pub 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
82/// Set ff device properties
83pub const FF_GAIN: u16 = 0x60;
84pub const FF_AUTOCENTER: u16 = 0x61;
85
86/// The greatest safe value for effect_id is `FF_GAIN - 1`
87pub 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	/// get driver version
207	ev_get_version, b'E', 0x01, c_int
208}
209
210ioctl_read! {
211	/// get device ID
212	ev_get_id, b'E', 0x02, input_id
213}
214
215ioctl_read! {
216	/// get repeat settings
217	ev_get_rep, b'E', 0x03, repeat_settings
218}
219
220ioctl_write_ptr! {
221	/// set repeat settings
222	ev_set_rep, b'E', 0x03, repeat_settings
223}
224
225ioctl_read! {
226	/// get keycode
227	ev_get_keycode, b'E', 0x04, [c_uint; 2]
228}
229
230ioctl_read! {
231	/// get keycode
232	ev_get_keycode_v2, b'E', 0x04, input_keymap_entry
233}
234
235ioctl_write_ptr! {
236	/// set keycode
237	ev_set_keycode, b'E', 0x04, [c_uint; 2]
238}
239
240ioctl_write_ptr! {
241	/// set keycode
242	ev_set_keycode_v2, b'E', 0x04, input_keymap_entry
243}
244
245ioctl_read_buf! {
246	/// get device name
247	ev_get_name, b'E', 0x06, c_char
248}
249
250ioctl_read_buf! {
251	/// get physical location
252	ev_get_phys, b'E', 0x07, c_char
253}
254
255ioctl_read_buf! {
256	/// get unique identifier
257	ev_get_uniq, b'E', 0x08, c_char
258}
259
260ioctl_read_buf! {
261	/// get device properties
262	ev_get_prop, b'E', 0x09, u8
263}
264
265/// get MT slot values
266pub unsafe fn ev_get_mtslots(fd: c_int, buf: *mut input_mt_request_layout) -> nix::Result<i32> {
267	// for some reason this isn't _IORW?
268	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	/// get global key state
273	ev_get_key, b'E', 0x18, u8
274}
275
276ioctl_read_buf! {
277	/// get all LEDs
278	ev_get_led, b'E', 0x19, u8
279}
280
281ioctl_read_buf! {
282	/// get all sounds status
283	ev_get_snd, b'E', 0x1a, u8
284}
285
286ioctl_read_buf! {
287	/// get all switch states
288	ev_get_sw, b'E', 0x1b, u8
289}
290
291/// get event bits
292pub 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
296/// get abs value/limits
297pub 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
301/// set abs value/limits
302pub 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
306/// send a force effect to a force feedback device
307pub unsafe fn ev_send_ff(fd: c_int, buf: *mut ff_effect) -> nix::Result<i32> {
308	// for some reason this isn't _IORW?
309	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	/// Erase a force effect
314	ev_erase_ff, b'E', 0x81
315}
316
317ioctl_read! {
318	/// Report number of effects playable at the same time
319	ev_get_effects, b'E', 0x84, c_int
320}
321
322ioctl_write_int! {
323	/// Grab/Release device
324	ev_grab, b'E', 0x90
325}
326
327ioctl_write_int! {
328	/// Revoke device access
329	ev_revoke, b'E', 0x91
330}
331
332ioctl_read! {
333	/// Retrieve current event mask
334	ev_get_mask, b'E', 0x92, input_mask
335}
336
337ioctl_write_ptr! {
338	/// Set event mask
339	ev_set_mask, b'E', 0x93, input_mask
340}
341
342ioctl_write_ptr! {
343	/// Set clockid to be used for timestamps
344	ev_set_clockid, b'E', 0xa0, clockid_t
345}