diff --git a/src/lib.rs b/src/lib.rs index fbad1b58..c634d5e7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -217,7 +217,7 @@ pub struct SerialPortBuilder { /// Number of bits to use to signal the end of a character stop_bits: StopBits, /// Amount of time to wait to receive data before timing out - timeout: Duration, + timeout: Option, } impl SerialPortBuilder { @@ -266,7 +266,14 @@ impl SerialPortBuilder { /// Set the amount of time to wait to receive data before timing out #[must_use] pub fn timeout(mut self, timeout: Duration) -> Self { - self.timeout = timeout; + self.timeout = Some(timeout); + self + } + + /// Makes the recive blocking + #[must_use] + pub fn blocking(mut self) -> Self { + self.timeout = None; self } @@ -352,6 +359,9 @@ pub trait SerialPort: Send + io::Read + io::Write { /// Returns the current timeout. fn timeout(&self) -> Duration; + /// Returns whether the read is blocking + fn blocking(&self) -> bool; + // Port settings setters /// Sets the baud rate. @@ -375,6 +385,9 @@ pub trait SerialPort: Send + io::Read + io::Write { /// Sets the number of stop bits. fn set_stop_bits(&mut self, stop_bits: StopBits) -> Result<()>; + /// Sets whether the recive will be blocking + fn set_blocking(&mut self, value: bool) -> Result<()>; + /// Sets the timeout for future I/O operations. fn set_timeout(&mut self, timeout: Duration) -> Result<()>; @@ -538,6 +551,10 @@ impl SerialPort for &mut T { (**self).stop_bits() } + fn blocking(&self) -> bool { + (**self).blocking() + } + fn timeout(&self) -> Duration { (**self).timeout() } @@ -613,6 +630,10 @@ impl SerialPort for &mut T { fn clear_break(&self) -> Result<()> { (**self).clear_break() } + + fn set_blocking(&mut self, value: bool) -> Result<()> { + (**self).set_blocking(value) + } } /// Contains all possible USB information about a `SerialPort` @@ -670,7 +691,7 @@ pub fn new<'a>(path: impl Into>, baud_rate: u32) -> Se flow_control: FlowControl::None, parity: Parity::None, stop_bits: StopBits::One, - timeout: Duration::from_millis(0), + timeout: None, } } diff --git a/src/posix/poll.rs b/src/posix/poll.rs index f10d5b69..1743a252 100644 --- a/src/posix/poll.rs +++ b/src/posix/poll.rs @@ -11,28 +11,31 @@ use nix::sys::signal::SigSet; #[cfg(target_os = "linux")] use nix::sys::time::{TimeSpec, TimeValLike}; -pub fn wait_read_fd(fd: RawFd, timeout: Duration) -> io::Result<()> { +pub fn wait_read_fd(fd: RawFd, timeout: Option) -> io::Result<()> { wait_fd(fd, PollFlags::POLLIN, timeout) } -pub fn wait_write_fd(fd: RawFd, timeout: Duration) -> io::Result<()> { +pub fn wait_write_fd(fd: RawFd, timeout: Option) -> io::Result<()> { wait_fd(fd, PollFlags::POLLOUT, timeout) } -fn wait_fd(fd: RawFd, events: PollFlags, timeout: Duration) -> io::Result<()> { +fn wait_fd(fd: RawFd, events: PollFlags, timeout: Option) -> io::Result<()> { use nix::errno::Errno::{EIO, EPIPE}; let mut fd = PollFd::new(fd, events); let milliseconds = - timeout.as_secs() as i64 * 1000 + i64::from(timeout.subsec_nanos()) / 1_000_000; + timeout.map(|t| t.as_secs() as i64 * 1000 + i64::from(t.subsec_nanos()) / 1_000_000); #[cfg(target_os = "linux")] let wait_res = { - let timespec = TimeSpec::milliseconds(milliseconds); - nix::poll::ppoll(slice::from_mut(&mut fd), Some(timespec), SigSet::empty()) + let timespec = milliseconds.map(TimeSpec::milliseconds); + nix::poll::ppoll(slice::from_mut(&mut fd), timespec, SigSet::empty()) }; #[cfg(not(target_os = "linux"))] - let wait_res = nix::poll::poll(slice::from_mut(&mut fd), milliseconds as nix::libc::c_int); + let wait_res = { + let milliseconds = milliseconds.unwrap_or(-1) as nix::libc::c_int; + nix::poll::poll(slice::from_mut(&mut fd), milliseconds) + }; let wait = match wait_res { Ok(r) => r, diff --git a/src/posix/tty.rs b/src/posix/tty.rs index 00a4863d..56b789dc 100644 --- a/src/posix/tty.rs +++ b/src/posix/tty.rs @@ -40,7 +40,7 @@ fn close(fd: RawFd) { #[derive(Debug)] pub struct TTYPort { fd: RawFd, - timeout: Duration, + timeout: Option, exclusive: bool, port_name: Option, #[cfg(any(target_os = "ios", target_os = "macos"))] @@ -281,7 +281,7 @@ impl TTYPort { let slave_tty = TTYPort { fd, - timeout: Duration::from_millis(100), + timeout: Some(Duration::from_millis(100)), exclusive: true, port_name: Some(ptty_name), #[cfg(any(target_os = "ios", target_os = "macos"))] @@ -293,7 +293,7 @@ impl TTYPort { // BSDs when used on the master port. let master_tty = TTYPort { fd: next_pty_fd.into_raw_fd(), - timeout: Duration::from_millis(100), + timeout: Some(Duration::from_millis(100)), exclusive: true, port_name: None, #[cfg(any(target_os = "ios", target_os = "macos"))] @@ -377,7 +377,7 @@ impl FromRawFd for TTYPort { unsafe fn from_raw_fd(fd: RawFd) -> Self { TTYPort { fd, - timeout: Duration::from_millis(100), + timeout: Some(Duration::from_millis(100)), exclusive: ioctl::tiocexcl(fd).is_ok(), // It is not trivial to get the file path corresponding to a file descriptor. // We'll punt on it and set it to `None` here. @@ -587,7 +587,11 @@ impl SerialPort for TTYPort { } fn timeout(&self) -> Duration { - self.timeout + self.timeout.unwrap_or(Duration::from_secs(0)) + } + + fn blocking(&self) -> bool { + self.timeout.is_none() } #[cfg(any( @@ -648,8 +652,16 @@ impl SerialPort for TTYPort { return termios::set_termios(self.fd, &termios); } + fn set_blocking(&mut self, value: bool) -> Result<()> { + self.timeout = match value { + true => Some(Duration::from_secs(0)), + false => None, + }; + Ok(()) + } + fn set_timeout(&mut self, timeout: Duration) -> Result<()> { - self.timeout = timeout; + self.timeout = Some(timeout); Ok(()) }