1 use std::os::unix::io::RawFd;
2
3 use bitflags::bitflags;
4 use nix::libc;
5
6 use crate::Result;
7
8 // These are wrapped in a module because they're `pub` by default
9 mod raw {
10 use nix::libc;
11 use nix::{ioctl_none_bad, ioctl_read, ioctl_read_bad, ioctl_write_ptr, ioctl_write_ptr_bad};
12
13 ioctl_none_bad!(tiocexcl, libc::TIOCEXCL);
14 ioctl_none_bad!(tiocnxcl, libc::TIOCNXCL);
15 ioctl_read_bad!(tiocmget, libc::TIOCMGET, libc::c_int);
16 ioctl_none_bad!(tiocsbrk, libc::TIOCSBRK);
17 ioctl_none_bad!(tioccbrk, libc::TIOCCBRK);
18
19 #[cfg(any(target_os = "android", target_os = "linux"))]
20 ioctl_read_bad!(fionread, libc::FIONREAD, libc::c_int);
21
22 // See: /usr/include/sys/filio.h
23 #[cfg(any(
24 target_os = "dragonfly",
25 target_os = "freebsd",
26 target_os = "ios",
27 target_os = "macos",
28 target_os = "netbsd",
29 target_os = "openbsd"
30 ))]
31 ioctl_read!(fionread, b'f', 127, libc::c_int);
32
33 #[cfg(any(target_os = "android", target_os = "linux"))]
34 ioctl_read_bad!(tiocoutq, libc::TIOCOUTQ, libc::c_int);
35
36 // See: /usr/include/sys/ttycom.h
37 #[cfg(any(
38 target_os = "dragonfly",
39 target_os = "freebsd",
40 target_os = "ios",
41 target_os = "macos",
42 target_os = "netbsd",
43 target_os = "openbsd"
44 ))]
45 ioctl_read!(tiocoutq, b't', 115, libc::c_int);
46
47 ioctl_write_ptr_bad!(tiocmbic, libc::TIOCMBIC, libc::c_int);
48 ioctl_write_ptr_bad!(tiocmbis, libc::TIOCMBIS, libc::c_int);
49 ioctl_read!(
50 #[cfg(any(
51 target_os = "android",
52 all(
53 target_os = "linux",
54 not(any(
55 target_env = "musl",
56 target_arch = "powerpc",
57 target_arch = "powerpc64"
58 ))
59 )
60 ))]
61 tcgets2,
62 b'T',
63 0x2A,
64 libc::termios2
65 );
66 ioctl_write_ptr!(
67 #[cfg(any(
68 target_os = "android",
69 all(
70 target_os = "linux",
71 not(any(
72 target_env = "musl",
73 target_arch = "powerpc",
74 target_arch = "powerpc64"
75 ))
76 )
77 ))]
78 tcsets2,
79 b'T',
80 0x2B,
81 libc::termios2
82 );
83 #[cfg(any(target_os = "ios", target_os = "macos"))]
84 const IOSSIOSPEED: libc::c_ulong = 0x80045402;
85 ioctl_write_ptr_bad!(
86 #[cfg(any(target_os = "ios", target_os = "macos"))]
87 iossiospeed,
88 IOSSIOSPEED,
89 libc::speed_t
90 );
91 }
92
93 bitflags! {
94 /// Flags to indicate which wires in a serial connection to use
95 pub struct SerialLines: libc::c_int {
96 const DATA_SET_READY = libc::TIOCM_DSR;
97 const DATA_TERMINAL_READY = libc::TIOCM_DTR;
98 const REQUEST_TO_SEND = libc::TIOCM_RTS;
99 const SECONDARY_TRANSMIT = libc::TIOCM_ST;
100 const SECONDARY_RECEIVE = libc::TIOCM_SR;
101 const CLEAR_TO_SEND = libc::TIOCM_CTS;
102 const DATA_CARRIER_DETECT = libc::TIOCM_CAR;
103 const RING = libc::TIOCM_RNG;
104 }
105 }
106
tiocexcl(fd: RawFd) -> Result<()>107 pub fn tiocexcl(fd: RawFd) -> Result<()> {
108 unsafe { raw::tiocexcl(fd) }
109 .map(|_| ())
110 .map_err(|e| e.into())
111 }
112
tiocnxcl(fd: RawFd) -> Result<()>113 pub fn tiocnxcl(fd: RawFd) -> Result<()> {
114 unsafe { raw::tiocnxcl(fd) }
115 .map(|_| ())
116 .map_err(|e| e.into())
117 }
118
tiocmget(fd: RawFd) -> Result<SerialLines>119 pub fn tiocmget(fd: RawFd) -> Result<SerialLines> {
120 let mut status: libc::c_int = 0;
121 unsafe { raw::tiocmget(fd, &mut status) }
122 .map(|_| SerialLines::from_bits_truncate(status))
123 .map_err(|e| e.into())
124 }
125
tiocsbrk(fd: RawFd) -> Result<()>126 pub fn tiocsbrk(fd: RawFd) -> Result<()> {
127 unsafe { raw::tiocsbrk(fd) }
128 .map(|_| ())
129 .map_err(|e| e.into())
130 }
131
tioccbrk(fd: RawFd) -> Result<()>132 pub fn tioccbrk(fd: RawFd) -> Result<()> {
133 unsafe { raw::tioccbrk(fd) }
134 .map(|_| ())
135 .map_err(|e| e.into())
136 }
137
fionread(fd: RawFd) -> Result<u32>138 pub fn fionread(fd: RawFd) -> Result<u32> {
139 let mut retval: libc::c_int = 0;
140 unsafe { raw::fionread(fd, &mut retval) }
141 .map(|_| retval as u32)
142 .map_err(|e| e.into())
143 }
144
tiocoutq(fd: RawFd) -> Result<u32>145 pub fn tiocoutq(fd: RawFd) -> Result<u32> {
146 let mut retval: libc::c_int = 0;
147 unsafe { raw::tiocoutq(fd, &mut retval) }
148 .map(|_| retval as u32)
149 .map_err(|e| e.into())
150 }
151
tiocmbic(fd: RawFd, status: SerialLines) -> Result<()>152 pub fn tiocmbic(fd: RawFd, status: SerialLines) -> Result<()> {
153 let bits = status.bits() as libc::c_int;
154 unsafe { raw::tiocmbic(fd, &bits) }
155 .map(|_| ())
156 .map_err(|e| e.into())
157 }
158
tiocmbis(fd: RawFd, status: SerialLines) -> Result<()>159 pub fn tiocmbis(fd: RawFd, status: SerialLines) -> Result<()> {
160 let bits = status.bits() as libc::c_int;
161 unsafe { raw::tiocmbis(fd, &bits) }
162 .map(|_| ())
163 .map_err(|e| e.into())
164 }
165
166 #[cfg(any(
167 target_os = "android",
168 all(
169 target_os = "linux",
170 not(any(
171 target_env = "musl",
172 target_arch = "powerpc",
173 target_arch = "powerpc64"
174 ))
175 )
176 ))]
tcgets2(fd: RawFd) -> Result<libc::termios2>177 pub fn tcgets2(fd: RawFd) -> Result<libc::termios2> {
178 let mut options = std::mem::MaybeUninit::uninit();
179 match unsafe { raw::tcgets2(fd, options.as_mut_ptr()) } {
180 Ok(_) => unsafe { Ok(options.assume_init()) },
181 Err(e) => Err(e.into()),
182 }
183 }
184
185 #[cfg(any(
186 target_os = "android",
187 all(
188 target_os = "linux",
189 not(any(
190 target_env = "musl",
191 target_arch = "powerpc",
192 target_arch = "powerpc64"
193 ))
194 )
195 ))]
tcsets2(fd: RawFd, options: &libc::termios2) -> Result<()>196 pub fn tcsets2(fd: RawFd, options: &libc::termios2) -> Result<()> {
197 unsafe { raw::tcsets2(fd, options) }
198 .map(|_| ())
199 .map_err(|e| e.into())
200 }
201
202 #[cfg(any(target_os = "ios", target_os = "macos"))]
iossiospeed(fd: RawFd, baud_rate: &libc::speed_t) -> Result<()>203 pub fn iossiospeed(fd: RawFd, baud_rate: &libc::speed_t) -> Result<()> {
204 unsafe { raw::iossiospeed(fd, baud_rate) }
205 .map(|_| ())
206 .map_err(|e| e.into())
207 }
208