1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
use std::fs::{File, OpenOptions}; use std::os::unix::prelude::*; use std::path::Path; use arrayref::array_ref; use input_event_codes::{ABS_CNT, BTN_MISC, KEY_CNT}; use crate::event_codes::{AbsoluteAxis, KeyOrButton}; use crate::io_control::{ get_axis_count, get_axis_mapping, get_button_count, get_button_mapping, get_correction_values, get_driver_version, get_event, get_identifier, set_axis_mapping, set_button_mapping, set_correction_values, }; use crate::{Correction, DeviceEvent, Result}; #[derive(Debug)] pub struct Device { axis_count: u8, axis_mapping: Vec<AbsoluteAxis>, button_count: u8, button_mapping: Vec<KeyOrButton>, driver_version: u32, file: File, identifier: String, } impl Device { pub const fn axis_count(&self) -> u8 { self.axis_count } pub fn axis_mapping(&self) -> &[AbsoluteAxis; ABS_CNT as usize] { array_ref!(self.axis_mapping, 0, ABS_CNT as usize) } pub fn axis_mapping_at(&self, number: u8) -> AbsoluteAxis { self.axis_mapping[number as usize] } pub const fn button_count(&self) -> u8 { self.button_count } pub fn button_mapping(&self) -> &[KeyOrButton; (KEY_CNT - BTN_MISC) as usize] { array_ref!(self.button_mapping, 0, (KEY_CNT - BTN_MISC) as usize) } pub fn button_mapping_at(&self, number: u8) -> KeyOrButton { self.button_mapping[number as usize] } pub fn driver_version(&self) -> u32 { self.driver_version } pub unsafe fn from_raw_fd(fd: RawFd) -> Result<Self> { Self::new(File::from_raw_fd(fd)) } pub fn get_correction_values(&self) -> Result<Vec<Correction>> { get_correction_values(self.as_raw_fd()) } pub fn get_event(&self) -> Result<DeviceEvent> { Ok(DeviceEvent::from_event(self, get_event(self.as_raw_fd())?)) } pub fn new(file: File) -> Result<Self> { let axis_count = get_axis_count(file.as_raw_fd())?; let axis_mapping = get_axis_mapping(file.as_raw_fd())?; let button_count = get_button_count(file.as_raw_fd())?; let button_mapping = get_button_mapping(file.as_raw_fd())?; let driver_version = get_driver_version(file.as_raw_fd())?; let identifier = get_identifier(file.as_raw_fd()).unwrap_or_else(|_| "Unknown".to_owned()); Ok(Self { axis_count, axis_mapping, button_count, button_mapping, driver_version, file, identifier, }) } pub fn open<P: AsRef<Path>>(path: P) -> Result<Self> { Self::new( OpenOptions::new() .custom_flags(libc::O_NONBLOCK) .read(true) .open(path)?, ) } pub fn refresh_axis_mapping(&mut self) -> Result<()> { self.axis_mapping = get_axis_mapping(self.as_raw_fd())?; Ok(()) } pub fn refresh_button_mapping(&mut self) -> Result<()> { self.button_mapping = get_button_mapping(self.as_raw_fd())?; Ok(()) } pub fn refresh_mapping(&mut self) -> Result<()> { self.refresh_axis_mapping()?; self.refresh_button_mapping() } pub fn set_axis_mapping(&mut self, mapping: &[AbsoluteAxis; ABS_CNT as usize]) -> Result<()> { set_axis_mapping(self.as_raw_fd(), mapping)?; self.refresh_axis_mapping() } pub fn set_axis_mapping_at(&mut self, number: u8, axis: AbsoluteAxis) -> Result<()> { let mut mapping = self.axis_mapping.clone(); mapping[number as usize] = axis; self.set_axis_mapping(array_ref!(mapping, 0, ABS_CNT as usize)) } pub fn set_button_mapping(&mut self, mapping: &[KeyOrButton; (KEY_CNT - BTN_MISC) as usize]) -> Result<()> { set_button_mapping(self.as_raw_fd(), mapping)?; self.refresh_button_mapping() } pub fn set_button_mapping_at(&mut self, number: u8, button: KeyOrButton) -> Result<()> { let mut mapping = self.button_mapping.clone(); mapping[number as usize] = button; self.set_button_mapping(array_ref!(mapping, 0, (KEY_CNT - BTN_MISC) as usize)) } pub fn set_correction_values(&self, mapping: &[Correction; ABS_CNT as usize]) -> Result<()> { set_correction_values(self.as_raw_fd(), mapping) } } impl AsRawFd for Device { fn as_raw_fd(&self) -> RawFd { self.file.as_raw_fd() } } impl IntoRawFd for Device { fn into_raw_fd(self) -> RawFd { self.file.into_raw_fd() } }