xref: /aosp_15_r20/external/crosvm/linux_input_sys/src/lib.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 //! Linux input system bindings.
6 
7 pub mod constants;
8 
9 use std::mem::size_of;
10 
11 use constants::*;
12 use data_model::Le16;
13 use data_model::SLe32;
14 use zerocopy::AsBytes;
15 use zerocopy::FromBytes;
16 use zerocopy::FromZeroes;
17 
18 /// Allows a raw input event of the implementor's type to be decoded into
19 /// a virtio_input_event.
20 pub trait InputEventDecoder {
21     const SIZE: usize;
decode(data: &[u8]) -> virtio_input_event22     fn decode(data: &[u8]) -> virtio_input_event;
23 }
24 
25 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq, FromZeroes, FromBytes, AsBytes)]
26 #[repr(C)]
27 pub struct input_event {
28     pub timestamp_fields: [u64; 2],
29     pub type_: u16,
30     pub code: u16,
31     pub value: i32,
32 }
33 
34 impl input_event {
from_virtio_input_event(other: &virtio_input_event) -> input_event35     pub fn from_virtio_input_event(other: &virtio_input_event) -> input_event {
36         input_event {
37             timestamp_fields: [0, 0],
38             type_: other.type_.into(),
39             code: other.code.into(),
40             value: other.value.into(),
41         }
42     }
43 }
44 
45 impl InputEventDecoder for input_event {
46     const SIZE: usize = size_of::<Self>();
47 
decode(data: &[u8]) -> virtio_input_event48     fn decode(data: &[u8]) -> virtio_input_event {
49         let e = input_event::read_from(data).unwrap();
50         virtio_input_event {
51             type_: Le16::from(e.type_),
52             code: Le16::from(e.code),
53             value: SLe32::from(e.value),
54         }
55     }
56 }
57 
58 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq, AsBytes, FromZeroes, FromBytes)]
59 #[repr(C)]
60 pub struct virtio_input_event {
61     pub type_: Le16,
62     pub code: Le16,
63     pub value: SLe32,
64 }
65 
66 impl InputEventDecoder for virtio_input_event {
67     const SIZE: usize = size_of::<Self>();
68 
decode(data: &[u8]) -> virtio_input_event69     fn decode(data: &[u8]) -> virtio_input_event {
70         virtio_input_event::read_from(data).unwrap()
71     }
72 }
73 
74 impl virtio_input_event {
75     #[inline]
syn() -> virtio_input_event76     pub fn syn() -> virtio_input_event {
77         virtio_input_event {
78             type_: Le16::from(EV_SYN),
79             code: Le16::from(SYN_REPORT),
80             value: SLe32::from(0),
81         }
82     }
83 
84     #[inline]
absolute(code: u16, value: i32) -> virtio_input_event85     pub fn absolute(code: u16, value: i32) -> virtio_input_event {
86         virtio_input_event {
87             type_: Le16::from(EV_ABS),
88             code: Le16::from(code),
89             value: SLe32::from(value),
90         }
91     }
92 
93     #[inline]
relative(code: u16, value: i32) -> virtio_input_event94     pub fn relative(code: u16, value: i32) -> virtio_input_event {
95         virtio_input_event {
96             type_: Le16::from(EV_REL),
97             code: Le16::from(code),
98             value: SLe32::from(value),
99         }
100     }
101 
102     #[inline]
multitouch_tracking_id(id: i32) -> virtio_input_event103     pub fn multitouch_tracking_id(id: i32) -> virtio_input_event {
104         Self::absolute(ABS_MT_TRACKING_ID, id)
105     }
106 
107     #[inline]
multitouch_slot(slot: i32) -> virtio_input_event108     pub fn multitouch_slot(slot: i32) -> virtio_input_event {
109         Self::absolute(ABS_MT_SLOT, slot)
110     }
111 
112     #[inline]
multitouch_absolute_x(x: i32) -> virtio_input_event113     pub fn multitouch_absolute_x(x: i32) -> virtio_input_event {
114         Self::absolute(ABS_MT_POSITION_X, x)
115     }
116 
117     #[inline]
multitouch_absolute_y(y: i32) -> virtio_input_event118     pub fn multitouch_absolute_y(y: i32) -> virtio_input_event {
119         Self::absolute(ABS_MT_POSITION_Y, y)
120     }
121 
122     #[inline]
absolute_x(x: i32) -> virtio_input_event123     pub fn absolute_x(x: i32) -> virtio_input_event {
124         Self::absolute(ABS_X, x)
125     }
126 
127     #[inline]
absolute_y(y: i32) -> virtio_input_event128     pub fn absolute_y(y: i32) -> virtio_input_event {
129         Self::absolute(ABS_Y, y)
130     }
131 
132     #[inline]
relative_x(x: i32) -> virtio_input_event133     pub fn relative_x(x: i32) -> virtio_input_event {
134         Self::relative(REL_X, x)
135     }
136 
137     #[inline]
relative_y(y: i32) -> virtio_input_event138     pub fn relative_y(y: i32) -> virtio_input_event {
139         Self::relative(REL_Y, y)
140     }
141 
142     #[inline]
touch(has_contact: bool) -> virtio_input_event143     pub fn touch(has_contact: bool) -> virtio_input_event {
144         Self::key(BTN_TOUCH, has_contact, false)
145     }
146 
147     #[inline]
left_click(has_contact: bool) -> virtio_input_event148     pub fn left_click(has_contact: bool) -> virtio_input_event {
149         Self::key(BTN_LEFT, has_contact, false)
150     }
151 
152     #[inline]
wheel(delta: i32) -> virtio_input_event153     pub fn wheel(delta: i32) -> virtio_input_event {
154         Self::relative(REL_WHEEL, delta)
155     }
156 
157     #[inline]
right_click(has_contact: bool) -> virtio_input_event158     pub fn right_click(has_contact: bool) -> virtio_input_event {
159         Self::key(BTN_RIGHT, has_contact, false)
160     }
161 
162     #[inline]
middle_click(has_contact: bool) -> virtio_input_event163     pub fn middle_click(has_contact: bool) -> virtio_input_event {
164         Self::key(BTN_MIDDLE, has_contact, false)
165     }
166 
167     #[inline]
forward_click(has_contact: bool) -> virtio_input_event168     pub fn forward_click(has_contact: bool) -> virtio_input_event {
169         Self::key(BTN_FORWARD, has_contact, false)
170     }
171 
172     #[inline]
back_click(has_contact: bool) -> virtio_input_event173     pub fn back_click(has_contact: bool) -> virtio_input_event {
174         Self::key(BTN_BACK, has_contact, false)
175     }
176 
177     #[inline]
finger_tool(active: bool) -> virtio_input_event178     pub fn finger_tool(active: bool) -> virtio_input_event {
179         Self::key(BTN_TOOL_FINGER, active, false)
180     }
181 
182     /// Repeated keys must set the `repeat` option if the key was already down, or repeated keys
183     /// will not be seen correctly by the guest.
184     #[inline]
key(code: u16, down: bool, repeat: bool) -> virtio_input_event185     pub fn key(code: u16, down: bool, repeat: bool) -> virtio_input_event {
186         virtio_input_event {
187             type_: Le16::from(EV_KEY),
188             code: Le16::from(code),
189             value: SLe32::from(match (down, repeat) {
190                 (true, true) => 2,
191                 (true, false) => 1,
192                 // repeat is not meaningful for key up events.
193                 _ => 0,
194             }),
195         }
196     }
197 
198     /// If the event is EV_LED for the given LED code, return if it is on.
get_led_state(&self, led_code: u16) -> Option<bool>199     pub fn get_led_state(&self, led_code: u16) -> Option<bool> {
200         if self.type_ == EV_LED && self.code == led_code {
201             return match self.value.to_native() {
202                 0 => Some(false),
203                 1 => Some(true),
204                 _ => None,
205             };
206         }
207         None
208     }
209 }
210