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 const EV_SYN: u16 = 0x00; 9 const EV_KEY: u16 = 0x01; 10 #[allow(dead_code)] 11 const EV_REL: u16 = 0x02; 12 const EV_ABS: u16 = 0x03; 13 const SYN_REPORT: u16 = 0; 14 #[allow(dead_code)] 15 const REL_X: u16 = 0x00; 16 #[allow(dead_code)] 17 const REL_Y: u16 = 0x01; 18 const ABS_MT_TRACKING_ID: u16 = 0x39; 19 const ABS_MT_SLOT: u16 = 0x2f; 20 const ABS_MT_POSITION_X: u16 = 0x35; 21 const ABS_MT_POSITION_Y: u16 = 0x36; 22 const ABS_X: u16 = 0x00; 23 const ABS_Y: u16 = 0x01; 24 const BTN_TOUCH: u16 = 0x14a; 25 const BTN_TOOL_FINGER: u16 = 0x145; 26 27 /// Allows a raw input event of the implementor's type to be decoded into 28 /// a virtio_input_event. 29 pub trait InputEventDecoder { 30 const SIZE: usize; decode(data: &[u8]) -> virtio_input_event31 fn decode(data: &[u8]) -> virtio_input_event; 32 } 33 34 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] 35 #[repr(C)] 36 pub struct input_event { 37 pub timestamp_fields: [u64; 2], 38 pub type_: u16, 39 pub code: u16, 40 pub value: i32, 41 } 42 // Safe because it only has data and has no implicit padding. 43 unsafe impl DataInit for input_event {} 44 45 impl input_event { from_virtio_input_event(other: &virtio_input_event) -> input_event46 pub fn from_virtio_input_event(other: &virtio_input_event) -> input_event { 47 input_event { 48 timestamp_fields: [0, 0], 49 type_: other.type_.into(), 50 code: other.code.into(), 51 value: other.value.into(), 52 } 53 } 54 } 55 56 impl InputEventDecoder for input_event { 57 const SIZE: usize = size_of::<Self>(); 58 decode(data: &[u8]) -> virtio_input_event59 fn decode(data: &[u8]) -> virtio_input_event { 60 #[repr(align(8))] 61 struct Aligner([u8; input_event::SIZE]); 62 let data_aligned = Aligner(*<[u8; input_event::SIZE]>::from_slice(data).unwrap()); 63 let e = Self::from_slice(&data_aligned.0).unwrap(); 64 virtio_input_event { 65 type_: Le16::from(e.type_), 66 code: Le16::from(e.code), 67 value: SLe32::from(e.value), 68 } 69 } 70 } 71 72 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] 73 #[repr(C)] 74 pub struct virtio_input_event { 75 pub type_: Le16, 76 pub code: Le16, 77 pub value: SLe32, 78 } 79 80 // Safe because it only has data and has no implicit padding. 81 unsafe impl DataInit for virtio_input_event {} 82 83 impl InputEventDecoder for virtio_input_event { 84 const SIZE: usize = size_of::<Self>(); 85 decode(data: &[u8]) -> virtio_input_event86 fn decode(data: &[u8]) -> virtio_input_event { 87 #[repr(align(4))] 88 struct Aligner([u8; virtio_input_event::SIZE]); 89 let data_aligned = Aligner(*<[u8; virtio_input_event::SIZE]>::from_slice(data).unwrap()); 90 *Self::from_slice(&data_aligned.0).unwrap() 91 } 92 } 93 94 impl virtio_input_event { 95 #[inline] syn() -> virtio_input_event96 pub fn syn() -> virtio_input_event { 97 virtio_input_event { 98 type_: Le16::from(EV_SYN), 99 code: Le16::from(SYN_REPORT), 100 value: SLe32::from(0), 101 } 102 } 103 104 #[inline] absolute(code: u16, value: i32) -> virtio_input_event105 pub fn absolute(code: u16, value: i32) -> virtio_input_event { 106 virtio_input_event { 107 type_: Le16::from(EV_ABS), 108 code: Le16::from(code), 109 value: SLe32::from(value), 110 } 111 } 112 113 #[inline] multitouch_tracking_id(id: i32) -> virtio_input_event114 pub fn multitouch_tracking_id(id: i32) -> virtio_input_event { 115 Self::absolute(ABS_MT_TRACKING_ID, id) 116 } 117 118 #[inline] multitouch_slot(slot: i32) -> virtio_input_event119 pub fn multitouch_slot(slot: i32) -> virtio_input_event { 120 Self::absolute(ABS_MT_SLOT, slot) 121 } 122 123 #[inline] multitouch_absolute_x(x: i32) -> virtio_input_event124 pub fn multitouch_absolute_x(x: i32) -> virtio_input_event { 125 Self::absolute(ABS_MT_POSITION_X, x) 126 } 127 128 #[inline] multitouch_absolute_y(y: i32) -> virtio_input_event129 pub fn multitouch_absolute_y(y: i32) -> virtio_input_event { 130 Self::absolute(ABS_MT_POSITION_Y, y) 131 } 132 133 #[inline] absolute_x(x: i32) -> virtio_input_event134 pub fn absolute_x(x: i32) -> virtio_input_event { 135 Self::absolute(ABS_X, x) 136 } 137 138 #[inline] absolute_y(y: i32) -> virtio_input_event139 pub fn absolute_y(y: i32) -> virtio_input_event { 140 Self::absolute(ABS_Y, y) 141 } 142 143 #[inline] touch(has_contact: bool) -> virtio_input_event144 pub fn touch(has_contact: bool) -> virtio_input_event { 145 Self::key(BTN_TOUCH, has_contact) 146 } 147 148 #[inline] finger_tool(active: bool) -> virtio_input_event149 pub fn finger_tool(active: bool) -> virtio_input_event { 150 Self::key(BTN_TOOL_FINGER, active) 151 } 152 153 #[inline] key(code: u16, pressed: bool) -> virtio_input_event154 pub fn key(code: u16, pressed: bool) -> virtio_input_event { 155 virtio_input_event { 156 type_: Le16::from(EV_KEY), 157 code: Le16::from(code), 158 value: SLe32::from(if pressed { 1 } else { 0 }), 159 } 160 } 161 } 162