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