1use evdev_rs::enums::*;
2use evdev_rs::*;
3use std::fs::OpenOptions;
4use std::io;
5use std::io::ErrorKind;
6use std::io::Read;
7use std::os::unix::fs::OpenOptionsExt;
8
9fn usage() {
10 println!("Usage: evtest /path/to/device");
11}
12
13fn print_abs_bits(dev: &Device, axis: &EV_ABS) {
14 let code = EventCode::EV_ABS(axis.clone());
15
16 if !dev.has(code) {
17 return;
18 }
19
20 let abs = dev.abs_info(&code).unwrap();
21
22 println!("\tValue\t{}", abs.value);
23 println!("\tMin\t{}", abs.minimum);
24 println!("\tMax\t{}", abs.maximum);
25 if abs.fuzz != 0 {
26 println!("\tFuzz\t{}", abs.fuzz);
27 }
28 if abs.flat != 0 {
29 println!("\tFlat\t{}", abs.flat);
30 }
31 if abs.resolution != 0 {
32 println!("\tResolution\t{}", abs.resolution);
33 }
34}
35
36fn print_code_bits(dev: &Device, ev_type: &EventType) {
37 for code in EventCodeIterator::new(ev_type) {
38 if !dev.has(code) {
39 continue;
40 }
41
42 println!(" Event code: {}", code);
43 match code {
44 EventCode::EV_ABS(k) => print_abs_bits(dev, &k),
45 _ => (),
46 }
47 }
48}
49
50fn print_bits(dev: &Device) {
51 println!("Supported events:");
52
53 for ev_type in EventTypeIterator::new() {
54 if dev.has(ev_type) {
55 println!(" Event type: {} ", ev_type);
56 }
57
58 match ev_type {
59 EventType::EV_KEY
60 | EventType::EV_REL
61 | EventType::EV_ABS
62 | EventType::EV_LED => print_code_bits(dev, &ev_type),
63 _ => (),
64 }
65 }
66}
67
68fn print_props(dev: &Device) {
69 println!("Properties:");
70
71 for input_prop in InputPropIterator::new() {
72 if dev.has_property(&input_prop) {
73 println!(" Property type: {}", input_prop);
74 }
75 }
76}
77
78fn print_event(ev: &InputEvent) {
79 match ev.event_code {
80 EventCode::EV_SYN(_) => println!(
81 "Event: time {}.{}, ++++++++++++++++++++ {} +++++++++++++++",
82 ev.time.tv_sec,
83 ev.time.tv_usec,
84 ev.event_type().unwrap()
85 ),
86 _ => println!(
87 "Event: time {}.{}, type {} , code {} , value {}",
88 ev.time.tv_sec,
89 ev.time.tv_usec,
90 ev.event_type()
91 .map(|ev_type| format!("{}", ev_type))
92 .unwrap_or("None".to_owned()),
93 ev.event_code,
94 ev.value
95 ),
96 }
97}
98
99fn print_sync_dropped_event(ev: &InputEvent) {
100 print!("SYNC DROPPED: ");
101 print_event(ev);
102}
103
104fn main() {
105 let mut args = std::env::args();
106
107 if args.len() != 2 {
108 usage();
109 std::process::exit(1);
110 }
111
112 let path = &args.nth(1).unwrap();
113 let mut file = OpenOptions::new()
114 .read(true)
115 .write(true)
116 .custom_flags(libc::O_NONBLOCK)
117 .open(path)
118 .unwrap();
119 let mut buffer = Vec::new();
120 let result = file.read_to_end(&mut buffer);
121 if result.is_ok() || result.unwrap_err().kind() != ErrorKind::WouldBlock {
122 println!("Failed to drain pending events from device file");
123 }
124
125 let u_d = UninitDevice::new().unwrap();
126 let d = u_d.set_file(file).unwrap();
127
128 println!(
129 "Input device ID: bus 0x{:x} vendor 0x{:x} product 0x{:x}",
130 d.bustype(),
131 d.vendor_id(),
132 d.product_id()
133 );
134 println!("Evdev version: {:x}", d.driver_version());
135 println!("Input device name: \"{}\"", d.name().unwrap_or(""));
136 println!("Phys location: {}", d.phys().unwrap_or(""));
137 println!("Uniq identifier: {}", d.uniq().unwrap_or(""));
138
139 print_bits(&d);
140 print_props(&d);
141
142 let mut a: io::Result<(ReadStatus, InputEvent)>;
143 loop {
144 a = d.next_event(ReadFlag::NORMAL);
145 if a.is_ok() {
146 let mut result = a.ok().unwrap();
147 match result.0 {
148 ReadStatus::Sync => {
149 println!("::::::::::::::::::::: dropped ::::::::::::::::::::::");
150 while result.0 == ReadStatus::Sync {
151 print_sync_dropped_event(&result.1);
152 a = d.next_event(ReadFlag::SYNC);
153 if a.is_ok() {
154 result = a.ok().unwrap();
155 } else {
156 break;
157 }
158 }
159 println!("::::::::::::::::::::: re-synced ::::::::::::::::::::");
160 }
161 ReadStatus::Success => print_event(&result.1),
162 }
163 } else {
164 let err = a.err().unwrap();
165 match err.raw_os_error() {
166 Some(libc::EAGAIN) => continue,
167 _ => {
168 println!("{}", err);
169 break;
170 }
171 }
172 }
173 }
174}