1 /*
2  * Copyright 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //! Wrappers for the Linux evdev APIs.
18 
19 use std::fs::File;
20 use std::io;
21 use std::mem;
22 use std::os::fd::{AsRawFd, OwnedFd};
23 use std::path::Path;
24 
25 use libc::c_int;
26 use nix::sys::time::TimeVal;
27 
28 pub const SYN_CNT: usize = 0x10;
29 pub const KEY_CNT: usize = 0x300;
30 pub const REL_CNT: usize = 0x10;
31 pub const ABS_CNT: usize = 0x40;
32 pub const MSC_CNT: usize = 0x08;
33 pub const SW_CNT: usize = 0x11;
34 pub const LED_CNT: usize = 0x10;
35 pub const SND_CNT: usize = 0x08;
36 pub const REP_CNT: usize = 0x02;
37 
38 // Disable naming warnings, as these are supposed to match the EV_ constants in input-event-codes.h.
39 #[allow(non_camel_case_types)]
40 // Some of these types aren't referenced for evemu purposes, but are included for completeness.
41 #[allow(dead_code)]
42 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
43 #[repr(u16)]
44 pub enum EventType {
45     SYN = 0x00,
46     KEY = 0x01,
47     REL = 0x02,
48     ABS = 0x03,
49     MSC = 0x04,
50     SW = 0x05,
51     LED = 0x11,
52     SND = 0x12,
53     REP = 0x14,
54     FF = 0x15,
55     PWR = 0x16,
56     FF_STATUS = 0x17,
57 }
58 
59 impl EventType {
code_count(&self) -> usize60     fn code_count(&self) -> usize {
61         match self {
62             EventType::SYN => SYN_CNT,
63             EventType::KEY => KEY_CNT,
64             EventType::REL => REL_CNT,
65             EventType::ABS => ABS_CNT,
66             EventType::MSC => MSC_CNT,
67             EventType::SW => SW_CNT,
68             EventType::LED => LED_CNT,
69             EventType::SND => SND_CNT,
70             EventType::REP => REP_CNT,
71             _ => {
72                 panic!("Event type {self:?} does not have a defined code count.");
73             }
74         }
75     }
76 }
77 
78 pub const EVENT_TYPES_WITH_BITMAPS: [EventType; 7] = [
79     EventType::KEY,
80     EventType::REL,
81     EventType::ABS,
82     EventType::MSC,
83     EventType::SW,
84     EventType::LED,
85     EventType::SND,
86 ];
87 
88 const INPUT_PROP_CNT: usize = 32;
89 
90 /// The `ioctl_*!` macros create public functions by default, so this module makes them private.
91 mod ioctl {
92     use nix::{ioctl_read, ioctl_read_buf};
93 
94     ioctl_read!(eviocgid, b'E', 0x02, super::DeviceId);
95     ioctl_read_buf!(eviocgname, b'E', 0x06, u8);
96     ioctl_read_buf!(eviocgprop, b'E', 0x09, u8);
97 }
98 
99 #[derive(Default)]
100 #[repr(C)]
101 pub struct DeviceId {
102     pub bus_type: u16,
103     pub vendor: u16,
104     pub product: u16,
105     pub version: u16,
106 }
107 
108 #[derive(Default)]
109 #[repr(C)]
110 pub struct AbsoluteAxisInfo {
111     pub value: i32,
112     pub minimum: i32,
113     pub maximum: i32,
114     pub fuzz: i32,
115     pub flat: i32,
116     pub resolution: i32,
117 }
118 
119 #[repr(C)]
120 pub struct InputEvent {
121     pub time: TimeVal,
122     pub type_: u16,
123     pub code: u16,
124     pub value: i32,
125 }
126 
127 impl InputEvent {
offset_time_by(&self, offset: TimeVal) -> InputEvent128     pub fn offset_time_by(&self, offset: TimeVal) -> InputEvent {
129         InputEvent { time: self.time - offset, ..*self }
130     }
131 }
132 
133 impl Default for InputEvent {
default() -> Self134     fn default() -> Self {
135         InputEvent { time: TimeVal::new(0, 0), type_: 0, code: 0, value: 0 }
136     }
137 }
138 
139 /// An object representing an input device using Linux's evdev protocol.
140 pub struct Device {
141     fd: OwnedFd,
142 }
143 
144 /// # Safety
145 ///
146 /// `ioctl` must be safe to call with the given file descriptor and a pointer to a buffer of
147 /// `initial_buf_size` `u8`s.
buf_from_ioctl( ioctl: unsafe fn(c_int, &mut [u8]) -> nix::Result<c_int>, fd: &OwnedFd, initial_buf_size: usize, ) -> Result<Vec<u8>, nix::errno::Errno>148 unsafe fn buf_from_ioctl(
149     ioctl: unsafe fn(c_int, &mut [u8]) -> nix::Result<c_int>,
150     fd: &OwnedFd,
151     initial_buf_size: usize,
152 ) -> Result<Vec<u8>, nix::errno::Errno> {
153     let mut buf = vec![0; initial_buf_size];
154     // SAFETY:
155     // Here we're relying on the safety guarantees for `ioctl` made by the caller.
156     match unsafe { ioctl(fd.as_raw_fd(), buf.as_mut_slice()) } {
157         Ok(len) if len < 0 => {
158             panic!("ioctl returned invalid length {len}");
159         }
160         Ok(len) => {
161             buf.truncate(len as usize);
162             Ok(buf)
163         }
164         Err(err) => Err(err),
165     }
166 }
167 
168 impl Device {
169     /// Opens a device from the evdev node at the given path.
open(path: &Path) -> io::Result<Device>170     pub fn open(path: &Path) -> io::Result<Device> {
171         Ok(Device { fd: OwnedFd::from(File::open(path)?) })
172     }
173 
174     /// Returns the name of the device, as set by the relevant kernel driver.
name(&self) -> Result<String, nix::errno::Errno>175     pub fn name(&self) -> Result<String, nix::errno::Errno> {
176         // There's no official maximum length for evdev device names. The Linux HID driver
177         // currently supports names of at most 151 bytes (128 from the device plus a suffix of up
178         // to 23 bytes). 256 seems to be the buffer size most commonly used in evdev bindings, so
179         // we use it here.
180         //
181         // SAFETY:
182         // We know that fd is a valid file descriptor as it comes from a File that we have open.
183         //
184         // The ioctl_read_buf macro prevents the retrieved data from overflowing the buffer created
185         // by buf_from_ioctl by passing in the size to the ioctl, meaning that the kernel's
186         // str_to_user function will truncate the string to that length.
187         let mut buf = unsafe { buf_from_ioctl(ioctl::eviocgname, &self.fd, 256)? };
188         assert!(!buf.is_empty(), "buf is too short for an empty null-terminated string");
189         assert_eq!(buf.pop().unwrap(), 0, "buf is not a null-terminated string");
190         Ok(String::from_utf8_lossy(buf.as_slice()).into_owned())
191     }
192 
ids(&self) -> Result<DeviceId, nix::errno::Errno>193     pub fn ids(&self) -> Result<DeviceId, nix::errno::Errno> {
194         let mut ids = DeviceId::default();
195         // SAFETY:
196         // We know that fd is a valid file descriptor as it comes from a File that we have open.
197         //
198         // We know that the pointer to ids is valid because we just allocated it.
199         unsafe { ioctl::eviocgid(self.fd.as_raw_fd(), &mut ids) }.map(|_| ids)
200     }
201 
properties_bitmap(&self) -> Result<Vec<u8>, nix::errno::Errno>202     pub fn properties_bitmap(&self) -> Result<Vec<u8>, nix::errno::Errno> {
203         let buf_size = (INPUT_PROP_CNT + 7) / 8;
204         // SAFETY:
205         // We know that fd is a valid file descriptor as it comes from a File that we have open.
206         //
207         // The ioctl_read_buf macro prevents the retrieved data from overflowing the buffer created
208         // by buf_from_ioctl by passing in the size to the ioctl, meaning that the kernel's
209         // str_to_user function will truncate the string to that length.
210         unsafe { buf_from_ioctl(ioctl::eviocgprop, &self.fd, buf_size) }
211     }
212 
bitmap_for_event_type(&self, event_type: EventType) -> nix::Result<Vec<u8>>213     pub fn bitmap_for_event_type(&self, event_type: EventType) -> nix::Result<Vec<u8>> {
214         let buf_size = (event_type.code_count() + 7) / 8;
215         let mut buf = vec![0; buf_size];
216 
217         // The EVIOCGBIT ioctl can't be bound using ioctl_read_buf! like the others, since it uses
218         // part of its ioctl code as an additional parameter, for the event type. Hence this unsafe
219         // block is a manual expansion of ioctl_read_buf!.
220         //
221         // SAFETY:
222         // We know that fd is a valid file descriptor as it comes from a File that we have open.
223         //
224         // We prevent the retrieved data from overflowing buf by passing in the size of buf to the
225         // ioctl, meaning that the kernel's str_to_user function will truncate the string to that
226         // length. We also panic if the ioctl returns a length longer than buf, hopefully before the
227         // overflow can do any damage.
228         match nix::errno::Errno::result(unsafe {
229             libc::ioctl(
230                 self.fd.as_raw_fd(),
231                 nix::request_code_read!(b'E', 0x20 + event_type as u16, buf.len())
232                     as nix::sys::ioctl::ioctl_num_type,
233                 buf.as_mut_ptr(),
234             )
235         }) {
236             Ok(len) if len < 0 => {
237                 panic!("EVIOCGBIT returned invalid length {len} for event type {event_type:?}");
238             }
239             Ok(len) => {
240                 buf.truncate(len as usize);
241                 Ok(buf)
242             }
243             Err(err) => Err(err),
244         }
245     }
246 
supported_axes_of_type(&self, event_type: EventType) -> nix::Result<Vec<u16>>247     pub fn supported_axes_of_type(&self, event_type: EventType) -> nix::Result<Vec<u16>> {
248         let mut axes = Vec::new();
249         for (i, byte_ref) in self.bitmap_for_event_type(event_type)?.iter().enumerate() {
250             let mut byte = *byte_ref;
251             for j in 0..8 {
252                 if byte & 1 == 1 {
253                     axes.push((i * 8 + j) as u16);
254                 }
255                 byte >>= 1;
256             }
257         }
258         Ok(axes)
259     }
260 
absolute_axis_info(&self, axis: u16) -> nix::Result<AbsoluteAxisInfo>261     pub fn absolute_axis_info(&self, axis: u16) -> nix::Result<AbsoluteAxisInfo> {
262         let mut info = AbsoluteAxisInfo::default();
263         // The EVIOCGABS ioctl can't be bound using ioctl_read! since it uses part of its ioctl code
264         // as an additional parameter, for the axis code. Hence this unsafe block is a manual
265         // expansion of ioctl_read!.
266         //
267         // SAFETY:
268         // We know that fd is a valid file descriptor as it comes from a File that we have open.
269         //
270         // We know that the pointer to info is valid because we just allocated it.
271         nix::errno::Errno::result(unsafe {
272             nix::libc::ioctl(
273                 self.fd.as_raw_fd(),
274                 nix::request_code_read!(b'E', 0x40 + axis, mem::size_of::<AbsoluteAxisInfo>()),
275                 &mut info,
276             )
277         })
278         .map(|_| info)
279     }
280 
read_event(&self) -> nix::Result<InputEvent>281     pub fn read_event(&self) -> nix::Result<InputEvent> {
282         let mut event = InputEvent::default();
283 
284         // SAFETY:
285         // We know that fd is a valid file descriptor as it comes from a File that we have open.
286         //
287         // We know that the pointer to event is valid because we just allocated it, and that the
288         // data structures match up because InputEvent is repr(C) and all its members are repr(C)
289         // or primitives that support all representations without niches.
290         nix::errno::Errno::result(unsafe {
291             libc::read(
292                 self.fd.as_raw_fd(),
293                 &mut event as *mut _ as *mut std::ffi::c_void,
294                 mem::size_of::<InputEvent>(),
295             )
296         })
297         .map(|_| event)
298     }
299 }
300