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