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