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 effect_id: u16,
145 cycle_count: i32
147 },
148 Disable {
149 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 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}