1use evdev_rs_tokio::enums::*;
2use evdev_rs_tokio::*;
3use std::io;
4use tokio::fs::File;
5
6fn usage() {
7 println!("Usage: evtest /path/to/device");
8}
9
10fn print_abs_bits(dev: &Device, axis: &EV_ABS) {
11 let code = EventCode::EV_ABS(axis.clone());
12
13 if !dev.has(&code) {
14 return;
15 }
16
17 let abs = dev.abs_info(&code).unwrap();
18
19 println!("\tValue\t{}", abs.value);
20 println!("\tMin\t{}", abs.minimum);
21 println!("\tMax\t{}", abs.maximum);
22 if abs.fuzz != 0 {
23 println!("\tFuzz\t{}", abs.fuzz);
24 }
25 if abs.flat != 0 {
26 println!("\tFlat\t{}", abs.flat);
27 }
28 if abs.resolution != 0 {
29 println!("\tResolution\t{}", abs.resolution);
30 }
31}
32
33fn print_code_bits(dev: &Device, ev_code: &EventCode, max: &EventCode) {
34 for code in ev_code.iter() {
35 if code == *max {
36 break;
37 }
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 EventType::EV_SYN.iter() {
54 if dev.has(&ev_type) {
55 println!(" Event type: {} ", ev_type);
56 }
57
58 match ev_type {
59 EventType::EV_KEY => print_code_bits(
60 dev,
61 &EventCode::EV_KEY(EV_KEY::KEY_RESERVED),
62 &EventCode::EV_KEY(EV_KEY::KEY_MAX),
63 ),
64 EventType::EV_REL => print_code_bits(
65 dev,
66 &EventCode::EV_REL(EV_REL::REL_X),
67 &EventCode::EV_REL(EV_REL::REL_MAX),
68 ),
69 EventType::EV_ABS => print_code_bits(
70 dev,
71 &EventCode::EV_ABS(EV_ABS::ABS_X),
72 &EventCode::EV_ABS(EV_ABS::ABS_MAX),
73 ),
74 EventType::EV_LED => print_code_bits(
75 dev,
76 &EventCode::EV_LED(EV_LED::LED_NUML),
77 &EventCode::EV_LED(EV_LED::LED_MAX),
78 ),
79 _ => (),
80 }
81 }
82}
83
84fn print_props(dev: &Device) {
85 println!("Properties:");
86
87 for input_prop in InputProp::INPUT_PROP_POINTER.iter() {
88 if dev.has(&input_prop) {
89 println!(" Property type: {}", input_prop);
90 }
91 }
92}
93
94fn print_event(ev: &InputEvent) {
95 match ev.event_code {
96 EventCode::EV_SYN(_) => println!(
97 "Event: time {}.{}, ++++++++++++++++++++ {} +++++++++++++++",
98 ev.time.tv_sec,
99 ev.time.tv_usec,
100 ev.event_type().unwrap()
101 ),
102 _ => println!(
103 "Event: time {}.{}, type {} , code {} , value {}",
104 ev.time.tv_sec,
105 ev.time.tv_usec,
106 ev.event_type()
107 .map(|ev_type| format!("{}", ev_type))
108 .unwrap_or("None".to_owned()),
109 ev.event_code,
110 ev.value
111 ),
112 }
113}
114
115fn print_sync_dropped_event(ev: &InputEvent) {
116 print!("SYNC DROPPED: ");
117 print_event(ev);
118}
119
120#[tokio::main]
121async fn main() {
122 let mut args = std::env::args();
123
124 if args.len() != 2 {
125 usage();
126 std::process::exit(1);
127 }
128
129 let path = &args.nth(1).unwrap();
130 let f = File::open(path).await.unwrap();
131
132 let u_d = UninitDevice::new().unwrap();
133 let d = u_d.set_file(f).unwrap();
134
135 println!(
136 "Input device ID: bus 0x{:x} vendor 0x{:x} product 0x{:x}",
137 d.bustype(),
138 d.vendor_id(),
139 d.product_id()
140 );
141 println!("Evdev version: {:x}", d.driver_version());
142 println!("Input device name: \"{}\"", d.name().unwrap_or(""));
143 println!("Phys location: {}", d.phys().unwrap_or(""));
144 println!("Uniq identifier: {}", d.uniq().unwrap_or(""));
145
146 print_bits(&d);
147 print_props(&d);
148
149 let mut a: io::Result<(ReadStatus, InputEvent)>;
150 loop {
151 a = d.next_event(ReadFlag::NORMAL | ReadFlag::BLOCKING);
152 if a.is_ok() {
153 let mut result = a.ok().unwrap();
154 match result.0 {
155 ReadStatus::Sync => {
156 println!("::::::::::::::::::::: dropped ::::::::::::::::::::::");
157 while result.0 == ReadStatus::Sync {
158 print_sync_dropped_event(&result.1);
159 a = d.next_event(ReadFlag::SYNC);
160 if a.is_ok() {
161 result = a.ok().unwrap();
162 } else {
163 break;
164 }
165 }
166 println!("::::::::::::::::::::: re-synced ::::::::::::::::::::");
167 }
168 ReadStatus::Success => print_event(&result.1),
169 }
170 } else {
171 let err = a.err().unwrap();
172 match err.raw_os_error() {
173 Some(libc::EAGAIN) => continue,
174 _ => {
175 println!("{}", err);
176 break;
177 }
178 }
179 }
180 }
181}