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}