• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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