evdev/
sys.rs

1#![allow(non_camel_case_types)]
2
3use crate::compat::{
4    ff_condition_effect, ff_constant_effect, ff_periodic_effect, ff_ramp_effect, ff_replay,
5    ff_rumble_effect, ff_trigger, input_absinfo, input_id, input_keymap_entry, uinput_abs_setup,
6    uinput_setup,
7};
8use nix::{
9    convert_ioctl_res, ioctl_none, ioctl_read, ioctl_read_buf, ioctl_readwrite, ioctl_write_int,
10    ioctl_write_ptr, request_code_read,
11};
12
13#[repr(C)]
14#[derive(Clone, Copy)]
15pub union ff_effect_union {
16    pub constant: ff_constant_effect,
17    pub ramp: ff_ramp_effect,
18    pub periodic: ff_periodic_effect,
19    pub condition: [ff_condition_effect; 2],
20    pub rumble: ff_rumble_effect,
21}
22
23#[repr(C)]
24#[derive(Clone, Copy)]
25pub struct ff_effect {
26    pub type_: u16,
27    pub id: i16,
28    pub direction: u16,
29    pub trigger: ff_trigger,
30    pub replay: ff_replay,
31    pub u: ff_effect_union,
32}
33
34#[repr(C)]
35#[derive(Clone, Copy)]
36pub struct uinput_ff_upload {
37    pub request_id: u32,
38    pub retval: i32,
39    pub effect: ff_effect,
40    pub old: ff_effect,
41}
42
43#[repr(C)]
44#[derive(Clone, Copy)]
45pub struct uinput_ff_erase {
46    pub request_id: u32,
47    pub retval: i32,
48    pub effect_id: u32,
49}
50
51ioctl_read!(eviocgeffects, b'E', 0x84, ::libc::c_int);
52ioctl_read!(eviocgid, b'E', 0x02, /*struct*/ input_id);
53ioctl_read!(eviocgkeycode, b'E', 0x04, [::libc::c_uint; 2]);
54ioctl_read!(eviocgrep, b'E', 0x03, [::libc::c_uint; 2]);
55ioctl_read!(eviocgversion, b'E', 0x01, ::libc::c_int);
56ioctl_write_int!(eviocrmff, b'E', 0x81);
57
58ioctl_read!(eviocgkeycode_v2, b'E', 0x04, input_keymap_entry);
59ioctl_write_ptr!(eviocskeycode, b'E', 0x04, [::libc::c_uint; 2]);
60ioctl_write_ptr!(eviocskeycode_v2, b'E', 0x04, input_keymap_entry);
61ioctl_write_ptr!(eviocsrep, b'E', 0x03, [::libc::c_uint; 2]);
62
63ioctl_read_buf!(eviocgname, b'E', 0x06, u8);
64ioctl_read_buf!(eviocgphys, b'E', 0x07, u8);
65ioctl_read_buf!(eviocguniq, b'E', 0x08, u8);
66ioctl_read_buf!(eviocgprop, b'E', 0x09, u8);
67ioctl_read_buf!(eviocgmtslots, b'E', 0x0a, u8);
68ioctl_read_buf!(eviocgkey, b'E', 0x18, u8);
69ioctl_read_buf!(eviocgled, b'E', 0x19, u8);
70ioctl_read_buf!(eviocgsnd, b'E', 0x1a, u8);
71ioctl_read_buf!(eviocgsw, b'E', 0x1b, u8);
72
73ioctl_write_ptr!(eviocsff, b'E', 0x80, ff_effect);
74ioctl_write_int!(eviocgrab, b'E', 0x90);
75ioctl_write_int!(eviocrevoke, b'E', 0x91);
76ioctl_write_int!(eviocsclockid, b'E', 0xa0);
77
78const UINPUT_IOCTL_BASE: u8 = b'U';
79ioctl_write_ptr!(ui_dev_setup, UINPUT_IOCTL_BASE, 3, uinput_setup);
80ioctl_write_ptr!(ui_abs_setup, UINPUT_IOCTL_BASE, 4, uinput_abs_setup);
81ioctl_none!(ui_dev_create, UINPUT_IOCTL_BASE, 1);
82
83ioctl_write_int!(ui_set_evbit, UINPUT_IOCTL_BASE, 100);
84ioctl_write_int!(ui_set_keybit, UINPUT_IOCTL_BASE, 101);
85ioctl_write_int!(ui_set_relbit, UINPUT_IOCTL_BASE, 102);
86ioctl_write_int!(ui_set_absbit, UINPUT_IOCTL_BASE, 103);
87ioctl_write_int!(ui_set_mscbit, UINPUT_IOCTL_BASE, 104);
88ioctl_write_int!(ui_set_ledbit, UINPUT_IOCTL_BASE, 105);
89ioctl_write_int!(ui_set_sndbit, UINPUT_IOCTL_BASE, 106);
90ioctl_write_int!(ui_set_ffbit, UINPUT_IOCTL_BASE, 107);
91ioctl_write_ptr!(ui_set_phys, UINPUT_IOCTL_BASE, 108, libc::c_char);
92ioctl_write_int!(ui_set_swbit, UINPUT_IOCTL_BASE, 109);
93ioctl_write_int!(ui_set_propbit, UINPUT_IOCTL_BASE, 110);
94
95ioctl_read_buf!(ui_get_sysname, UINPUT_IOCTL_BASE, 300, u8);
96
97ioctl_readwrite!(ui_begin_ff_upload, UINPUT_IOCTL_BASE, 200, uinput_ff_upload);
98ioctl_write_ptr!(ui_end_ff_upload, UINPUT_IOCTL_BASE, 201, uinput_ff_upload);
99ioctl_readwrite!(ui_begin_ff_erase, UINPUT_IOCTL_BASE, 202, uinput_ff_erase);
100ioctl_write_ptr!(ui_end_ff_erase, UINPUT_IOCTL_BASE, 203, uinput_ff_erase);
101
102macro_rules! eviocgbit_ioctl {
103    ($mac:ident!($name:ident, $ev:ident, $ty:ty)) => {
104        eviocgbit_ioctl!($mac!($name, $crate::EventType::$ev.0, $ty));
105    };
106    ($mac:ident!($name:ident, $ev:expr, $ty:ty)) => {
107        $mac!($name, b'E', 0x20 + $ev, $ty);
108    };
109}
110
111eviocgbit_ioctl!(ioctl_read_buf!(eviocgbit_type, 0, u8));
112eviocgbit_ioctl!(ioctl_read_buf!(eviocgbit_key, KEY, u8));
113eviocgbit_ioctl!(ioctl_read_buf!(eviocgbit_relative, RELATIVE, u8));
114eviocgbit_ioctl!(ioctl_read_buf!(eviocgbit_absolute, ABSOLUTE, u8));
115eviocgbit_ioctl!(ioctl_read_buf!(eviocgbit_misc, MISC, u8));
116eviocgbit_ioctl!(ioctl_read_buf!(eviocgbit_switch, SWITCH, u8));
117eviocgbit_ioctl!(ioctl_read_buf!(eviocgbit_led, LED, u8));
118eviocgbit_ioctl!(ioctl_read_buf!(eviocgbit_sound, SOUND, u8));
119eviocgbit_ioctl!(ioctl_read_buf!(eviocgbit_repeat, REPEAT, u8));
120eviocgbit_ioctl!(ioctl_read_buf!(eviocgbit_ff, FORCEFEEDBACK, u8));
121eviocgbit_ioctl!(ioctl_read_buf!(eviocgbit_power, POWER, u8));
122eviocgbit_ioctl!(ioctl_read_buf!(eviocgbit_ffstatus, FORCEFEEDBACKSTATUS, u8));
123
124/// ioctl: "get abs value/limits"
125///
126/// `abs` should be one of the "Absolute axes" values defined in the Linux kernel headers.
127/// In modern (5.11) kernels these are in `include/uapi/linux/input-event-codes.h`, and in older
128/// kernels these defines can be found in `include/uapi/linux/input.h`
129///
130/// # Panics
131///
132/// Calling this with a value greater than the kernel-defined `ABS_MAX` (typically 0x3f) will panic.
133///
134/// # Safety
135///
136/// 'abs' must be a valid axis number and supported by the device, otherwise the behavior is
137/// undefined.
138pub unsafe fn eviocgabs(
139    fd: ::libc::c_int,
140    abs: u32,
141    buf: &mut input_absinfo,
142) -> ::nix::Result<::libc::c_int> {
143    assert!(abs <= 0x3f);
144    convert_ioctl_res!(::nix::libc::ioctl(
145        fd,
146        request_code_read!(b'E', 0x40 + abs, ::std::mem::size_of::<input_absinfo>()),
147        buf as *mut input_absinfo
148    ))
149}