Skip to content

Can't seem to be able to read data on Windows #29

@jessebraham

Description

@jessebraham

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    migratedThis issue was migrated from GitLabwindowsThis issue is specific to Windows systems

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions