diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 54cd566d..8022a3f5 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -52,7 +52,7 @@ jobs: disable_extra_builds: true disable_tests: true target: aarch64-apple-darwin - toolchain: "1.59.0" + toolchain: "1.69.0" msrv-arm-linux-androideabi: uses: ./.github/workflows/build.yaml @@ -60,7 +60,7 @@ jobs: disable_extra_builds: true disable_tests: true target: arm-linux-androideabi - toolchain: "1.59.0" + toolchain: "1.69.0" msrv-x86_64-unknown-freebsd: uses: ./.github/workflows/build.yaml @@ -68,7 +68,7 @@ jobs: disable_extra_builds: true disable_tests: true target: x86_64-unknown-freebsd - toolchain: "1.59.0" + toolchain: "1.69.0" msrv-x86_64-unknown-linux-gnu: uses: ./.github/workflows/build.yaml @@ -77,7 +77,7 @@ jobs: disable_tests: true extra_packages: libudev-dev target: x86_64-unknown-linux-gnu - toolchain: "1.59.0" + toolchain: "1.69.0" msrv-x86_64-unknown-linux-musl: uses: ./.github/workflows/build.yaml @@ -86,7 +86,7 @@ jobs: disable_tests: true extra_packages: gcc-aarch64-linux-gnu target: aarch64-unknown-linux-musl - toolchain: "1.59.0" + toolchain: "1.69.0" msrv-x86_64-pc-windows-msvc: uses: ./.github/workflows/build.yaml @@ -95,7 +95,7 @@ jobs: disable_tests: true runs_on: windows-2019 target: x86_64-pc-windows-msvc - toolchain: "1.59.0" + toolchain: "1.69.0" msrv-x86_64-unknown-netbsd: uses: ./.github/workflows/build.yaml @@ -103,7 +103,7 @@ jobs: disable_extra_builds: true disable_tests: true target: x86_64-unknown-netbsd - toolchain: "1.59.0" + toolchain: "1.69.0" # -------------------------------------------------------------------------- # Semantic Versioning diff --git a/Cargo.toml b/Cargo.toml index 6a8a31d3..2175f509 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ authors = [ "Jesse Braham ", ] edition = "2021" -rust-version = "1.59.0" +rust-version = "1.69.0" description = "A cross-platform low-level serial port library." documentation = "https://docs.rs/serialport" repository = "https://github.com/serialport/serialport-rs" @@ -16,7 +16,7 @@ categories = ["hardware-support"] [target."cfg(unix)".dependencies] bitflags = "2.4.0" -nix = { version = "0.26", default-features = false, features = ["fs", "ioctl", "poll", "signal", "term"] } +nix = { version = "0.30", default-features = false, features = ["fs", "ioctl", "poll", "signal", "term"] } [target.'cfg(all(target_os = "linux", not(target_env = "musl")))'.dependencies] libudev = { version = "0.3.0", optional = true } @@ -44,21 +44,10 @@ serde = { version = "1.0", features = ["derive"], optional = true } assert_hex = "0.4.1" clap = { version = "3.1.6", features = ["derive"] } envconfig = "0.10.0" -# TODES Remove pinning this subdependency (of clap) when we are bumping our -# MSRV (libc raised its MSRV with a patch release 0.2.167 from 1.19.0 to -# 1.63.0). Trick the resolver into picking a compatible release of libc by -# adding it as a direct dependency meanwhile. -libc = ">=0.2.0, <=0.2.163" -# TODO: Remove pinning this subdependency of clap when we are bumping our MSRV. -# (There has been an incompatible change with the MSRV of os_str_bytes with -# 6.6.0) Until then we are tricking the dependency resolver into using a -# compatible version by adding it as a direct dependency here. -os_str_bytes = ">=6.0, <6.6.0" quickcheck = "1.0.3" quickcheck_macros = "1.0.0" rstest = { version = "0.12.0", default-features = false } rstest_reuse = "0.6.0" -rustversion = "1.0.16" [features] default = ["libudev"] diff --git a/README.md b/README.md index 8bdaf6ce..052ac306 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ [![crates.io version badge](https://img.shields.io/crates/v/serialport.svg)](https://crates.io/crates/serialport) [![Documentation](https://docs.rs/serialport/badge.svg)](https://docs.rs/serialport) [![GitHub workflow status](https://img.shields.io/github/actions/workflow/status/serialport/serialport-rs/ci.yaml?branch=main&logo=github)](https://github.com/serialport/serialport-rs/actions) -[![Minimum Stable Rust Version](https://img.shields.io/badge/Rust-1.59.0-blue?logo=rust)](https://blog.rust-lang.org/2022/02/24/Rust-1.59.0.html) +[![Minimum Stable Rust Version](https://img.shields.io/badge/Rust-1.69.0-blue?logo=rust)](https://blog.rust-lang.org/2023/04/20/Rust-1.69.0/) # Introduction @@ -105,7 +105,7 @@ can help debug software or hardware errors. # Dependencies -Rust versions 1.59.0 and higher are supported by the library itself. There are +Rust versions 1.69.0 and higher are supported by the library itself. There are examples requiring newer versions of Rust. For GNU/Linux `pkg-config` headers are required: diff --git a/examples/loopback.rs b/examples/loopback.rs index dc519345..65f5bd35 100644 --- a/examples/loopback.rs +++ b/examples/loopback.rs @@ -193,16 +193,6 @@ fn loopback_standard<'a>( } } -#[rustversion::before(1.63)] -fn loopback_split<'a>( - _port: &mut Box, - _read_stats: &mut Stats<'a>, - _write_stats: &mut Stats<'a>, -) { - unimplemented!("requires Rust 1.63 or later"); -} - -#[rustversion::since(1.63)] fn loopback_split<'a>( port: &mut Box, read_stats: &mut Stats<'a>, diff --git a/src/lib.rs b/src/lib.rs index fbc7ab85..7e43eeed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -337,11 +337,9 @@ pub struct SerialPortBuilder { impl SerialPortBuilder { /// Set the path to the serial port - // TODO: Switch to `clone_into` when bumping our MSRV past 1.63 and remove this exemption. - #[allow(clippy::assigning_clones)] #[must_use] pub fn path<'a>(mut self, path: impl Into>) -> Self { - self.path = path.into().as_ref().to_owned(); + self.path = path.into().into_owned(); self } diff --git a/src/posix/poll.rs b/src/posix/poll.rs index 36d05cb4..6905224d 100644 --- a/src/posix/poll.rs +++ b/src/posix/poll.rs @@ -1,7 +1,7 @@ #![allow(non_camel_case_types, dead_code)] use std::io; -use std::os::unix::io::RawFd; +use std::os::fd::AsFd; use std::slice; use std::time::Duration; @@ -12,18 +12,18 @@ use nix::sys::signal::SigSet; #[cfg(any(target_os = "linux", test))] use nix::sys::time::TimeSpec; -pub fn wait_read_fd(fd: RawFd, timeout: Duration) -> io::Result<()> { - wait_fd(fd, PollFlags::POLLIN, timeout) +pub fn wait_read_fd(fd: Fd, timeout: Duration) -> io::Result<()> { + wait_fd(fd.as_fd(), PollFlags::POLLIN, timeout) } -pub fn wait_write_fd(fd: RawFd, timeout: Duration) -> io::Result<()> { - wait_fd(fd, PollFlags::POLLOUT, timeout) +pub fn wait_write_fd(fd: Fd, timeout: Duration) -> io::Result<()> { + wait_fd(fd.as_fd(), PollFlags::POLLOUT, timeout) } -fn wait_fd(fd: RawFd, events: PollFlags, timeout: Duration) -> io::Result<()> { +fn wait_fd(fd: Fd, events: PollFlags, timeout: Duration) -> io::Result<()> { use nix::errno::Errno::{EIO, EPIPE}; - let mut fd = PollFd::new(fd, events); + let mut fd = PollFd::new(fd.as_fd(), events); let wait = match poll_clamped(&mut fd, timeout) { Ok(r) => r, @@ -86,44 +86,39 @@ fn clamped_time_spec(duration: Duration) -> TimeSpec { // by `poll`. #[cfg(not(target_os = "linux"))] fn poll_clamped(fd: &mut PollFd, timeout: Duration) -> nix::Result { - let millis = clamped_millis_c_int(timeout); + let millis = clamped_duration_nix(timeout); nix::poll::poll(slice::from_mut(fd), millis) } #[cfg(any(not(target_os = "linux"), test))] -fn clamped_millis_c_int(duration: Duration) -> c_int { - let secs_limit = (c_int::MAX as u64) / 1000; - let secs = duration.as_secs(); - - if secs <= secs_limit { - secs as c_int * 1000 + duration.subsec_millis() as c_int - } else { - c_int::MAX - } +fn clamped_duration_nix(duration: Duration) -> nix::poll::PollTimeout { + nix::poll::PollTimeout::try_from(duration).unwrap_or(nix::poll::PollTimeout::MAX) } #[cfg(test)] mod tests { + use nix::poll::PollTimeout; + use super::*; use crate::tests::timeout::MONOTONIC_DURATIONS; #[test] - fn clamped_millis_c_int_is_monotonic() { - let mut last = clamped_millis_c_int(Duration::ZERO); + fn clamped_duration_nix_is_monotonic() { + let mut last = clamped_duration_nix(Duration::ZERO); for (i, d) in MONOTONIC_DURATIONS.iter().enumerate() { - let next = clamped_millis_c_int(*d); + let next = clamped_duration_nix(*d); assert!( next >= last, - "{next} >= {last} failed for {d:?} at index {i}" + "{next:?} >= {last:?} failed for {d:?} at index {i}" ); last = next; } } #[test] - fn clamped_millis_c_int_zero_is_zero() { - assert_eq!(0, clamped_millis_c_int(Duration::ZERO)); + fn clamped_duration_nix_zero_is_zero() { + assert_eq!(PollTimeout::ZERO, clamped_duration_nix(Duration::ZERO)); } #[test] diff --git a/src/posix/tty.rs b/src/posix/tty.rs index 8e6caea3..4e10b53b 100644 --- a/src/posix/tty.rs +++ b/src/posix/tty.rs @@ -1,11 +1,12 @@ +use std::io; use std::mem::MaybeUninit; +use std::os::fd::OwnedFd; use std::os::unix::prelude::*; use std::path::Path; use std::time::{Duration, Instant}; -use std::{io, mem}; use nix::fcntl::{fcntl, OFlag}; -use nix::{libc, unistd}; +use nix::libc; use crate::posix::ioctl::{self, SerialLines}; use crate::posix::termios; @@ -16,6 +17,7 @@ use crate::{ /// Convenience method for removing exclusive access from /// a fd and closing it. +#[cfg(test)] fn close(fd: RawFd) { // remove exclusive access let _ = ioctl::tiocnxcl(fd); @@ -28,7 +30,7 @@ fn close(fd: RawFd) { // // close() also should never be retried, and the error code // in most cases in purely informative - let _ = unistd::close(fd); + let _ = nix::unistd::close(fd); } /// A serial port implementation for POSIX TTY ports @@ -59,7 +61,7 @@ fn close(fd: RawFd) { /// ``` #[derive(Debug)] pub struct TTYPort { - fd: RawFd, + fd: OwnedFd, timeout: Duration, exclusive: bool, port_name: Option, @@ -76,26 +78,6 @@ pub enum BreakDuration { Arbitrary(std::num::NonZeroI32), } -/// Wrapper for RawFd to assure that it's properly closed, -/// even if the enclosing function exits early. -/// -/// This is similar to the (nightly-only) std::os::unix::io::OwnedFd. -struct OwnedFd(RawFd); - -impl Drop for OwnedFd { - fn drop(&mut self) { - close(self.0); - } -} - -impl OwnedFd { - fn into_raw(self) -> RawFd { - let fd = self.0; - mem::forget(self); - fd - } -} - impl TTYPort { /// Opens a TTY device as a serial port. /// @@ -119,19 +101,19 @@ impl TTYPort { use nix::libc::{cfmakeraw, tcgetattr, tcsetattr}; let path = Path::new(&builder.path); - let fd = OwnedFd(nix::fcntl::open( + let fd = nix::fcntl::open( path, OFlag::O_RDWR | OFlag::O_NOCTTY | OFlag::O_NONBLOCK | OFlag::O_CLOEXEC, nix::sys::stat::Mode::empty(), - )?); + )?; // Try to claim exclusive access to the port. This is performed even // if the port will later be set as non-exclusive, in order to respect // other applications that may have an exclusive port lock. - ioctl::tiocexcl(fd.0)?; + ioctl::tiocexcl(fd.as_raw_fd())?; let mut termios = MaybeUninit::uninit(); - nix::errno::Errno::result(unsafe { tcgetattr(fd.0, termios.as_mut_ptr()) })?; + nix::errno::Errno::result(unsafe { tcgetattr(fd.as_raw_fd(), termios.as_mut_ptr()) })?; let mut termios = unsafe { termios.assume_init() }; // setup TTY for binary serial port access @@ -143,11 +125,11 @@ impl TTYPort { unsafe { cfmakeraw(&mut termios) }; // write settings to TTY - unsafe { tcsetattr(fd.0, libc::TCSANOW, &termios) }; + unsafe { tcsetattr(fd.as_raw_fd(), libc::TCSANOW, &termios) }; // Read back settings from port and confirm they were applied correctly let mut actual_termios = MaybeUninit::uninit(); - unsafe { tcgetattr(fd.0, actual_termios.as_mut_ptr()) }; + unsafe { tcgetattr(fd.as_raw_fd(), actual_termios.as_mut_ptr()) }; let actual_termios = unsafe { actual_termios.assume_init() }; if actual_termios.c_iflag != termios.c_iflag @@ -163,14 +145,14 @@ impl TTYPort { #[cfg(any(target_os = "ios", target_os = "macos"))] if builder.baud_rate > 0 { - unsafe { libc::tcflush(fd.0, libc::TCIOFLUSH) }; + unsafe { libc::tcflush(fd.as_raw_fd(), libc::TCIOFLUSH) }; } // clear O_NONBLOCK flag - fcntl(fd.0, F_SETFL(nix::fcntl::OFlag::empty()))?; + fcntl(fd.as_fd(), F_SETFL(nix::fcntl::OFlag::empty()))?; // Configure the low-level port settings - let mut termios = termios::get_termios(fd.0)?; + let mut termios = termios::get_termios(fd.as_raw_fd())?; termios::set_parity(&mut termios, builder.parity); termios::set_flow_control(&mut termios, builder.flow_control); termios::set_data_bits(&mut termios, builder.data_bits); @@ -178,13 +160,13 @@ impl TTYPort { #[cfg(not(any(target_os = "ios", target_os = "macos")))] termios::set_baud_rate(&mut termios, builder.baud_rate)?; #[cfg(any(target_os = "ios", target_os = "macos"))] - termios::set_termios(fd.0, &termios, builder.baud_rate)?; + termios::set_termios(fd.as_raw_fd(), &termios, builder.baud_rate)?; #[cfg(not(any(target_os = "ios", target_os = "macos")))] - termios::set_termios(fd.0, &termios)?; + termios::set_termios(fd.as_raw_fd(), &termios)?; // Return the final port object let mut port = TTYPort { - fd: fd.into_raw(), + fd, timeout: builder.timeout, exclusive: true, port_name: Some(builder.path.clone()), @@ -222,9 +204,9 @@ impl TTYPort { /// * `Io` for any error while setting exclusivity for the port. pub fn set_exclusive(&mut self, exclusive: bool) -> Result<()> { let setting_result = if exclusive { - ioctl::tiocexcl(self.fd) + ioctl::tiocexcl(self.fd.as_raw_fd()) } else { - ioctl::tiocnxcl(self.fd) + ioctl::tiocnxcl(self.fd.as_raw_fd()) }; setting_result?; @@ -234,14 +216,14 @@ impl TTYPort { fn set_pin(&mut self, pin: ioctl::SerialLines, level: bool) -> Result<()> { if level { - ioctl::tiocmbis(self.fd, pin) + ioctl::tiocmbis(self.fd.as_raw_fd(), pin) } else { - ioctl::tiocmbic(self.fd, pin) + ioctl::tiocmbic(self.fd.as_raw_fd(), pin) } } fn read_pin(&mut self, pin: ioctl::SerialLines) -> Result { - ioctl::tiocmget(self.fd).map(|pins| pins.contains(pin)) + ioctl::tiocmget(self.fd.as_raw_fd()).map(|pins| pins.contains(pin)) } /// Create a pair of pseudo serial terminals @@ -304,17 +286,17 @@ impl TTYPort { // Set the port to a raw state. Using these ports will not work without this. let mut termios = MaybeUninit::uninit(); - let res = unsafe { crate::posix::tty::libc::tcgetattr(fd, termios.as_mut_ptr()) }; + let res = + unsafe { crate::posix::tty::libc::tcgetattr(fd.as_raw_fd(), termios.as_mut_ptr()) }; if let Err(e) = nix::errno::Errno::result(res) { - close(fd); return Err(e.into()); } let mut termios = unsafe { termios.assume_init() }; unsafe { crate::posix::tty::libc::cfmakeraw(&mut termios) }; - unsafe { crate::posix::tty::libc::tcsetattr(fd, libc::TCSANOW, &termios) }; + unsafe { crate::posix::tty::libc::tcsetattr(fd.as_raw_fd(), libc::TCSANOW, &termios) }; fcntl( - fd, + fd.as_fd(), nix::fcntl::FcntlArg::F_SETFL(nix::fcntl::OFlag::empty()), )?; @@ -331,7 +313,7 @@ impl TTYPort { // `tcgetattr()` doesn't work on Mac, Solaris, and maybe other // BSDs when used on the master port. let master_tty = TTYPort { - fd: next_pty_fd.into_raw_fd(), + fd: unsafe { OwnedFd::from_raw_fd(next_pty_fd.into_raw_fd()) }, timeout: Duration::from_millis(100), exclusive: true, port_name: None, @@ -345,8 +327,8 @@ impl TTYPort { /// Sends 0-valued bits over the port for a set duration pub fn send_break(&self, duration: BreakDuration) -> Result<()> { match duration { - BreakDuration::Short => nix::sys::termios::tcsendbreak(self.fd, 0), - BreakDuration::Arbitrary(n) => nix::sys::termios::tcsendbreak(self.fd, n.get()), + BreakDuration::Short => nix::sys::termios::tcsendbreak(self.fd.as_fd(), 0), + BreakDuration::Arbitrary(n) => nix::sys::termios::tcsendbreak(self.fd.as_fd(), n.get()), } .map_err(|e| e.into()) } @@ -366,9 +348,12 @@ impl TTYPort { /// /// This function returns an error if the serial port couldn't be cloned. pub fn try_clone_native(&self) -> Result { - let fd_cloned: i32 = fcntl(self.fd, nix::fcntl::F_DUPFD_CLOEXEC(self.fd))?; + let fd_cloned: i32 = fcntl( + self.fd.as_fd(), + nix::fcntl::F_DUPFD_CLOEXEC(self.fd.as_raw_fd()), + )?; Ok(TTYPort { - fd: fd_cloned, + fd: unsafe { OwnedFd::from_raw_fd(fd_cloned) }, exclusive: self.exclusive, port_name: self.port_name.clone(), timeout: self.timeout, @@ -378,26 +363,15 @@ impl TTYPort { } } -impl Drop for TTYPort { - fn drop(&mut self) { - close(self.fd); - } -} - impl AsRawFd for TTYPort { fn as_raw_fd(&self) -> RawFd { - self.fd + self.fd.as_raw_fd() } } impl IntoRawFd for TTYPort { fn into_raw_fd(self) -> RawFd { - // Pull just the file descriptor out. We also prevent the destructor - // from being run by calling `mem::forget`. If we didn't do this, the - // port would be closed, which would make `into_raw_fd` unusable. - let TTYPort { fd, .. } = self; - mem::forget(self); - fd + self.fd.into_raw_fd() } } @@ -415,7 +389,7 @@ fn get_termios_speed(fd: RawFd) -> u32 { impl FromRawFd for TTYPort { unsafe fn from_raw_fd(fd: RawFd) -> Self { TTYPort { - fd, + fd: unsafe { OwnedFd::from_raw_fd(fd) }, timeout: Duration::from_millis(100), exclusive: ioctl::tiocexcl(fd).is_ok(), // It is not trivial to get the file path corresponding to a file descriptor. @@ -432,27 +406,27 @@ impl FromRawFd for TTYPort { impl io::Read for TTYPort { fn read(&mut self, buf: &mut [u8]) -> io::Result { - if let Err(e) = super::poll::wait_read_fd(self.fd, self.timeout) { + if let Err(e) = super::poll::wait_read_fd(self.fd.as_fd(), self.timeout) { return Err(io::Error::from(Error::from(e))); } - nix::unistd::read(self.fd, buf).map_err(|e| io::Error::from(Error::from(e))) + nix::unistd::read(self.fd.as_fd(), buf).map_err(|e| io::Error::from(Error::from(e))) } } impl io::Write for TTYPort { fn write(&mut self, buf: &[u8]) -> io::Result { - if let Err(e) = super::poll::wait_write_fd(self.fd, self.timeout) { + if let Err(e) = super::poll::wait_write_fd(self.fd.as_fd(), self.timeout) { return Err(io::Error::from(Error::from(e))); } - nix::unistd::write(self.fd, buf).map_err(|e| io::Error::from(Error::from(e))) + nix::unistd::write(self.fd.as_fd(), buf).map_err(|e| io::Error::from(Error::from(e))) } fn flush(&mut self) -> io::Result<()> { let timeout = Instant::now() + self.timeout; loop { - return match nix::sys::termios::tcdrain(self.fd) { + return match nix::sys::termios::tcdrain(self.fd.as_fd()) { Ok(_) => Ok(()), Err(nix::errno::Errno::EINTR) => { // Retry flushing. But only up to the ports timeout for not retrying @@ -493,7 +467,7 @@ impl SerialPort for TTYPort { ) ))] fn baud_rate(&self) -> Result { - let termios2 = ioctl::tcgets2(self.fd)?; + let termios2 = ioctl::tcgets2(self.fd.as_raw_fd())?; assert!(termios2.c_ospeed == termios2.c_ispeed); @@ -511,7 +485,7 @@ impl SerialPort for TTYPort { target_os = "openbsd" ))] fn baud_rate(&self) -> Result { - let termios = termios::get_termios(self.fd)?; + let termios = termios::get_termios(self.fd.as_raw_fd())?; let ospeed = unsafe { libc::cfgetospeed(&termios) }; let ispeed = unsafe { libc::cfgetispeed(&termios) }; @@ -552,7 +526,7 @@ impl SerialPort for TTYPort { B4800, B50, B57600, B600, B75, B9600, }; - let termios = termios::get_termios(self.fd)?; + let termios = termios::get_termios(self.fd.as_raw_fd())?; let ospeed = unsafe { libc::cfgetospeed(&termios) }; let ispeed = unsafe { libc::cfgetispeed(&termios) }; @@ -596,7 +570,7 @@ impl SerialPort for TTYPort { } fn data_bits(&self) -> Result { - let termios = termios::get_termios(self.fd)?; + let termios = termios::get_termios(self.fd.as_raw_fd())?; match termios.c_cflag & libc::CSIZE { libc::CS8 => Ok(DataBits::Eight), libc::CS7 => Ok(DataBits::Seven), @@ -610,7 +584,7 @@ impl SerialPort for TTYPort { } fn flow_control(&self) -> Result { - let termios = termios::get_termios(self.fd)?; + let termios = termios::get_termios(self.fd.as_raw_fd())?; if termios.c_cflag & libc::CRTSCTS == libc::CRTSCTS { Ok(FlowControl::Hardware) } else if termios.c_iflag & (libc::IXON | libc::IXOFF) == (libc::IXON | libc::IXOFF) { @@ -621,7 +595,7 @@ impl SerialPort for TTYPort { } fn parity(&self) -> Result { - let termios = termios::get_termios(self.fd)?; + let termios = termios::get_termios(self.fd.as_raw_fd())?; if termios.c_cflag & libc::PARENB == libc::PARENB { if termios.c_cflag & libc::PARODD == libc::PARODD { Ok(Parity::Odd) @@ -634,7 +608,7 @@ impl SerialPort for TTYPort { } fn stop_bits(&self) -> Result { - let termios = termios::get_termios(self.fd)?; + let termios = termios::get_termios(self.fd.as_raw_fd())?; if termios.c_cflag & libc::CSTOPB == libc::CSTOPB { Ok(StopBits::Two) } else { @@ -655,53 +629,53 @@ impl SerialPort for TTYPort { target_os = "linux" ))] fn set_baud_rate(&mut self, baud_rate: u32) -> Result<()> { - let mut termios = termios::get_termios(self.fd)?; + let mut termios = termios::get_termios(self.fd.as_raw_fd())?; termios::set_baud_rate(&mut termios, baud_rate)?; - termios::set_termios(self.fd, &termios) + termios::set_termios(self.fd.as_raw_fd(), &termios) } // Mac OS needs special logic for setting arbitrary baud rates. #[cfg(any(target_os = "ios", target_os = "macos"))] fn set_baud_rate(&mut self, baud_rate: u32) -> Result<()> { - ioctl::iossiospeed(self.fd, &(baud_rate as libc::speed_t))?; + ioctl::iossiospeed(self.fd.as_raw_fd(), &(baud_rate as libc::speed_t))?; self.baud_rate = baud_rate; Ok(()) } fn set_flow_control(&mut self, flow_control: FlowControl) -> Result<()> { - let mut termios = termios::get_termios(self.fd)?; + let mut termios = termios::get_termios(self.fd.as_raw_fd())?; termios::set_flow_control(&mut termios, flow_control); #[cfg(any(target_os = "ios", target_os = "macos"))] - return termios::set_termios(self.fd, &termios, self.baud_rate); + return termios::set_termios(self.fd.as_raw_fd(), &termios, self.baud_rate); #[cfg(not(any(target_os = "ios", target_os = "macos")))] - return termios::set_termios(self.fd, &termios); + return termios::set_termios(self.fd.as_raw_fd(), &termios); } fn set_parity(&mut self, parity: Parity) -> Result<()> { - let mut termios = termios::get_termios(self.fd)?; + let mut termios = termios::get_termios(self.fd.as_raw_fd())?; termios::set_parity(&mut termios, parity); #[cfg(any(target_os = "ios", target_os = "macos"))] - return termios::set_termios(self.fd, &termios, self.baud_rate); + return termios::set_termios(self.fd.as_raw_fd(), &termios, self.baud_rate); #[cfg(not(any(target_os = "ios", target_os = "macos")))] - return termios::set_termios(self.fd, &termios); + return termios::set_termios(self.fd.as_raw_fd(), &termios); } fn set_data_bits(&mut self, data_bits: DataBits) -> Result<()> { - let mut termios = termios::get_termios(self.fd)?; + let mut termios = termios::get_termios(self.fd.as_raw_fd())?; termios::set_data_bits(&mut termios, data_bits); #[cfg(any(target_os = "ios", target_os = "macos"))] - return termios::set_termios(self.fd, &termios, self.baud_rate); + return termios::set_termios(self.fd.as_raw_fd(), &termios, self.baud_rate); #[cfg(not(any(target_os = "ios", target_os = "macos")))] - return termios::set_termios(self.fd, &termios); + return termios::set_termios(self.fd.as_raw_fd(), &termios); } fn set_stop_bits(&mut self, stop_bits: StopBits) -> Result<()> { - let mut termios = termios::get_termios(self.fd)?; + let mut termios = termios::get_termios(self.fd.as_raw_fd())?; termios::set_stop_bits(&mut termios, stop_bits); #[cfg(any(target_os = "ios", target_os = "macos"))] - return termios::set_termios(self.fd, &termios, self.baud_rate); + return termios::set_termios(self.fd.as_raw_fd(), &termios, self.baud_rate); #[cfg(not(any(target_os = "ios", target_os = "macos")))] - return termios::set_termios(self.fd, &termios); + return termios::set_termios(self.fd.as_raw_fd(), &termios); } fn set_timeout(&mut self, timeout: Duration) -> Result<()> { @@ -734,11 +708,11 @@ impl SerialPort for TTYPort { } fn bytes_to_read(&self) -> Result { - ioctl::fionread(self.fd) + ioctl::fionread(self.fd.as_raw_fd()) } fn bytes_to_write(&self) -> Result { - ioctl::tiocoutq(self.fd) + ioctl::tiocoutq(self.fd.as_raw_fd()) } fn clear(&self, buffer_to_clear: ClearBuffer) -> Result<()> { @@ -748,7 +722,7 @@ impl SerialPort for TTYPort { ClearBuffer::All => libc::TCIOFLUSH, }; - let res = unsafe { nix::libc::tcflush(self.fd, buffer_id) }; + let res = unsafe { nix::libc::tcflush(self.fd.as_raw_fd(), buffer_id) }; nix::errno::Errno::result(res) .map(|_| ()) @@ -763,11 +737,11 @@ impl SerialPort for TTYPort { } fn set_break(&self) -> Result<()> { - ioctl::tiocsbrk(self.fd) + ioctl::tiocsbrk(self.fd.as_raw_fd()) } fn clear_break(&self) -> Result<()> { - ioctl::tioccbrk(self.fd) + ioctl::tioccbrk(self.fd.as_raw_fd()) } }