cognitive_device_manager/
udev.rs1use std::ffi::OsStr;
9use std::path::Path;
10
11use libudev;
12use nix;
13
14use qualia::DeviceKind;
15
16const INPUT_MOUSE: &'static str = "ID_INPUT_MOUSE";
19const INPUT_TOUCHPAD: &'static str = "ID_INPUT_TOUCHPAD";
20const INPUT_KEYBOARD: &'static str = "ID_INPUT_KEYBOARD";
21
22pub struct Udev {
26 context: libudev::Context,
27}
28
29impl Udev {
32 pub fn new() -> Self {
34 Udev { context: libudev::Context::new().expect("Failed to create udev context") }
35 }
36
37 pub fn iterate_input_devices<F>(&self, mut f: F)
40 where F: FnMut(&Path, DeviceKind, &libudev::Device)
41 {
42 let mut enumerator =
43 libudev::Enumerator::new(&self.context).expect("Failed to create device enumerator");
44
45 enumerator.match_subsystem("input").expect("Failed to apply filter for device enumerator");
46 for device in enumerator.scan_devices().expect("Failed to scan devices") {
47 let device_kind = determine_device_kind(&device);
48 if device_kind != DeviceKind::Unknown && is_input_device(device.sysname()) {
49 if let Some(devnode) = device.devnode() {
50 if exists_in_filesystem(&devnode) {
51 f(devnode, device_kind, &device);
52 }
53 }
54 }
55 }
56 }
57
58 pub fn iterate_output_devices<F: FnMut(&Path, &libudev::Device)>(&self, mut f: F) {
61 let mut enumerator =
62 libudev::Enumerator::new(&self.context).expect("Failed to create device enumerator");
63
64 enumerator.match_subsystem("drm").expect("Failed to apply filter for device enumerator");
65 for device in enumerator.scan_devices().expect("Failed to scan devices") {
66 if is_output_device(device.sysname()) {
67 if let Some(devnode) = device.devnode() {
68 if exists_in_filesystem(&devnode) {
69 log_info1!("Found output device: {:?}", devnode);
70 f(devnode, &device);
71 }
72 }
73 }
74 }
75 }
76}
77
78pub fn exists_in_filesystem(devnode: &Path) -> bool {
82 nix::sys::stat::stat(devnode).is_ok()
83}
84
85pub fn is_input_device(sysname: &OsStr) -> bool {
89 match sysname.to_os_string().into_string() {
90 Ok(sysname) => sysname.starts_with("event"),
91 Err(_) => false,
92 }
93}
94
95pub fn is_output_device(sysname: &OsStr) -> bool {
99 match sysname.to_os_string().into_string() {
100 Ok(sysname) => sysname.starts_with("card"),
101 Err(_) => false,
102 }
103}
104
105pub fn determine_device_kind(device: &libudev::Device) -> DeviceKind {
109 for property in device.properties() {
110 if property.name() == INPUT_MOUSE {
111 return DeviceKind::Mouse;
112 } else if property.name() == INPUT_TOUCHPAD {
113 return DeviceKind::Touchpad;
114 } else if property.name() == INPUT_KEYBOARD {
115 return DeviceKind::Keyboard;
116 }
117 }
118 DeviceKind::Unknown
119}
120
121