1 // Copyright 2019 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 use std::collections::BTreeMap;
6 use std::os::raw::c_uint;
7 use std::ptr::null;
8
9 use base::ioctl_ior_nr;
10 use base::ioctl_iow_nr;
11 use base::ioctl_with_mut_ref;
12 use base::ioctl_with_ptr;
13 use base::ioctl_with_ref;
14 use base::AsRawDescriptor;
15 use data_model::Le32;
16 use linux_input_sys::constants::*;
17
18 use super::virtio_input_absinfo;
19 use super::virtio_input_bitmap;
20 use super::virtio_input_device_ids;
21 use super::InputError;
22 use super::Result;
23
24 const EVDEV: c_uint = 69;
25
26 #[repr(C)]
27 #[derive(Copy, Clone)]
28 struct evdev_buffer {
29 buffer: [std::os::raw::c_uchar; 128],
30 }
31
32 impl evdev_buffer {
new() -> evdev_buffer33 fn new() -> evdev_buffer {
34 evdev_buffer { buffer: [0u8; 128] }
35 }
36
get(&self, bit: usize) -> bool37 fn get(&self, bit: usize) -> bool {
38 let idx = bit / 8;
39 let inner_bit = bit % 8;
40 self.buffer
41 .get(idx)
42 .map_or(false, |val| val & (1u8 << inner_bit) != 0)
43 }
44 }
45
46 #[repr(C)]
47 #[derive(Copy, Clone)]
48 struct evdev_id {
49 bustype: u16,
50 vendor: u16,
51 product: u16,
52 version: u16,
53 }
54
55 impl evdev_id {
new() -> evdev_id56 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)]
68 struct evdev_abs_info {
69 // These should technically by signed ints, but Le32 is only compatible with u32 and we only
70 // forward the bytes but don't care about its actual values.
71 value: u32,
72 minimum: u32,
73 maximum: u32,
74 fuzz: u32,
75 flat: u32,
76 resolution: u32,
77 }
78
79 impl evdev_abs_info {
new() -> evdev_abs_info80 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
92 impl From<evdev_abs_info> for virtio_input_absinfo {
from(other: evdev_abs_info) -> Self93 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
103 ioctl_ior_nr!(EVIOCGID, EVDEV, 0x02, evdev_id);
104 ioctl_ior_nr!(EVIOCGNAME, EVDEV, 0x06, evdev_buffer);
105 ioctl_ior_nr!(EVIOCGUNIQ, EVDEV, 0x08, evdev_buffer);
106 ioctl_ior_nr!(EVIOCGPROP, EVDEV, 0x09, evdev_buffer);
107 ioctl_ior_nr!(EVIOCGBIT, EVDEV, 0x20 + evt, evdev_buffer, evt);
108 ioctl_ior_nr!(EVIOCGABS, EVDEV, 0x40 + abs, evdev_abs_info, abs);
109 ioctl_iow_nr!(EVIOCGRAB, EVDEV, 0x90, u32);
110
errno() -> base::Error111 fn errno() -> base::Error {
112 base::Error::last()
113 }
114
115 /// Gets id information from an event device (see EVIOCGID ioctl for details).
device_ids<T: AsRawDescriptor>(descriptor: &T) -> Result<virtio_input_device_ids>116 pub fn device_ids<T: AsRawDescriptor>(descriptor: &T) -> Result<virtio_input_device_ids> {
117 let mut dev_id = evdev_id::new();
118 let len = {
119 // SAFETY:
120 // Safe because the kernel won't write more than size of evdev_id and we check the return
121 // value
122 unsafe { ioctl_with_mut_ref(descriptor, EVIOCGID(), &mut dev_id) }
123 };
124 if len < 0 {
125 return Err(InputError::EvdevIdError(errno()));
126 }
127 Ok(virtio_input_device_ids::new(
128 dev_id.bustype,
129 dev_id.vendor,
130 dev_id.product,
131 dev_id.version,
132 ))
133 }
134
135 /// Gets the name of an event device (see EVIOCGNAME ioctl for details).
name<T: AsRawDescriptor>(descriptor: &T) -> Result<Vec<u8>>136 pub fn name<T: AsRawDescriptor>(descriptor: &T) -> Result<Vec<u8>> {
137 let mut name = evdev_buffer::new();
138 let len = {
139 // SAFETY:
140 // Safe because the kernel won't write more than size of evdev_buffer and we check the
141 // return value
142 unsafe { ioctl_with_mut_ref(descriptor, EVIOCGNAME(), &mut name) }
143 };
144 if len < 0 {
145 return Err(InputError::EvdevNameError(errno()));
146 }
147 Ok(name.buffer[0..len as usize].to_vec())
148 }
149
150 /// Gets the unique (serial) name of an event device (see EVIOCGUNIQ ioctl for details).
serial_name<T: AsRawDescriptor>(descriptor: &T) -> Result<Vec<u8>>151 pub fn serial_name<T: AsRawDescriptor>(descriptor: &T) -> Result<Vec<u8>> {
152 let mut uniq = evdev_buffer::new();
153 let len = {
154 // SAFETY:
155 // Safe because the kernel won't write more than size of evdev_buffer and we check the
156 // return value
157 unsafe { ioctl_with_mut_ref(descriptor, EVIOCGUNIQ(), &mut uniq) }
158 };
159 if len < 0 {
160 return Err(InputError::EvdevSerialError(errno()));
161 }
162 Ok(uniq.buffer[0..len as usize].to_vec())
163 }
164
165 /// Gets the properties of an event device (see EVIOCGPROP ioctl for details).
properties<T: AsRawDescriptor>(descriptor: &T) -> Result<virtio_input_bitmap>166 pub fn properties<T: AsRawDescriptor>(descriptor: &T) -> Result<virtio_input_bitmap> {
167 let mut props = evdev_buffer::new();
168 let len = {
169 // SAFETY:
170 // Safe because the kernel won't write more than size of evdev_buffer and we check the
171 // return value
172 unsafe { ioctl_with_mut_ref(descriptor, EVIOCGPROP(), &mut props) }
173 };
174 if len < 0 {
175 return Err(InputError::EvdevPropertiesError(errno()));
176 }
177 Ok(virtio_input_bitmap::new(props.buffer))
178 }
179
180 /// Gets the event types supported by an event device as well as the event codes supported for each
181 /// type (see EVIOCGBIT ioctl for details).
supported_events<T: AsRawDescriptor>( descriptor: &T, ) -> Result<BTreeMap<u16, virtio_input_bitmap>>182 pub fn supported_events<T: AsRawDescriptor>(
183 descriptor: &T,
184 ) -> Result<BTreeMap<u16, virtio_input_bitmap>> {
185 let mut evts: BTreeMap<u16, virtio_input_bitmap> = BTreeMap::new();
186
187 let mut evt_types = evdev_buffer::new();
188 let len = {
189 // SAFETY:
190 // Safe because the kernel won't write more than size of evdev_buffer and we check the
191 // return value
192 unsafe { ioctl_with_mut_ref(descriptor, EVIOCGBIT(0), &mut evt_types) }
193 };
194 if len < 0 {
195 return Err(InputError::EvdevEventTypesError(errno()));
196 }
197
198 // no need to ask for zero (EV_SYN) since it's always supported and treated as a special case
199 for ev in 1..EV_MAX {
200 if ev == EV_REP || !evt_types.get(ev as usize) {
201 // Event type not supported, skip it.
202 continue;
203 }
204 // Create a new zero-filled buffer every time to avoid carry-overs.
205 let mut evt_codes = evdev_buffer::new();
206 let len = {
207 // SAFETY:
208 // Safe because the kernel won't write more than size of evdev_buffer and we check the
209 // return value
210 unsafe { ioctl_with_mut_ref(descriptor, EVIOCGBIT(ev as c_uint), &mut evt_codes) }
211 };
212 if len < 0 {
213 return Err(InputError::EvdevEventTypesError(errno()));
214 }
215 evts.insert(ev, virtio_input_bitmap::new(evt_codes.buffer));
216 }
217 Ok(evts)
218 }
219
220 /// Gets the absolute axes of an event device (see EVIOCGABS ioctl for details).
abs_info<T: AsRawDescriptor>(descriptor: &T) -> BTreeMap<u16, virtio_input_absinfo>221 pub fn abs_info<T: AsRawDescriptor>(descriptor: &T) -> BTreeMap<u16, virtio_input_absinfo> {
222 let mut map: BTreeMap<u16, virtio_input_absinfo> = BTreeMap::new();
223
224 for abs in 0..ABS_MAX {
225 // Create a new one, zero-ed out every time to avoid carry-overs.
226 let mut abs_info = evdev_abs_info::new();
227 let ret = {
228 // SAFETY:
229 // Safe because the kernel won't write more than size of evdev_buffer and we check the
230 // return value
231 unsafe { ioctl_with_mut_ref(descriptor, EVIOCGABS(abs as c_uint), &mut abs_info) }
232 };
233 if ret == 0 {
234 map.insert(abs, virtio_input_absinfo::from(abs_info));
235 }
236 }
237 map
238 }
239
240 /// Grabs an event device (see EVIOCGGRAB ioctl for details). After this function succeeds the given
241 /// descriptor has exclusive access to the device, effectively making it unusable for any other
242 /// process in the host.
grab_evdev<T: AsRawDescriptor>(descriptor: &mut T) -> Result<()>243 pub fn grab_evdev<T: AsRawDescriptor>(descriptor: &mut T) -> Result<()> {
244 let val: u32 = 1;
245 let ret = {
246 // SAFETY:
247 // Safe because the kernel only read the value of the ptr and we check the return value
248 unsafe { ioctl_with_ref(descriptor, EVIOCGRAB(), &val) }
249 };
250 if ret == 0 {
251 Ok(())
252 } else {
253 Err(InputError::EvdevGrabError(errno()))
254 }
255 }
256
ungrab_evdev<T: AsRawDescriptor>(descriptor: &mut T) -> Result<()>257 pub fn ungrab_evdev<T: AsRawDescriptor>(descriptor: &mut T) -> Result<()> {
258 let ret = {
259 // SAFETY:
260 // Safe because the kernel only reads the value of the ptr (doesn't dereference) and
261 // we check the return value
262 unsafe { ioctl_with_ptr(descriptor, EVIOCGRAB(), null::<u32>()) }
263 };
264 if ret == 0 {
265 Ok(())
266 } else {
267 Err(InputError::EvdevGrabError(errno()))
268 }
269 }
270