1 //
2 // Provides a way to test clearing and querying the size of the serial output buffer.
3 //
4 // USAGE:
5 //
6 // 1. Connect a serial device to your host computer. E.g. an Arduino could be used. It will be able
7 // to receive data without any specific sketch loaded.
8 // 2. Run this example
9 // 3. Observe the output - it reports how many bytes are waiting to be sent to the connected device
10 // 4. Press the Return key to make the example clear the output buffer. You should see the number
11 // of bytes queued to send momentarily drop to 0
12 // 5. Try passing different values for the buffer-size argument to see how that affects the speed
13 // and saturation point of the output buffer
14 // 6. Press Ctrl+D (Unix) or Ctrl+Z (Win) to quit
15 //
16
17 use std::error::Error;
18 use std::io::{self, Read};
19 use std::panic::panic_any;
20 use std::sync::mpsc;
21 use std::thread;
22 use std::time::Duration;
23
24 use clap::{Arg, ArgMatches, Command};
25
26 use serialport::ClearBuffer;
27
28 const DEFAULT_BLOCK_SIZE: &str = "128";
29
main()30 fn main() {
31 let block_size_help = format!(
32 "The size in bytes of the block of data to write to the port (default: {} bytes)",
33 DEFAULT_BLOCK_SIZE
34 );
35
36 let matches = Command::new("Serialport Example - Clear Output Buffer")
37 .about("Reports how many bytes are waiting to be read and allows the user to clear the output buffer")
38 .disable_version_flag(true)
39 .arg(Arg::new("port")
40 .help("The device path to a serial port")
41 .use_value_delimiter(false)
42 .required(true))
43 .arg(Arg::new("baud")
44 .help("The baud rate to connect at")
45 .use_value_delimiter(false)
46 .required(true))
47 .arg(Arg::new("block-size")
48 .help(Some(block_size_help.as_str()))
49 .use_value_delimiter(false)
50 .default_value(DEFAULT_BLOCK_SIZE))
51 .get_matches();
52
53 let port_name = matches.value_of("port").unwrap();
54 let baud_rate = matches.value_of("baud").unwrap();
55 let block_size = ArgMatches::value_of_t(&matches, "block-size").unwrap_or_else(|e| e.exit());
56
57 let exit_code = match run(port_name, baud_rate, block_size) {
58 Ok(_) => 0,
59 Err(e) => {
60 println!("Error: {}", e);
61 1
62 }
63 };
64
65 std::process::exit(exit_code);
66 }
67
run(port_name: &str, baud_rate: &str, block_size: usize) -> Result<(), Box<dyn Error>>68 fn run(port_name: &str, baud_rate: &str, block_size: usize) -> Result<(), Box<dyn Error>> {
69 let rate = baud_rate
70 .parse::<u32>()
71 .map_err(|_| format!("Invalid baud rate '{}' specified", baud_rate))?;
72
73 let mut port = serialport::new(port_name, rate)
74 .timeout(Duration::from_millis(10))
75 .open()
76 .map_err(|ref e| format!("Port '{}' not available: {}", &port_name, e))?;
77
78 let chan_clear_buf = input_service();
79
80 println!("Connected to {} at {} baud", &port_name, &baud_rate);
81 println!("Ctrl+D (Unix) or Ctrl+Z (Win) to stop. Press Return to clear the buffer.");
82
83 let block = vec![0; block_size];
84
85 // This loop writes the block repeatedly, as fast as possible, to try to saturate the
86 // output buffer. If you don't see much data queued to send, try changing the block size.
87 loop {
88 match port.write_all(&block) {
89 Ok(_) => (),
90 Err(ref e) if e.kind() == io::ErrorKind::TimedOut => (),
91 Err(e) => panic!("Error while writing data to the port: {}", e),
92 };
93
94 match chan_clear_buf.try_recv() {
95 Ok(_) => {
96 println!("------------------------- Discarding buffer ------------------------- ");
97 port.clear(ClearBuffer::Output)
98 .expect("Failed to discard output buffer")
99 }
100 Err(mpsc::TryRecvError::Empty) => (),
101 Err(mpsc::TryRecvError::Disconnected) => {
102 println!("Stopping.");
103 break;
104 }
105 }
106
107 println!(
108 "Bytes queued to send: {}",
109 port.bytes_to_write().expect("Error calling bytes_to_write")
110 );
111 }
112
113 Ok(())
114 }
115
input_service() -> mpsc::Receiver<()>116 fn input_service() -> mpsc::Receiver<()> {
117 let (tx, rx) = mpsc::channel();
118
119 thread::spawn(move || {
120 let mut buffer = [0; 32];
121 loop {
122 // Block awaiting any user input
123 match io::stdin().read(&mut buffer) {
124 Ok(0) => {
125 drop(tx); // EOF, drop the channel and stop the thread
126 break;
127 }
128 Ok(_bytes_read) => tx.send(()).unwrap(), // Signal main to clear the buffer
129 Err(e) => panic_any(e),
130 }
131 }
132 });
133
134 rx
135 }
136