xref: /relibc/src/header/termios/mod.rs (revision be35961d82cd98f2a2e61c4f1869271b9f4af571)
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