evtest/
evtest.rs

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}