1 //! termios implementation, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/termios.h.html 2 3 use crate::{ 4 header::{errno, sys_ioctl}, 5 platform::{self, types::*}, 6 }; 7 8 pub use self::sys::*; 9 10 #[cfg(target_os = "linux")] 11 #[path = "linux.rs"] 12 pub mod sys; 13 14 #[cfg(target_os = "redox")] 15 #[path = "redox.rs"] 16 pub mod sys; 17 18 pub type cc_t = u8; 19 pub type speed_t = u32; 20 pub type tcflag_t = u32; 21 22 pub const TCOOFF: usize = 0; 23 pub const TCOON: usize = 1; 24 pub const TCIOFF: usize = 2; 25 pub const TCION: usize = 3; 26 27 pub const TCIFLUSH: usize = 0; 28 pub const TCOFLUSH: usize = 1; 29 pub const TCIOFLUSH: usize = 2; 30 31 pub const TCSANOW: usize = 0; 32 pub const TCSADRAIN: usize = 1; 33 pub const TCSAFLUSH: usize = 2; 34 35 #[cfg(target_os = "linux")] 36 #[repr(C)] 37 #[derive(Default)] 38 pub struct termios { 39 c_iflag: tcflag_t, 40 c_oflag: tcflag_t, 41 c_cflag: tcflag_t, 42 c_lflag: tcflag_t, 43 c_line: cc_t, 44 c_cc: [cc_t; NCCS], 45 __c_ispeed: speed_t, 46 __c_ospeed: speed_t, 47 } 48 49 // Must match structure in redox_termios 50 #[cfg(target_os = "redox")] 51 #[repr(C)] 52 #[derive(Default)] 53 pub struct termios { 54 c_iflag: tcflag_t, 55 c_oflag: tcflag_t, 56 c_cflag: tcflag_t, 57 c_lflag: tcflag_t, 58 c_cc: [cc_t; NCCS], 59 } 60 61 #[no_mangle] 62 pub unsafe extern "C" fn tcgetattr(fd: c_int, out: *mut termios) -> c_int { 63 sys_ioctl::ioctl(fd, sys_ioctl::TCGETS, out as *mut c_void) 64 } 65 66 #[no_mangle] 67 pub unsafe extern "C" fn tcsetattr(fd: c_int, act: c_int, value: *mut termios) -> c_int { 68 if act < 0 || act > 2 { 69 platform::errno = errno::EINVAL; 70 return -1; 71 } 72 // This is safe because ioctl shouldn't modify the value 73 sys_ioctl::ioctl(fd, sys_ioctl::TCSETS + act as c_ulong, value as *mut c_void) 74 } 75 76 #[cfg(target_os = "linux")] 77 #[no_mangle] 78 pub unsafe extern "C" fn cfgetispeed(termios_p: *const termios) -> speed_t { 79 (*termios_p).__c_ispeed 80 } 81 82 #[cfg(target_os = "redox")] 83 #[no_mangle] 84 pub unsafe extern "C" fn cfgetispeed(termios_p: *const termios) -> speed_t { 85 //TODO 86 0 87 } 88 89 #[cfg(target_os = "linux")] 90 #[no_mangle] 91 pub unsafe extern "C" fn cfgetospeed(termios_p: *const termios) -> speed_t { 92 (*termios_p).__c_ospeed 93 } 94 95 #[cfg(target_os = "redox")] 96 #[no_mangle] 97 pub unsafe extern "C" fn cfgetospeed(termios_p: *const termios) -> speed_t { 98 //TODO 99 0 100 } 101 102 #[cfg(target_os = "linux")] 103 #[no_mangle] 104 pub unsafe extern "C" fn cfsetispeed(termios_p: *mut termios, speed: speed_t) -> c_int { 105 match speed as usize { 106 B0..=B38400 | B57600..=B4000000 => { 107 (*termios_p).__c_ispeed = speed; 108 0 109 } 110 _ => { 111 platform::errno = errno::EINVAL; 112 -1 113 } 114 } 115 } 116 117 #[cfg(target_os = "linux")] 118 #[no_mangle] 119 pub unsafe extern "C" fn cfsetospeed(termios_p: *mut termios, speed: speed_t) -> c_int { 120 match speed as usize { 121 B0..=B38400 | B57600..=B4000000 => { 122 (*termios_p).__c_ospeed = speed; 123 0 124 } 125 _ => { 126 platform::errno = errno::EINVAL; 127 -1 128 } 129 } 130 } 131 132 #[no_mangle] 133 pub unsafe extern "C" fn tcflush(fd: c_int, queue: c_int) -> c_int { 134 sys_ioctl::ioctl(fd, sys_ioctl::TCFLSH, queue as *mut c_void) 135 } 136 137 #[no_mangle] 138 pub unsafe extern "C" fn tcdrain(fd: c_int) -> c_int { 139 sys_ioctl::ioctl(fd, sys_ioctl::TCSBRK, 1 as *mut _) 140 } 141 142 #[no_mangle] 143 pub unsafe extern "C" fn tcsendbreak(fd: c_int, _dur: c_int) -> c_int { 144 // non-zero duration is ignored by musl due to it being 145 // implementation-defined. we do the same. 146 sys_ioctl::ioctl(fd, sys_ioctl::TCSBRK, 0 as *mut _) 147 } 148 149 #[no_mangle] 150 pub unsafe extern "C" fn tcflow(fd: c_int, action: c_int) -> c_int { 151 // non-zero duration is ignored by musl due to it being 152 // implementation-defined. we do the same. 153 sys_ioctl::ioctl(fd, sys_ioctl::TCXONC, action as *mut _) 154 } 155