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