Skip to content

Commit

Permalink
Add Mark and Space variants to Parity enum
Browse files Browse the repository at this point in the history
  • Loading branch information
YgorSouza committed Jan 7, 2025
1 parent 22d69ba commit d941df5
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 3 deletions.
12 changes: 12 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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"),
}
}
}
Expand Down
48 changes: 47 additions & 1 deletion src/posix/termios.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions src/posix/tty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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")))]
Expand Down
2 changes: 2 additions & 0 deletions src/windows/com.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions src/windows/dcb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit d941df5

Please sign in to comment.