summary refs log tree commit diff
path: root/linux_input_sys/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'linux_input_sys/src/lib.rs')
-rw-r--r--linux_input_sys/src/lib.rs99
1 files changed, 75 insertions, 24 deletions
diff --git a/linux_input_sys/src/lib.rs b/linux_input_sys/src/lib.rs
index 3880be2..f70dcc9 100644
--- a/linux_input_sys/src/lib.rs
+++ b/linux_input_sys/src/lib.rs
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-use data_model::DataInit;
+use data_model::{DataInit, Le16, Le32};
 use std::mem::size_of;
 
 const EV_SYN: u16 = 0x00;
@@ -20,6 +20,13 @@ const ABS_Y: u16 = 0x01;
 const BTN_TOUCH: u16 = 0x14a;
 const BTN_TOOL_FINGER: u16 = 0x145;
 
+/// Allows a raw input event of the implementor's type to be decoded into
+/// a virtio_input_event.
+pub trait InputEventDecoder {
+    const SIZE: usize;
+    fn decode(data: &[u8]) -> virtio_input_event;
+}
+
 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
 #[repr(C)]
 pub struct input_event {
@@ -32,55 +39,99 @@ pub struct input_event {
 unsafe impl DataInit for input_event {}
 
 impl input_event {
-    pub const EVENT_SIZE: usize = size_of::<input_event>();
-
-    #[inline]
-    pub fn syn() -> input_event {
+    pub fn from_virtio_input_event(other: &virtio_input_event) -> input_event {
         input_event {
             timestamp_fields: [0, 0],
-            type_: EV_SYN,
-            code: SYN_REPORT,
-            value: 0,
+            type_: other.type_.into(),
+            code: other.code.into(),
+            value: other.value.into(),
+        }
+    }
+}
+
+impl InputEventDecoder for input_event {
+    const SIZE: usize = size_of::<Self>();
+
+    fn decode(data: &[u8]) -> virtio_input_event {
+        #[repr(align(8))]
+        struct Aligner([u8; input_event::SIZE]);
+        let data_aligned = Aligner(*<[u8; input_event::SIZE]>::from_slice(data).unwrap());
+        let e = Self::from_slice(&data_aligned.0).unwrap();
+        virtio_input_event {
+            type_: Le16::from(e.type_),
+            code: Le16::from(e.code),
+            value: Le32::from(e.value),
+        }
+    }
+}
+
+#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
+#[repr(C)]
+pub struct virtio_input_event {
+    pub type_: Le16,
+    pub code: Le16,
+    pub value: Le32,
+}
+
+// Safe because it only has data and has no implicit padding.
+unsafe impl DataInit for virtio_input_event {}
+
+impl InputEventDecoder for virtio_input_event {
+    const SIZE: usize = size_of::<Self>();
+
+    fn decode(data: &[u8]) -> virtio_input_event {
+        #[repr(align(4))]
+        struct Aligner([u8; virtio_input_event::SIZE]);
+        let data_aligned = Aligner(*<[u8; virtio_input_event::SIZE]>::from_slice(data).unwrap());
+        *Self::from_slice(&data_aligned.0).unwrap()
+    }
+}
+
+impl virtio_input_event {
+    #[inline]
+    pub fn syn() -> virtio_input_event {
+        virtio_input_event {
+            type_: Le16::from(EV_SYN),
+            code: Le16::from(SYN_REPORT),
+            value: Le32::from(0),
         }
     }
 
     #[inline]
-    pub fn absolute(code: u16, value: u32) -> input_event {
-        input_event {
-            timestamp_fields: [0, 0],
-            type_: EV_ABS,
-            code,
-            value,
+    pub fn absolute(code: u16, value: u32) -> virtio_input_event {
+        virtio_input_event {
+            type_: Le16::from(EV_ABS),
+            code: Le16::from(code),
+            value: Le32::from(value),
         }
     }
 
     #[inline]
-    pub fn absolute_x(x: u32) -> input_event {
+    pub fn absolute_x(x: u32) -> virtio_input_event {
         Self::absolute(ABS_X, x)
     }
 
     #[inline]
-    pub fn absolute_y(y: u32) -> input_event {
+    pub fn absolute_y(y: u32) -> virtio_input_event {
         Self::absolute(ABS_Y, y)
     }
 
     #[inline]
-    pub fn touch(has_contact: bool) -> input_event {
+    pub fn touch(has_contact: bool) -> virtio_input_event {
         Self::key(BTN_TOUCH, has_contact)
     }
 
     #[inline]
-    pub fn finger_tool(active: bool) -> input_event {
+    pub fn finger_tool(active: bool) -> virtio_input_event {
         Self::key(BTN_TOOL_FINGER, active)
     }
 
     #[inline]
-    pub fn key(code: u16, pressed: bool) -> input_event {
-        input_event {
-            timestamp_fields: [0, 0],
-            type_: EV_KEY,
-            code,
-            value: if pressed { 1 } else { 0 },
+    pub fn key(code: u16, pressed: bool) -> virtio_input_event {
+        virtio_input_event {
+            type_: Le16::from(EV_KEY),
+            code: Le16::from(code),
+            value: Le32::from(if pressed { 1 } else { 0 }),
         }
     }
 }