devices/virtio/input/
evdev.rs1use std::collections::BTreeMap;
6use std::os::raw::c_uint;
7use std::ptr::null;
8
9use base::ioctl_ior_nr;
10use base::ioctl_iow_nr;
11use base::ioctl_with_mut_ref;
12use base::ioctl_with_ptr;
13use base::ioctl_with_ref;
14use base::AsRawDescriptor;
15use data_model::Le32;
16use linux_input_sys::constants::*;
17
18use super::virtio_input_absinfo;
19use super::virtio_input_bitmap;
20use super::virtio_input_device_ids;
21use super::InputError;
22use super::Result;
23
24const EVDEV: c_uint = 69;
25
26#[repr(C)]
27#[derive(Copy, Clone)]
28struct evdev_buffer {
29 buffer: [std::os::raw::c_uchar; 128],
30}
31
32impl evdev_buffer {
33 fn new() -> evdev_buffer {
34 evdev_buffer { buffer: [0u8; 128] }
35 }
36
37 fn get(&self, bit: usize) -> bool {
38 let idx = bit / 8;
39 let inner_bit = bit % 8;
40 self.buffer
41 .get(idx)
42 .is_some_and(|val| val & (1u8 << inner_bit) != 0)
43 }
44}
45
46#[repr(C)]
47#[derive(Copy, Clone)]
48struct evdev_id {
49 bustype: u16,
50 vendor: u16,
51 product: u16,
52 version: u16,
53}
54
55impl evdev_id {
56 fn new() -> evdev_id {
57 evdev_id {
58 bustype: 0,
59 vendor: 0,
60 product: 0,
61 version: 0,
62 }
63 }
64}
65
66#[repr(C)]
67#[derive(Copy, Clone)]
68struct evdev_abs_info {
69 value: u32,
72 minimum: u32,
73 maximum: u32,
74 fuzz: u32,
75 flat: u32,
76 resolution: u32,
77}
78
79impl evdev_abs_info {
80 fn new() -> evdev_abs_info {
81 evdev_abs_info {
82 value: 0,
83 minimum: 0,
84 maximum: 0,
85 fuzz: 0,
86 flat: 0,
87 resolution: 0,
88 }
89 }
90}
91
92impl From<evdev_abs_info> for virtio_input_absinfo {
93 fn from(other: evdev_abs_info) -> Self {
94 virtio_input_absinfo {
95 min: Le32::from(other.minimum),
96 max: Le32::from(other.maximum),
97 fuzz: Le32::from(other.fuzz),
98 flat: Le32::from(other.flat),
99 }
100 }
101}
102
103ioctl_ior_nr!(EVIOCGID, EVDEV, 0x02, evdev_id);
104ioctl_ior_nr!(EVIOCGNAME, EVDEV, 0x06, evdev_buffer);
105ioctl_ior_nr!(EVIOCGUNIQ, EVDEV, 0x08, evdev_buffer);
106ioctl_ior_nr!(EVIOCGPROP, EVDEV, 0x09, evdev_buffer);
107ioctl_ior_nr!(EVIOCGBIT, EVDEV, 0x20 + evt, evdev_buffer, evt);
108ioctl_ior_nr!(EVIOCGABS, EVDEV, 0x40 + abs, evdev_abs_info, abs);
109ioctl_iow_nr!(EVIOCGRAB, EVDEV, 0x90, u32);
110
111fn errno() -> base::Error {
112 base::Error::last()
113}
114
115fn string_from_bytes_with_nul(buffer: &[u8], mut len: usize) -> Result<String> {
116 if len > 0 && buffer[len] == 0 {
118 len -= 1;
119 }
120 String::from_utf8(buffer[0..len].to_vec()).map_err(InputError::InvalidString)
121}
122
123pub fn device_ids<T: AsRawDescriptor>(descriptor: &T) -> Result<virtio_input_device_ids> {
125 let mut dev_id = evdev_id::new();
126 let len = {
127 unsafe { ioctl_with_mut_ref(descriptor, EVIOCGID, &mut dev_id) }
131 };
132 if len < 0 {
133 return Err(InputError::EvdevIdError(errno()));
134 }
135 Ok(virtio_input_device_ids::new(
136 dev_id.bustype,
137 dev_id.vendor,
138 dev_id.product,
139 dev_id.version,
140 ))
141}
142
143pub fn name<T: AsRawDescriptor>(descriptor: &T) -> Result<String> {
145 let mut name = evdev_buffer::new();
146 let len = {
147 unsafe { ioctl_with_mut_ref(descriptor, EVIOCGNAME, &mut name) }
151 };
152 if len < 0 {
153 return Err(InputError::EvdevNameError(errno()));
154 }
155 string_from_bytes_with_nul(&name.buffer, len as usize)
156}
157
158pub fn serial_name<T: AsRawDescriptor>(descriptor: &T) -> Result<String> {
160 let mut uniq = evdev_buffer::new();
161 let len = {
162 unsafe { ioctl_with_mut_ref(descriptor, EVIOCGUNIQ, &mut uniq) }
166 };
167 if len < 0 {
168 return Err(InputError::EvdevSerialError(errno()));
169 }
170 string_from_bytes_with_nul(&uniq.buffer, len as usize)
171}
172
173pub fn properties<T: AsRawDescriptor>(descriptor: &T) -> Result<virtio_input_bitmap> {
175 let mut props = evdev_buffer::new();
176 let len = {
177 unsafe { ioctl_with_mut_ref(descriptor, EVIOCGPROP, &mut props) }
181 };
182 if len < 0 {
183 return Err(InputError::EvdevPropertiesError(errno()));
184 }
185 Ok(virtio_input_bitmap::new(props.buffer))
186}
187
188pub fn supported_events<T: AsRawDescriptor>(
191 descriptor: &T,
192) -> Result<BTreeMap<u16, virtio_input_bitmap>> {
193 let mut evts: BTreeMap<u16, virtio_input_bitmap> = BTreeMap::new();
194
195 let mut evt_types = evdev_buffer::new();
196 let len = {
197 unsafe { ioctl_with_mut_ref(descriptor, EVIOCGBIT(0), &mut evt_types) }
201 };
202 if len < 0 {
203 return Err(InputError::EvdevEventTypesError(errno()));
204 }
205
206 for ev in 1..EV_MAX {
208 if ev == EV_REP || !evt_types.get(ev as usize) {
209 continue;
211 }
212 let mut evt_codes = evdev_buffer::new();
214 let len = {
215 unsafe { ioctl_with_mut_ref(descriptor, EVIOCGBIT(ev as c_uint), &mut evt_codes) }
219 };
220 if len < 0 {
221 return Err(InputError::EvdevEventTypesError(errno()));
222 }
223 evts.insert(ev, virtio_input_bitmap::new(evt_codes.buffer));
224 }
225 Ok(evts)
226}
227
228pub fn abs_info<T: AsRawDescriptor>(descriptor: &T) -> BTreeMap<u16, virtio_input_absinfo> {
230 let mut map: BTreeMap<u16, virtio_input_absinfo> = BTreeMap::new();
231
232 for abs in 0..ABS_MAX {
233 let mut abs_info = evdev_abs_info::new();
235 let ret = {
236 unsafe { ioctl_with_mut_ref(descriptor, EVIOCGABS(abs as c_uint), &mut abs_info) }
240 };
241 if ret == 0 {
242 map.insert(abs, virtio_input_absinfo::from(abs_info));
243 }
244 }
245 map
246}
247
248pub fn grab_evdev<T: AsRawDescriptor>(descriptor: &mut T) -> Result<()> {
252 let val: u32 = 1;
253 let ret = {
254 unsafe { ioctl_with_ref(descriptor, EVIOCGRAB, &val) }
257 };
258 if ret == 0 {
259 Ok(())
260 } else {
261 Err(InputError::EvdevGrabError(errno()))
262 }
263}
264
265pub fn ungrab_evdev<T: AsRawDescriptor>(descriptor: &mut T) -> Result<()> {
266 let ret = {
267 unsafe { ioctl_with_ptr(descriptor, EVIOCGRAB, null::<u32>()) }
271 };
272 if ret == 0 {
273 Ok(())
274 } else {
275 Err(InputError::EvdevGrabError(errno()))
276 }
277}