evdev_rs_tokio/
device.rs

1use crate::{AbsInfo, GrabMode, InputEvent, LedState, ReadFlag, ReadStatus, TimeVal};
2use libc::{c_int, c_uint, c_void};
3use std::any::Any;
4use std::ffi::CString;
5use std::mem::ManuallyDrop;
6use std::os::unix::io::{AsRawFd, FromRawFd};
7use std::{io, ptr};
8use tokio::fs::File;
9
10use crate::enums::*;
11use crate::util::*;
12
13use evdev_sys as raw;
14
15/// Abstraction over structs which contain an inner `*mut libevdev`
16pub trait DeviceWrapper {
17    fn raw(&self) -> *mut raw::libevdev;
18
19    /// Forcibly enable an EventType/InputProp on this device, even if the underlying
20    /// device does not support it. While this cannot make the device actually
21    /// report such events, it will now return true for has().
22    ///
23    /// This is a local modification only affecting only this representation of
24    /// this device.
25    fn enable(&self, blob: &dyn Any) -> io::Result<()> {
26        if let Some(ev_type) = blob.downcast_ref::<EventType>() {
27            self.enable_event_type(ev_type)
28        } else if let Some(ev_code) = blob.downcast_ref::<EventCode>() {
29            self.enable_event_code(ev_code, None)
30        } else if let Some(prop) = blob.downcast_ref::<InputProp>() {
31            self.enable_property(prop)
32        } else {
33            Err(io::Error::from_raw_os_error(-1))
34        }
35    }
36
37    /// Enables this property, a call to `set_file` will overwrite any previously set values
38    ///
39    /// Note: Please use the `enable` function instead. This function is only
40    /// available for the sake of maintaining compatibility with libevdev.
41    fn enable_property(&self, prop: &InputProp) -> io::Result<()> {
42        let result =
43            unsafe { raw::libevdev_enable_property(self.raw(), *prop as c_uint) as i32 };
44
45        match result {
46            0 => Ok(()),
47            error => Err(io::Error::from_raw_os_error(-error)),
48        }
49    }
50
51    /// Forcibly enable an event type on this device, even if the underlying
52    /// device does not support it. While this cannot make the device actually
53    /// report such events, it will now return true for libevdev_has_event_type().
54    ///
55    /// This is a local modification only affecting only this representation of
56    /// this device.
57    ///
58    /// Note: Please use the `enable` function instead. This function is only
59    /// available for the sake of maintaining compatibility with libevdev.
60    fn enable_event_type(&self, ev_type: &EventType) -> io::Result<()> {
61        let result =
62            unsafe { raw::libevdev_enable_event_type(self.raw(), *ev_type as c_uint) };
63
64        match result {
65            0 => Ok(()),
66            error => Err(io::Error::from_raw_os_error(-error)),
67        }
68    }
69
70    /// Forcibly enable an event type on this device, even if the underlying
71    /// device does not support it. While this cannot make the device actually
72    /// report such events, it will now return true for libevdev_has_event_code().
73    ///
74    /// The last argument depends on the type and code:
75    /// If type is EV_ABS, data must be a pointer to a struct input_absinfo
76    /// containing the data for this axis.
77    /// If type is EV_REP, data must be a pointer to a int containing the data
78    /// for this axis.
79    /// For all other types, the argument must be NULL.
80    ///
81    /// Note: Please use the `enable` function instead. This function is only
82    /// available for the sake of maintaining compatibility with libevdev.
83    fn enable_event_code(
84        &self,
85        ev_code: &EventCode,
86        blob: Option<&dyn Any>,
87    ) -> io::Result<()> {
88        let (ev_type, ev_code) = event_code_to_int(ev_code);
89
90        let data = blob
91            .map(|data| {
92                data.downcast_ref::<AbsInfo>()
93                    .map(|absinfo| &absinfo.as_raw() as *const _ as *const c_void)
94                    .unwrap_or_else(|| data as *const _ as *const c_void)
95            })
96            .unwrap_or_else(|| ptr::null() as *const _ as *const c_void);
97
98        let result = unsafe {
99            raw::libevdev_enable_event_code(
100                self.raw(),
101                ev_type as c_uint,
102                ev_code as c_uint,
103                data,
104            )
105        };
106
107        match result {
108            0 => Ok(()),
109            error => Err(io::Error::from_raw_os_error(-error)),
110        }
111    }
112
113    /// Forcibly disable an EventType/EventCode on this device, even if the
114    /// underlying device provides it. This effectively mutes the respective set of
115    /// events. has() will return false for this EventType/EventCode
116    ///
117    /// In most cases, a caller likely only wants to disable a single code, not
118    /// the whole type.
119    ///
120    /// Disabling EV_SYN will not work. In Peter's Words "Don't shoot yourself
121    /// in the foot. It hurts".
122    ///
123    /// This is a local modification only affecting only this representation of
124    /// this device.
125    fn disable(&self, blob: &dyn Any) -> io::Result<()> {
126        if let Some(ev_type) = blob.downcast_ref::<EventType>() {
127            self.disable_event_type(ev_type)
128        } else if let Some(ev_code) = blob.downcast_ref::<EventCode>() {
129            self.disable_event_code(ev_code)
130        } else {
131            Err(io::Error::from_raw_os_error(-1))
132        }
133    }
134
135    /// Forcibly disable an event type on this device, even if the underlying
136    /// device provides it. This effectively mutes the respective set of
137    /// events. libevdev will filter any events matching this type and none will
138    /// reach the caller. libevdev_has_event_type() will return false for this
139    /// type.
140    ///
141    /// In most cases, a caller likely only wants to disable a single code, not
142    /// the whole type. Use `disable_event_code` for that.
143    ///
144    /// Disabling EV_SYN will not work. In Peter's Words "Don't shoot yourself
145    /// in the foot. It hurts".
146    ///
147    /// This is a local modification only affecting only this representation of
148    /// this device.
149    ///
150    /// Note: Please use the `disable` function instead. This function is only
151    /// available for the sake of maintaining compatibility with libevdev.
152    fn disable_event_type(&self, ev_type: &EventType) -> io::Result<()> {
153        let result =
154            unsafe { raw::libevdev_disable_event_type(self.raw(), *ev_type as c_uint) };
155
156        match result {
157            0 => Ok(()),
158            error => Err(io::Error::from_raw_os_error(-error)),
159        }
160    }
161    /// Forcibly disable an event code on this device, even if the underlying
162    /// device provides it. This effectively mutes the respective set of
163    /// events. libevdev will filter any events matching this type and code and
164    /// none will reach the caller. `has_event_code` will return false for
165    /// this code.
166    ///
167    /// Disabling all event codes for a given type will not disable the event
168    /// type. Use `disable_event_type` for that.
169    ///
170    /// This is a local modification only affecting only this representation of
171    /// this device.
172    ///
173    /// Disabling codes of type EV_SYN will not work. Don't shoot yourself in the
174    /// foot. It hurts.
175    ///
176    /// Note: Please use the `disable` function instead. This function is only
177    /// available for the sake of maintaining compatibility with libevdev.
178    fn disable_event_code(&self, code: &EventCode) -> io::Result<()> {
179        let (ev_type, ev_code) = event_code_to_int(code);
180        let result =
181            unsafe { raw::libevdev_disable_event_code(self.raw(), ev_type, ev_code) };
182
183        match result {
184            0 => Ok(()),
185            error => Err(io::Error::from_raw_os_error(-error)),
186        }
187    }
188
189    /// Returns `true` if device support the InputProp/EventType/EventCode and false otherwise
190    fn has(&self, blob: &dyn Any) -> bool {
191        if let Some(ev_type) = blob.downcast_ref::<EventType>() {
192            self.has_event_type(ev_type)
193        } else if let Some(ev_code) = blob.downcast_ref::<EventCode>() {
194            self.has_event_code(ev_code)
195        } else if let Some(prop) = blob.downcast_ref::<InputProp>() {
196            self.has_property(prop)
197        } else {
198            false
199        }
200    }
201
202    /// Returns `true` if device support the property and false otherwise
203    ///
204    /// Note: Please use the `has` function instead. This function is only
205    /// available for the sake of maintaining compatibility with libevdev.
206    fn has_property(&self, prop: &InputProp) -> bool {
207        unsafe { raw::libevdev_has_property(self.raw(), *prop as c_uint) != 0 }
208    }
209
210    /// Returns `true` is the device support this event type and `false` otherwise
211    ///
212    /// Note: Please use the `has` function instead. This function is only
213    /// available for the sake of maintaining compatibility with libevdev.
214    fn has_event_type(&self, ev_type: &EventType) -> bool {
215        unsafe { raw::libevdev_has_event_type(self.raw(), *ev_type as c_uint) != 0 }
216    }
217
218    /// Return `true` is the device support this event type and code and `false` otherwise
219    ///
220    /// Note: Please use the `has` function instead. This function is only
221    /// available for the sake of maintaining compatibility with libevdev.
222    fn has_event_code(&self, code: &EventCode) -> bool {
223        unsafe {
224            let (ev_type, ev_code) = event_code_to_int(code);
225            raw::libevdev_has_event_code(self.raw(), ev_type, ev_code) != 0
226        }
227    }
228
229    string_getter!(
230        #[doc = "Get device's name, as set by the kernel, or overridden by a call to `set_name`"],
231        name, libevdev_get_name,
232        #[doc = "Get device's physical location, as set by the kernel, or overridden by a call to `set_phys`"],
233        phys, libevdev_get_phys,
234        #[doc = "Get device's unique identifier, as set by the kernel, or overridden by a call to `set_uniq`"],
235        uniq, libevdev_get_uniq
236    );
237
238    string_setter!(
239        set_name,
240        libevdev_set_name,
241        set_phys,
242        libevdev_set_phys,
243        set_uniq,
244        libevdev_set_uniq
245    );
246
247    product_getter!(
248        product_id,
249        libevdev_get_id_product,
250        vendor_id,
251        libevdev_get_id_vendor,
252        bustype,
253        libevdev_get_id_bustype,
254        version,
255        libevdev_get_id_version
256    );
257
258    product_setter!(
259        set_product_id,
260        libevdev_set_id_product,
261        set_vendor_id,
262        libevdev_set_id_vendor,
263        set_bustype,
264        libevdev_set_id_bustype,
265        set_version,
266        libevdev_set_id_version
267    );
268
269    /// Get the axis info for the given axis, as advertised by the kernel.
270    ///
271    /// Returns the `AbsInfo` for the given the code or None if the device
272    /// doesn't support this code
273    fn abs_info(&self, code: &EventCode) -> Option<AbsInfo> {
274        let (_, ev_code) = event_code_to_int(code);
275        let a = unsafe { raw::libevdev_get_abs_info(self.raw(), ev_code).as_ref()? };
276
277        Some(AbsInfo {
278            value: a.value,
279            minimum: a.minimum,
280            maximum: a.maximum,
281            fuzz: a.fuzz,
282            flat: a.flat,
283            resolution: a.resolution,
284        })
285    }
286
287    /// Change the abs info for the given EV_ABS event code, if the code exists.
288    ///
289    /// This function has no effect if `has_event_code` returns false for
290    /// this code.
291    fn set_abs_info(&self, code: &EventCode, absinfo: &AbsInfo) {
292        let (_, ev_code) = event_code_to_int(code);
293
294        unsafe {
295            raw::libevdev_set_abs_info(
296                self.raw(),
297                ev_code,
298                &absinfo.as_raw() as *const _,
299            );
300        }
301    }
302
303    ///  Returns the current value of the event type.
304    ///
305    /// If the device supports this event type and code, the return value is
306    /// set to the current value of this axis. Otherwise, `None` is returned.
307    fn event_value(&self, code: &EventCode) -> Option<i32> {
308        let mut value: i32 = 0;
309        let (ev_type, ev_code) = event_code_to_int(code);
310        let valid = unsafe {
311            raw::libevdev_fetch_event_value(self.raw(), ev_type, ev_code, &mut value)
312        };
313
314        match valid {
315            0 => None,
316            _ => Some(value),
317        }
318    }
319
320    /// Set the value for a given event type and code.
321    ///
322    /// This only makes sense for some event types, e.g. setting the value for
323    /// EV_REL is pointless.
324    ///
325    /// This is a local modification only affecting only this representation of
326    /// this device. A future call to event_value() will return this
327    /// value, unless the value was overwritten by an event.
328    ///
329    /// If the device supports ABS_MT_SLOT, the value set for any ABS_MT_*
330    /// event code is the value of the currently active slot. You should use
331    /// `set_slot_value` instead.
332    ///
333    /// If the device supports ABS_MT_SLOT and the type is EV_ABS and the code is
334    /// ABS_MT_SLOT, the value must be a positive number less then the number of
335    /// slots on the device. Otherwise, `set_event_value` returns Err.
336    fn set_event_value(&self, code: &EventCode, val: i32) -> io::Result<()> {
337        let (ev_type, ev_code) = event_code_to_int(code);
338        let result = unsafe {
339            raw::libevdev_set_event_value(self.raw(), ev_type, ev_code, val as c_int)
340        };
341
342        match result {
343            0 => Ok(()),
344            error => Err(io::Error::from_raw_os_error(-error)),
345        }
346    }
347
348    abs_getter!(
349        abs_minimum,
350        libevdev_get_abs_minimum,
351        abs_maximum,
352        libevdev_get_abs_maximum,
353        abs_fuzz,
354        libevdev_get_abs_fuzz,
355        abs_flat,
356        libevdev_get_abs_flat,
357        abs_resolution,
358        libevdev_get_abs_resolution
359    );
360
361    abs_setter!(
362        set_abs_minimum,
363        libevdev_set_abs_minimum,
364        set_abs_maximum,
365        libevdev_set_abs_maximum,
366        set_abs_fuzz,
367        libevdev_set_abs_fuzz,
368        set_abs_flat,
369        libevdev_set_abs_flat,
370        set_abs_resolution,
371        libevdev_set_abs_resolution
372    );
373
374    /// Return the current value of the code for the given slot.
375    ///
376    /// If the device supports this event code, the return value is
377    /// is set to the current value of this axis. Otherwise, or
378    /// if the event code is not an ABS_MT_* event code, `None` is returned
379    fn slot_value(&self, slot: u32, code: &EventCode) -> Option<i32> {
380        let (_, ev_code) = event_code_to_int(code);
381        let mut value: i32 = 0;
382        let valid = unsafe {
383            raw::libevdev_fetch_slot_value(
384                self.raw(),
385                slot as c_uint,
386                ev_code,
387                &mut value,
388            )
389        };
390
391        match valid {
392            0 => None,
393            _ => Some(value),
394        }
395    }
396
397    /// Set the value for a given code for the given slot.
398    ///
399    /// This is a local modification only affecting only this representation of
400    /// this device. A future call to `slot_value` will return this value,
401    /// unless the value was overwritten by an event.
402    ///
403    /// This function does not set event values for axes outside the ABS_MT range,
404    /// use `set_event_value` instead.
405    fn set_slot_value(&self, slot: u32, code: &EventCode, val: i32) -> io::Result<()> {
406        let (_, ev_code) = event_code_to_int(code);
407        let result = unsafe {
408            raw::libevdev_set_slot_value(
409                self.raw(),
410                slot as c_uint,
411                ev_code,
412                val as c_int,
413            )
414        };
415
416        match result {
417            0 => Ok(()),
418            error => Err(io::Error::from_raw_os_error(-error)),
419        }
420    }
421
422    /// Get the number of slots supported by this device.
423    ///
424    /// The number of slots supported, or `None` if the device does not provide
425    /// any slots
426    ///
427    /// A device may provide ABS_MT_SLOT but a total number of 0 slots. Hence
428    /// the return value of `None` for "device does not provide slots at all"
429    fn num_slots(&self) -> Option<i32> {
430        let result = unsafe { raw::libevdev_get_num_slots(self.raw()) };
431
432        match result {
433            -1 => None,
434            slots => Some(slots),
435        }
436    }
437
438    /// Get the currently active slot.
439    ///
440    /// This may differ from the value an ioctl may return at this time as
441    /// events may have been read off the file since changing the slot value
442    /// but those events are still in the buffer waiting to be processed.
443    /// The returned value is the value a caller would see if it were to
444    /// process events manually one-by-one.
445    fn current_slot(&self) -> Option<i32> {
446        let result = unsafe { raw::libevdev_get_current_slot(self.raw()) };
447
448        match result {
449            -1 => None,
450            slots => Some(slots),
451        }
452    }
453}
454
455/// Opaque struct representing an evdev device with no backing file
456pub struct UninitDevice {
457    raw: *mut raw::libevdev,
458}
459
460unsafe impl Send for UninitDevice {}
461
462impl DeviceWrapper for UninitDevice {
463    fn raw(&self) -> *mut raw::libevdev {
464        self.raw
465    }
466}
467
468impl UninitDevice {
469    /// Initialize a new libevdev device.
470    ///
471    /// Generally you should use Device::new_from_file instead of this method
472    /// This function only initializes the struct to sane default values.
473    /// To actually hook up the device to a kernel device, use `set_file`.
474    pub fn new() -> Option<UninitDevice> {
475        let libevdev = unsafe { raw::libevdev_new() };
476
477        if libevdev.is_null() {
478            None
479        } else {
480            Some(UninitDevice { raw: libevdev })
481        }
482    }
483
484    /// Set the file for this struct and initialize internal data.
485    ///
486    /// If the device changed and you need to re-read a device, use `Device::new_from_file` method.
487    /// If you need to change the file after
488    /// closing and re-opening the same device, use `change_file`.
489    pub fn set_file(self, file: File) -> io::Result<Device> {
490        // Don't call UninitDevice's destructor so we can reuse the inner libevdev
491        let leak = ManuallyDrop::new(self);
492        let result = unsafe { raw::libevdev_set_fd(leak.raw, file.as_raw_fd()) };
493        match result {
494            0 => Ok(Device {
495                file,
496                raw: leak.raw,
497            }),
498            error => Err(io::Error::from_raw_os_error(-error)),
499        }
500    }
501
502    #[deprecated(
503        since = "0.5.0",
504        note = "Prefer `set_file`. Some function names were changed so they
505        more closely match their type signature. See issue 42 for discussion
506        https://github.com/ndesh26/evdev-rs/issues/42"
507    )]
508    pub fn set_fd(self, file: File) -> io::Result<Device> {
509        self.set_file(file)
510    }
511}
512
513impl Drop for UninitDevice {
514    fn drop(&mut self) {
515        unsafe {
516            raw::libevdev_free(self.raw);
517        }
518    }
519}
520
521/// Opaque struct representing an evdev device
522///
523/// Unlike libevdev, this `Device` mantains an associated file as an invariant
524pub struct Device {
525    file: File,
526    raw: *mut raw::libevdev,
527}
528
529unsafe impl Send for Device {}
530
531impl DeviceWrapper for Device {
532    fn raw(&self) -> *mut raw::libevdev {
533        self.raw
534    }
535}
536
537impl Device {
538    /// Initialize a new libevdev device from the given file.
539    ///
540    /// This is a shortcut for
541    ///
542    /// ```rust,no_run
543    /// use evdev_rs::{Device, UninitDevice};
544    /// # use std::fs::File;
545    ///
546    /// let uninit_device = UninitDevice::new().unwrap();
547    /// # let file = File::open("/dev/input/event0").unwrap();
548    /// let device = uninit_device.set_file(file);
549    /// ```
550    pub fn new_from_file(file: File) -> io::Result<Device> {
551        let mut libevdev = std::ptr::null_mut();
552        let result =
553            unsafe { raw::libevdev_new_from_fd(file.as_raw_fd(), &mut libevdev) };
554
555        match result {
556            0 => Ok(Device {
557                file,
558                raw: libevdev,
559            }),
560            error => Err(io::Error::from_raw_os_error(-error)),
561        }
562    }
563
564    #[deprecated(
565        since = "0.5.0",
566        note = "Prefer `new_from_file`. Some function names were changed so they
567        more closely match their type signature. See issue 42 for discussion
568        https://github.com/ndesh26/evdev-rs/issues/42"
569    )]
570    pub fn new_from_fd(file: File) -> io::Result<Device> {
571        Self::new_from_file(file)
572    }
573
574    /// Returns the file associated with the device
575    pub fn file(&self) -> &File {
576        &self.file
577    }
578
579    #[deprecated(
580        since = "0.5.0",
581        note = "Prefer `file`. This function can easily be misused. Calling
582        this method, then dropping the returned file will lead to failures
583        e.g. next_event will return an Err()"
584    )]
585    pub fn fd(&self) -> Option<File> {
586        let result = unsafe { raw::libevdev_get_fd(self.raw) };
587        match result {
588            0 => None,
589            _ => unsafe { Some(File::from_raw_fd(result)) },
590        }
591    }
592
593    /// Change the file for this device, without re-reading the actual device.
594    ///
595    /// On success, returns the file that was previously associated with this
596    /// device.
597    ///
598    /// If the file changes after initializing the device, for example after a
599    /// VT-switch in the X.org X server, this function updates the internal
600    /// file to the newly opened. No check is made that new file points to the
601    /// same device. If the device has changed, evdev's behavior is undefined.
602    ///
603    /// evdev device does not sync itself after changing the file and keeps the
604    /// current device state. Use next_event with the FORCE_SYNC flag to force
605    /// a re-sync.
606    ///
607    /// # Example
608    ///
609    /// ```rust,no_run
610    /// use evdev_rs::{Device, UninitDevice, ReadFlag, ReadStatus};
611    /// # use std::fs::File;
612    /// # fn hidden() -> std::io::Result<()> {
613    /// let mut dev = Device::new_from_file(File::open("/dev/input/input0")?)?;
614    /// dev.change_file(File::open("/dev/input/input1")?)?;
615    /// dev.next_event(ReadFlag::FORCE_SYNC);
616    /// while dev.next_event(ReadFlag::SYNC).ok().unwrap().0 == ReadStatus::Sync
617    ///                             {} // noop
618    /// # Ok(())
619    /// # }
620    /// ```
621    /// After changing the file, the device is assumed ungrabbed and a caller must
622    /// call libevdev_grab() again.
623    pub fn change_file(&mut self, file: File) -> io::Result<File> {
624        let result = unsafe { raw::libevdev_change_fd(self.raw, file.as_raw_fd()) };
625
626        match result {
627            0 => {
628                let mut file = file;
629                std::mem::swap(&mut file, &mut self.file);
630                Ok(file)
631            }
632            error => Err(io::Error::from_raw_os_error(-error)),
633        }
634    }
635
636    #[deprecated(
637        since = "0.5.0",
638        note = "Prefer new_from_file. Some function names were changed so they
639        more closely match their type signature. See issue 42 for discussion
640        https://github.com/ndesh26/evdev-rs/issues/42"
641    )]
642    pub fn change_fd(&mut self, file: File) -> io::Result<()> {
643        self.change_file(file)?;
644        Ok(())
645    }
646
647    /// Grab or ungrab the device through a kernel EVIOCGRAB.
648    ///
649    /// This prevents other clients (including kernel-internal ones such as
650    /// rfkill) from receiving events from this device. This is generally a
651    /// bad idea. Don't do this. Grabbing an already grabbed device, or
652    /// ungrabbing an ungrabbed device is a noop and always succeeds.
653    ///
654    /// A grab is an operation tied to a file descriptor, not a device. If a
655    /// client changes the file descriptor with Device::change_file(), it must
656    /// also re-issue a grab with libevdev_grab().
657    pub fn grab(&mut self, grab: GrabMode) -> io::Result<()> {
658        let result = unsafe { raw::libevdev_grab(self.raw, grab as c_int) };
659
660        match result {
661            0 => Ok(()),
662            error => Err(io::Error::from_raw_os_error(-error)),
663        }
664    }
665
666    /// Check if there are events waiting for us.
667    ///
668    /// This function does not consume an event and may not access the device
669    /// file at all. If there are events queued internally this function will
670    /// return true. If the internal queue is empty, this function will poll
671    /// the file descriptor for data.
672    ///
673    /// This is a convenience function for simple processes, most complex programs
674    /// are expected to use select(2) or poll(2) on the file descriptor. The kernel
675    /// guarantees that if data is available, it is a multiple of sizeof(struct
676    /// input_event), and thus calling `next_event` when select(2) or
677    /// poll(2) return is safe. You do not need `has_event_pending` if
678    /// you're using select(2) or poll(2).
679    pub fn has_event_pending(&self) -> bool {
680        unsafe { raw::libevdev_has_event_pending(self.raw) > 0 }
681    }
682
683    /// Return the driver version of a device already intialize with `set_file`
684    pub fn driver_version(&self) -> i32 {
685        unsafe { raw::libevdev_get_driver_version(self.raw) as i32 }
686    }
687
688    /// Set the device's EV_ABS axis to the value defined in the abs
689    /// parameter. This will be written to the kernel.
690    pub fn set_kernel_abs_info(&self, code: &EventCode, absinfo: &AbsInfo) {
691        let (_, ev_code) = event_code_to_int(code);
692
693        unsafe {
694            raw::libevdev_kernel_set_abs_info(
695                self.raw,
696                ev_code,
697                &absinfo.as_raw() as *const _,
698            );
699        }
700    }
701
702    /// Turn an LED on or off.
703    ///
704    /// enabling an LED requires write permissions on the device's file descriptor.
705    pub fn kernel_set_led_value(
706        &self,
707        code: &EventCode,
708        value: LedState,
709    ) -> io::Result<()> {
710        let (_, ev_code) = event_code_to_int(code);
711        let result = unsafe {
712            raw::libevdev_kernel_set_led_value(self.raw, ev_code, value as c_int)
713        };
714
715        match result {
716            0 => Ok(()),
717            error => Err(io::Error::from_raw_os_error(-error)),
718        }
719    }
720
721    /// Set the clock ID to be used for timestamps. Further events from this device
722    /// will report an event time based on the given clock.
723    ///
724    /// This is a modification only affecting this representation of
725    /// this device.
726    pub fn set_clock_id(&self, clockid: i32) -> io::Result<()> {
727        let result = unsafe { raw::libevdev_set_clock_id(self.raw, clockid) };
728
729        match result {
730            0 => Ok(()),
731            error => Err(io::Error::from_raw_os_error(-error)),
732        }
733    }
734
735    /// Get the next event from the device. This function operates in two different
736    /// modes: normal mode or sync mode.
737    ///
738    /// In normal mode (when flags has `evdev::NORMAL` set), this function returns
739    /// `ReadStatus::Success` and returns the event. If no events are available at
740    /// this time, it returns `-EAGAIN` as `Err`.
741    ///
742    /// If the current event is an `EV_SYN::SYN_DROPPED` event, this function returns
743    /// `ReadStatus::Sync` and is set to the `EV_SYN` event.The caller should now call
744    /// this function with the `evdev::SYNC` flag set, to get the set of events that
745    /// make up the device state delta. This function returns ReadStatus::Sync for
746    /// each event part of that delta, until it returns `-EAGAIN` once all events
747    /// have been synced.
748    ///
749    /// If a device needs to be synced by the caller but the caller does not call
750    /// with the `evdev::SYNC` flag set, all events from the diff are dropped after
751    /// evdev updates its internal state and event processing continues as normal.
752    /// Note that the current slot and the state of touch points may have updated
753    /// during the `SYN_DROPPED` event, it is strongly recommended that a caller
754    /// ignoring all sync events calls `current_slot` and checks the
755    /// `ABS_MT_TRACKING_ID` values for all slots.
756    ///
757    /// If a device has changed state without events being enqueued in evdev,
758    /// e.g. after changing the file descriptor, use the `evdev::FORCE_SYNC` flag.
759    /// This triggers an internal sync of the device and `next_event` returns
760    /// `ReadStatus::Sync`.
761    pub fn next_event(&self, flags: ReadFlag) -> io::Result<(ReadStatus, InputEvent)> {
762        let mut ev = raw::input_event {
763            time: raw::timeval {
764                tv_sec: 0,
765                tv_usec: 0,
766            },
767            type_: 0,
768            code: 0,
769            value: 0,
770        };
771
772        let result =
773            unsafe { raw::libevdev_next_event(self.raw, flags.bits as c_uint, &mut ev) };
774
775        let event = InputEvent {
776            time: TimeVal {
777                tv_sec: ev.time.tv_sec,
778                tv_usec: ev.time.tv_usec,
779            },
780            event_code: int_to_event_code(ev.type_ as u32, ev.code as u32),
781            value: ev.value,
782        };
783
784        match result {
785            raw::LIBEVDEV_READ_STATUS_SUCCESS => Ok((ReadStatus::Success, event)),
786            raw::LIBEVDEV_READ_STATUS_SYNC => Ok((ReadStatus::Sync, event)),
787            error => Err(io::Error::from_raw_os_error(-error)),
788        }
789    }
790}
791
792impl Drop for Device {
793    fn drop(&mut self) {
794        unsafe {
795            raw::libevdev_free(self.raw);
796        }
797    }
798}