| use crate::backend::c; |
| use crate::{backend, io}; |
| use bitflags::bitflags; |
| |
| /// `struct termios` for use with [`tcgetattr`] and [`tcsetattr`]. |
| /// |
| /// [`tcgetattr`]: crate::termios::tcgetattr |
| /// [`tcsetattr`]: crate::termios::tcsetattr |
| #[repr(C)] |
| #[derive(Clone)] |
| pub struct Termios { |
| /// How is input interpreted? |
| #[doc(alias = "c_iflag")] |
| pub input_modes: InputModes, |
| |
| /// How is output translated? |
| #[doc(alias = "c_oflag")] |
| pub output_modes: OutputModes, |
| |
| /// Low-level configuration flags. |
| #[doc(alias = "c_cflag")] |
| pub control_modes: ControlModes, |
| |
| /// High-level configuration flags. |
| #[doc(alias = "c_lflag")] |
| pub local_modes: LocalModes, |
| |
| /// Line discipline. |
| #[doc(alias = "c_line")] |
| #[cfg(not(all(linux_raw, any(target_arch = "powerpc", target_arch = "powerpc64"))))] |
| #[cfg(any( |
| linux_like, |
| target_env = "newlib", |
| target_os = "fuchsia", |
| target_os = "haiku", |
| target_os = "redox" |
| ))] |
| pub line_discipline: c::cc_t, |
| |
| /// How are various special control codes handled? |
| #[doc(alias = "c_cc")] |
| #[cfg(not(target_os = "haiku"))] |
| pub special_codes: SpecialCodes, |
| |
| #[cfg(target_os = "nto")] |
| pub(crate) __reserved: [c::c_uint; 3], |
| |
| /// Line discipline. |
| // On PowerPC, this field comes after `c_cc`. |
| #[doc(alias = "c_line")] |
| #[cfg(all(linux_raw, any(target_arch = "powerpc", target_arch = "powerpc64")))] |
| pub line_discipline: c::cc_t, |
| |
| /// See the `input_speed` and `set_input_seed` functions. |
| /// |
| /// On Linux and BSDs, this is the arbitrary integer speed value. On all |
| /// other platforms, this is the encoded speed value. |
| #[cfg(not(any(solarish, all(libc, target_env = "newlib"), target_os = "aix")))] |
| pub(crate) input_speed: c::speed_t, |
| |
| /// See the `output_speed` and `set_output_seed` functions. |
| /// |
| /// On Linux and BSDs, this is the integer speed value. On all other |
| /// platforms, this is the encoded speed value. |
| #[cfg(not(any(solarish, all(libc, target_env = "newlib"), target_os = "aix")))] |
| pub(crate) output_speed: c::speed_t, |
| |
| /// How are various special control codes handled? |
| #[doc(alias = "c_cc")] |
| #[cfg(target_os = "haiku")] |
| pub special_codes: SpecialCodes, |
| } |
| |
| impl Termios { |
| /// `cfmakeraw(self)`—Set a `Termios` value to the settings for “raw” mode. |
| /// |
| /// In raw mode, input is available a byte at a time, echoing is disabled, |
| /// and special terminal input and output codes are disabled. |
| #[cfg(not(target_os = "nto"))] |
| #[doc(alias = "cfmakeraw")] |
| #[inline] |
| pub fn make_raw(&mut self) { |
| backend::termios::syscalls::cfmakeraw(self) |
| } |
| |
| /// Return the input communication speed. |
| /// |
| /// Unlike the `c_ispeed` field in GLIBC and others, this returns the |
| /// integer value of the speed, rather than the `B*` encoded constant |
| /// value. |
| #[doc(alias = "c_ispeed")] |
| #[doc(alias = "cfgetispeed")] |
| #[doc(alias = "cfgetspeed")] |
| #[inline] |
| pub fn input_speed(&self) -> u32 { |
| // On Linux and BSDs, `input_speed` is the arbitrary integer speed. |
| #[cfg(any(linux_kernel, bsd))] |
| { |
| debug_assert!(u32::try_from(self.input_speed).is_ok()); |
| self.input_speed as u32 |
| } |
| |
| // On illumos, `input_speed` is not present. |
| #[cfg(any(solarish, all(libc, target_env = "newlib"), target_os = "aix"))] |
| unsafe { |
| speed::decode(c::cfgetispeed(crate::utils::as_ptr(self).cast())).unwrap() |
| } |
| |
| // On other platforms, it's the encoded speed. |
| #[cfg(not(any( |
| linux_kernel, |
| bsd, |
| solarish, |
| all(libc, target_env = "newlib"), |
| target_os = "aix" |
| )))] |
| { |
| speed::decode(self.input_speed).unwrap() |
| } |
| } |
| |
| /// Return the output communication speed. |
| /// |
| /// Unlike the `c_ospeed` field in GLIBC and others, this returns the |
| /// arbitrary integer value of the speed, rather than the `B*` encoded |
| /// constant value. |
| #[inline] |
| pub fn output_speed(&self) -> u32 { |
| // On Linux and BSDs, `input_speed` is the arbitrary integer speed. |
| #[cfg(any(linux_kernel, bsd))] |
| { |
| debug_assert!(u32::try_from(self.output_speed).is_ok()); |
| self.output_speed as u32 |
| } |
| |
| // On illumos, `output_speed` is not present. |
| #[cfg(any(solarish, all(libc, target_env = "newlib"), target_os = "aix"))] |
| unsafe { |
| speed::decode(c::cfgetospeed(crate::utils::as_ptr(self).cast())).unwrap() |
| } |
| |
| // On other platforms, it's the encoded speed. |
| #[cfg(not(any( |
| linux_kernel, |
| bsd, |
| solarish, |
| all(libc, target_env = "newlib"), |
| target_os = "aix" |
| )))] |
| { |
| speed::decode(self.output_speed).unwrap() |
| } |
| } |
| |
| /// Set the input and output communication speeds. |
| /// |
| /// Unlike the `c_ispeed` and `c_ospeed` fields in GLIBC and others, this |
| /// takes the arbitrary integer value of the speed, rather than the `B*` |
| /// encoded constant value. Not all implementations support all integer |
| /// values; use the constants in the [`speed`] module for likely-supported |
| /// speeds. |
| #[cfg(not(target_os = "nto"))] |
| #[doc(alias = "cfsetspeed")] |
| #[doc(alias = "CBAUD")] |
| #[doc(alias = "CBAUDEX")] |
| #[doc(alias = "CIBAUD")] |
| #[doc(alias = "CIBAUDEX")] |
| #[inline] |
| pub fn set_speed(&mut self, new_speed: u32) -> io::Result<()> { |
| backend::termios::syscalls::set_speed(self, new_speed) |
| } |
| |
| /// Set the input communication speed. |
| /// |
| /// Unlike the `c_ispeed` field in GLIBC and others, this takes the |
| /// arbitrary integer value of the speed, rather than the `B*` encoded |
| /// constant value. Not all implementations support all integer values; use |
| /// the constants in the [`speed`] module for known-supported speeds. |
| /// |
| /// On some platforms, changing the input speed changes the output speed |
| /// to the same speed. |
| #[doc(alias = "c_ispeed")] |
| #[doc(alias = "cfsetispeed")] |
| #[doc(alias = "CIBAUD")] |
| #[doc(alias = "CIBAUDEX")] |
| #[inline] |
| pub fn set_input_speed(&mut self, new_speed: u32) -> io::Result<()> { |
| backend::termios::syscalls::set_input_speed(self, new_speed) |
| } |
| |
| /// Set the output communication speed. |
| /// |
| /// Unlike the `c_ospeed` field in GLIBC and others, this takes the |
| /// arbitrary integer value of the speed, rather than the `B*` encoded |
| /// constant value. Not all implementations support all integer values; use |
| /// the constants in the [`speed`] module for known-supported speeds. |
| /// |
| /// On some platforms, changing the output speed changes the input speed |
| /// to the same speed. |
| #[doc(alias = "c_ospeed")] |
| #[doc(alias = "cfsetospeed")] |
| #[doc(alias = "CBAUD")] |
| #[doc(alias = "CBAUDEX")] |
| #[inline] |
| pub fn set_output_speed(&mut self, new_speed: u32) -> io::Result<()> { |
| backend::termios::syscalls::set_output_speed(self, new_speed) |
| } |
| } |
| |
| impl core::fmt::Debug for Termios { |
| fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { |
| let mut d = f.debug_struct("Termios"); |
| d.field("input_modes", &self.input_modes); |
| d.field("output_modes", &self.output_modes); |
| d.field("control_modes", &self.control_modes); |
| d.field("local_modes", &self.local_modes); |
| #[cfg(any( |
| linux_like, |
| target_env = "newlib", |
| target_os = "fuchsia", |
| target_os = "haiku", |
| target_os = "redox" |
| ))] |
| { |
| d.field("line_discipline", &self.line_discipline); |
| } |
| d.field("special_codes", &self.special_codes); |
| d.field("input_speed", &self.input_speed()); |
| d.field("output_speed", &self.output_speed()); |
| d.finish() |
| } |
| } |
| |
| bitflags! { |
| /// Flags controlling terminal input. |
| #[repr(transparent)] |
| #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] |
| pub struct InputModes: c::tcflag_t { |
| /// `IGNBRK` |
| const IGNBRK = c::IGNBRK; |
| |
| /// `BRKINT` |
| const BRKINT = c::BRKINT; |
| |
| /// `IGNPAR` |
| const IGNPAR = c::IGNPAR; |
| |
| /// `PARMRK` |
| const PARMRK = c::PARMRK; |
| |
| /// `INPCK` |
| const INPCK = c::INPCK; |
| |
| /// `ISTRIP` |
| const ISTRIP = c::ISTRIP; |
| |
| /// `INLCR` |
| const INLCR = c::INLCR; |
| |
| /// `IGNCR` |
| const IGNCR = c::IGNCR; |
| |
| /// `ICRNL` |
| const ICRNL = c::ICRNL; |
| |
| /// `IUCLC` |
| #[cfg(any(linux_kernel, solarish, target_os = "aix", target_os = "haiku", target_os = "nto"))] |
| const IUCLC = c::IUCLC; |
| |
| /// `IXON` |
| const IXON = c::IXON; |
| |
| /// `IXANY` |
| #[cfg(not(target_os = "redox"))] |
| const IXANY = c::IXANY; |
| |
| /// `IXOFF` |
| const IXOFF = c::IXOFF; |
| |
| /// `IMAXBEL` |
| #[cfg(not(any(target_os = "haiku", target_os = "redox")))] |
| const IMAXBEL = c::IMAXBEL; |
| |
| /// `IUTF8` |
| #[cfg(not(any( |
| freebsdlike, |
| netbsdlike, |
| solarish, |
| target_os = "aix", |
| target_os = "emscripten", |
| target_os = "haiku", |
| target_os = "hurd", |
| target_os = "redox", |
| )))] |
| const IUTF8 = c::IUTF8; |
| |
| /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags> |
| const _ = !0; |
| } |
| } |
| |
| bitflags! { |
| /// Flags controlling terminal output. |
| #[repr(transparent)] |
| #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] |
| pub struct OutputModes: c::tcflag_t { |
| /// `OPOST` |
| const OPOST = c::OPOST; |
| |
| /// `OLCUC` |
| #[cfg(not(any( |
| apple, |
| freebsdlike, |
| target_os = "aix", |
| target_os = "netbsd", |
| target_os = "redox", |
| )))] |
| const OLCUC = c::OLCUC; |
| |
| /// `ONLCR` |
| const ONLCR = c::ONLCR; |
| |
| /// `OCRNL` |
| const OCRNL = c::OCRNL; |
| |
| /// `ONOCR` |
| const ONOCR = c::ONOCR; |
| |
| /// `ONLRET` |
| const ONLRET = c::ONLRET; |
| |
| /// `OFILL` |
| #[cfg(not(bsd))] |
| const OFILL = c::OFILL; |
| |
| /// `OFDEL` |
| #[cfg(not(bsd))] |
| const OFDEL = c::OFDEL; |
| |
| /// `NLDLY` |
| #[cfg(not(any(bsd, solarish, target_os = "redox")))] |
| const NLDLY = c::NLDLY; |
| |
| /// `NL0` |
| #[cfg(not(any(bsd, solarish, target_os = "fuchsia", target_os = "redox")))] |
| const NL0 = c::NL0; |
| |
| /// `NL1` |
| #[cfg(not(any(bsd, solarish, target_os = "fuchsia", target_os = "redox")))] |
| const NL1 = c::NL1; |
| |
| /// `CRDLY` |
| #[cfg(not(any(bsd, solarish, target_os = "redox")))] |
| const CRDLY = c::CRDLY; |
| |
| /// `CR0` |
| #[cfg(not(any(bsd, solarish, target_os = "fuchsia", target_os = "redox")))] |
| const CR0 = c::CR0; |
| |
| /// `CR1` |
| #[cfg(not(any( |
| target_env = "musl", |
| bsd, |
| solarish, |
| target_os = "emscripten", |
| target_os = "fuchsia", |
| target_os = "redox", |
| )))] |
| const CR1 = c::CR1; |
| |
| /// `CR2` |
| #[cfg(not(any( |
| target_env = "musl", |
| bsd, |
| solarish, |
| target_os = "emscripten", |
| target_os = "fuchsia", |
| target_os = "redox", |
| )))] |
| const CR2 = c::CR2; |
| |
| /// `CR3` |
| #[cfg(not(any( |
| target_env = "musl", |
| bsd, |
| solarish, |
| target_os = "emscripten", |
| target_os = "fuchsia", |
| target_os = "redox", |
| )))] |
| const CR3 = c::CR3; |
| |
| /// `TABDLY` |
| #[cfg(not(any( |
| netbsdlike, |
| solarish, |
| target_os = "dragonfly", |
| target_os = "redox", |
| )))] |
| const TABDLY = c::TABDLY; |
| |
| /// `TAB0` |
| #[cfg(not(any( |
| netbsdlike, |
| solarish, |
| target_os = "dragonfly", |
| target_os = "fuchsia", |
| target_os = "redox", |
| )))] |
| const TAB0 = c::TAB0; |
| |
| /// `TAB1` |
| #[cfg(not(any( |
| target_env = "musl", |
| bsd, |
| solarish, |
| target_os = "emscripten", |
| target_os = "fuchsia", |
| target_os = "redox", |
| )))] |
| const TAB1 = c::TAB1; |
| |
| /// `TAB2` |
| #[cfg(not(any( |
| target_env = "musl", |
| bsd, |
| solarish, |
| target_os = "emscripten", |
| target_os = "fuchsia", |
| target_os = "redox", |
| )))] |
| const TAB2 = c::TAB2; |
| |
| /// `TAB3` |
| #[cfg(not(any( |
| target_env = "musl", |
| bsd, |
| solarish, |
| target_os = "emscripten", |
| target_os = "fuchsia", |
| target_os = "redox", |
| )))] |
| const TAB3 = c::TAB3; |
| |
| /// `XTABS` |
| #[cfg(not(any( |
| bsd, |
| solarish, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "redox", |
| )))] |
| const XTABS = c::XTABS; |
| |
| /// `BSDLY` |
| #[cfg(not(any(bsd, solarish, target_os = "redox")))] |
| const BSDLY = c::BSDLY; |
| |
| /// `BS0` |
| #[cfg(not(any(bsd, solarish, target_os = "fuchsia", target_os = "redox")))] |
| const BS0 = c::BS0; |
| |
| /// `BS1` |
| #[cfg(not(any( |
| target_env = "musl", |
| bsd, |
| solarish, |
| target_os = "emscripten", |
| target_os = "fuchsia", |
| target_os = "redox", |
| )))] |
| const BS1 = c::BS1; |
| |
| /// `FFDLY` |
| #[cfg(not(any(bsd, solarish, target_os = "redox")))] |
| const FFDLY = c::FFDLY; |
| |
| /// `FF0` |
| #[cfg(not(any(bsd, solarish, target_os = "fuchsia", target_os = "redox")))] |
| const FF0 = c::FF0; |
| |
| /// `FF1` |
| #[cfg(not(any( |
| target_env = "musl", |
| bsd, |
| solarish, |
| target_os = "emscripten", |
| target_os = "fuchsia", |
| target_os = "redox", |
| )))] |
| const FF1 = c::FF1; |
| |
| /// `VTDLY` |
| #[cfg(not(any(bsd, solarish, target_os = "redox")))] |
| const VTDLY = c::VTDLY; |
| |
| /// `VT0` |
| #[cfg(not(any(bsd, solarish, target_os = "fuchsia", target_os = "redox")))] |
| const VT0 = c::VT0; |
| |
| /// `VT1` |
| #[cfg(not(any( |
| target_env = "musl", |
| bsd, |
| solarish, |
| target_os = "emscripten", |
| target_os = "fuchsia", |
| target_os = "redox", |
| )))] |
| const VT1 = c::VT1; |
| |
| /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags> |
| const _ = !0; |
| } |
| } |
| |
| bitflags! { |
| /// Flags controlling special terminal modes. |
| /// |
| /// `CBAUD`, `CBAUDEX`, `CIBAUD`, and `CIBAUDEX` are not defined here, |
| /// because they're handled automatically by [`Termios::set_speed`] and |
| /// related functions. |
| #[repr(transparent)] |
| #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] |
| pub struct ControlModes: c::tcflag_t { |
| /// `CSIZE` |
| const CSIZE = c::CSIZE; |
| |
| /// `CS5` |
| const CS5 = c::CS5; |
| |
| /// `CS6` |
| const CS6 = c::CS6; |
| |
| /// `CS7` |
| const CS7 = c::CS7; |
| |
| /// `CS8` |
| const CS8 = c::CS8; |
| |
| /// `CSTOPB` |
| const CSTOPB = c::CSTOPB; |
| |
| /// `CREAD` |
| const CREAD = c::CREAD; |
| |
| /// `PARENB` |
| const PARENB = c::PARENB; |
| |
| /// `PARODD` |
| const PARODD = c::PARODD; |
| |
| /// `HUPCL` |
| const HUPCL = c::HUPCL; |
| |
| /// `CLOCAL` |
| const CLOCAL = c::CLOCAL; |
| |
| /// `CRTSCTS` |
| #[cfg(not(any(target_os = "aix", target_os = "nto", target_os = "redox")))] |
| const CRTSCTS = c::CRTSCTS; |
| |
| /// `CMSPAR` |
| #[cfg(not(any( |
| bsd, |
| solarish, |
| target_os = "aix", |
| target_os = "emscripten", |
| target_os = "haiku", |
| target_os = "hurd", |
| target_os = "nto", |
| target_os = "redox", |
| )))] |
| const CMSPAR = c::CMSPAR; |
| |
| /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags> |
| const _ = !0; |
| } |
| } |
| |
| bitflags! { |
| /// Flags controlling “local” terminal modes. |
| #[repr(transparent)] |
| #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] |
| pub struct LocalModes: c::tcflag_t { |
| /// `XCASE` |
| #[cfg(any(linux_kernel, target_arch = "s390x", target_os = "haiku"))] |
| const XCASE = c::XCASE; |
| |
| /// `ECHOCTL` |
| #[cfg(not(target_os = "redox"))] |
| const ECHOCTL = c::ECHOCTL; |
| |
| /// `ECHOPRT` |
| #[cfg(not(any(target_os = "nto", target_os = "redox")))] |
| const ECHOPRT = c::ECHOPRT; |
| |
| /// `ECHOKE` |
| #[cfg(not(target_os = "redox"))] |
| const ECHOKE = c::ECHOKE; |
| |
| /// `FLUSHO` |
| #[cfg(not(any(target_os = "nto", target_os = "redox")))] |
| const FLUSHO = c::FLUSHO; |
| |
| /// `PENDIN` |
| #[cfg(not(any(target_os = "nto", target_os = "redox")))] |
| const PENDIN = c::PENDIN; |
| |
| /// `EXTPROC` |
| #[cfg(not(any(target_os = "aix", target_os = "haiku", target_os = "nto", target_os = "redox")))] |
| const EXTPROC = c::EXTPROC; |
| |
| /// `ISIG` |
| const ISIG = c::ISIG; |
| |
| /// `ICANON`—A flag for the `c_lflag` field of [`Termios`] indicating |
| /// canonical mode. |
| const ICANON = c::ICANON; |
| |
| /// `ECHO` |
| const ECHO = c::ECHO; |
| |
| /// `ECHOE` |
| const ECHOE = c::ECHOE; |
| |
| /// `ECHOK` |
| const ECHOK = c::ECHOK; |
| |
| /// `ECHONL` |
| const ECHONL = c::ECHONL; |
| |
| /// `NOFLSH` |
| const NOFLSH = c::NOFLSH; |
| |
| /// `TOSTOP` |
| const TOSTOP = c::TOSTOP; |
| |
| /// `IEXTEN` |
| const IEXTEN = c::IEXTEN; |
| |
| /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags> |
| const _ = !0; |
| } |
| } |
| |
| /// Speeds for use with [`Termios::set_input_speed`] and |
| /// [`Termios::set_output_speed`]. |
| /// |
| /// Unlike in some platforms' libc APIs, these always have the same numerical |
| /// value as their names; for example, `B50` has the value `50`, and so on. |
| /// Consequently, it's not necessary to use them. They are provided here |
| /// because they help identify speeds which are likely to be supported, on |
| /// platforms which don't support arbitrary speeds. |
| pub mod speed { |
| #[cfg(not(bsd))] |
| use crate::backend::c; |
| |
| /// `B0` |
| pub const B0: u32 = 0; |
| |
| /// `B50` |
| pub const B50: u32 = 50; |
| |
| /// `B75` |
| pub const B75: u32 = 75; |
| |
| /// `B110` |
| pub const B110: u32 = 110; |
| |
| /// `B134` |
| pub const B134: u32 = 134; |
| |
| /// `B150` |
| pub const B150: u32 = 150; |
| |
| /// `B200` |
| pub const B200: u32 = 200; |
| |
| /// `B300` |
| pub const B300: u32 = 300; |
| |
| /// `B600` |
| pub const B600: u32 = 600; |
| |
| /// `B1200` |
| pub const B1200: u32 = 1200; |
| |
| /// `B1800` |
| pub const B1800: u32 = 1800; |
| |
| /// `B2400` |
| pub const B2400: u32 = 2400; |
| |
| /// `B4800` |
| pub const B4800: u32 = 4800; |
| |
| /// `B9600` |
| pub const B9600: u32 = 9600; |
| |
| /// `B19200` |
| #[doc(alias = "EXTA")] |
| pub const B19200: u32 = 19200; |
| |
| /// `B38400` |
| #[doc(alias = "EXTB")] |
| pub const B38400: u32 = 38400; |
| |
| /// `B57600` |
| #[cfg(not(target_os = "aix"))] |
| pub const B57600: u32 = 57600; |
| |
| /// `B115200` |
| #[cfg(not(target_os = "aix"))] |
| pub const B115200: u32 = 115_200; |
| |
| /// `B230400` |
| #[cfg(not(target_os = "aix"))] |
| pub const B230400: u32 = 230_400; |
| |
| /// `B460800` |
| #[cfg(not(any( |
| apple, |
| target_os = "aix", |
| target_os = "dragonfly", |
| target_os = "haiku", |
| target_os = "openbsd" |
| )))] |
| pub const B460800: u32 = 460_800; |
| |
| /// `B500000` |
| #[cfg(not(any(bsd, solarish, target_os = "aix", target_os = "haiku")))] |
| pub const B500000: u32 = 500_000; |
| |
| /// `B576000` |
| #[cfg(not(any(bsd, solarish, target_os = "aix", target_os = "haiku")))] |
| pub const B576000: u32 = 576_000; |
| |
| /// `B921600` |
| #[cfg(not(any( |
| apple, |
| target_os = "aix", |
| target_os = "dragonfly", |
| target_os = "haiku", |
| target_os = "openbsd" |
| )))] |
| pub const B921600: u32 = 921_600; |
| |
| /// `B1000000` |
| #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))] |
| pub const B1000000: u32 = 1_000_000; |
| |
| /// `B1152000` |
| #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))] |
| pub const B1152000: u32 = 1_152_000; |
| |
| /// `B1500000` |
| #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))] |
| pub const B1500000: u32 = 1_500_000; |
| |
| /// `B2000000` |
| #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))] |
| pub const B2000000: u32 = 2_000_000; |
| |
| /// `B2500000` |
| #[cfg(not(any( |
| target_arch = "sparc", |
| target_arch = "sparc64", |
| bsd, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "solaris", |
| )))] |
| pub const B2500000: u32 = 2_500_000; |
| |
| /// `B3000000` |
| #[cfg(not(any( |
| target_arch = "sparc", |
| target_arch = "sparc64", |
| bsd, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "solaris", |
| )))] |
| pub const B3000000: u32 = 3_000_000; |
| |
| /// `B3500000` |
| #[cfg(not(any( |
| target_arch = "sparc", |
| target_arch = "sparc64", |
| bsd, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "solaris", |
| )))] |
| pub const B3500000: u32 = 3_500_000; |
| |
| /// `B4000000` |
| #[cfg(not(any( |
| target_arch = "sparc", |
| target_arch = "sparc64", |
| bsd, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "solaris", |
| )))] |
| pub const B4000000: u32 = 4_000_000; |
| |
| /// Translate from a `c::speed_t` code to an arbitrary integer speed value |
| /// `u32`. |
| /// |
| /// On BSD platforms, integer speed values are already the same as their |
| /// encoded values, and on Linux platforms, we use `TCGETS2`/`TCSETS2` |
| /// and the `c_ispeed`/`c_ospeed`` fields, except that on Linux on |
| /// PowerPC on QEMU, `TCGETS2`/`TCSETS2` don't set `c_ispeed`/`c_ospeed`. |
| #[cfg(not(any( |
| bsd, |
| all( |
| linux_kernel, |
| not(any(target_arch = "powerpc", target_arch = "powerpc64")) |
| ) |
| )))] |
| pub(crate) const fn decode(encoded_speed: c::speed_t) -> Option<u32> { |
| match encoded_speed { |
| c::B0 => Some(0), |
| c::B50 => Some(50), |
| c::B75 => Some(75), |
| c::B110 => Some(110), |
| c::B134 => Some(134), |
| c::B150 => Some(150), |
| c::B200 => Some(200), |
| c::B300 => Some(300), |
| c::B600 => Some(600), |
| c::B1200 => Some(1200), |
| c::B1800 => Some(1800), |
| c::B2400 => Some(2400), |
| c::B4800 => Some(4800), |
| c::B9600 => Some(9600), |
| c::B19200 => Some(19200), |
| c::B38400 => Some(38400), |
| #[cfg(not(target_os = "aix"))] |
| c::B57600 => Some(57600), |
| #[cfg(not(target_os = "aix"))] |
| c::B115200 => Some(115_200), |
| #[cfg(not(any(target_os = "aix", target_os = "nto")))] |
| c::B230400 => Some(230_400), |
| #[cfg(not(any( |
| apple, |
| target_os = "aix", |
| target_os = "dragonfly", |
| target_os = "haiku", |
| target_os = "nto", |
| target_os = "openbsd" |
| )))] |
| c::B460800 => Some(460_800), |
| #[cfg(not(any( |
| bsd, |
| solarish, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "nto" |
| )))] |
| c::B500000 => Some(500_000), |
| #[cfg(not(any( |
| bsd, |
| solarish, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "nto" |
| )))] |
| c::B576000 => Some(576_000), |
| #[cfg(not(any( |
| apple, |
| target_os = "aix", |
| target_os = "dragonfly", |
| target_os = "haiku", |
| target_os = "nto", |
| target_os = "openbsd" |
| )))] |
| c::B921600 => Some(921_600), |
| #[cfg(not(any( |
| bsd, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "nto", |
| target_os = "solaris" |
| )))] |
| c::B1000000 => Some(1_000_000), |
| #[cfg(not(any( |
| bsd, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "nto", |
| target_os = "solaris" |
| )))] |
| c::B1152000 => Some(1_152_000), |
| #[cfg(not(any( |
| bsd, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "nto", |
| target_os = "solaris" |
| )))] |
| c::B1500000 => Some(1_500_000), |
| #[cfg(not(any( |
| bsd, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "nto", |
| target_os = "solaris" |
| )))] |
| c::B2000000 => Some(2_000_000), |
| #[cfg(not(any( |
| target_arch = "sparc", |
| target_arch = "sparc64", |
| bsd, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "nto", |
| target_os = "solaris", |
| )))] |
| c::B2500000 => Some(2_500_000), |
| #[cfg(not(any( |
| target_arch = "sparc", |
| target_arch = "sparc64", |
| bsd, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "nto", |
| target_os = "solaris", |
| )))] |
| c::B3000000 => Some(3_000_000), |
| #[cfg(not(any( |
| target_arch = "sparc", |
| target_arch = "sparc64", |
| bsd, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "nto", |
| target_os = "solaris", |
| )))] |
| c::B3500000 => Some(3_500_000), |
| #[cfg(not(any( |
| target_arch = "sparc", |
| target_arch = "sparc64", |
| bsd, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "nto", |
| target_os = "solaris", |
| )))] |
| c::B4000000 => Some(4_000_000), |
| _ => None, |
| } |
| } |
| |
| /// Translate from an arbitrary `u32` arbitrary integer speed value to a |
| /// `c::speed_t` code. |
| #[cfg(not(bsd))] |
| pub(crate) const fn encode(speed: u32) -> Option<c::speed_t> { |
| match speed { |
| 0 => Some(c::B0), |
| 50 => Some(c::B50), |
| 75 => Some(c::B75), |
| 110 => Some(c::B110), |
| 134 => Some(c::B134), |
| 150 => Some(c::B150), |
| 200 => Some(c::B200), |
| 300 => Some(c::B300), |
| 600 => Some(c::B600), |
| 1200 => Some(c::B1200), |
| 1800 => Some(c::B1800), |
| 2400 => Some(c::B2400), |
| 4800 => Some(c::B4800), |
| 9600 => Some(c::B9600), |
| 19200 => Some(c::B19200), |
| 38400 => Some(c::B38400), |
| #[cfg(not(target_os = "aix"))] |
| 57600 => Some(c::B57600), |
| #[cfg(not(target_os = "aix"))] |
| 115_200 => Some(c::B115200), |
| #[cfg(not(any(target_os = "aix", target_os = "nto")))] |
| 230_400 => Some(c::B230400), |
| #[cfg(not(any( |
| apple, |
| target_os = "aix", |
| target_os = "dragonfly", |
| target_os = "haiku", |
| target_os = "nto", |
| target_os = "openbsd", |
| )))] |
| 460_800 => Some(c::B460800), |
| #[cfg(not(any( |
| bsd, |
| solarish, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "nto" |
| )))] |
| 500_000 => Some(c::B500000), |
| #[cfg(not(any( |
| bsd, |
| solarish, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "nto" |
| )))] |
| 576_000 => Some(c::B576000), |
| #[cfg(not(any( |
| apple, |
| target_os = "aix", |
| target_os = "dragonfly", |
| target_os = "haiku", |
| target_os = "nto", |
| target_os = "openbsd" |
| )))] |
| 921_600 => Some(c::B921600), |
| #[cfg(not(any( |
| bsd, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "nto", |
| target_os = "solaris" |
| )))] |
| 1_000_000 => Some(c::B1000000), |
| #[cfg(not(any( |
| bsd, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "nto", |
| target_os = "solaris" |
| )))] |
| 1_152_000 => Some(c::B1152000), |
| #[cfg(not(any( |
| bsd, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "nto", |
| target_os = "solaris" |
| )))] |
| 1_500_000 => Some(c::B1500000), |
| #[cfg(not(any( |
| bsd, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "nto", |
| target_os = "solaris" |
| )))] |
| 2_000_000 => Some(c::B2000000), |
| #[cfg(not(any( |
| target_arch = "sparc", |
| target_arch = "sparc64", |
| bsd, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "nto", |
| target_os = "solaris", |
| )))] |
| 2_500_000 => Some(c::B2500000), |
| #[cfg(not(any( |
| target_arch = "sparc", |
| target_arch = "sparc64", |
| bsd, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "nto", |
| target_os = "solaris", |
| )))] |
| 3_000_000 => Some(c::B3000000), |
| #[cfg(not(any( |
| target_arch = "sparc", |
| target_arch = "sparc64", |
| bsd, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "nto", |
| target_os = "solaris", |
| )))] |
| 3_500_000 => Some(c::B3500000), |
| #[cfg(not(any( |
| target_arch = "sparc", |
| target_arch = "sparc64", |
| bsd, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "nto", |
| target_os = "solaris", |
| )))] |
| 4_000_000 => Some(c::B4000000), |
| _ => None, |
| } |
| } |
| } |
| |
| /// An array indexed by [`SpecialCodeIndex`] indicating the current values |
| /// of various special control codes. |
| #[repr(transparent)] |
| #[derive(Clone, Debug)] |
| pub struct SpecialCodes(pub(crate) [c::cc_t; c::NCCS as usize]); |
| |
| impl core::ops::Index<SpecialCodeIndex> for SpecialCodes { |
| type Output = c::cc_t; |
| |
| fn index(&self, index: SpecialCodeIndex) -> &Self::Output { |
| &self.0[index.0] |
| } |
| } |
| |
| impl core::ops::IndexMut<SpecialCodeIndex> for SpecialCodes { |
| fn index_mut(&mut self, index: SpecialCodeIndex) -> &mut Self::Output { |
| &mut self.0[index.0] |
| } |
| } |
| |
| /// Indices for use with [`Termios::special_codes`]. |
| pub struct SpecialCodeIndex(usize); |
| |
| #[rustfmt::skip] |
| impl SpecialCodeIndex { |
| /// `VINTR` |
| pub const VINTR: Self = Self(c::VINTR as usize); |
| |
| /// `VQUIT` |
| pub const VQUIT: Self = Self(c::VQUIT as usize); |
| |
| /// `VERASE` |
| pub const VERASE: Self = Self(c::VERASE as usize); |
| |
| /// `VKILL` |
| pub const VKILL: Self = Self(c::VKILL as usize); |
| |
| /// `VEOF` |
| pub const VEOF: Self = Self(c::VEOF as usize); |
| |
| /// `VTIME` |
| pub const VTIME: Self = Self(c::VTIME as usize); |
| |
| /// `VMIN` |
| pub const VMIN: Self = Self(c::VMIN as usize); |
| |
| /// `VSWTC` |
| #[cfg(not(any( |
| bsd, |
| solarish, |
| target_os = "aix", |
| target_os = "haiku", |
| target_os = "hurd", |
| target_os = "nto", |
| )))] |
| pub const VSWTC: Self = Self(c::VSWTC as usize); |
| |
| /// `VSTART` |
| pub const VSTART: Self = Self(c::VSTART as usize); |
| |
| /// `VSTOP` |
| pub const VSTOP: Self = Self(c::VSTOP as usize); |
| |
| /// `VSUSP` |
| pub const VSUSP: Self = Self(c::VSUSP as usize); |
| |
| /// `VEOL` |
| pub const VEOL: Self = Self(c::VEOL as usize); |
| |
| /// `VREPRINT` |
| #[cfg(not(target_os = "haiku"))] |
| pub const VREPRINT: Self = Self(c::VREPRINT as usize); |
| |
| /// `VDISCARD` |
| #[cfg(not(any(target_os = "aix", target_os = "haiku")))] |
| pub const VDISCARD: Self = Self(c::VDISCARD as usize); |
| |
| /// `VWERASE` |
| #[cfg(not(any(target_os = "aix", target_os = "haiku")))] |
| pub const VWERASE: Self = Self(c::VWERASE as usize); |
| |
| /// `VLNEXT` |
| #[cfg(not(target_os = "haiku"))] |
| pub const VLNEXT: Self = Self(c::VLNEXT as usize); |
| |
| /// `VEOL2` |
| pub const VEOL2: Self = Self(c::VEOL2 as usize); |
| } |
| |
| /// `TCSA*` values for use with [`tcsetattr`]. |
| /// |
| /// [`tcsetattr`]: crate::termios::tcsetattr |
| #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] |
| #[repr(u32)] |
| pub enum OptionalActions { |
| /// `TCSANOW`—Make the change immediately. |
| #[doc(alias = "TCSANOW")] |
| Now = c::TCSANOW as u32, |
| |
| /// `TCSADRAIN`—Make the change after all output has been transmitted. |
| #[doc(alias = "TCSADRAIN")] |
| Drain = c::TCSADRAIN as u32, |
| |
| /// `TCSAFLUSH`—Discard any pending input and then make the change |
| /// after all output has been transmitted. |
| #[doc(alias = "TCSAFLUSH")] |
| Flush = c::TCSAFLUSH as u32, |
| } |
| |
| /// `TC*` values for use with [`tcflush`]. |
| /// |
| /// [`tcflush`]: crate::termios::tcflush |
| #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] |
| #[repr(u32)] |
| pub enum QueueSelector { |
| /// `TCIFLUSH`—Flush data received but not read. |
| #[doc(alias = "TCIFLUSH")] |
| IFlush = c::TCIFLUSH as u32, |
| |
| /// `TCOFLUSH`—Flush data written but not transmitted. |
| #[doc(alias = "TCOFLUSH")] |
| OFlush = c::TCOFLUSH as u32, |
| |
| /// `TCIOFLUSH`—`IFlush` and `OFlush` combined. |
| #[doc(alias = "TCIOFLUSH")] |
| IOFlush = c::TCIOFLUSH as u32, |
| } |
| |
| /// `TC*` values for use with [`tcflow`]. |
| /// |
| /// [`tcflow`]: crate::termios::tcflow |
| #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] |
| #[repr(u32)] |
| pub enum Action { |
| /// `TCOOFF`—Suspend output. |
| #[doc(alias = "TCOOFF")] |
| OOff = c::TCOOFF as u32, |
| |
| /// `TCOON`—Restart suspended output. |
| #[doc(alias = "TCOON")] |
| OOn = c::TCOON as u32, |
| |
| /// `TCIOFF`—Transmits a STOP byte. |
| #[doc(alias = "TCIOFF")] |
| IOff = c::TCIOFF as u32, |
| |
| /// `TCION`—Transmits a START byte. |
| #[doc(alias = "TCION")] |
| IOn = c::TCION as u32, |
| } |
| |
| /// `struct winsize` for use with [`tcgetwinsize`]. |
| /// |
| /// [`tcgetwinsize`]: crate::termios::tcgetwinsize |
| #[doc(alias = "winsize")] |
| pub type Winsize = c::winsize; |
| |
| #[test] |
| fn termios_layouts() { |
| check_renamed_type!(InputModes, tcflag_t); |
| check_renamed_type!(OutputModes, tcflag_t); |
| check_renamed_type!(ControlModes, tcflag_t); |
| check_renamed_type!(LocalModes, tcflag_t); |
| |
| // On platforms with a termios/termios2 split, check `termios`. |
| #[cfg(linux_raw)] |
| { |
| check_renamed_type!(Termios, termios2); |
| check_renamed_struct_renamed_field!(Termios, termios2, input_modes, c_iflag); |
| check_renamed_struct_renamed_field!(Termios, termios2, output_modes, c_oflag); |
| check_renamed_struct_renamed_field!(Termios, termios2, control_modes, c_cflag); |
| check_renamed_struct_renamed_field!(Termios, termios2, local_modes, c_lflag); |
| check_renamed_struct_renamed_field!(Termios, termios2, line_discipline, c_line); |
| check_renamed_struct_renamed_field!(Termios, termios2, special_codes, c_cc); |
| check_renamed_struct_renamed_field!(Termios, termios2, input_speed, c_ispeed); |
| check_renamed_struct_renamed_field!(Termios, termios2, output_speed, c_ospeed); |
| |
| // We assume that `termios` has the same layout as `termios2` minus the |
| // `c_ispeed` and `c_ospeed` fields. |
| check_renamed_struct_renamed_field!(Termios, termios, input_modes, c_iflag); |
| check_renamed_struct_renamed_field!(Termios, termios, output_modes, c_oflag); |
| check_renamed_struct_renamed_field!(Termios, termios, control_modes, c_cflag); |
| check_renamed_struct_renamed_field!(Termios, termios, local_modes, c_lflag); |
| check_renamed_struct_renamed_field!(Termios, termios, special_codes, c_cc); |
| |
| // On everything except PowerPC, `termios` matches `termios2` except |
| // for the addition of `c_ispeed` and `c_ospeed`. |
| #[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))] |
| const_assert_eq!( |
| memoffset::offset_of!(Termios, input_speed), |
| core::mem::size_of::<c::termios>() |
| ); |
| |
| // On PowerPC, `termios2` is `termios`. |
| #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] |
| assert_eq_size!(c::termios2, c::termios); |
| } |
| |
| #[cfg(not(linux_raw))] |
| { |
| // On Mips, Sparc, and Android, the libc lacks the ospeed and ispeed |
| // fields. |
| #[cfg(all( |
| not(all( |
| target_env = "gnu", |
| any( |
| target_arch = "mips", |
| target_arch = "mips32r6", |
| target_arch = "mips64", |
| target_arch = "mips64r6", |
| target_arch = "sparc", |
| target_arch = "sparc64" |
| ) |
| )), |
| not(all(libc, target_os = "android")) |
| ))] |
| check_renamed_type!(Termios, termios); |
| #[cfg(not(all( |
| not(all( |
| target_env = "gnu", |
| any( |
| target_arch = "mips", |
| target_arch = "mips32r6", |
| target_arch = "mips64", |
| target_arch = "mips64r6", |
| target_arch = "sparc", |
| target_arch = "sparc64" |
| ) |
| )), |
| not(all(libc, target_os = "android")) |
| )))] |
| const_assert!(core::mem::size_of::<Termios>() >= core::mem::size_of::<c::termios>()); |
| |
| check_renamed_struct_renamed_field!(Termios, termios, input_modes, c_iflag); |
| check_renamed_struct_renamed_field!(Termios, termios, output_modes, c_oflag); |
| check_renamed_struct_renamed_field!(Termios, termios, control_modes, c_cflag); |
| check_renamed_struct_renamed_field!(Termios, termios, local_modes, c_lflag); |
| #[cfg(any( |
| linux_like, |
| target_env = "newlib", |
| target_os = "fuchsia", |
| target_os = "haiku", |
| target_os = "redox" |
| ))] |
| check_renamed_struct_renamed_field!(Termios, termios, line_discipline, c_line); |
| check_renamed_struct_renamed_field!(Termios, termios, special_codes, c_cc); |
| #[cfg(not(any( |
| linux_kernel, |
| solarish, |
| target_os = "emscripten", |
| target_os = "fuchsia" |
| )))] |
| { |
| check_renamed_struct_renamed_field!(Termios, termios, input_speed, c_ispeed); |
| check_renamed_struct_renamed_field!(Termios, termios, output_speed, c_ospeed); |
| } |
| #[cfg(any(target_env = "musl", target_os = "fuchsia"))] |
| { |
| check_renamed_struct_renamed_field!(Termios, termios, input_speed, __c_ispeed); |
| check_renamed_struct_renamed_field!(Termios, termios, output_speed, __c_ospeed); |
| } |
| } |
| |
| check_renamed_type!(OptionalActions, c_int); |
| check_renamed_type!(QueueSelector, c_int); |
| check_renamed_type!(Action, c_int); |
| } |
| |
| #[test] |
| #[cfg(not(any( |
| solarish, |
| target_os = "emscripten", |
| target_os = "haiku", |
| target_os = "redox" |
| )))] |
| fn termios_legacy() { |
| // Check that our doc aliases above are correct. |
| const_assert_eq!(c::EXTA, c::B19200); |
| const_assert_eq!(c::EXTB, c::B38400); |
| } |
| |
| #[cfg(bsd)] |
| #[test] |
| fn termios_bsd() { |
| // On BSD platforms we can assume that the `B*` constants have their |
| // arbitrary integer speed value. Confirm this. |
| const_assert_eq!(c::B0, 0); |
| const_assert_eq!(c::B50, 50); |
| const_assert_eq!(c::B19200, 19200); |
| const_assert_eq!(c::B38400, 38400); |
| } |
| |
| #[test] |
| #[cfg(not(bsd))] |
| fn termios_speed_encoding() { |
| assert_eq!(speed::encode(0), Some(c::B0)); |
| assert_eq!(speed::encode(50), Some(c::B50)); |
| assert_eq!(speed::encode(19200), Some(c::B19200)); |
| assert_eq!(speed::encode(38400), Some(c::B38400)); |
| assert_eq!(speed::encode(1), None); |
| assert_eq!(speed::encode(!0), None); |
| |
| #[cfg(not(linux_kernel))] |
| { |
| assert_eq!(speed::decode(c::B0), Some(0)); |
| assert_eq!(speed::decode(c::B50), Some(50)); |
| assert_eq!(speed::decode(c::B19200), Some(19200)); |
| assert_eq!(speed::decode(c::B38400), Some(38400)); |
| } |
| } |
| |
| #[cfg(linux_kernel)] |
| #[test] |
| fn termios_ioctl_contiguity() { |
| // When using `termios2`, we assume that we can add the optional actions |
| // value to the ioctl request code. Test this assumption. |
| |
| const_assert_eq!(c::TCSETS2, c::TCSETS2 + 0); |
| const_assert_eq!(c::TCSETSW2, c::TCSETS2 + 1); |
| const_assert_eq!(c::TCSETSF2, c::TCSETS2 + 2); |
| |
| const_assert_eq!(c::TCSANOW - c::TCSANOW, 0); |
| const_assert_eq!(c::TCSADRAIN - c::TCSANOW, 1); |
| const_assert_eq!(c::TCSAFLUSH - c::TCSANOW, 2); |
| |
| // MIPS is different here. |
| #[cfg(any( |
| target_arch = "mips", |
| target_arch = "mips32r6", |
| target_arch = "mips64", |
| target_arch = "mips64r6" |
| ))] |
| { |
| assert_eq!(i128::from(c::TCSANOW) - i128::from(c::TCSETS), 0); |
| assert_eq!(i128::from(c::TCSADRAIN) - i128::from(c::TCSETS), 1); |
| assert_eq!(i128::from(c::TCSAFLUSH) - i128::from(c::TCSETS), 2); |
| } |
| #[cfg(not(any( |
| target_arch = "mips", |
| target_arch = "mips32r6", |
| target_arch = "mips64", |
| target_arch = "mips64r6" |
| )))] |
| { |
| const_assert_eq!(c::TCSANOW, 0); |
| const_assert_eq!(c::TCSADRAIN, 1); |
| const_assert_eq!(c::TCSAFLUSH, 2); |
| } |
| } |
| |
| #[cfg(linux_kernel)] |
| #[test] |
| fn termios_cibaud() { |
| // Test an assumption. |
| const_assert_eq!(c::CIBAUD, c::CBAUD << c::IBSHIFT); |
| } |