linux_input/
uinput.rs

1use {
2    std::{
3        fs::{
4            self,
5            File
6        },
7        io::{
8            self
9        },
10        os::{
11            unix::{
12                io::{
13                    AsRawFd
14                }
15            }
16        },
17        time::{
18            Duration
19        },
20        path::{
21            PathBuf
22        }
23    },
24
25    crate::{
26        input::{
27            DeviceId,
28            EventBit,
29            ForceFeedbackEffect,
30            InputEventBody,
31            emit_into
32        },
33        input_sys::{
34            EventKind,
35            RawAbsInfo,
36            RawForceFeedbackEffect
37        },
38        uinput_sys::{
39            self,
40            RawAbsSetup,
41            RawForceFeedbackErase,
42            RawForceFeedbackUpload,
43            RawDeviceSetup
44        },
45        utils::{
46            ioctl_get_string
47        }
48    }
49};
50
51#[derive(Debug)]
52pub enum DeviceCreateError {
53    DeviceNameTooLong,
54    DeviceSetupFailed( nix::Error ),
55    DeviceCreateFailed( nix::Error ),
56    IoFailure( io::Error )
57}
58
59pub struct ForceFeedbackEffectUpload< 'a > {
60    device: &'a VirtualDevice,
61    raw: RawForceFeedbackUpload,
62    is_finished: bool
63}
64
65impl< 'a > ForceFeedbackEffectUpload< 'a > {
66    pub fn effect_id( &self ) -> u16 {
67        self.raw.effect.id as u16
68    }
69
70    pub fn raw_effect( &self ) -> RawForceFeedbackEffect {
71        self.raw.effect.clone()
72    }
73
74    pub fn effect( &self ) -> ForceFeedbackEffect {
75        unsafe {
76            ForceFeedbackEffect::from_raw( &self.raw.effect )
77        }
78    }
79
80    pub fn complete( mut self ) -> Result< (), nix::Error > {
81        self.finish()
82    }
83
84    fn finish( &mut self ) -> Result< (), nix::Error > {
85        if self.is_finished {
86            return Ok(());
87        }
88        self.is_finished = true;
89
90        unsafe {
91            uinput_sys::end_force_feedback_upload( self.device.fp.as_raw_fd(), &mut self.raw )?;
92        }
93
94        Ok(())
95    }
96}
97
98impl< 'a > Drop for ForceFeedbackEffectUpload< 'a > {
99    fn drop( &mut self ) {
100        let _ = self.finish();
101    }
102}
103
104pub struct ForceFeedbackEffectErase< 'a > {
105    device: &'a VirtualDevice,
106    raw: RawForceFeedbackErase,
107    is_finished: bool
108}
109
110impl< 'a > ForceFeedbackEffectErase< 'a > {
111    pub fn effect_id( &self ) -> u16 {
112        self.raw.effect_id as u16
113    }
114
115    pub fn complete( mut self ) -> Result< (), nix::Error > {
116        self.finish()
117    }
118
119    fn finish( &mut self ) -> Result< (), nix::Error > {
120        if self.is_finished {
121            return Ok(());
122        }
123        self.is_finished = true;
124
125        unsafe {
126            uinput_sys::end_force_feedback_erase( self.device.fp.as_raw_fd(), &mut self.raw )?;
127        }
128
129        Ok(())
130    }
131}
132
133impl< 'a > Drop for ForceFeedbackEffectErase< 'a > {
134    fn drop( &mut self ) {
135        let _ = self.finish();
136    }
137}
138
139pub enum ForceFeedbackRequest< 'a > {
140    Upload( ForceFeedbackEffectUpload< 'a > ),
141    Erase( ForceFeedbackEffectErase< 'a > ),
142    Enable {
143        /// The ID of the effect to enable.
144        effect_id: u16,
145        /// The number of times the effect should be run.
146        cycle_count: i32
147    },
148    Disable {
149        /// The ID of the effect to disable.
150        effect_id: u16
151    },
152    Other {
153        code: u16,
154        value: i32
155    }
156}
157
158pub struct VirtualDevice {
159    fp: File
160}
161
162impl VirtualDevice {
163    pub fn create< I >( id: DeviceId, name: &str, event_bits: I ) -> Result< Self, DeviceCreateError >
164        where I: IntoIterator< Item = EventBit >
165    {
166        if name.len() >= 80 {
167            return Err( DeviceCreateError::DeviceNameTooLong );
168        }
169
170        let fp = fs::OpenOptions::new()
171            .read( true )
172            .write( true )
173            .create( false )
174            .open( "/dev/uinput" ).map_err( DeviceCreateError::IoFailure )?;
175
176        let mut has_event_key = false;
177        let mut has_event_relative_axis = false;
178        let mut has_event_absolute_axis = false;
179        let mut has_event_force_feedback = false;
180
181        for event_bit in event_bits {
182            match event_bit {
183                EventBit::Key( key ) => {
184                    has_event_key = true;
185                    unsafe {
186                        uinput_sys::device_set_key_bit( fp.as_raw_fd(), key.raw() as _ )
187                    }.unwrap();
188                },
189                EventBit::RelativeAxis( axis ) => {
190                    has_event_relative_axis = true;
191                    unsafe {
192                        uinput_sys::device_set_relative_axis_bit( fp.as_raw_fd(), axis.raw() as _ )
193                    }.unwrap();
194                },
195                EventBit::AbsoluteAxis( descriptor ) => {
196                    has_event_absolute_axis = true;
197                    unsafe {
198                        uinput_sys::device_set_absolute_axis_bit( fp.as_raw_fd(), descriptor.axis.raw() as _ )
199                    }.unwrap();
200
201                    assert!( descriptor.maximum >= descriptor.minimum );
202
203                    let abs_setup = RawAbsSetup {
204                        axis: descriptor.axis.raw(),
205                        info: RawAbsInfo {
206                            value: (descriptor.maximum - descriptor.minimum) / 2 + descriptor.minimum,
207                            minimum: descriptor.minimum,
208                            maximum: descriptor.maximum,
209                            noise_threshold: descriptor.noise_threshold,
210                            deadzone: descriptor.deadzone,
211                            resolution: descriptor.resolution
212                        }
213                    };
214
215                    unsafe {
216                        uinput_sys::abs_setup( fp.as_raw_fd(), &abs_setup )
217                    }.unwrap();
218                },
219                EventBit::ForceFeedback( bit ) => {
220                    has_event_force_feedback = true;
221                    unsafe {
222                        uinput_sys::device_set_force_feedback_bit( fp.as_raw_fd(), bit.raw() as _ )
223                    }.unwrap();
224                }
225            }
226        }
227
228        if has_event_key {
229            unsafe {
230                uinput_sys::device_set_event_bit( fp.as_raw_fd(), EventKind::Key.raw() as _ )
231            }.unwrap();
232        }
233
234        if has_event_relative_axis {
235            unsafe {
236                uinput_sys::device_set_event_bit( fp.as_raw_fd(), EventKind::RelativeAxis.raw() as _ )
237            }.unwrap();
238        }
239
240        if has_event_absolute_axis {
241            unsafe {
242                uinput_sys::device_set_event_bit( fp.as_raw_fd(), EventKind::AbsoluteAxis.raw() as _ )
243            }.unwrap();
244        }
245
246        if has_event_force_feedback {
247            unsafe {
248                uinput_sys::device_set_event_bit( fp.as_raw_fd(), EventKind::ForceFeedback.raw() as _ )
249            }.unwrap();
250        }
251
252        let mut setup = RawDeviceSetup {
253            id: id.into(),
254            name: [0; 80],
255            force_feedback_effects_max: if has_event_force_feedback { 1 } else { 0 }
256        };
257
258        setup.name[ 0..name.len() ].copy_from_slice( name.as_bytes() );
259
260        unsafe {
261            uinput_sys::device_setup( fp.as_raw_fd(), &setup )
262        }.map_err( DeviceCreateError::DeviceSetupFailed )?;
263
264        unsafe {
265            uinput_sys::device_create( fp.as_raw_fd() )
266        }.map_err( DeviceCreateError::DeviceCreateFailed )?;
267
268        let device = VirtualDevice {
269            fp
270        };
271
272        Ok( device )
273    }
274
275    fn sysname( &self ) -> Result< String, nix::Error > {
276        unsafe {
277            ioctl_get_string( self.fp.as_raw_fd(), b'U', 44 )
278        }
279    }
280
281    pub fn path( &self ) -> Result< PathBuf, nix::Error > {
282        let sysname = self.sysname()?;
283        let dir_path = format!( "/sys/devices/virtual/input/{}", sysname );
284        let dir = fs::read_dir( dir_path ).unwrap();
285        for entry in dir {
286            let entry = entry.unwrap();
287            if !entry.path().is_dir() {
288                continue;
289            }
290
291            let path = entry.path();
292            if path.file_name().unwrap().to_str().unwrap().starts_with( "event" ) {
293                let output: PathBuf = "/dev/input".into();
294                let output = output.join( path.file_name().unwrap() );
295                return Ok( output );
296            }
297        }
298
299        unreachable!();
300    }
301
302    pub fn poll_force_feedback( &self, timeout: Option< Duration > ) -> Result< Option< ForceFeedbackRequest >, io::Error > {
303        match crate::input::read_raw_input_event( &self.fp, timeout )? {
304            Some( event ) if event.kind == uinput_sys::EV_UINPUT && event.code == uinput_sys::UI_FF_UPLOAD => {
305                let upload = unsafe {
306                    let mut upload = std::mem::MaybeUninit::< RawForceFeedbackUpload >::zeroed();
307                    (*upload.as_mut_ptr()).request_id = event.value as u32;
308                    uinput_sys::begin_force_feedback_upload( self.fp.as_raw_fd(), upload.as_mut_ptr() )
309                        .map_err( |error| io::Error::new( io::ErrorKind::Other, error ) )?;
310                    upload.assume_init()
311                };
312
313                let request = ForceFeedbackRequest::Upload( ForceFeedbackEffectUpload {
314                    device: self,
315                    raw: upload,
316                    is_finished: false
317                });
318
319                Ok( Some( request ) )
320            },
321            Some( event ) if event.kind == uinput_sys::EV_UINPUT && event.code == uinput_sys::UI_FF_ERASE => {
322                let mut erase = RawForceFeedbackErase {
323                    request_id: event.value as u32,
324                    return_value: 0,
325                    effect_id: 0
326                };
327
328                unsafe {
329                    uinput_sys::begin_force_feedback_erase( self.fp.as_raw_fd(), &mut erase )
330                        .map_err( |error| io::Error::new( io::ErrorKind::Other, error ) )?;
331                }
332
333                let request = ForceFeedbackRequest::Erase( ForceFeedbackEffectErase {
334                    device: self,
335                    raw: erase,
336                    is_finished: false
337                });
338
339                Ok( Some( request ) )
340            },
341            Some( event ) if event.kind == EventKind::ForceFeedback.raw() => {
342                let event = if event.code < crate::input_sys::FF_GAIN {
343                    if event.value > 0 {
344                        ForceFeedbackRequest::Enable {
345                            effect_id: event.code as _,
346                            cycle_count: event.value
347                        }
348                    } else {
349                        ForceFeedbackRequest::Disable {
350                            effect_id: event.code as _
351                        }
352                    }
353                } else {
354                    ForceFeedbackRequest::Other {
355                        code: event.code,
356                        value: event.value
357                    }
358                };
359
360                Ok( Some( event ) )
361            },
362            Some( event ) => unreachable!( "unknown event kind: {}", event.kind ),
363            _ => Ok( None )
364        }
365    }
366
367    /// Emits an event into the device.
368    ///
369    /// You can also pass a whole `InputEvent` here, however
370    /// the timestamp will be ignored.
371    ///
372    /// The events are buffered and will not be sent immediately;
373    /// you need to send `InputEventBody::Flush` to flush them.
374    pub fn emit< T >( &self, body: T ) -> Result< (), io::Error > where T: AsRef< InputEventBody > {
375        emit_into( &self.fp, body )
376    }
377}
378
379impl Drop for VirtualDevice {
380    fn drop( &mut self ) {
381        unsafe {
382            let _ = uinput_sys::device_destroy( self.fp.as_raw_fd() );
383        }
384    }
385}