• 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 data_model::{DataInit, Le16, SLe32};
6 use std::mem::size_of;
7 
8 pub const EV_SYN: u16 = 0x00;
9 pub const EV_KEY: u16 = 0x01;
10 pub const EV_REL: u16 = 0x02;
11 pub const EV_ABS: u16 = 0x03;
12 pub const SYN_REPORT: u16 = 0;
13 pub const REL_X: u16 = 0x00;
14 pub const REL_Y: u16 = 0x01;
15 pub const ABS_X: u16 = 0x00;
16 pub const ABS_Y: u16 = 0x01;
17 pub const ABS_PRESSURE: u16 = 0x18;
18 pub const ABS_TILT_X: u16 = 0x1a;
19 pub const ABS_TILT_Y: u16 = 0x1b;
20 pub const ABS_TOOL_WIDTH: u16 = 0x1c;
21 pub const BTN_TOUCH: u16 = 0x14a;
22 pub const BTN_TOOL_FINGER: u16 = 0x145;
23 pub const ABS_MT_SLOT: u16 = 0x2f;
24 pub const ABS_MT_TOUCH_MAJOR: u16 = 0x30;
25 pub const ABS_MT_TOUCH_MINOR: u16 = 0x31;
26 pub const ABS_MT_WIDTH_MAJOR: u16 = 0x32;
27 pub const ABS_MT_WIDTH_MINOR: u16 = 0x33;
28 pub const ABS_MT_ORIENTATION: u16 = 0x34;
29 pub const ABS_MT_POSITION_X: u16 = 0x35;
30 pub const ABS_MT_POSITION_Y: u16 = 0x36;
31 pub const ABS_MT_TOOL_TYPE: u16 = 0x37;
32 pub const ABS_MT_BLOB_ID: u16 = 0x38;
33 pub const ABS_MT_TRACKING_ID: u16 = 0x39;
34 pub const ABS_MT_PRESSURE: u16 = 0x3a;
35 pub const ABS_MT_DISTANCE: u16 = 0x3b;
36 pub const ABS_MT_TOOL_X: u16 = 0x3c;
37 pub const ABS_MT_TOOL_Y: u16 = 0x3d;
38 
39 /// Allows a raw input event of the implementor's type to be decoded into
40 /// a virtio_input_event.
41 pub trait InputEventDecoder {
42     const SIZE: usize;
decode(data: &[u8]) -> virtio_input_event43     fn decode(data: &[u8]) -> virtio_input_event;
44 }
45 
46 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
47 #[repr(C)]
48 pub struct input_event {
49     pub timestamp_fields: [u64; 2],
50     pub type_: u16,
51     pub code: u16,
52     pub value: i32,
53 }
54 // Safe because it only has data and has no implicit padding.
55 unsafe impl DataInit for input_event {}
56 
57 impl input_event {
from_virtio_input_event(other: &virtio_input_event) -> input_event58     pub fn from_virtio_input_event(other: &virtio_input_event) -> input_event {
59         input_event {
60             timestamp_fields: [0, 0],
61             type_: other.type_.into(),
62             code: other.code.into(),
63             value: other.value.into(),
64         }
65     }
66 }
67 
68 impl InputEventDecoder for input_event {
69     const SIZE: usize = size_of::<Self>();
70 
decode(data: &[u8]) -> virtio_input_event71     fn decode(data: &[u8]) -> virtio_input_event {
72         #[repr(align(8))]
73         struct Aligner([u8; input_event::SIZE]);
74         let data_aligned = Aligner(*<[u8; input_event::SIZE]>::from_slice(data).unwrap());
75         let e = Self::from_slice(&data_aligned.0).unwrap();
76         virtio_input_event {
77             type_: Le16::from(e.type_),
78             code: Le16::from(e.code),
79             value: SLe32::from(e.value),
80         }
81     }
82 }
83 
84 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
85 #[repr(C)]
86 pub struct virtio_input_event {
87     pub type_: Le16,
88     pub code: Le16,
89     pub value: SLe32,
90 }
91 
92 // Safe because it only has data and has no implicit padding.
93 unsafe impl DataInit for virtio_input_event {}
94 
95 impl InputEventDecoder for virtio_input_event {
96     const SIZE: usize = size_of::<Self>();
97 
decode(data: &[u8]) -> virtio_input_event98     fn decode(data: &[u8]) -> virtio_input_event {
99         #[repr(align(4))]
100         struct Aligner([u8; virtio_input_event::SIZE]);
101         let data_aligned = Aligner(*<[u8; virtio_input_event::SIZE]>::from_slice(data).unwrap());
102         *Self::from_slice(&data_aligned.0).unwrap()
103     }
104 }
105 
106 impl virtio_input_event {
107     #[inline]
syn() -> virtio_input_event108     pub fn syn() -> virtio_input_event {
109         virtio_input_event {
110             type_: Le16::from(EV_SYN),
111             code: Le16::from(SYN_REPORT),
112             value: SLe32::from(0),
113         }
114     }
115 
116     #[inline]
absolute(code: u16, value: i32) -> virtio_input_event117     pub fn absolute(code: u16, value: i32) -> virtio_input_event {
118         virtio_input_event {
119             type_: Le16::from(EV_ABS),
120             code: Le16::from(code),
121             value: SLe32::from(value),
122         }
123     }
124 
125     #[inline]
relative(code: u16, value: i32) -> virtio_input_event126     pub fn relative(code: u16, value: i32) -> virtio_input_event {
127         virtio_input_event {
128             type_: Le16::from(EV_REL),
129             code: Le16::from(code),
130             value: SLe32::from(value),
131         }
132     }
133 
134     #[inline]
multitouch_tracking_id(id: i32) -> virtio_input_event135     pub fn multitouch_tracking_id(id: i32) -> virtio_input_event {
136         Self::absolute(ABS_MT_TRACKING_ID, id)
137     }
138 
139     #[inline]
multitouch_slot(slot: i32) -> virtio_input_event140     pub fn multitouch_slot(slot: i32) -> virtio_input_event {
141         Self::absolute(ABS_MT_SLOT, slot)
142     }
143 
144     #[inline]
multitouch_absolute_x(x: i32) -> virtio_input_event145     pub fn multitouch_absolute_x(x: i32) -> virtio_input_event {
146         Self::absolute(ABS_MT_POSITION_X, x)
147     }
148 
149     #[inline]
multitouch_absolute_y(y: i32) -> virtio_input_event150     pub fn multitouch_absolute_y(y: i32) -> virtio_input_event {
151         Self::absolute(ABS_MT_POSITION_Y, y)
152     }
153 
154     #[inline]
absolute_x(x: i32) -> virtio_input_event155     pub fn absolute_x(x: i32) -> virtio_input_event {
156         Self::absolute(ABS_X, x)
157     }
158 
159     #[inline]
absolute_y(y: i32) -> virtio_input_event160     pub fn absolute_y(y: i32) -> virtio_input_event {
161         Self::absolute(ABS_Y, y)
162     }
163 
164     #[inline]
relative_x(x: i32) -> virtio_input_event165     pub fn relative_x(x: i32) -> virtio_input_event {
166         Self::relative(REL_X, x)
167     }
168 
169     #[inline]
relative_y(y: i32) -> virtio_input_event170     pub fn relative_y(y: i32) -> virtio_input_event {
171         Self::relative(REL_Y, y)
172     }
173 
174     #[inline]
touch(has_contact: bool) -> virtio_input_event175     pub fn touch(has_contact: bool) -> virtio_input_event {
176         Self::key(BTN_TOUCH, has_contact)
177     }
178 
179     #[inline]
finger_tool(active: bool) -> virtio_input_event180     pub fn finger_tool(active: bool) -> virtio_input_event {
181         Self::key(BTN_TOOL_FINGER, active)
182     }
183 
184     #[inline]
key(code: u16, pressed: bool) -> virtio_input_event185     pub fn key(code: u16, pressed: bool) -> virtio_input_event {
186         virtio_input_event {
187             type_: Le16::from(EV_KEY),
188             code: Le16::from(code),
189             value: SLe32::from(if pressed { 1 } else { 0 }),
190         }
191     }
192 
193     #[inline]
is_valid_mt_event(self) -> bool194     pub fn is_valid_mt_event(self) -> bool {
195         match self.type_.to_native() {
196             EV_KEY => self.code.to_native() == BTN_TOUCH,
197             EV_ABS => matches!(
198                 self.code.to_native(),
199                 ABS_MT_SLOT
200                     | ABS_MT_TOUCH_MAJOR
201                     | ABS_MT_TOUCH_MINOR
202                     | ABS_MT_WIDTH_MAJOR
203                     | ABS_MT_WIDTH_MINOR
204                     | ABS_MT_ORIENTATION
205                     | ABS_MT_POSITION_X
206                     | ABS_MT_POSITION_Y
207                     | ABS_MT_TOOL_TYPE
208                     | ABS_MT_BLOB_ID
209                     | ABS_MT_TRACKING_ID
210                     | ABS_MT_PRESSURE
211                     | ABS_MT_DISTANCE
212                     | ABS_MT_TOOL_X
213                     | ABS_MT_TOOL_Y
214             ),
215             _ => false,
216         }
217     }
218 
219     #[inline]
is_valid_st_event(self) -> bool220     pub fn is_valid_st_event(self) -> bool {
221         match self.type_.to_native() {
222             EV_KEY => self.code.to_native() == BTN_TOUCH,
223             EV_ABS => matches!(
224                 self.code.to_native(),
225                 ABS_X | ABS_Y | ABS_PRESSURE | ABS_TILT_X | ABS_TILT_Y | ABS_TOOL_WIDTH
226             ),
227             _ => false,
228         }
229     }
230 }
231