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