1 // Copyright 2019 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use data_model::{DataInit, Le16, SLe32}; 6 use std::mem::size_of; 7 8 pub const EV_SYN: u16 = 0x00; 9 pub const EV_KEY: u16 = 0x01; 10 pub const EV_REL: u16 = 0x02; 11 pub const EV_ABS: u16 = 0x03; 12 pub const SYN_REPORT: u16 = 0; 13 pub const REL_X: u16 = 0x00; 14 pub const REL_Y: u16 = 0x01; 15 pub const ABS_X: u16 = 0x00; 16 pub const ABS_Y: u16 = 0x01; 17 pub const ABS_PRESSURE: u16 = 0x18; 18 pub const ABS_TILT_X: u16 = 0x1a; 19 pub const ABS_TILT_Y: u16 = 0x1b; 20 pub const ABS_TOOL_WIDTH: u16 = 0x1c; 21 pub const BTN_TOUCH: u16 = 0x14a; 22 pub const BTN_TOOL_FINGER: u16 = 0x145; 23 pub const ABS_MT_SLOT: u16 = 0x2f; 24 pub const ABS_MT_TOUCH_MAJOR: u16 = 0x30; 25 pub const ABS_MT_TOUCH_MINOR: u16 = 0x31; 26 pub const ABS_MT_WIDTH_MAJOR: u16 = 0x32; 27 pub const ABS_MT_WIDTH_MINOR: u16 = 0x33; 28 pub const ABS_MT_ORIENTATION: u16 = 0x34; 29 pub const ABS_MT_POSITION_X: u16 = 0x35; 30 pub const ABS_MT_POSITION_Y: u16 = 0x36; 31 pub const ABS_MT_TOOL_TYPE: u16 = 0x37; 32 pub const ABS_MT_BLOB_ID: u16 = 0x38; 33 pub const ABS_MT_TRACKING_ID: u16 = 0x39; 34 pub const ABS_MT_PRESSURE: u16 = 0x3a; 35 pub const ABS_MT_DISTANCE: u16 = 0x3b; 36 pub const ABS_MT_TOOL_X: u16 = 0x3c; 37 pub const ABS_MT_TOOL_Y: u16 = 0x3d; 38 39 /// Allows a raw input event of the implementor's type to be decoded into 40 /// a virtio_input_event. 41 pub trait InputEventDecoder { 42 const SIZE: usize; decode(data: &[u8]) -> virtio_input_event43 fn decode(data: &[u8]) -> virtio_input_event; 44 } 45 46 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] 47 #[repr(C)] 48 pub struct input_event { 49 pub timestamp_fields: [u64; 2], 50 pub type_: u16, 51 pub code: u16, 52 pub value: i32, 53 } 54 // Safe because it only has data and has no implicit padding. 55 unsafe impl DataInit for input_event {} 56 57 impl input_event { from_virtio_input_event(other: &virtio_input_event) -> input_event58 pub fn from_virtio_input_event(other: &virtio_input_event) -> input_event { 59 input_event { 60 timestamp_fields: [0, 0], 61 type_: other.type_.into(), 62 code: other.code.into(), 63 value: other.value.into(), 64 } 65 } 66 } 67 68 impl InputEventDecoder for input_event { 69 const SIZE: usize = size_of::<Self>(); 70 decode(data: &[u8]) -> virtio_input_event71 fn decode(data: &[u8]) -> virtio_input_event { 72 #[repr(align(8))] 73 struct Aligner([u8; input_event::SIZE]); 74 let data_aligned = Aligner(*<[u8; input_event::SIZE]>::from_slice(data).unwrap()); 75 let e = Self::from_slice(&data_aligned.0).unwrap(); 76 virtio_input_event { 77 type_: Le16::from(e.type_), 78 code: Le16::from(e.code), 79 value: SLe32::from(e.value), 80 } 81 } 82 } 83 84 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] 85 #[repr(C)] 86 pub struct virtio_input_event { 87 pub type_: Le16, 88 pub code: Le16, 89 pub value: SLe32, 90 } 91 92 // Safe because it only has data and has no implicit padding. 93 unsafe impl DataInit for virtio_input_event {} 94 95 impl InputEventDecoder for virtio_input_event { 96 const SIZE: usize = size_of::<Self>(); 97 decode(data: &[u8]) -> virtio_input_event98 fn decode(data: &[u8]) -> virtio_input_event { 99 #[repr(align(4))] 100 struct Aligner([u8; virtio_input_event::SIZE]); 101 let data_aligned = Aligner(*<[u8; virtio_input_event::SIZE]>::from_slice(data).unwrap()); 102 *Self::from_slice(&data_aligned.0).unwrap() 103 } 104 } 105 106 impl virtio_input_event { 107 #[inline] syn() -> virtio_input_event108 pub fn syn() -> virtio_input_event { 109 virtio_input_event { 110 type_: Le16::from(EV_SYN), 111 code: Le16::from(SYN_REPORT), 112 value: SLe32::from(0), 113 } 114 } 115 116 #[inline] absolute(code: u16, value: i32) -> virtio_input_event117 pub fn absolute(code: u16, value: i32) -> virtio_input_event { 118 virtio_input_event { 119 type_: Le16::from(EV_ABS), 120 code: Le16::from(code), 121 value: SLe32::from(value), 122 } 123 } 124 125 #[inline] relative(code: u16, value: i32) -> virtio_input_event126 pub fn relative(code: u16, value: i32) -> virtio_input_event { 127 virtio_input_event { 128 type_: Le16::from(EV_REL), 129 code: Le16::from(code), 130 value: SLe32::from(value), 131 } 132 } 133 134 #[inline] multitouch_tracking_id(id: i32) -> virtio_input_event135 pub fn multitouch_tracking_id(id: i32) -> virtio_input_event { 136 Self::absolute(ABS_MT_TRACKING_ID, id) 137 } 138 139 #[inline] multitouch_slot(slot: i32) -> virtio_input_event140 pub fn multitouch_slot(slot: i32) -> virtio_input_event { 141 Self::absolute(ABS_MT_SLOT, slot) 142 } 143 144 #[inline] multitouch_absolute_x(x: i32) -> virtio_input_event145 pub fn multitouch_absolute_x(x: i32) -> virtio_input_event { 146 Self::absolute(ABS_MT_POSITION_X, x) 147 } 148 149 #[inline] multitouch_absolute_y(y: i32) -> virtio_input_event150 pub fn multitouch_absolute_y(y: i32) -> virtio_input_event { 151 Self::absolute(ABS_MT_POSITION_Y, y) 152 } 153 154 #[inline] absolute_x(x: i32) -> virtio_input_event155 pub fn absolute_x(x: i32) -> virtio_input_event { 156 Self::absolute(ABS_X, x) 157 } 158 159 #[inline] absolute_y(y: i32) -> virtio_input_event160 pub fn absolute_y(y: i32) -> virtio_input_event { 161 Self::absolute(ABS_Y, y) 162 } 163 164 #[inline] relative_x(x: i32) -> virtio_input_event165 pub fn relative_x(x: i32) -> virtio_input_event { 166 Self::relative(REL_X, x) 167 } 168 169 #[inline] relative_y(y: i32) -> virtio_input_event170 pub fn relative_y(y: i32) -> virtio_input_event { 171 Self::relative(REL_Y, y) 172 } 173 174 #[inline] touch(has_contact: bool) -> virtio_input_event175 pub fn touch(has_contact: bool) -> virtio_input_event { 176 Self::key(BTN_TOUCH, has_contact) 177 } 178 179 #[inline] finger_tool(active: bool) -> virtio_input_event180 pub fn finger_tool(active: bool) -> virtio_input_event { 181 Self::key(BTN_TOOL_FINGER, active) 182 } 183 184 #[inline] key(code: u16, pressed: bool) -> virtio_input_event185 pub fn key(code: u16, pressed: bool) -> virtio_input_event { 186 virtio_input_event { 187 type_: Le16::from(EV_KEY), 188 code: Le16::from(code), 189 value: SLe32::from(if pressed { 1 } else { 0 }), 190 } 191 } 192 193 #[inline] is_valid_mt_event(self) -> bool194 pub fn is_valid_mt_event(self) -> bool { 195 match self.type_.to_native() { 196 EV_KEY => self.code.to_native() == BTN_TOUCH, 197 EV_ABS => matches!( 198 self.code.to_native(), 199 ABS_MT_SLOT 200 | ABS_MT_TOUCH_MAJOR 201 | ABS_MT_TOUCH_MINOR 202 | ABS_MT_WIDTH_MAJOR 203 | ABS_MT_WIDTH_MINOR 204 | ABS_MT_ORIENTATION 205 | ABS_MT_POSITION_X 206 | ABS_MT_POSITION_Y 207 | ABS_MT_TOOL_TYPE 208 | ABS_MT_BLOB_ID 209 | ABS_MT_TRACKING_ID 210 | ABS_MT_PRESSURE 211 | ABS_MT_DISTANCE 212 | ABS_MT_TOOL_X 213 | ABS_MT_TOOL_Y 214 ), 215 _ => false, 216 } 217 } 218 219 #[inline] is_valid_st_event(self) -> bool220 pub fn is_valid_st_event(self) -> bool { 221 match self.type_.to_native() { 222 EV_KEY => self.code.to_native() == BTN_TOUCH, 223 EV_ABS => matches!( 224 self.code.to_native(), 225 ABS_X | ABS_Y | ABS_PRESSURE | ABS_TILT_X | ABS_TILT_Y | ABS_TOOL_WIDTH 226 ), 227 _ => false, 228 } 229 } 230 } 231