xref: /aosp_15_r20/external/crosvm/devices/src/virtio/input/evdev.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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 
string_from_bytes_with_nul(buffer: &[u8], mut len: usize) -> Result<String>115 fn string_from_bytes_with_nul(buffer: &[u8], mut len: usize) -> Result<String> {
116     // Trim NUL byte.
117     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 
123 /// Gets id information from an event device (see EVIOCGID ioctl for details).
device_ids<T: AsRawDescriptor>(descriptor: &T) -> Result<virtio_input_device_ids>124 pub fn device_ids<T: AsRawDescriptor>(descriptor: &T) -> Result<virtio_input_device_ids> {
125     let mut dev_id = evdev_id::new();
126     let len = {
127         // SAFETY:
128         // Safe because the kernel won't write more than size of evdev_id and we check the return
129         // value
130         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 
143 /// Gets the name of an event device (see EVIOCGNAME ioctl for details).
name<T: AsRawDescriptor>(descriptor: &T) -> Result<String>144 pub fn name<T: AsRawDescriptor>(descriptor: &T) -> Result<String> {
145     let mut name = evdev_buffer::new();
146     let len = {
147         // SAFETY:
148         // Safe because the kernel won't write more than size of evdev_buffer and we check the
149         // return value
150         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 
158 /// Gets the unique (serial) name of an event device (see EVIOCGUNIQ ioctl for details).
serial_name<T: AsRawDescriptor>(descriptor: &T) -> Result<String>159 pub fn serial_name<T: AsRawDescriptor>(descriptor: &T) -> Result<String> {
160     let mut uniq = evdev_buffer::new();
161     let len = {
162         // SAFETY:
163         // Safe because the kernel won't write more than size of evdev_buffer and we check the
164         // return value
165         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 
173 /// Gets the properties of an event device (see EVIOCGPROP ioctl for details).
properties<T: AsRawDescriptor>(descriptor: &T) -> Result<virtio_input_bitmap>174 pub fn properties<T: AsRawDescriptor>(descriptor: &T) -> Result<virtio_input_bitmap> {
175     let mut props = evdev_buffer::new();
176     let len = {
177         // SAFETY:
178         // Safe because the kernel won't write more than size of evdev_buffer and we check the
179         // return value
180         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 
188 /// Gets the event types supported by an event device as well as the event codes supported for each
189 /// type (see EVIOCGBIT ioctl for details).
supported_events<T: AsRawDescriptor>( descriptor: &T, ) -> Result<BTreeMap<u16, virtio_input_bitmap>>190 pub 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         // SAFETY:
198         // Safe because the kernel won't write more than size of evdev_buffer and we check the
199         // return value
200         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     // no need to ask for zero (EV_SYN) since it's always supported and treated as a special case
207     for ev in 1..EV_MAX {
208         if ev == EV_REP || !evt_types.get(ev as usize) {
209             // Event type not supported, skip it.
210             continue;
211         }
212         // Create a new zero-filled buffer every time to avoid carry-overs.
213         let mut evt_codes = evdev_buffer::new();
214         let len = {
215             // SAFETY:
216             // Safe because the kernel won't write more than size of evdev_buffer and we check the
217             // return value
218             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 
228 /// Gets the absolute axes of an event device (see EVIOCGABS ioctl for details).
abs_info<T: AsRawDescriptor>(descriptor: &T) -> BTreeMap<u16, virtio_input_absinfo>229 pub 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         // Create a new one, zero-ed out every time to avoid carry-overs.
234         let mut abs_info = evdev_abs_info::new();
235         let ret = {
236             // SAFETY:
237             // Safe because the kernel won't write more than size of evdev_buffer and we check the
238             // return value
239             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 
248 /// Grabs an event device (see EVIOCGGRAB ioctl for details). After this function succeeds the given
249 /// descriptor has exclusive access to the device, effectively making it unusable for any other
250 /// process in the host.
grab_evdev<T: AsRawDescriptor>(descriptor: &mut T) -> Result<()>251 pub fn grab_evdev<T: AsRawDescriptor>(descriptor: &mut T) -> Result<()> {
252     let val: u32 = 1;
253     let ret = {
254         // SAFETY:
255         // Safe because the kernel only read the value of the ptr and we check the return value
256         unsafe { ioctl_with_ref(descriptor, EVIOCGRAB, &val) }
257     };
258     if ret == 0 {
259         Ok(())
260     } else {
261         Err(InputError::EvdevGrabError(errno()))
262     }
263 }
264 
ungrab_evdev<T: AsRawDescriptor>(descriptor: &mut T) -> Result<()>265 pub fn ungrab_evdev<T: AsRawDescriptor>(descriptor: &mut T) -> Result<()> {
266     let ret = {
267         // SAFETY:
268         // Safe because the kernel only reads the value of the ptr (doesn't dereference) and
269         // we check the return value
270         unsafe { ioctl_with_ptr(descriptor, EVIOCGRAB, null::<u32>()) }
271     };
272     if ret == 0 {
273         Ok(())
274     } else {
275         Err(InputError::EvdevGrabError(errno()))
276     }
277 }
278