Skip to content

Commit

Permalink
Add example application to experiment with the drivers
Browse files Browse the repository at this point in the history
  • Loading branch information
Notgnoshi committed Aug 8, 2023
1 parent 5aad0de commit c005efa
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 0 deletions.
7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,10 @@ socketcan = { version = "2.0.0", optional = true }
[features]
default = ["socketcan"]
socketcan = ["dep:socketcan"]

[dev-dependencies]
clap = { version = "4.3.19", features = ["derive"] }
ctrlc = "3.4.0"
# TODO: Add optional tracing to the main library
tracing = "0.1.37"
tracing-subscriber = "0.3.17"
100 changes: 100 additions & 0 deletions examples/forward.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
use std::sync::mpsc::channel;

use ag_iso_stack::driver::{Driver, DriverReadError, DriverWriteError, Frame, SocketcanDriver};
use clap::Parser;

/// Forward CAN traffic from one interface to another
#[derive(Debug, Parser)]
#[clap(name = "forward", verbatim_doc_comment)]
struct Options {
/// The log level
#[clap(short, long, default_value_t = tracing::Level::DEBUG)]
pub log_level: tracing::Level,

/// The interface to read traffic from
///
/// Can be either a string interface name, or an integer interface index
#[clap(short, long, default_value_t = String::from("can0"))]
pub input_interface: String,

/// The interface to write traffic to
///
/// Can be either a string interface name, or an integer interface index
#[clap(short, long, default_value_t = String::from("can1"))]
pub output_interface: String,

/// Whether to use blocking send()/recv()s
#[clap(short, long)]
pub blocking: bool,
}

fn create_driver(iface: &str) -> impl Driver {
if let Ok(index) = iface.parse::<u32>() {
SocketcanDriver::new_by_index(index)
} else {
SocketcanDriver::new_by_name(iface)
}
}

fn read(input: &mut impl Driver, frame: &mut Frame, blocking: bool) -> Result<(), DriverReadError> {
if blocking {
input.read_blocking(frame)
} else {
input.read_nonblocking(frame)
}
}

fn write(output: &mut impl Driver, frame: &Frame, blocking: bool) -> Result<(), DriverWriteError> {
if blocking {
output.write_blocking(frame)
} else {
output.write_nonblocking(frame)
}
}

fn main() {
let opts = Options::parse();

let subscriber = tracing_subscriber::fmt()
// ... add configuration
.finish();
tracing::subscriber::set_global_default(subscriber)
.map_err(|_err| eprintln!("Unable to set global default subscriber"))
.unwrap();

tracing::info!(
"Forwarding CAN traffic from {} to {}",
opts.input_interface,
opts.output_interface
);

let mut input = create_driver(&opts.input_interface);
let mut output = create_driver(&opts.output_interface);

input.open().unwrap();
output.open().unwrap();

let (tx, rx) = channel();
ctrlc::set_handler(move || tx.send(true).unwrap()).unwrap();

loop {
if rx.try_recv().is_ok() {
break;
}

let mut frame = Frame::default();

match read(&mut input, &mut frame, opts.blocking) {
Ok(_) => {
tracing::info!("Read frame: {frame:?}");
tracing::info!("Attempting to write frame");
match write(&mut output, &frame, opts.blocking) {
Ok(_) => tracing::info!("Wrote frame: {frame:?}"),
Err(e) => tracing::info!("Failed to write frame: {e:?}"),
}
}
Err(DriverReadError::NoFrameReady) => {}
Err(e) => tracing::error!("Failed to read frame: {e:?}"),
}
}
}

0 comments on commit c005efa

Please sign in to comment.