input_linux/
macros.rs

1use std::io;
2use crate::sys;
3
4pub(crate) const STRING_BUFFER_LENGTH: usize = 0x200;
5
6pub(crate) fn convert_error(e: sys::Error) -> io::Error {
7    e.into()
8}
9
10macro_rules! impl_iterable {
11    (@impliter $name: ident($start:expr, $count:expr)) => {
12        impl crate::bitmask::BitmaskTrait for $name {
13            type Array = [u8; (Self::COUNT + 7) / 8];
14            type Index = $name;
15            const ZERO: Self::Array = [0u8; (Self::COUNT + 7) / 8];
16
17            fn array_default() -> Self::Array { unsafe {std::mem::zeroed() } }
18            fn array_slice(array: &Self::Array) -> &[u8] { array }
19            fn array_slice_mut(array: &mut Self::Array) -> &mut [u8] { array }
20            fn index(index: Self::Index) -> usize { index as usize }
21        }
22
23        impl crate::enum_iterator::IterableEnum for $name {
24            fn iter_next(v: usize) -> Option<(usize, Self)> {
25                if v < Self::COUNT {
26                    unsafe {
27                        Some((v + 1, std::mem::transmute(v as u16)))
28                    }
29                } else {
30                    None
31                }
32            }
33
34            fn iter() -> crate::enum_iterator::EnumIterator<Self> {
35                crate::enum_iterator::EnumIterator::new($start)
36            }
37        }
38
39        impl $name {
40            /// The maximum valid value.
41            pub const COUNT: usize = $count as usize;
42
43            /// An iterator over all values of the enum.
44            pub fn iter() -> crate::enum_iterator::EnumIterator<Self> {
45                crate::enum_iterator::IterableEnum::iter()
46            }
47
48            /// A bitmask that can contain all values of the enum.
49            pub fn bitmask() -> crate::bitmask::Bitmask<Self> {
50                Default::default()
51            }
52
53            /// Get the raw [code](crate::InputEvent.code) value of the enum.
54            pub const fn code(&self) -> u16 {
55                *self as _
56            }
57        }
58
59        impl From<$name> for u16 {
60            fn from(v: $name) -> Self {
61                v.code()
62            }
63        }
64    };
65    (@implcode $name: ident($start:expr, $count:expr)) => {
66        impl $name {
67            /// Instantiates the enum from a raw code value.
68            pub fn from_code(code: u16) -> Result<Self, crate::kinds::RangeError> {
69                use std::mem;
70
71                if code < Self::COUNT as u16 {
72                    Ok(unsafe { mem::transmute(code) })
73                } else {
74                    Err(crate::kinds::RangeError)
75                }
76            }
77        }
78
79        impl std::convert::TryFrom<u16> for $name {
80            type Error = crate::kinds::RangeError;
81
82            fn try_from(code: u16) -> Result<Self, Self::Error> {
83                Self::from_code(code)
84            }
85        }
86    };
87    ($name: ident($start:expr, $count:expr)) => {
88        impl_iterable! { @impliter $name($start, $count) }
89        impl_iterable! { @implcode $name($start, $count) }
90    };
91    (@nofromcode $name: ident($start:expr, $count:expr)) => {
92        impl_iterable! { @impliter $name($start, $count) }
93    };
94}
95
96macro_rules! ioctl_impl {
97    ($(#[$attr:meta])* @get $f:ident = $ev:ident -> $ret:ty) => {
98        $(#[$attr])*
99        pub fn $f(&self) -> io::Result<$ret> {
100            unsafe {
101                let mut v = std::mem::MaybeUninit::uninit();
102                sys::$ev(self.fd(), &mut *v.as_mut_ptr())
103                    .map(|_| v.assume_init().into())
104                    .map_err(crate::macros::convert_error)
105            }
106        }
107    };
108    ($(#[$attr:meta])* @call $f:ident = $ev:ident) => {
109        $(#[$attr])*
110        pub fn $f(&self) -> io::Result<()> {
111            unsafe {
112                sys::$ev(self.fd())
113                    .map(drop)
114                    .map_err(crate::macros::convert_error)
115            }
116        }
117    };
118    ($(#[$attr:meta])* @get_buf $f:ident($ty:ty) = $ev:ident) => {
119        $(#[$attr])*
120        pub fn $f(&self, buffer: &mut [$ty]) -> io::Result<usize> {
121            unsafe {
122                sys::$ev(self.fd(), &mut *(buffer as *mut [$ty] as *mut [_]))
123                    .map(|len| len as _)
124                    .map_err(crate::macros::convert_error)
125            }
126        }
127    };
128    ($(#[$attr:meta])* @get_str $f:ident, $fbuf:ident = $ev:ident) => {
129        ioctl_impl! {
130            $(#[$attr])*
131            @get_buf $fbuf(u8) = $ev
132        }
133
134        $(#[$attr])*
135        pub fn $f(&self) -> io::Result<Vec<u8>> {
136            let mut buf = vec![0; crate::macros::STRING_BUFFER_LENGTH];
137            self.$fbuf(&mut buf[..]).map(move |len| {
138                buf.truncate(len as _);
139                buf
140            })
141        }
142    };
143    ($(#[$attr:meta])* @set_str $f:ident = $ev:ident) => {
144        $(#[$attr])*
145        pub fn $f(&self, value: &::std::ffi::CStr) -> io::Result<()> {
146            unsafe {
147                sys::$ev(self.fd(), value.as_ptr())
148                    .map(drop)
149                    .map_err(crate::macros::convert_error)
150            }
151        }
152    };
153    ($(#[$attr:meta])* @set $f:ident($in:ty) = $ev:ident) => {
154        $(#[$attr])*
155        pub fn $f(&self, value: $in) -> io::Result<()> {
156            unsafe {
157                sys::$ev(self.fd(), value as _)
158                    .map(drop)
159                    .map_err(crate::macros::convert_error)
160            }
161        }
162    };
163    ($({ $($tt:tt)* })*) => {
164        $(
165            ioctl_impl! {$($tt)*}
166        )*
167    };
168}
169
170macro_rules! impl_bitmasks {
171    { $kind:path, $event: expr, $name_mask:ident, $name_mask_set:ident, $name_bits:ident } => {
172        /// `EVIOCGMASK`
173        pub fn $name_mask(&self) -> io::Result<crate::bitmask::Bitmask<$kind>> {
174            let mut bitmask = crate::bitmask::Bitmask::default();
175            self.event_mask_raw($event, &mut bitmask).map(|_| bitmask)
176        }
177
178        /// `EVIOCSMASK`
179        pub fn $name_mask_set(&self, bitmask: &crate::bitmask::Bitmask<$kind>) -> io::Result<()> {
180            self.set_event_mask_raw($event, bitmask)
181        }
182
183        /// `EVIOCGBIT`
184        pub fn $name_bits(&self) -> io::Result<crate::bitmask::Bitmask<$kind>> {
185            let mut bitmask = crate::bitmask::Bitmask::default();
186            self.event_bits_raw($event, &mut bitmask).map(|_| bitmask)
187        }
188    };
189}