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