diff --git a/src/lib.rs b/src/lib.rs index f8379ce..42580fe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -81,6 +81,14 @@ pub struct SerialStream { pipe: NamedPipe, } +#[cfg(unix)] +fn map_nix_error(e: nix::Error) -> crate::Error { + crate::Error { + kind: crate::ErrorKind::Io(StdIoErrorKind::Other), + description: e.to_string(), + } +} + impl SerialStream { /// Open a nonblocking serial port from the provided builder /// @@ -525,11 +533,21 @@ impl TryFrom for SerialStream { type Error = crate::Error; #[cfg(unix)] fn try_from(port: NativeBlockingSerialPort) -> std::result::Result { - // Set the O_NONBLOCK flag. log::debug!( - "setting O_NONBLOCK for {}", + "switching {} to asynchronous mode", port.name().unwrap_or_else(|| String::from("")) ); + log::debug!("setting VMIN = 1"); + use nix::sys::termios::{self, SetArg, SpecialCharacterIndices}; + let port_fd = unsafe { BorrowedFd::borrow_raw(port.as_raw_fd()) }; + let mut t = termios::tcgetattr(port_fd).map_err(map_nix_error)?; + + // Set VMIN = 1 to block until at least one character is received. + t.control_chars[SpecialCharacterIndices::VMIN as usize] = 1; + termios::tcsetattr(port_fd, SetArg::TCSANOW, &t).map_err(map_nix_error)?; + + // Set the O_NONBLOCK flag. + log::debug!("setting O_NONBLOCK flag"); let flags = unsafe { libc::fcntl(port.as_raw_fd(), libc::F_GETFL) }; if flags < 0 { return Err(StdIoError::last_os_error().into());