1 // Copyright (c) 2018 The rust-gpio-cdev Project Developers.
2 //
3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6 // option. This file may not be copied, modified, or distributed
7 // except according to those terms.
8 
9 use gpio_cdev::*;
10 use nix::poll::*;
11 use quicli::prelude::*;
12 use std::os::unix::io::{AsRawFd, FromRawFd, OwnedFd};
13 use structopt::StructOpt;
14 
15 type PollEventFlags = nix::poll::PollFlags;
16 
17 #[derive(Debug, StructOpt)]
18 struct Cli {
19     /// The gpiochip device (e.g. /dev/gpiochip0)
20     chip: String,
21     /// The offset of the GPIO lines for the provided chip
22     lines: Vec<u32>,
23 }
24 
do_main(args: Cli) -> anyhow::Result<()>25 fn do_main(args: Cli) -> anyhow::Result<()> {
26     let mut chip = Chip::new(args.chip)?;
27 
28     // Get event handles for each line to monitor.
29     let mut evt_handles: Vec<LineEventHandle> = args
30         .lines
31         .into_iter()
32         .map(|off| {
33             let line = chip.get_line(off).unwrap();
34             line.events(
35                 LineRequestFlags::INPUT,
36                 EventRequestFlags::BOTH_EDGES,
37                 "monitor",
38             )
39             .unwrap()
40         })
41         .collect();
42 
43     // Create a vector of file descriptors for polling
44     let ownedfd: Vec<OwnedFd> = evt_handles
45         .iter()
46         .map(|h| unsafe { OwnedFd::from_raw_fd(h.as_raw_fd()) })
47         .collect();
48     let mut pollfds: Vec<PollFd> = ownedfd
49         .iter()
50         .map(|fd| PollFd::new(fd, PollEventFlags::POLLIN | PollEventFlags::POLLPRI))
51         .collect();
52 
53     loop {
54         // poll for an event on any of the lines
55         if poll(&mut pollfds, -1)? == 0 {
56             println!("Timeout?!?");
57         } else {
58             for i in 0..pollfds.len() {
59                 if let Some(revts) = pollfds[i].revents() {
60                     let h = &mut evt_handles[i];
61                     if revts.contains(PollEventFlags::POLLIN) {
62                         let event = h.get_event()?;
63                         println!("[{}] {:?}", h.line().offset(), event);
64 
65                         // You can figure out the new level from the event,
66                         // but this shows that you can use the event handle
67                         // to read the value of the bit.
68                         let val = h.get_value()?;
69                         println!("    {}", val);
70                     } else if revts.contains(PollEventFlags::POLLPRI) {
71                         println!("[{}] Got a POLLPRI", h.line().offset());
72                     }
73                 }
74             }
75         }
76     }
77 }
78 
main() -> CliResult79 fn main() -> CliResult {
80     let args = Cli::from_args();
81     do_main(args).or_else(|e| {
82         error!("{:?}", e);
83         Ok(())
84     })
85 }
86