-
Notifications
You must be signed in to change notification settings - Fork 148
Description
This issue was migrated from GitLab. The original issue can be found here:
https://gitlab.com/susurrus/serialport-rs/-/issues/113
This code works on Linux, and I think it used to work on Windows as well, if I remember correctly, I might have used a different version of the crate. But it does not work with 4.0.1.
The code:
use std::thread;
use serialport::{available_ports, SerialPortType};
use std::time::Duration;
fn main() {
let mut buf = [0u8; 256];
'retry: loop {
let ports = available_ports().unwrap_or_default();
let ports: Vec<_> = ports
.iter()
.filter(|p| match &p.port_type {
SerialPortType::UsbPort(info) => info.vid == 0x1209 || info.pid == 0x6969,
_ => false,
})
.collect();
// we haven't found any ports, wait a bit, and try again
if ports.len() == 0 {
println!("no ports found, retrying");
thread::sleep(Duration::from_millis(1000));
continue;
}
let port_info = ports[0];
let found_port = serialport::new(&port_info.port_name.to_owned(), 115200)
.timeout(Duration::from_millis(5000))
.open();
let mut found_port = match found_port {
Ok(port) => port,
Err(err) => {
println!("error opening port: {}, retrying", err);
thread::sleep(Duration::from_millis(1000));
continue;
}
};
println!("opened {}", port_info.port_name);
loop {
// we should always have a port at this time
let n = match found_port.read(&mut buf[..]) {
Ok(n) => n,
Err(err) => {
println!("error while reading: {}, reconnecting", err);
//if err.kind() == io::ErrorKind::TimedOut {
// continue;
//}
thread::sleep(Duration::from_millis(1000));
continue 'retry;
}
};
println!("got {} bytes of data", n);
}
}
}
In case the timeout is enabled, the read always times out, even though data is sent several times a second. If timeout is disabled, read hangs indefinitely.
Using a buffer of 1byte didn't seem to solve the issue either.
Using other applications for reading the serial port works just fine.
Edit in case it might matter:
This code is cross-compiled from linux. It's receiving binary data from an usb dongle with firmware also written in rust, using https://github.com/mvirkkunen/usbd-serial which emulates a CDC-ACM device. The serial settings are correct, as previously mentioned, reading works on both linux with this exact same code, and in windows using other programs.
I've also tested both https://github.com/jacobsa/go-serial and https://github.com/tarm/serial, both work just fine in Windows when cross-compiled. Here's the code I've used to test:
package main
import (
"io"
"log"
"github.com/jacobsa/go-serial/serial"
)
func main() {
s, err := serial.Open(serial.OpenOptions{
PortName: "COM3",
BaudRate: 115200,
DataBits: 8,
StopBits: 1,
ParityMode: serial.PARITY_NONE,
InterCharacterTimeout: 500,
MinimumReadSize: 5000, // timeout?
})
if err != nil {
panic(err)
}
log.Println("opened port")
for {
n, err := io.CopyN(io.Discard, s, 256)
log.Println(n, err)
}
}
I get a continuous stream of 256bytes logs, no timeouts, because the device keeps sending data.