summaryrefslogtreecommitdiffstats
path: root/vendor/rustix/src/termios/types.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rustix/src/termios/types.rs')
-rw-r--r--vendor/rustix/src/termios/types.rs1273
1 files changed, 1273 insertions, 0 deletions
diff --git a/vendor/rustix/src/termios/types.rs b/vendor/rustix/src/termios/types.rs
new file mode 100644
index 000000000..d978bfcca
--- /dev/null
+++ b/vendor/rustix/src/termios/types.rs
@@ -0,0 +1,1273 @@
+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 = "haiku",
+ target_os = "fuchsia",
+ target_os = "redox"
+ ))]
+ pub line_discipline: c::cc_t,
+
+ /// How are various special control codes handled?
+ #[doc(alias = "c_cc")]
+ pub special_codes: SpecialCodes,
+
+ /// 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.
+ 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.
+ pub(crate) output_speed: c::speed_t,
+}
+
+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.
+ #[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 other platforms, it's the encoded speed.
+ #[cfg(not(any(linux_kernel, bsd)))]
+ {
+ 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 other platforms, it's the encoded speed.
+ #[cfg(not(any(linux_kernel, bsd)))]
+ {
+ 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.
+ #[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 = "haiku",
+ target_os = "fuchsia",
+ 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 = "haiku"))]
+ 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(
+ solarish,
+ target_os = "aix",
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "haiku",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ )))]
+ const IUTF8 = c::IUTF8;
+ }
+}
+
+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,
+ target_os = "aix",
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ 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;
+ }
+}
+
+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 = "redox")))]
+ const CRTSCTS = c::CRTSCTS;
+
+ /// `CMSPAR`
+ #[cfg(not(any(
+ bsd,
+ solarish,
+ target_os = "aix",
+ target_os = "emscripten",
+ target_os = "haiku",
+ target_os = "redox",
+ )))]
+ const CMSPAR = c::CMSPAR;
+ }
+}
+
+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(target_os = "redox"))]
+ const ECHOPRT = c::ECHOPRT;
+
+ /// `ECHOKE`
+ #[cfg(not(target_os = "redox"))]
+ const ECHOKE = c::ECHOKE;
+
+ /// `FLUSHO`
+ #[cfg(not(target_os = "redox"))]
+ const FLUSHO = c::FLUSHO;
+
+ /// `PENDIN`
+ #[cfg(not(target_os = "redox"))]
+ const PENDIN = c::PENDIN;
+
+ /// `EXTPROC`
+ #[cfg(not(any(target_os = "aix", target_os = "haiku", 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;
+ }
+}
+
+/// 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`.
+ #[cfg(not(any(linux_kernel, bsd)))]
+ pub(crate) 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(target_os = "aix"))]
+ c::B230400 => Some(230_400),
+ #[cfg(not(any(
+ apple,
+ target_os = "aix",
+ target_os = "dragonfly",
+ target_os = "haiku",
+ target_os = "openbsd"
+ )))]
+ c::B460800 => Some(460_800),
+ #[cfg(not(any(bsd, solarish, target_os = "aix", target_os = "haiku")))]
+ c::B500000 => Some(500_000),
+ #[cfg(not(any(bsd, solarish, target_os = "aix", target_os = "haiku")))]
+ c::B576000 => Some(576_000),
+ #[cfg(not(any(
+ apple,
+ target_os = "aix",
+ target_os = "dragonfly",
+ target_os = "haiku",
+ target_os = "openbsd"
+ )))]
+ c::B921600 => Some(921_600),
+ #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))]
+ c::B1000000 => Some(1_000_000),
+ #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))]
+ c::B1152000 => Some(1_152_000),
+ #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))]
+ c::B1500000 => Some(1_500_000),
+ #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", 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 = "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 = "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 = "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 = "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) 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(target_os = "aix"))]
+ 230_400 => Some(c::B230400),
+ #[cfg(not(any(
+ apple,
+ target_os = "aix",
+ target_os = "dragonfly",
+ target_os = "haiku",
+ target_os = "openbsd"
+ )))]
+ 460_800 => Some(c::B460800),
+ #[cfg(not(any(bsd, solarish, target_os = "aix", target_os = "haiku")))]
+ 500_000 => Some(c::B500000),
+ #[cfg(not(any(bsd, solarish, target_os = "aix", target_os = "haiku")))]
+ 576_000 => Some(c::B576000),
+ #[cfg(not(any(
+ apple,
+ target_os = "aix",
+ target_os = "dragonfly",
+ target_os = "haiku",
+ target_os = "openbsd"
+ )))]
+ 921_600 => Some(c::B921600),
+ #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))]
+ 1_000_000 => Some(c::B1000000),
+ #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))]
+ 1_152_000 => Some(c::B1152000),
+ #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))]
+ 1_500_000 => Some(c::B1500000),
+ #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", 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 = "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 = "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 = "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 = "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(
+ apple,
+ solarish,
+ target_os = "aix",
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "haiku",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ 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")))]
+ 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!(
+ core::mem::size_of::<c::termios2>(),
+ core::mem::size_of::<c::termios>()
+ );
+ }
+
+ #[cfg(not(linux_raw))]
+ {
+ #[cfg(not(all(
+ target_env = "gnu",
+ any(
+ target_arch = "sparc",
+ target_arch = "sparc64",
+ target_arch = "mips",
+ target_arch = "mips64"
+ )
+ )))]
+ check_renamed_type!(Termios, 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 = "haiku",
+ target_os = "fuchsia",
+ 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")))]
+fn termios_legacy() {
+ // Check that our doc aliases above are correct.
+ assert_eq!(c::EXTA, c::B19200);
+ 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.
+ assert_eq!(c::B0, 0);
+ assert_eq!(c::B50, 50);
+ assert_eq!(c::B19200, 19200);
+ 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.
+
+ assert_eq!(c::TCSETS2, c::TCSETS2 + 0);
+ assert_eq!(c::TCSETSW2, c::TCSETS2 + 1);
+ assert_eq!(c::TCSETSF2, c::TCSETS2 + 2);
+
+ assert_eq!(c::TCSANOW - c::TCSANOW, 0);
+ assert_eq!(c::TCSADRAIN - c::TCSANOW, 1);
+ assert_eq!(c::TCSAFLUSH - c::TCSANOW, 2);
+
+ // MIPS is different here.
+ #[cfg(any(target_arch = "mips", target_arch = "mips64"))]
+ {
+ 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 = "mips64")))]
+ {
+ assert_eq!(c::TCSANOW, 0);
+ assert_eq!(c::TCSADRAIN, 1);
+ assert_eq!(c::TCSAFLUSH, 2);
+ }
+}
+
+#[cfg(linux_kernel)]
+#[test]
+fn termios_cibaud() {
+ // Test an assumption.
+ assert_eq!(c::CIBAUD, c::CBAUD << c::IBSHIFT);
+}