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