summaryrefslogtreecommitdiff
path: root/src/sys/termios.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/sys/termios.rs')
-rw-r--r--src/sys/termios.rs408
1 files changed, 408 insertions, 0 deletions
diff --git a/src/sys/termios.rs b/src/sys/termios.rs
new file mode 100644
index 00000000..30eb38b3
--- /dev/null
+++ b/src/sys/termios.rs
@@ -0,0 +1,408 @@
+use errno::{SysResult, from_ffi};
+use fcntl::Fd;
+use libc::c_int;
+
+pub use self::ffi::consts::*;
+
+mod ffi {
+ use libc::c_int;
+
+ pub use self::consts::*;
+
+ // `Termios` contains bitflags which are not considered
+ // `foreign-function-safe` by the compiler.
+ #[allow(improper_ctypes)]
+ extern {
+ pub fn cfgetispeed(termios: *const Termios) -> speed_t;
+ pub fn cfgetospeed(termios: *const Termios) -> speed_t;
+ pub fn cfsetispeed(termios: *mut Termios, speed: speed_t) -> c_int;
+ pub fn cfsetospeed(termios: *mut Termios, speed: speed_t) -> c_int;
+ pub fn tcgetattr(fd: c_int, termios: *mut Termios) -> c_int;
+ pub fn tcsetattr(fd: c_int,
+ optional_actions: c_int,
+ termios: *const Termios) -> c_int;
+ pub fn tcdrain(fd: c_int) -> c_int;
+ pub fn tcflow(fd: c_int, action: c_int) -> c_int;
+ pub fn tcflush(fd: c_int, action: c_int) -> c_int;
+ pub fn tcsendbreak(fd: c_int, duration: c_int) -> c_int;
+ }
+
+ #[cfg(target_os = "macos")]
+ pub mod consts {
+ use libc::{c_int, c_ulong, c_uchar};
+
+ pub type tcflag_t = c_ulong;
+ pub type cc_t = c_uchar;
+ pub type speed_t = c_ulong;
+
+ #[repr(C)]
+ #[derive(Copy)]
+ pub struct Termios {
+ pub c_iflag: InputFlags,
+ pub c_oflag: OutputFlags,
+ pub c_cflag: ControlFlags,
+ pub c_lflag: LocalFlags,
+ pub c_cc: [cc_t; NCCS],
+ pub c_ispeed: speed_t,
+ pub c_ospeed: speed_t
+ }
+
+ pub const VEOF: usize = 0;
+ pub const VEOL: usize = 1;
+ pub const VEOL2: usize = 2;
+ pub const VERASE: usize = 3;
+ pub const VWERASE: usize = 4;
+ pub const VKILL: usize = 5;
+ pub const VREPRINT: usize = 6;
+ pub const VINTR: usize = 8;
+ pub const VQUIT: usize = 9;
+ pub const VSUSP: usize = 10;
+ pub const VDSUSP: usize = 11;
+ pub const VSTART: usize = 12;
+ pub const VSTOP: usize = 13;
+ pub const VLNEXT: usize = 14;
+ pub const VDISCARD: usize = 15;
+ pub const VMIN: usize = 16;
+ pub const VTIME: usize = 17;
+ pub const VSTATUS: usize = 18;
+ pub const NCCS: usize = 20;
+
+ bitflags! {
+ flags InputFlags: tcflag_t {
+ const IGNBRK = 0x00000001,
+ const BRKINT = 0x00000002,
+ const IGNPAR = 0x00000004,
+ const PARMRK = 0x00000008,
+ const INPCK = 0x00000010,
+ const ISTRIP = 0x00000020,
+ const INLCR = 0x00000040,
+ const IGNCR = 0x00000080,
+ const ICRNL = 0x00000100,
+ const IXON = 0x00000200,
+ const IXOFF = 0x00000400,
+ const IXANY = 0x00000800,
+ const IMAXBEL = 0x00002000,
+ const IUTF8 = 0x00004000,
+ }
+ }
+
+ bitflags! {
+ flags OutputFlags: tcflag_t {
+ const OPOST = 0x00000001,
+ const ONLCR = 0x00000002,
+ const OXTABS = 0x00000004,
+ const ONOEOT = 0x00000008,
+ }
+ }
+
+ bitflags! {
+ flags ControlFlags: tcflag_t {
+ const CIGNORE = 0x00000001,
+ const CSIZE = 0x00000300,
+ const CS5 = 0x00000000,
+ const CS6 = 0x00000100,
+ const CS7 = 0x00000200,
+ const CS8 = 0x00000300,
+ const CSTOPB = 0x00000400,
+ const CREAD = 0x00000800,
+ const PARENB = 0x00001000,
+ const PARODD = 0x00002000,
+ const HUPCL = 0x00004000,
+ const CLOCAL = 0x00008000,
+ const CCTS_OFLOW = 0x00010000,
+ const CRTSCTS = 0x00030000,
+ const CRTS_IFLOW = 0x00020000,
+ const CDTR_IFLOW = 0x00040000,
+ const CDSR_OFLOW = 0x00080000,
+ const CCAR_OFLOW = 0x00100000,
+ const MDMBUF = 0x00100000,
+ }
+ }
+
+ bitflags! {
+ flags LocalFlags: tcflag_t {
+ const ECHOKE = 0x00000001,
+ const ECHOE = 0x00000002,
+ const ECHOK = 0x00000004,
+ const ECHO = 0x00000008,
+ const ECHONL = 0x00000010,
+ const ECHOPRT = 0x00000020,
+ const ECHOCTL = 0x00000040,
+ const ISIG = 0x00000080,
+ const ICANON = 0x00000100,
+ const ALTWERASE = 0x00000200,
+ const IEXTEN = 0x00000400,
+ const EXTPROC = 0x00000800,
+ const TOSTOP = 0x00400000,
+ const FLUSHO = 0x00800000,
+ const NOKERNINFO = 0x02000000,
+ const PENDIN = 0x20000000,
+ const NOFLSH = 0x80000000,
+ }
+ }
+
+ pub const NL0: c_int = 0x00000000;
+ pub const NL1: c_int = 0x00000100;
+ pub const NL2: c_int = 0x00000200;
+ pub const NL3: c_int = 0x00000300;
+ pub const TAB0: c_int = 0x00000000;
+ pub const TAB1: c_int = 0x00000400;
+ pub const TAB2: c_int = 0x00000800;
+ pub const TAB3: c_int = 0x00000004;
+ pub const CR0: c_int = 0x00000000;
+ pub const CR1: c_int = 0x00001000;
+ pub const CR2: c_int = 0x00002000;
+ pub const CR3: c_int = 0x00003000;
+ pub const FF0: c_int = 0x00000000;
+ pub const FF1: c_int = 0x00004000;
+ pub const BS0: c_int = 0x00000000;
+ pub const BS1: c_int = 0x00008000;
+ pub const VT0: c_int = 0x00000000;
+ pub const VT1: c_int = 0x00010000;
+
+ // XXX: We're using `repr(C)` because `c_int` doesn't work here.
+ // See https://github.com/rust-lang/rust/issues/10374.
+ #[derive(Copy)]
+ #[repr(C)]
+ pub enum SetArg {
+ TCSANOW = 0,
+ TCSADRAIN = 1,
+ TCSAFLUSH = 2,
+ TCSASOFT = 16,
+ }
+
+ // XXX: We're using `repr(C)` because `c_int` doesn't work here.
+ // See https://github.com/rust-lang/rust/issues/10374.
+ #[derive(Copy)]
+ #[repr(C)]
+ pub enum FlushArg {
+ TCIFLUSH = 1,
+ TCOFLUSH = 2,
+ TCIOFLUSH = 3,
+ }
+
+ // XXX: We're using `repr(C)` because `c_int` doesn't work here.
+ // See https://github.com/rust-lang/rust/issues/10374.
+ #[derive(Copy)]
+ #[repr(C)]
+ pub enum FlowArg {
+ TCOOFF = 1,
+ TCOON = 2,
+ TCIOFF = 3,
+ TCION = 4,
+ }
+ }
+
+ #[cfg(target_os = "linux")]
+ pub mod consts {
+ use libc::{c_int, c_uint, c_uchar};
+
+ pub type tcflag_t = c_uint;
+ pub type cc_t = c_uchar;
+ pub type speed_t = c_uint;
+
+ #[repr(C)]
+ #[derive(Copy)]
+ pub struct Termios {
+ pub c_iflag: InputFlags,
+ pub c_oflag: OutputFlags,
+ pub c_cflag: ControlFlags,
+ pub c_lflag: LocalFlags,
+ pub c_line: cc_t,
+ pub c_cc: [cc_t; NCCS],
+ pub c_ispeed: speed_t,
+ pub c_ospeed: speed_t
+ }
+
+ pub const VEOF: usize = 4;
+ pub const VEOL: usize = 11;
+ pub const VEOL2: usize = 16;
+ pub const VERASE: usize = 2;
+ pub const VWERASE: usize = 14;
+ pub const VKILL: usize = 3;
+ pub const VREPRINT: usize = 12;
+ pub const VINTR: usize = 0;
+ pub const VQUIT: usize = 1;
+ pub const VSUSP: usize = 10;
+ pub const VSTART: usize = 8;
+ pub const VSTOP: usize = 9;
+ pub const VLNEXT: usize = 15;
+ pub const VDISCARD: usize = 13;
+ pub const VMIN: usize = 6;
+ pub const VTIME: usize = 5;
+ pub const NCCS: usize = 32;
+
+ bitflags! {
+ flags InputFlags: tcflag_t {
+ const IGNBRK = 0x00000001,
+ const BRKINT = 0x00000002,
+ const IGNPAR = 0x00000004,
+ const PARMRK = 0x00000008,
+ const INPCK = 0x00000010,
+ const ISTRIP = 0x00000020,
+ const INLCR = 0x00000040,
+ const IGNCR = 0x00000080,
+ const ICRNL = 0x00000100,
+ const IXON = 0x00000400,
+ const IXOFF = 0x00001000,
+ const IXANY = 0x00000800,
+ const IMAXBEL = 0x00002000,
+ const IUTF8 = 0x00004000,
+ }
+ }
+
+ bitflags! {
+ flags OutputFlags: tcflag_t {
+ const OPOST = 0x00000001,
+ const ONLCR = 0x00000004,
+ }
+ }
+
+ bitflags! {
+ flags ControlFlags: tcflag_t {
+ const CSIZE = 0x00000030,
+ const CS5 = 0x00000000,
+ const CS6 = 0x00000010,
+ const CS7 = 0x00000020,
+ const CS8 = 0x00000030,
+ const CSTOPB = 0x00000040,
+ const CREAD = 0x00000080,
+ const PARENB = 0x00000100,
+ const PARODD = 0x00000200,
+ const HUPCL = 0x00000400,
+ const CLOCAL = 0x00000800,
+ const CRTSCTS = 0x80000000,
+ }
+ }
+
+ bitflags! {
+ flags LocalFlags: tcflag_t {
+ const ECHOKE = 0x00000800,
+ const ECHOE = 0x00000010,
+ const ECHOK = 0x00000020,
+ const ECHO = 0x00000008,
+ const ECHONL = 0x00000040,
+ const ECHOPRT = 0x00000400,
+ const ECHOCTL = 0x00000200,
+ const ISIG = 0x00000001,
+ const ICANON = 0x00000002,
+ const IEXTEN = 0x00008000,
+ const EXTPROC = 0x00010000,
+ const TOSTOP = 0x00000100,
+ const FLUSHO = 0x00001000,
+ const PENDIN = 0x00004000,
+ const NOFLSH = 0x00000080,
+ }
+ }
+
+ pub const NL0: c_int = 0x00000000;
+ pub const NL1: c_int = 0x00000100;
+ pub const TAB0: c_int = 0x00000000;
+ pub const TAB1: c_int = 0x00000800;
+ pub const TAB2: c_int = 0x00001000;
+ pub const TAB3: c_int = 0x00001800;
+ pub const CR0: c_int = 0x00000000;
+ pub const CR1: c_int = 0x00000200;
+ pub const CR2: c_int = 0x00000400;
+ pub const CR3: c_int = 0x00000600;
+ pub const FF0: c_int = 0x00000000;
+ pub const FF1: c_int = 0x00008000;
+ pub const BS0: c_int = 0x00000000;
+ pub const BS1: c_int = 0x00002000;
+ pub const VT0: c_int = 0x00000000;
+ pub const VT1: c_int = 0x00004000;
+
+ // XXX: We're using `repr(C)` because `c_int` doesn't work here.
+ // See https://github.com/rust-lang/rust/issues/10374.
+ #[derive(Copy)]
+ #[repr(C)]
+ pub enum SetArg {
+ TCSANOW = 0,
+ TCSADRAIN = 1,
+ TCSAFLUSH = 2,
+ }
+
+ // XXX: We're using `repr(C)` because `c_int` doesn't work here.
+ // See https://github.com/rust-lang/rust/issues/10374.
+ #[derive(Copy)]
+ #[repr(C)]
+ pub enum FlushArg {
+ TCIFLUSH = 0,
+ TCOFLUSH = 1,
+ TCIOFLUSH = 2,
+ }
+
+ // XXX: We're using `repr(C)` because `c_int` doesn't work here.
+ // See https://github.com/rust-lang/rust/issues/10374.
+ #[derive(Copy)]
+ #[repr(C)]
+ pub enum FlowArg {
+ TCOOFF = 0,
+ TCOON = 1,
+ TCIOFF = 2,
+ TCION = 3,
+ }
+ }
+}
+
+pub fn cfgetispeed(termios: &Termios) -> speed_t {
+ unsafe {
+ ffi::cfgetispeed(termios)
+ }
+}
+
+pub fn cfgetospeed(termios: &Termios) -> speed_t {
+ unsafe {
+ ffi::cfgetospeed(termios)
+ }
+}
+
+pub fn cfsetispeed(termios: &mut Termios, speed: speed_t) -> SysResult<()> {
+ from_ffi(unsafe {
+ ffi::cfsetispeed(termios, speed)
+ })
+}
+
+pub fn cfsetospeed(termios: &mut Termios, speed: speed_t) -> SysResult<()> {
+ from_ffi(unsafe {
+ ffi::cfsetospeed(termios, speed)
+ })
+}
+
+pub fn tcgetattr(fd: Fd, termios: &mut Termios) -> SysResult<()> {
+ from_ffi(unsafe {
+ ffi::tcgetattr(fd, termios)
+ })
+}
+
+pub fn tcsetattr(fd: Fd,
+ actions: SetArg,
+ termios: &Termios) -> SysResult<()> {
+ from_ffi(unsafe {
+ ffi::tcsetattr(fd, actions as c_int, termios)
+ })
+}
+
+pub fn tcdrain(fd: Fd) -> SysResult<()> {
+ from_ffi(unsafe {
+ ffi::tcdrain(fd)
+ })
+}
+
+pub fn tcflow(fd: Fd, action: FlowArg) -> SysResult<()> {
+ from_ffi(unsafe {
+ ffi::tcflow(fd, action as c_int)
+ })
+}
+
+pub fn tcflush(fd: Fd, action: FlushArg) -> SysResult<()> {
+ from_ffi(unsafe {
+ ffi::tcflush(fd, action as c_int)
+ })
+}
+
+pub fn tcsendbreak(fd: Fd, action: c_int) -> SysResult<()> {
+ from_ffi(unsafe {
+ ffi::tcsendbreak(fd, action)
+ })
+}