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

Added blocking support for posix #50

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
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
27 changes: 24 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Duration>,
}

impl SerialPortBuilder {
Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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.
Expand All @@ -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<()>;

Expand Down Expand Up @@ -538,6 +551,10 @@ impl<T: SerialPort> SerialPort for &mut T {
(**self).stop_bits()
}

fn blocking(&self) -> bool {
(**self).blocking()
}

fn timeout(&self) -> Duration {
(**self).timeout()
}
Expand Down Expand Up @@ -613,6 +630,10 @@ impl<T: SerialPort> 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`
Expand Down Expand Up @@ -670,7 +691,7 @@ pub fn new<'a>(path: impl Into<std::borrow::Cow<'a, str>>, baud_rate: u32) -> Se
flow_control: FlowControl::None,
parity: Parity::None,
stop_bits: StopBits::One,
timeout: Duration::from_millis(0),
timeout: None,
}
}

Expand Down
17 changes: 10 additions & 7 deletions src/posix/poll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Duration>) -> 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<Duration>) -> 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<Duration>) -> 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,
Expand Down
24 changes: 18 additions & 6 deletions src/posix/tty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ fn close(fd: RawFd) {
#[derive(Debug)]
pub struct TTYPort {
fd: RawFd,
timeout: Duration,
timeout: Option<Duration>,
exclusive: bool,
port_name: Option<String>,
#[cfg(any(target_os = "ios", target_os = "macos"))]
Expand Down Expand Up @@ -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"))]
Expand All @@ -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"))]
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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(())
}

Expand Down