From d941df5e63241577e4c0fa9c4d822c1dbb1b7787 Mon Sep 17 00:00:00 2001 From: Ygor Souza Date: Wed, 15 May 2024 19:43:49 +0200 Subject: [PATCH] Add Mark and Space variants to Parity enum --- src/lib.rs | 12 +++++++++++ src/posix/termios.rs | 48 +++++++++++++++++++++++++++++++++++++++++++- src/posix/tty.rs | 4 ++-- src/windows/com.rs | 2 ++ src/windows/dcb.rs | 2 ++ 5 files changed, 65 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 79d0f377..b465c394 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -208,6 +208,16 @@ pub enum Parity { /// Parity bit sets even number of 1 bits. Even, + + /// Parity bit is set to 1. + /// + /// Only supported on Windows and Linux. + Mark, + + /// Parity bit is set to 0. + /// + /// Only supported on Windows and Linux. + Space, } impl fmt::Display for Parity { @@ -216,6 +226,8 @@ impl fmt::Display for Parity { Parity::None => write!(f, "None"), Parity::Odd => write!(f, "Odd"), Parity::Even => write!(f, "Even"), + Parity::Mark => write!(f, "Mark"), + Parity::Space => write!(f, "Space"), } } } diff --git a/src/posix/termios.rs b/src/posix/termios.rs index cc5671ea..b9aa4dfe 100644 --- a/src/posix/termios.rs +++ b/src/posix/termios.rs @@ -145,25 +145,71 @@ pub(crate) fn set_termios(fd: RawFd, termios: &Termios) -> Result<()> { crate::posix::ioctl::tcsets2(fd, termios) } -pub(crate) fn set_parity(termios: &mut Termios, parity: Parity) { +// The Result return will seem pointless on platforms that support all parity variants, but we need +// it for the others. +#[allow(clippy::unnecessary_wraps)] +pub(crate) fn set_parity(termios: &mut Termios, parity: Parity) -> Result<()> { match parity { Parity::None => { termios.c_cflag &= !(libc::PARENB | libc::PARODD); termios.c_iflag &= !libc::INPCK; termios.c_iflag |= libc::IGNPAR; + #[cfg(any(target_os = "linux", target_os = "android"))] + { + termios.c_iflag &= !libc::CMSPAR; + } } Parity::Odd => { termios.c_cflag |= libc::PARENB | libc::PARODD; termios.c_iflag |= libc::INPCK; termios.c_iflag &= !libc::IGNPAR; + #[cfg(any(target_os = "linux", target_os = "android"))] + { + termios.c_iflag &= !libc::CMSPAR; + } } Parity::Even => { termios.c_cflag &= !libc::PARODD; termios.c_cflag |= libc::PARENB; termios.c_iflag |= libc::INPCK; termios.c_iflag &= !libc::IGNPAR; + #[cfg(any(target_os = "linux", target_os = "android"))] + { + termios.c_iflag &= !libc::CMSPAR; + } + } + #[cfg(any(target_os = "linux", target_os = "android"))] + Parity::Mark => { + termios.c_cflag |= libc::PARODD; + termios.c_cflag |= libc::PARENB; + termios.c_iflag |= libc::INPCK; + termios.c_iflag &= !libc::IGNPAR; + termios.c_iflag |= libc::CMSPAR; + } + #[cfg(any(target_os = "linux", target_os = "android"))] + Parity::Space => { + termios.c_cflag &= !libc::PARODD; + termios.c_cflag |= libc::PARENB; + termios.c_iflag |= libc::INPCK; + termios.c_iflag &= !libc::IGNPAR; + termios.c_iflag |= libc::CMSPAR; + } + #[cfg(not(any(target_os = "linux", target_os = "android")))] + Parity::Mark => { + return Err(crate::Error::new( + crate::ErrorKind::InvalidInput, + "Mark parity not supported on this platform", + )); + } + #[cfg(not(any(target_os = "linux", target_os = "android")))] + Parity::Space => { + return Err(crate::Error::new( + crate::ErrorKind::InvalidInput, + "Space parity not supported on this platform", + )); } }; + Ok(()) } pub(crate) fn set_flow_control(termios: &mut Termios, flow_control: FlowControl) { diff --git a/src/posix/tty.rs b/src/posix/tty.rs index fe7e8499..42e2f77a 100644 --- a/src/posix/tty.rs +++ b/src/posix/tty.rs @@ -171,7 +171,7 @@ impl TTYPort { // Configure the low-level port settings let mut termios = termios::get_termios(fd.0)?; - termios::set_parity(&mut termios, builder.parity); + 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); termios::set_stop_bits(&mut termios, builder.stop_bits); @@ -653,7 +653,7 @@ impl SerialPort for TTYPort { fn set_parity(&mut self, parity: Parity) -> Result<()> { let mut termios = termios::get_termios(self.fd)?; - termios::set_parity(&mut termios, parity); + termios::set_parity(&mut termios, parity)?; #[cfg(any(target_os = "ios", target_os = "macos"))] return termios::set_termios(self.fd, &termios, self.baud_rate); #[cfg(not(any(target_os = "ios", target_os = "macos")))] diff --git a/src/windows/com.rs b/src/windows/com.rs index fa1abbca..3785c0f9 100644 --- a/src/windows/com.rs +++ b/src/windows/com.rs @@ -334,6 +334,8 @@ impl SerialPort for COMPort { match dcb.Parity { ODDPARITY => Ok(Parity::Odd), EVENPARITY => Ok(Parity::Even), + MARKPARITY => Ok(Parity::Mark), + SPACEPARITY => Ok(Parity::Space), NOPARITY => Ok(Parity::None), _ => Err(Error::new( ErrorKind::Unknown, diff --git a/src/windows/dcb.rs b/src/windows/dcb.rs index d0207fd6..66f0221d 100644 --- a/src/windows/dcb.rs +++ b/src/windows/dcb.rs @@ -81,6 +81,8 @@ pub(crate) fn set_parity(dcb: &mut DCB, parity: Parity) { Parity::None => NOPARITY, Parity::Odd => ODDPARITY, Parity::Even => EVENPARITY, + Parity::Mark => MARKPARITY, + Parity::Space => SPACEPARITY, }; dcb.set_fParity(if parity == Parity::None { FALSE } else { TRUE } as DWORD);