Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement usbser.sys workaround on Windows #154

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/windows/com.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ pub struct COMPort {
handle: HANDLE,
timeout: Duration,
port_name: Option<String>,
// keeps track of DTR state so we can re-send DTR on RTS change to work
// around USB Serial driver misbehaviour
dtr: bool,
}

unsafe impl Send for COMPort {}
Expand Down Expand Up @@ -122,6 +125,7 @@ impl COMPort {
handle: cloned_handle,
port_name: self.port_name.clone(),
timeout: self.timeout,
dtr: self.dtr,
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This clones the dtr state when a COMPort is cloned, which might not always be the right behaviour.

Another option could be to remove the dtr field from this struct, and instead call DeviceIoControl with IOCTL_SERIAL_GET_DTRRTS in write_request_to_send to find the current state of the DTR pin, as described in this Stack Overflow answer. It's another potentially fallible syscall though, so I just went with this approach for now. Happy to make this change if desired however

})
} else {
Err(super::error::last_os_error())
Expand Down Expand Up @@ -152,6 +156,7 @@ impl COMPort {
handle: handle as HANDLE,
timeout: Duration::from_millis(100),
port_name: None,
dtr: false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would do the call to DeviceIoControl here since we cannot assume the state. But if the call fails (which I would consider unlikely), the most sane option is to just panic as it means that the handle from FFI did something weird.

}
}
}
Expand Down Expand Up @@ -260,13 +265,17 @@ impl SerialPort for COMPort {

fn write_request_to_send(&mut self, level: bool) -> Result<()> {
if level {
self.escape_comm_function(SETRTS)
self.escape_comm_function(SETRTS)?;
} else {
self.escape_comm_function(CLRRTS)
self.escape_comm_function(CLRRTS)?;
}

self.write_data_terminal_ready(self.dtr)
}

fn write_data_terminal_ready(&mut self, level: bool) -> Result<()> {
self.dtr = level;

if level {
self.escape_comm_function(SETDTR)
} else {
Expand Down
Loading