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 const EV_SYN: u16 = 0x00;
9 const EV_KEY: u16 = 0x01;
10 #[allow(dead_code)]
11 const EV_REL: u16 = 0x02;
12 const EV_ABS: u16 = 0x03;
13 const SYN_REPORT: u16 = 0;
14 #[allow(dead_code)]
15 const REL_X: u16 = 0x00;
16 #[allow(dead_code)]
17 const REL_Y: u16 = 0x01;
18 const ABS_MT_TRACKING_ID: u16 = 0x39;
19 const ABS_MT_SLOT: u16 = 0x2f;
20 const ABS_MT_POSITION_X: u16 = 0x35;
21 const ABS_MT_POSITION_Y: u16 = 0x36;
22 const ABS_X: u16 = 0x00;
23 const ABS_Y: u16 = 0x01;
24 const BTN_TOUCH: u16 = 0x14a;
25 const BTN_TOOL_FINGER: u16 = 0x145;
26 
27 /// Allows a raw input event of the implementor's type to be decoded into
28 /// a virtio_input_event.
29 pub trait InputEventDecoder {
30     const SIZE: usize;
decode(data: &[u8]) -> virtio_input_event31     fn decode(data: &[u8]) -> virtio_input_event;
32 }
33 
34 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
35 #[repr(C)]
36 pub struct input_event {
37     pub timestamp_fields: [u64; 2],
38     pub type_: u16,
39     pub code: u16,
40     pub value: i32,
41 }
42 // Safe because it only has data and has no implicit padding.
43 unsafe impl DataInit for input_event {}
44 
45 impl input_event {
from_virtio_input_event(other: &virtio_input_event) -> input_event46     pub fn from_virtio_input_event(other: &virtio_input_event) -> input_event {
47         input_event {
48             timestamp_fields: [0, 0],
49             type_: other.type_.into(),
50             code: other.code.into(),
51             value: other.value.into(),
52         }
53     }
54 }
55 
56 impl InputEventDecoder for input_event {
57     const SIZE: usize = size_of::<Self>();
58 
decode(data: &[u8]) -> virtio_input_event59     fn decode(data: &[u8]) -> virtio_input_event {
60         #[repr(align(8))]
61         struct Aligner([u8; input_event::SIZE]);
62         let data_aligned = Aligner(*<[u8; input_event::SIZE]>::from_slice(data).unwrap());
63         let e = Self::from_slice(&data_aligned.0).unwrap();
64         virtio_input_event {
65             type_: Le16::from(e.type_),
66             code: Le16::from(e.code),
67             value: SLe32::from(e.value),
68         }
69     }
70 }
71 
72 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
73 #[repr(C)]
74 pub struct virtio_input_event {
75     pub type_: Le16,
76     pub code: Le16,
77     pub value: SLe32,
78 }
79 
80 // Safe because it only has data and has no implicit padding.
81 unsafe impl DataInit for virtio_input_event {}
82 
83 impl InputEventDecoder for virtio_input_event {
84     const SIZE: usize = size_of::<Self>();
85 
decode(data: &[u8]) -> virtio_input_event86     fn decode(data: &[u8]) -> virtio_input_event {
87         #[repr(align(4))]
88         struct Aligner([u8; virtio_input_event::SIZE]);
89         let data_aligned = Aligner(*<[u8; virtio_input_event::SIZE]>::from_slice(data).unwrap());
90         *Self::from_slice(&data_aligned.0).unwrap()
91     }
92 }
93 
94 impl virtio_input_event {
95     #[inline]
syn() -> virtio_input_event96     pub fn syn() -> virtio_input_event {
97         virtio_input_event {
98             type_: Le16::from(EV_SYN),
99             code: Le16::from(SYN_REPORT),
100             value: SLe32::from(0),
101         }
102     }
103 
104     #[inline]
absolute(code: u16, value: i32) -> virtio_input_event105     pub fn absolute(code: u16, value: i32) -> virtio_input_event {
106         virtio_input_event {
107             type_: Le16::from(EV_ABS),
108             code: Le16::from(code),
109             value: SLe32::from(value),
110         }
111     }
112 
113     #[inline]
multitouch_tracking_id(id: i32) -> virtio_input_event114     pub fn multitouch_tracking_id(id: i32) -> virtio_input_event {
115         Self::absolute(ABS_MT_TRACKING_ID, id)
116     }
117 
118     #[inline]
multitouch_slot(slot: i32) -> virtio_input_event119     pub fn multitouch_slot(slot: i32) -> virtio_input_event {
120         Self::absolute(ABS_MT_SLOT, slot)
121     }
122 
123     #[inline]
multitouch_absolute_x(x: i32) -> virtio_input_event124     pub fn multitouch_absolute_x(x: i32) -> virtio_input_event {
125         Self::absolute(ABS_MT_POSITION_X, x)
126     }
127 
128     #[inline]
multitouch_absolute_y(y: i32) -> virtio_input_event129     pub fn multitouch_absolute_y(y: i32) -> virtio_input_event {
130         Self::absolute(ABS_MT_POSITION_Y, y)
131     }
132 
133     #[inline]
absolute_x(x: i32) -> virtio_input_event134     pub fn absolute_x(x: i32) -> virtio_input_event {
135         Self::absolute(ABS_X, x)
136     }
137 
138     #[inline]
absolute_y(y: i32) -> virtio_input_event139     pub fn absolute_y(y: i32) -> virtio_input_event {
140         Self::absolute(ABS_Y, y)
141     }
142 
143     #[inline]
touch(has_contact: bool) -> virtio_input_event144     pub fn touch(has_contact: bool) -> virtio_input_event {
145         Self::key(BTN_TOUCH, has_contact)
146     }
147 
148     #[inline]
finger_tool(active: bool) -> virtio_input_event149     pub fn finger_tool(active: bool) -> virtio_input_event {
150         Self::key(BTN_TOOL_FINGER, active)
151     }
152 
153     #[inline]
key(code: u16, pressed: bool) -> virtio_input_event154     pub fn key(code: u16, pressed: bool) -> virtio_input_event {
155         virtio_input_event {
156             type_: Le16::from(EV_KEY),
157             code: Le16::from(code),
158             value: SLe32::from(if pressed { 1 } else { 0 }),
159         }
160     }
161 }
162