diff options
Diffstat (limited to 'linux_input_sys/src')
-rw-r--r-- | linux_input_sys/src/lib.rs | 99 |
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 }), } } } |