1 //
2 // Provides a way to test clearing and querying the size of the serial input buffer.
3 //
4 // USAGE:
5 //
6 // 1. Connect a serial device to your host computer. E.g. an Arduino loaded with the example sketch
7 // given below
8 // 2. Run this example
9 // 3. Observe the output - it reports how many bytes have been received from the device and are
10 // waiting to be read
11 // 4. Press the Return key to make the example clear the input buffer. You should see the number of
12 // bytes queued to read momentarily drop to 0
13 // 5. Press Ctrl+D (Unix) or Ctrl+Z (Win) to quit
14 //
15 // The following Arduino firmware could be used to generate input:
16 //
17 // ```
18 // #include <Arduino.h>
19 //
20 // void setup() {
21 // Serial.begin(9600);
22 // while (!Serial); // wait for serial port to connect. Needed for native USB
23 // }
24 //
25 // int iter = 0;
26 //
27 // void loop() {
28 // Serial.print(iter);
29 // if (++iter == 10) {
30 // Serial.println();
31 // iter = 0;
32 // }
33 // delay(1000 / 20);
34 // }
35 // ```
36
37 use std::error::Error;
38 use std::io::{self, Read};
39 use std::panic::panic_any;
40 use std::sync::mpsc;
41 use std::thread;
42 use std::time::Duration;
43
44 use clap::{Arg, Command};
45
46 use serialport::ClearBuffer;
47
main()48 fn main() {
49 let matches = Command::new("Serialport Example - Clear Input Buffer")
50 .about("Reports how many bytes are waiting to be read and allows the user to clear the input buffer")
51 .disable_version_flag(true)
52 .arg(Arg::new("port")
53 .help("The device path to a serial port")
54 .use_value_delimiter(false)
55 .required(true))
56 .arg(Arg::new("baud")
57 .help("The baud rate to connect at")
58 .use_value_delimiter(false)
59 .required(true))
60 .get_matches();
61
62 let port_name = matches.value_of("port").unwrap();
63 let baud_rate = matches.value_of("baud").unwrap();
64
65 let exit_code = match run(port_name, baud_rate) {
66 Ok(_) => 0,
67 Err(e) => {
68 println!("Error: {}", e);
69 1
70 }
71 };
72
73 std::process::exit(exit_code);
74 }
75
run(port_name: &str, baud_rate: &str) -> Result<(), Box<dyn Error>>76 fn run(port_name: &str, baud_rate: &str) -> Result<(), Box<dyn Error>> {
77 let rate = baud_rate
78 .parse::<u32>()
79 .map_err(|_| format!("Invalid baud rate '{}' specified", baud_rate))?;
80
81 let port = serialport::new(port_name, rate)
82 .timeout(Duration::from_millis(10))
83 .open()
84 .map_err(|ref e| format!("Port '{}' not available: {}", &port_name, e))?;
85
86 let chan_clear_buf = input_service();
87
88 println!("Connected to {} at {} baud", &port_name, &baud_rate);
89 println!("Ctrl+D (Unix) or Ctrl+Z (Win) to stop. Press Return to clear the buffer.");
90
91 loop {
92 println!(
93 "Bytes available to read: {}",
94 port.bytes_to_read().expect("Error calling bytes_to_read")
95 );
96
97 match chan_clear_buf.try_recv() {
98 Ok(_) => {
99 println!("------------------------- Discarding buffer ------------------------- ");
100 port.clear(ClearBuffer::Input)
101 .expect("Failed to discard input buffer")
102 }
103 Err(mpsc::TryRecvError::Empty) => (),
104 Err(mpsc::TryRecvError::Disconnected) => {
105 println!("Stopping.");
106 break;
107 }
108 }
109
110 thread::sleep(Duration::from_millis(100));
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