On Fri, Jul 08, 2022 at 05:04:58PM +0530, Viresh Kumar wrote: > Add examples for the usage of the rust bindings, quite similar to the > ones in cxx bindings. > > Signed-off-by: Viresh Kumar <viresh.kumar@xxxxxxxxxx> > --- > bindings/rust/examples/gpiodetect.rs | 37 ++++++++++++ > bindings/rust/examples/gpiofind.rs | 42 +++++++++++++ > bindings/rust/examples/gpioget.rs | 42 +++++++++++++ > bindings/rust/examples/gpioinfo.rs | 89 ++++++++++++++++++++++++++++ > bindings/rust/examples/gpiomon.rs | 68 +++++++++++++++++++++ > bindings/rust/examples/gpioset.rs | 52 ++++++++++++++++ > 6 files changed, 330 insertions(+) > create mode 100644 bindings/rust/examples/gpiodetect.rs > create mode 100644 bindings/rust/examples/gpiofind.rs > create mode 100644 bindings/rust/examples/gpioget.rs > create mode 100644 bindings/rust/examples/gpioinfo.rs > create mode 100644 bindings/rust/examples/gpiomon.rs > create mode 100644 bindings/rust/examples/gpioset.rs > > diff --git a/bindings/rust/examples/gpiodetect.rs b/bindings/rust/examples/gpiodetect.rs > new file mode 100644 > index 000000000000..82307e4eecea > --- /dev/null > +++ b/bindings/rust/examples/gpiodetect.rs > @@ -0,0 +1,37 @@ > +// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause > +// > +// Copyright 2022 Linaro Ltd. All Rights Reserved. > +// Viresh Kumar <viresh.kumar@xxxxxxxxxx> > +// > +// Simplified Rust implementation of gpiodetect tool. > + > +use std::env; > +use std::fs; > +use std::path::Path; > + > +use libgpiod::{gpiod_is_gpiochip_device, Chip}; > + > +fn main() { > + let args: Vec<String> = env::args().collect(); > + if args.len() > 1 { > + println!("Usage: {}", args[0]); > + return; > + } > + > + for entry in fs::read_dir(Path::new("/dev")).unwrap() { use .flatten() to have the iterator unwrap the entry so it is actually an entry, not a Result. > + let pathbuf = entry.unwrap().path(); > + let path = pathbuf.to_str().unwrap(); > + is_gpiochip_device() and Chip::open() (and ChipInternal) should accept anything that can be converted into a &Path, e.g. a PathBuf, so the path variable becomes redundant. e.g. pub(crate) fn open<P: AsRef<std::path::Path>>(path: &P) -> Result<Self> { // Null-terminate the string let path = path.as_ref().to_string_lossy() + "\0"; ... and then example code becomes: for entry in fs::read_dir(Path::new("/dev")).unwrap().flatten() { let path = entry.path(); if gpiod_is_gpiochip_device(&path) { let chip = Chip::open(&path).unwrap(); ... (renaming pathbuf to path) Similarly other examples. > + if gpiod_is_gpiochip_device(path) { > + let chip = Chip::open(path).unwrap(); > + let ngpio = chip.get_num_lines(); > + Why does ngpio get a variable, unlike name and label? > + println!( > + "{} [{}] ({})", > + chip.get_name().unwrap(), > + chip.get_label().unwrap(), > + ngpio > + ); > + } > + } > +} Avoid using unwrap(). Have main return a Result and use ?. Not so important here, but below for helper functions returning Results allows the caller to determine how to handle the error. And it reads better. > diff --git a/bindings/rust/examples/gpiofind.rs b/bindings/rust/examples/gpiofind.rs > new file mode 100644 > index 000000000000..bbbd7a87ece8 > --- /dev/null > +++ b/bindings/rust/examples/gpiofind.rs > @@ -0,0 +1,42 @@ > +// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause > +// > +// Copyright 2022 Linaro Ltd. All Rights Reserved. > +// Viresh Kumar <viresh.kumar@xxxxxxxxxx> > +// > +// Simplified Rust implementation of gpiofind tool. > + > +use std::env; > +use std::fs; > +use std::path::Path; > + > +use libgpiod::{gpiod_is_gpiochip_device, Chip}; > + > +fn main() { > + let args: Vec<String> = env::args().collect(); > + if args.len() != 2 { > + println!("Usage: {} <line-name>", args[0]); > + return; > + } > + > + for entry in fs::read_dir(Path::new("/dev")).unwrap() { > + let pathbuf = entry.unwrap().path(); > + let path = pathbuf.to_str().unwrap(); > + > + if gpiod_is_gpiochip_device(path) { Perhaps have the bindings provide an iterator that returns the paths of available gpiochips? > + let chip = Chip::open(path).unwrap(); > + > + let offset = chip.find_line(&args[1]); > + if offset.is_ok() { > + println!( > + "Line {} found: Chip: {}, offset: {}", > + args[1], > + chip.get_name().unwrap(), > + offset.unwrap() > + ); > + return; > + } > + } > + } > + > + println!("Failed to find line: {}", args[1]); > +} > diff --git a/bindings/rust/examples/gpioget.rs b/bindings/rust/examples/gpioget.rs > new file mode 100644 > index 000000000000..c3bc35fcfdb6 > --- /dev/null > +++ b/bindings/rust/examples/gpioget.rs > @@ -0,0 +1,42 @@ > +// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause > +// > +// Copyright 2022 Linaro Ltd. All Rights Reserved. > +// Viresh Kumar <viresh.kumar@xxxxxxxxxx> > +// > +// Simplified Rust implementation of gpioget tool. > + > +use std::env; > + > +use libgpiod::{Chip, Direction, LineConfig, RequestConfig}; > + > +fn main() { > + let args: Vec<String> = env::args().collect(); > + if args.len() < 3 { > + println!("Usage: {} <chip> <line_offset0> ...", args[0]); > + return; > + } > + > + let mut config = LineConfig::new().unwrap(); > + let mut offsets = Vec::<u32>::new(); > + > + for arg in &args[2..] { > + let offset = arg.parse::<u32>().unwrap(); > + > + offsets.push(offset); > + config.set_direction_override(Direction::Input, offset); > + } > + > + let path = format!("/dev/gpiochip{}", args[1]); > + let chip = Chip::open(&path).unwrap(); > + > + let rconfig = RequestConfig::new().unwrap(); > + rconfig.set_consumer(&args[0]); > + rconfig.set_offsets(&offsets); > + > + let request = chip.request_lines(&rconfig, &config).unwrap(); > + > + let mut values: Vec<i32> = vec![0; offsets.len()]; > + request.get_values(&mut values).unwrap(); > + > + println!("{:?}", values); > +} > diff --git a/bindings/rust/examples/gpioinfo.rs b/bindings/rust/examples/gpioinfo.rs > new file mode 100644 > index 000000000000..bd30d9096ce8 > --- /dev/null > +++ b/bindings/rust/examples/gpioinfo.rs > @@ -0,0 +1,89 @@ > +// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause > +// > +// Copyright 2022 Linaro Ltd. All Rights Reserved. > +// Viresh Kumar <viresh.kumar@xxxxxxxxxx> > +// > +// Simplified Rust implementation of gpioinfo tool. > + > +use std::env; > +use std::fs; > +use std::path::Path; > + > +use libgpiod::{gpiod_is_gpiochip_device, Chip, Direction}; > + > +fn line_info(chip: &Chip, offset: u32) { > + let info = chip.line_info(offset).unwrap(); > + let off = info.get_offset(); > + > + let name = match info.get_name() { > + Ok(name) => name, > + _ => "unused", > + }; > + > + let consumer = match info.get_consumer() { > + Ok(name) => name, > + _ => "unnamed", > + }; > + > + let low = if info.is_active_low() { > + "active-low" > + } else { > + "active-high" > + }; > + > + let dir = match info.get_direction().unwrap() { > + Direction::AsIs => "None", > + Direction::Input => "Input", > + Direction::Output => "Output", > + }; > + > + println!( > + "\tline {:>3}\ > + \t{:>10}\ > + \t{:>10}\ > + \t{:>6}\ > + \t{:>14}", > + off, name, consumer, dir, low > + ); > +} > + > +fn chip_info(path: &str) { > + if gpiod_is_gpiochip_device(path) { > + let chip = Chip::open(path).unwrap(); > + let ngpio = chip.get_num_lines(); > + > + println!("GPIO Chip name: {}", chip.get_name().unwrap()); > + println!("\tlabel: {}", chip.get_label().unwrap()); > + println!("\tpath: {}", chip.get_path().unwrap()); > + println!("\tngpio: {}\n", ngpio); > + > + println!("\tLine information:"); > + > + for offset in 0..ngpio { > + line_info(&chip, offset); > + } > + println!("\n"); > + } > +} > + > +fn main() { > + let args: Vec<String> = env::args().collect(); > + if args.len() > 2 { > + println!("Usage: {}", args[0]); > + return; > + } > + > + if args.len() == 1 { > + for entry in fs::read_dir(Path::new("/dev")).unwrap() { > + let pathbuf = entry.unwrap().path(); > + let path = pathbuf.to_str().unwrap(); > + > + chip_info(path); > + } > + } else { > + let index = args[1].parse::<u32>().unwrap(); > + let path = format!("/dev/gpiochip{}", index); > + > + chip_info(&path); > + } > +} > diff --git a/bindings/rust/examples/gpiomon.rs b/bindings/rust/examples/gpiomon.rs > new file mode 100644 > index 000000000000..872907b386f3 > --- /dev/null > +++ b/bindings/rust/examples/gpiomon.rs > @@ -0,0 +1,68 @@ > +// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause > +// > +// Copyright 2022 Linaro Ltd. All Rights Reserved. > +// Viresh Kumar <viresh.kumar@xxxxxxxxxx> > +// > +// Simplified Rust implementation of the gpiomon tool. > + > +use std::env; > +use std::time::Duration; > + > +use libgpiod::{Chip, Edge, EdgeEventBuffer, Error, LineConfig, LineEdgeEvent, RequestConfig}; > + > +fn usage(name: &str) { > + println!("Usage: {} <chip> <offset0> ...", name); > +} > + > +fn main() { > + let args: Vec<String> = env::args().collect(); > + if args.len() < 3 { > + usage(&args[0]); > + return; > + } > + > + let mut config = LineConfig::new().unwrap(); > + let mut offsets = Vec::<u32>::new(); > + > + for arg in &args[2..] { > + let offset = arg.parse::<u32>().unwrap(); > + > + offsets.push(offset); > + } > + > + config.set_edge_detection_default(Edge::Both); > + > + let path = format!("/dev/gpiochip{}", args[1]); > + let chip = Chip::open(&path).unwrap(); > + > + let rconfig = RequestConfig::new().unwrap(); > + rconfig.set_offsets(&offsets); > + > + let buffer = EdgeEventBuffer::new(1).unwrap(); > + let request = chip.request_lines(&rconfig, &config).unwrap(); > + > + loop { > + match request.wait_edge_event(Duration::new(1, 0)) { > + Err(Error::OperationTimedOut) => continue, timeout/continue required as you can't (currently) block indefinitely? > + Err(x) => { > + println!("{:?}", x); > + return; > + } > + Ok(()) => (), > + } > + > + let count = request.read_edge_event(&buffer, 1).unwrap(); > + if count == 1 { > + let event = buffer.get_event(0).unwrap(); > + println!( > + "line: {} type: {}, time: {:?}", > + event.get_line_offset(), > + match event.get_event_type().unwrap() { > + LineEdgeEvent::Rising => "Rising", > + LineEdgeEvent::Falling => "Falling", > + }, > + event.get_timestamp() > + ); > + } > + } > +} > diff --git a/bindings/rust/examples/gpioset.rs b/bindings/rust/examples/gpioset.rs > new file mode 100644 > index 000000000000..ef70e8edbaae > --- /dev/null > +++ b/bindings/rust/examples/gpioset.rs > @@ -0,0 +1,52 @@ > +// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause > +// > +// Copyright 2022 Linaro Ltd. All Rights Reserved. > +// Viresh Kumar <viresh.kumar@xxxxxxxxxx> > +// > +// Simplified Rust implementation of the gpioset tool. > + > +use std::env; > + > +use libgpiod::{Chip, Direction, LineConfig, RequestConfig}; > + > +fn usage(name: &str) { > + println!("Usage: {} <chip> <line_offset0>=<value0> ...", name); > +} > + > +fn main() { > + let args: Vec<String> = env::args().collect(); > + if args.len() < 3 { > + usage(&args[0]); > + return; > + } > + > + let mut config = LineConfig::new().unwrap(); > + let mut offsets = Vec::<u32>::new(); > + let mut values = Vec::<i32>::new(); > + > + for arg in &args[2..] { > + let pair: Vec<&str> = arg.split('=').collect(); > + if pair.len() != 2 { > + usage(&args[0]); > + return; > + } > + > + let offset = pair[0].parse::<u32>().unwrap(); > + let value = pair[1].parse::<u32>().unwrap(); > + > + offsets.push(offset); > + values.push(value as i32); > + } > + > + config.set_direction_default(Direction::Output); > + config.set_output_values(&offsets, &values).unwrap(); > + > + let path = format!("/dev/gpiochip{}", args[1]); > + let chip = Chip::open(&path).unwrap(); > + > + let rconfig = RequestConfig::new().unwrap(); > + rconfig.set_consumer(&args[0]); > + rconfig.set_offsets(&offsets); > + > + chip.request_lines(&rconfig, &config).unwrap(); Wait rather than exiting immediately? > +} > -- > 2.31.1.272.g89b43f80a514 > And, as mentioned elsewhere, add a gpiowatch example. Cheers, Kent.