1 | use crate::backend::c; |
2 | use crate::{backend, io}; |
3 | use bitflags::bitflags; |
4 | |
5 | /// `struct termios` for use with [`tcgetattr`] and [`tcsetattr`]. |
6 | /// |
7 | /// [`tcgetattr`]: crate::termios::tcgetattr |
8 | /// [`tcsetattr`]: crate::termios::tcsetattr |
9 | #[repr (C)] |
10 | #[derive (Clone)] |
11 | pub struct Termios { |
12 | /// How is input interpreted? |
13 | #[doc (alias = "c_iflag" )] |
14 | pub input_modes: InputModes, |
15 | |
16 | /// How is output translated? |
17 | #[doc (alias = "c_oflag" )] |
18 | pub output_modes: OutputModes, |
19 | |
20 | /// Low-level configuration flags. |
21 | #[doc (alias = "c_cflag" )] |
22 | pub control_modes: ControlModes, |
23 | |
24 | /// High-level configuration flags. |
25 | #[doc (alias = "c_lflag" )] |
26 | pub local_modes: LocalModes, |
27 | |
28 | /// Line discipline. |
29 | #[doc (alias = "c_line" )] |
30 | #[cfg (not(all(linux_raw, any(target_arch = "powerpc" , target_arch = "powerpc64" ))))] |
31 | #[cfg (any( |
32 | linux_like, |
33 | target_env = "newlib" , |
34 | target_os = "fuchsia" , |
35 | target_os = "haiku" , |
36 | target_os = "redox" |
37 | ))] |
38 | pub line_discipline: c::cc_t, |
39 | |
40 | /// How are various special control codes handled? |
41 | #[doc (alias = "c_cc" )] |
42 | #[cfg (not(target_os = "haiku" ))] |
43 | pub special_codes: SpecialCodes, |
44 | |
45 | #[cfg (target_os = "nto" )] |
46 | pub(crate) __reserved: [c::c_uint; 3], |
47 | |
48 | /// Line discipline. |
49 | // On PowerPC, this field comes after `c_cc`. |
50 | #[doc (alias = "c_line" )] |
51 | #[cfg (all(linux_raw, any(target_arch = "powerpc" , target_arch = "powerpc64" )))] |
52 | pub line_discipline: c::cc_t, |
53 | |
54 | /// See the `input_speed` and `set_input_seed` functions. |
55 | /// |
56 | /// On Linux and BSDs, this is the arbitrary integer speed value. On all |
57 | /// other platforms, this is the encoded speed value. |
58 | #[cfg (not(any(solarish, all(libc, target_env = "newlib" ), target_os = "aix" )))] |
59 | pub(crate) input_speed: c::speed_t, |
60 | |
61 | /// See the `output_speed` and `set_output_seed` functions. |
62 | /// |
63 | /// On Linux and BSDs, this is the integer speed value. On all other |
64 | /// platforms, this is the encoded speed value. |
65 | #[cfg (not(any(solarish, all(libc, target_env = "newlib" ), target_os = "aix" )))] |
66 | pub(crate) output_speed: c::speed_t, |
67 | |
68 | /// How are various special control codes handled? |
69 | #[doc (alias = "c_cc" )] |
70 | #[cfg (target_os = "haiku" )] |
71 | pub special_codes: SpecialCodes, |
72 | } |
73 | |
74 | impl Termios { |
75 | /// `cfmakeraw(self)`—Set a `Termios` value to the settings for “raw” mode. |
76 | /// |
77 | /// In raw mode, input is available a byte at a time, echoing is disabled, |
78 | /// and special terminal input and output codes are disabled. |
79 | #[cfg (not(target_os = "nto" ))] |
80 | #[doc (alias = "cfmakeraw" )] |
81 | #[inline ] |
82 | pub fn make_raw(&mut self) { |
83 | backend::termios::syscalls::cfmakeraw(self) |
84 | } |
85 | |
86 | /// Return the input communication speed. |
87 | /// |
88 | /// Unlike the `c_ispeed` field in GLIBC and others, this returns the |
89 | /// integer value of the speed, rather than the `B*` encoded constant |
90 | /// value. |
91 | #[doc (alias = "c_ispeed" )] |
92 | #[doc (alias = "cfgetispeed" )] |
93 | #[doc (alias = "cfgetspeed" )] |
94 | #[inline ] |
95 | pub fn input_speed(&self) -> u32 { |
96 | // On Linux and BSDs, `input_speed` is the arbitrary integer speed. |
97 | #[cfg (any(linux_kernel, bsd))] |
98 | { |
99 | debug_assert!(u32::try_from(self.input_speed).is_ok()); |
100 | self.input_speed as u32 |
101 | } |
102 | |
103 | // On illumos, `input_speed` is not present. |
104 | #[cfg (any(solarish, all(libc, target_env = "newlib" ), target_os = "aix" ))] |
105 | unsafe { |
106 | speed::decode(c::cfgetispeed(crate::utils::as_ptr(self).cast())).unwrap() |
107 | } |
108 | |
109 | // On other platforms, it's the encoded speed. |
110 | #[cfg (not(any( |
111 | linux_kernel, |
112 | bsd, |
113 | solarish, |
114 | all(libc, target_env = "newlib" ), |
115 | target_os = "aix" |
116 | )))] |
117 | { |
118 | speed::decode(self.input_speed).unwrap() |
119 | } |
120 | } |
121 | |
122 | /// Return the output communication speed. |
123 | /// |
124 | /// Unlike the `c_ospeed` field in GLIBC and others, this returns the |
125 | /// arbitrary integer value of the speed, rather than the `B*` encoded |
126 | /// constant value. |
127 | #[inline ] |
128 | pub fn output_speed(&self) -> u32 { |
129 | // On Linux and BSDs, `input_speed` is the arbitrary integer speed. |
130 | #[cfg (any(linux_kernel, bsd))] |
131 | { |
132 | debug_assert!(u32::try_from(self.output_speed).is_ok()); |
133 | self.output_speed as u32 |
134 | } |
135 | |
136 | // On illumos, `output_speed` is not present. |
137 | #[cfg (any(solarish, all(libc, target_env = "newlib" ), target_os = "aix" ))] |
138 | unsafe { |
139 | speed::decode(c::cfgetospeed(crate::utils::as_ptr(self).cast())).unwrap() |
140 | } |
141 | |
142 | // On other platforms, it's the encoded speed. |
143 | #[cfg (not(any( |
144 | linux_kernel, |
145 | bsd, |
146 | solarish, |
147 | all(libc, target_env = "newlib" ), |
148 | target_os = "aix" |
149 | )))] |
150 | { |
151 | speed::decode(self.output_speed).unwrap() |
152 | } |
153 | } |
154 | |
155 | /// Set the input and output communication speeds. |
156 | /// |
157 | /// Unlike the `c_ispeed` and `c_ospeed` fields in GLIBC and others, this |
158 | /// takes the arbitrary integer value of the speed, rather than the `B*` |
159 | /// encoded constant value. Not all implementations support all integer |
160 | /// values; use the constants in the [`speed`] module for likely-supported |
161 | /// speeds. |
162 | #[cfg (not(target_os = "nto" ))] |
163 | #[doc (alias = "cfsetspeed" )] |
164 | #[doc (alias = "CBAUD" )] |
165 | #[doc (alias = "CBAUDEX" )] |
166 | #[doc (alias = "CIBAUD" )] |
167 | #[doc (alias = "CIBAUDEX" )] |
168 | #[inline ] |
169 | pub fn set_speed(&mut self, new_speed: u32) -> io::Result<()> { |
170 | backend::termios::syscalls::set_speed(self, new_speed) |
171 | } |
172 | |
173 | /// Set the input communication speed. |
174 | /// |
175 | /// Unlike the `c_ispeed` field in GLIBC and others, this takes the |
176 | /// arbitrary integer value of the speed, rather than the `B*` encoded |
177 | /// constant value. Not all implementations support all integer values; use |
178 | /// the constants in the [`speed`] module for known-supported speeds. |
179 | /// |
180 | /// On some platforms, changing the input speed changes the output speed |
181 | /// to the same speed. |
182 | #[doc (alias = "c_ispeed" )] |
183 | #[doc (alias = "cfsetispeed" )] |
184 | #[doc (alias = "CIBAUD" )] |
185 | #[doc (alias = "CIBAUDEX" )] |
186 | #[inline ] |
187 | pub fn set_input_speed(&mut self, new_speed: u32) -> io::Result<()> { |
188 | backend::termios::syscalls::set_input_speed(self, new_speed) |
189 | } |
190 | |
191 | /// Set the output communication speed. |
192 | /// |
193 | /// Unlike the `c_ospeed` field in GLIBC and others, this takes the |
194 | /// arbitrary integer value of the speed, rather than the `B*` encoded |
195 | /// constant value. Not all implementations support all integer values; use |
196 | /// the constants in the [`speed`] module for known-supported speeds. |
197 | /// |
198 | /// On some platforms, changing the output speed changes the input speed |
199 | /// to the same speed. |
200 | #[doc (alias = "c_ospeed" )] |
201 | #[doc (alias = "cfsetospeed" )] |
202 | #[doc (alias = "CBAUD" )] |
203 | #[doc (alias = "CBAUDEX" )] |
204 | #[inline ] |
205 | pub fn set_output_speed(&mut self, new_speed: u32) -> io::Result<()> { |
206 | backend::termios::syscalls::set_output_speed(self, new_speed) |
207 | } |
208 | } |
209 | |
210 | impl core::fmt::Debug for Termios { |
211 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { |
212 | let mut d: DebugStruct<'_, '_> = f.debug_struct(name:"Termios" ); |
213 | d.field(name:"input_modes" , &self.input_modes); |
214 | d.field(name:"output_modes" , &self.output_modes); |
215 | d.field(name:"control_modes" , &self.control_modes); |
216 | d.field(name:"local_modes" , &self.local_modes); |
217 | #[cfg (any( |
218 | linux_like, |
219 | target_env = "newlib" , |
220 | target_os = "fuchsia" , |
221 | target_os = "haiku" , |
222 | target_os = "redox" |
223 | ))] |
224 | { |
225 | d.field(name:"line_discipline" , &self.line_discipline); |
226 | } |
227 | d.field(name:"special_codes" , &self.special_codes); |
228 | d.field(name:"input_speed" , &self.input_speed()); |
229 | d.field(name:"output_speed" , &self.output_speed()); |
230 | d.finish() |
231 | } |
232 | } |
233 | |
234 | bitflags! { |
235 | /// Flags controlling terminal input. |
236 | #[repr (transparent)] |
237 | #[derive (Copy, Clone, Eq, PartialEq, Hash, Debug)] |
238 | pub struct InputModes: c::tcflag_t { |
239 | /// `IGNBRK` |
240 | const IGNBRK = c::IGNBRK; |
241 | |
242 | /// `BRKINT` |
243 | const BRKINT = c::BRKINT; |
244 | |
245 | /// `IGNPAR` |
246 | const IGNPAR = c::IGNPAR; |
247 | |
248 | /// `PARMRK` |
249 | const PARMRK = c::PARMRK; |
250 | |
251 | /// `INPCK` |
252 | const INPCK = c::INPCK; |
253 | |
254 | /// `ISTRIP` |
255 | const ISTRIP = c::ISTRIP; |
256 | |
257 | /// `INLCR` |
258 | const INLCR = c::INLCR; |
259 | |
260 | /// `IGNCR` |
261 | const IGNCR = c::IGNCR; |
262 | |
263 | /// `ICRNL` |
264 | const ICRNL = c::ICRNL; |
265 | |
266 | /// `IUCLC` |
267 | #[cfg(any(linux_kernel, solarish, target_os = "aix" , target_os = "haiku" , target_os = "nto" ))] |
268 | const IUCLC = c::IUCLC; |
269 | |
270 | /// `IXON` |
271 | const IXON = c::IXON; |
272 | |
273 | /// `IXANY` |
274 | #[cfg(not(target_os = "redox" ))] |
275 | const IXANY = c::IXANY; |
276 | |
277 | /// `IXOFF` |
278 | const IXOFF = c::IXOFF; |
279 | |
280 | /// `IMAXBEL` |
281 | #[cfg(not(any(target_os = "haiku" , target_os = "redox" )))] |
282 | const IMAXBEL = c::IMAXBEL; |
283 | |
284 | /// `IUTF8` |
285 | #[cfg(not(any( |
286 | freebsdlike, |
287 | netbsdlike, |
288 | solarish, |
289 | target_os = "aix" , |
290 | target_os = "emscripten" , |
291 | target_os = "haiku" , |
292 | target_os = "hurd" , |
293 | target_os = "redox" , |
294 | )))] |
295 | const IUTF8 = c::IUTF8; |
296 | |
297 | /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags> |
298 | const _ = !0; |
299 | } |
300 | } |
301 | |
302 | bitflags! { |
303 | /// Flags controlling terminal output. |
304 | #[repr (transparent)] |
305 | #[derive (Copy, Clone, Eq, PartialEq, Hash, Debug)] |
306 | pub struct OutputModes: c::tcflag_t { |
307 | /// `OPOST` |
308 | const OPOST = c::OPOST; |
309 | |
310 | /// `OLCUC` |
311 | #[cfg(not(any( |
312 | apple, |
313 | freebsdlike, |
314 | target_os = "aix" , |
315 | target_os = "netbsd" , |
316 | target_os = "redox" , |
317 | )))] |
318 | const OLCUC = c::OLCUC; |
319 | |
320 | /// `ONLCR` |
321 | const ONLCR = c::ONLCR; |
322 | |
323 | /// `OCRNL` |
324 | const OCRNL = c::OCRNL; |
325 | |
326 | /// `ONOCR` |
327 | const ONOCR = c::ONOCR; |
328 | |
329 | /// `ONLRET` |
330 | const ONLRET = c::ONLRET; |
331 | |
332 | /// `OFILL` |
333 | #[cfg(not(bsd))] |
334 | const OFILL = c::OFILL; |
335 | |
336 | /// `OFDEL` |
337 | #[cfg(not(bsd))] |
338 | const OFDEL = c::OFDEL; |
339 | |
340 | /// `NLDLY` |
341 | #[cfg(not(any(bsd, solarish, target_os = "redox" )))] |
342 | const NLDLY = c::NLDLY; |
343 | |
344 | /// `NL0` |
345 | #[cfg(not(any(bsd, solarish, target_os = "fuchsia" , target_os = "redox" )))] |
346 | const NL0 = c::NL0; |
347 | |
348 | /// `NL1` |
349 | #[cfg(not(any(bsd, solarish, target_os = "fuchsia" , target_os = "redox" )))] |
350 | const NL1 = c::NL1; |
351 | |
352 | /// `CRDLY` |
353 | #[cfg(not(any(bsd, solarish, target_os = "redox" )))] |
354 | const CRDLY = c::CRDLY; |
355 | |
356 | /// `CR0` |
357 | #[cfg(not(any(bsd, solarish, target_os = "fuchsia" , target_os = "redox" )))] |
358 | const CR0 = c::CR0; |
359 | |
360 | /// `CR1` |
361 | #[cfg(not(any( |
362 | target_env = "musl" , |
363 | bsd, |
364 | solarish, |
365 | target_os = "emscripten" , |
366 | target_os = "fuchsia" , |
367 | target_os = "redox" , |
368 | )))] |
369 | const CR1 = c::CR1; |
370 | |
371 | /// `CR2` |
372 | #[cfg(not(any( |
373 | target_env = "musl" , |
374 | bsd, |
375 | solarish, |
376 | target_os = "emscripten" , |
377 | target_os = "fuchsia" , |
378 | target_os = "redox" , |
379 | )))] |
380 | const CR2 = c::CR2; |
381 | |
382 | /// `CR3` |
383 | #[cfg(not(any( |
384 | target_env = "musl" , |
385 | bsd, |
386 | solarish, |
387 | target_os = "emscripten" , |
388 | target_os = "fuchsia" , |
389 | target_os = "redox" , |
390 | )))] |
391 | const CR3 = c::CR3; |
392 | |
393 | /// `TABDLY` |
394 | #[cfg(not(any( |
395 | netbsdlike, |
396 | solarish, |
397 | target_os = "dragonfly" , |
398 | target_os = "redox" , |
399 | )))] |
400 | const TABDLY = c::TABDLY; |
401 | |
402 | /// `TAB0` |
403 | #[cfg(not(any( |
404 | netbsdlike, |
405 | solarish, |
406 | target_os = "dragonfly" , |
407 | target_os = "fuchsia" , |
408 | target_os = "redox" , |
409 | )))] |
410 | const TAB0 = c::TAB0; |
411 | |
412 | /// `TAB1` |
413 | #[cfg(not(any( |
414 | target_env = "musl" , |
415 | bsd, |
416 | solarish, |
417 | target_os = "emscripten" , |
418 | target_os = "fuchsia" , |
419 | target_os = "redox" , |
420 | )))] |
421 | const TAB1 = c::TAB1; |
422 | |
423 | /// `TAB2` |
424 | #[cfg(not(any( |
425 | target_env = "musl" , |
426 | bsd, |
427 | solarish, |
428 | target_os = "emscripten" , |
429 | target_os = "fuchsia" , |
430 | target_os = "redox" , |
431 | )))] |
432 | const TAB2 = c::TAB2; |
433 | |
434 | /// `TAB3` |
435 | #[cfg(not(any( |
436 | target_env = "musl" , |
437 | bsd, |
438 | solarish, |
439 | target_os = "emscripten" , |
440 | target_os = "fuchsia" , |
441 | target_os = "redox" , |
442 | )))] |
443 | const TAB3 = c::TAB3; |
444 | |
445 | /// `XTABS` |
446 | #[cfg(not(any( |
447 | bsd, |
448 | solarish, |
449 | target_os = "aix" , |
450 | target_os = "haiku" , |
451 | target_os = "redox" , |
452 | )))] |
453 | const XTABS = c::XTABS; |
454 | |
455 | /// `BSDLY` |
456 | #[cfg(not(any(bsd, solarish, target_os = "redox" )))] |
457 | const BSDLY = c::BSDLY; |
458 | |
459 | /// `BS0` |
460 | #[cfg(not(any(bsd, solarish, target_os = "fuchsia" , target_os = "redox" )))] |
461 | const BS0 = c::BS0; |
462 | |
463 | /// `BS1` |
464 | #[cfg(not(any( |
465 | target_env = "musl" , |
466 | bsd, |
467 | solarish, |
468 | target_os = "emscripten" , |
469 | target_os = "fuchsia" , |
470 | target_os = "redox" , |
471 | )))] |
472 | const BS1 = c::BS1; |
473 | |
474 | /// `FFDLY` |
475 | #[cfg(not(any(bsd, solarish, target_os = "redox" )))] |
476 | const FFDLY = c::FFDLY; |
477 | |
478 | /// `FF0` |
479 | #[cfg(not(any(bsd, solarish, target_os = "fuchsia" , target_os = "redox" )))] |
480 | const FF0 = c::FF0; |
481 | |
482 | /// `FF1` |
483 | #[cfg(not(any( |
484 | target_env = "musl" , |
485 | bsd, |
486 | solarish, |
487 | target_os = "emscripten" , |
488 | target_os = "fuchsia" , |
489 | target_os = "redox" , |
490 | )))] |
491 | const FF1 = c::FF1; |
492 | |
493 | /// `VTDLY` |
494 | #[cfg(not(any(bsd, solarish, target_os = "redox" )))] |
495 | const VTDLY = c::VTDLY; |
496 | |
497 | /// `VT0` |
498 | #[cfg(not(any(bsd, solarish, target_os = "fuchsia" , target_os = "redox" )))] |
499 | const VT0 = c::VT0; |
500 | |
501 | /// `VT1` |
502 | #[cfg(not(any( |
503 | target_env = "musl" , |
504 | bsd, |
505 | solarish, |
506 | target_os = "emscripten" , |
507 | target_os = "fuchsia" , |
508 | target_os = "redox" , |
509 | )))] |
510 | const VT1 = c::VT1; |
511 | |
512 | /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags> |
513 | const _ = !0; |
514 | } |
515 | } |
516 | |
517 | bitflags! { |
518 | /// Flags controlling special terminal modes. |
519 | /// |
520 | /// `CBAUD`, `CBAUDEX`, `CIBAUD`, and `CIBAUDEX` are not defined here, |
521 | /// because they're handled automatically by [`Termios::set_speed`] and |
522 | /// related functions. |
523 | #[repr (transparent)] |
524 | #[derive (Copy, Clone, Eq, PartialEq, Hash, Debug)] |
525 | pub struct ControlModes: c::tcflag_t { |
526 | /// `CSIZE` |
527 | const CSIZE = c::CSIZE; |
528 | |
529 | /// `CS5` |
530 | const CS5 = c::CS5; |
531 | |
532 | /// `CS6` |
533 | const CS6 = c::CS6; |
534 | |
535 | /// `CS7` |
536 | const CS7 = c::CS7; |
537 | |
538 | /// `CS8` |
539 | const CS8 = c::CS8; |
540 | |
541 | /// `CSTOPB` |
542 | const CSTOPB = c::CSTOPB; |
543 | |
544 | /// `CREAD` |
545 | const CREAD = c::CREAD; |
546 | |
547 | /// `PARENB` |
548 | const PARENB = c::PARENB; |
549 | |
550 | /// `PARODD` |
551 | const PARODD = c::PARODD; |
552 | |
553 | /// `HUPCL` |
554 | const HUPCL = c::HUPCL; |
555 | |
556 | /// `CLOCAL` |
557 | const CLOCAL = c::CLOCAL; |
558 | |
559 | /// `CRTSCTS` |
560 | #[cfg(not(any(target_os = "aix" , target_os = "nto" , target_os = "redox" )))] |
561 | const CRTSCTS = c::CRTSCTS; |
562 | |
563 | /// `CMSPAR` |
564 | #[cfg(not(any( |
565 | bsd, |
566 | solarish, |
567 | target_os = "aix" , |
568 | target_os = "emscripten" , |
569 | target_os = "haiku" , |
570 | target_os = "hurd" , |
571 | target_os = "nto" , |
572 | target_os = "redox" , |
573 | )))] |
574 | const CMSPAR = c::CMSPAR; |
575 | |
576 | /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags> |
577 | const _ = !0; |
578 | } |
579 | } |
580 | |
581 | bitflags! { |
582 | /// Flags controlling “local” terminal modes. |
583 | #[repr (transparent)] |
584 | #[derive (Copy, Clone, Eq, PartialEq, Hash, Debug)] |
585 | pub struct LocalModes: c::tcflag_t { |
586 | /// `XCASE` |
587 | #[cfg(any(linux_kernel, target_arch = "s390x" , target_os = "haiku" ))] |
588 | const XCASE = c::XCASE; |
589 | |
590 | /// `ECHOCTL` |
591 | #[cfg(not(target_os = "redox" ))] |
592 | const ECHOCTL = c::ECHOCTL; |
593 | |
594 | /// `ECHOPRT` |
595 | #[cfg(not(any(target_os = "nto" , target_os = "redox" )))] |
596 | const ECHOPRT = c::ECHOPRT; |
597 | |
598 | /// `ECHOKE` |
599 | #[cfg(not(target_os = "redox" ))] |
600 | const ECHOKE = c::ECHOKE; |
601 | |
602 | /// `FLUSHO` |
603 | #[cfg(not(any(target_os = "nto" , target_os = "redox" )))] |
604 | const FLUSHO = c::FLUSHO; |
605 | |
606 | /// `PENDIN` |
607 | #[cfg(not(any(target_os = "nto" , target_os = "redox" )))] |
608 | const PENDIN = c::PENDIN; |
609 | |
610 | /// `EXTPROC` |
611 | #[cfg(not(any(target_os = "aix" , target_os = "haiku" , target_os = "nto" , target_os = "redox" )))] |
612 | const EXTPROC = c::EXTPROC; |
613 | |
614 | /// `ISIG` |
615 | const ISIG = c::ISIG; |
616 | |
617 | /// `ICANON`—A flag for the `c_lflag` field of [`Termios`] indicating |
618 | /// canonical mode. |
619 | const ICANON = c::ICANON; |
620 | |
621 | /// `ECHO` |
622 | const ECHO = c::ECHO; |
623 | |
624 | /// `ECHOE` |
625 | const ECHOE = c::ECHOE; |
626 | |
627 | /// `ECHOK` |
628 | const ECHOK = c::ECHOK; |
629 | |
630 | /// `ECHONL` |
631 | const ECHONL = c::ECHONL; |
632 | |
633 | /// `NOFLSH` |
634 | const NOFLSH = c::NOFLSH; |
635 | |
636 | /// `TOSTOP` |
637 | const TOSTOP = c::TOSTOP; |
638 | |
639 | /// `IEXTEN` |
640 | const IEXTEN = c::IEXTEN; |
641 | |
642 | /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags> |
643 | const _ = !0; |
644 | } |
645 | } |
646 | |
647 | /// Speeds for use with [`Termios::set_input_speed`] and |
648 | /// [`Termios::set_output_speed`]. |
649 | /// |
650 | /// Unlike in some platforms' libc APIs, these always have the same numerical |
651 | /// value as their names; for example, `B50` has the value `50`, and so on. |
652 | /// Consequently, it's not necessary to use them. They are provided here |
653 | /// because they help identify speeds which are likely to be supported, on |
654 | /// platforms which don't support arbitrary speeds. |
655 | pub mod speed { |
656 | #[cfg (not(bsd))] |
657 | use crate::backend::c; |
658 | |
659 | /// `B0` |
660 | pub const B0: u32 = 0; |
661 | |
662 | /// `B50` |
663 | pub const B50: u32 = 50; |
664 | |
665 | /// `B75` |
666 | pub const B75: u32 = 75; |
667 | |
668 | /// `B110` |
669 | pub const B110: u32 = 110; |
670 | |
671 | /// `B134` |
672 | pub const B134: u32 = 134; |
673 | |
674 | /// `B150` |
675 | pub const B150: u32 = 150; |
676 | |
677 | /// `B200` |
678 | pub const B200: u32 = 200; |
679 | |
680 | /// `B300` |
681 | pub const B300: u32 = 300; |
682 | |
683 | /// `B600` |
684 | pub const B600: u32 = 600; |
685 | |
686 | /// `B1200` |
687 | pub const B1200: u32 = 1200; |
688 | |
689 | /// `B1800` |
690 | pub const B1800: u32 = 1800; |
691 | |
692 | /// `B2400` |
693 | pub const B2400: u32 = 2400; |
694 | |
695 | /// `B4800` |
696 | pub const B4800: u32 = 4800; |
697 | |
698 | /// `B9600` |
699 | pub const B9600: u32 = 9600; |
700 | |
701 | /// `B19200` |
702 | #[doc (alias = "EXTA" )] |
703 | pub const B19200: u32 = 19200; |
704 | |
705 | /// `B38400` |
706 | #[doc (alias = "EXTB" )] |
707 | pub const B38400: u32 = 38400; |
708 | |
709 | /// `B57600` |
710 | #[cfg (not(target_os = "aix" ))] |
711 | pub const B57600: u32 = 57600; |
712 | |
713 | /// `B115200` |
714 | #[cfg (not(target_os = "aix" ))] |
715 | pub const B115200: u32 = 115_200; |
716 | |
717 | /// `B230400` |
718 | #[cfg (not(target_os = "aix" ))] |
719 | pub const B230400: u32 = 230_400; |
720 | |
721 | /// `B460800` |
722 | #[cfg (not(any( |
723 | apple, |
724 | target_os = "aix" , |
725 | target_os = "dragonfly" , |
726 | target_os = "haiku" , |
727 | target_os = "openbsd" |
728 | )))] |
729 | pub const B460800: u32 = 460_800; |
730 | |
731 | /// `B500000` |
732 | #[cfg (not(any(bsd, solarish, target_os = "aix" , target_os = "haiku" )))] |
733 | pub const B500000: u32 = 500_000; |
734 | |
735 | /// `B576000` |
736 | #[cfg (not(any(bsd, solarish, target_os = "aix" , target_os = "haiku" )))] |
737 | pub const B576000: u32 = 576_000; |
738 | |
739 | /// `B921600` |
740 | #[cfg (not(any( |
741 | apple, |
742 | target_os = "aix" , |
743 | target_os = "dragonfly" , |
744 | target_os = "haiku" , |
745 | target_os = "openbsd" |
746 | )))] |
747 | pub const B921600: u32 = 921_600; |
748 | |
749 | /// `B1000000` |
750 | #[cfg (not(any(bsd, target_os = "aix" , target_os = "haiku" , target_os = "solaris" )))] |
751 | pub const B1000000: u32 = 1_000_000; |
752 | |
753 | /// `B1152000` |
754 | #[cfg (not(any(bsd, target_os = "aix" , target_os = "haiku" , target_os = "solaris" )))] |
755 | pub const B1152000: u32 = 1_152_000; |
756 | |
757 | /// `B1500000` |
758 | #[cfg (not(any(bsd, target_os = "aix" , target_os = "haiku" , target_os = "solaris" )))] |
759 | pub const B1500000: u32 = 1_500_000; |
760 | |
761 | /// `B2000000` |
762 | #[cfg (not(any(bsd, target_os = "aix" , target_os = "haiku" , target_os = "solaris" )))] |
763 | pub const B2000000: u32 = 2_000_000; |
764 | |
765 | /// `B2500000` |
766 | #[cfg (not(any( |
767 | target_arch = "sparc" , |
768 | target_arch = "sparc64" , |
769 | bsd, |
770 | target_os = "aix" , |
771 | target_os = "haiku" , |
772 | target_os = "solaris" , |
773 | )))] |
774 | pub const B2500000: u32 = 2_500_000; |
775 | |
776 | /// `B3000000` |
777 | #[cfg (not(any( |
778 | target_arch = "sparc" , |
779 | target_arch = "sparc64" , |
780 | bsd, |
781 | target_os = "aix" , |
782 | target_os = "haiku" , |
783 | target_os = "solaris" , |
784 | )))] |
785 | pub const B3000000: u32 = 3_000_000; |
786 | |
787 | /// `B3500000` |
788 | #[cfg (not(any( |
789 | target_arch = "sparc" , |
790 | target_arch = "sparc64" , |
791 | bsd, |
792 | target_os = "aix" , |
793 | target_os = "haiku" , |
794 | target_os = "solaris" , |
795 | )))] |
796 | pub const B3500000: u32 = 3_500_000; |
797 | |
798 | /// `B4000000` |
799 | #[cfg (not(any( |
800 | target_arch = "sparc" , |
801 | target_arch = "sparc64" , |
802 | bsd, |
803 | target_os = "aix" , |
804 | target_os = "haiku" , |
805 | target_os = "solaris" , |
806 | )))] |
807 | pub const B4000000: u32 = 4_000_000; |
808 | |
809 | /// Translate from a `c::speed_t` code to an arbitrary integer speed value |
810 | /// `u32`. |
811 | /// |
812 | /// On BSD platforms, integer speed values are already the same as their |
813 | /// encoded values, and on Linux platforms, we use `TCGETS2`/`TCSETS2` |
814 | /// and the `c_ispeed`/`c_ospeed`` fields, except that on Linux on |
815 | /// PowerPC on QEMU, `TCGETS2`/`TCSETS2` don't set `c_ispeed`/`c_ospeed`. |
816 | #[cfg (not(any( |
817 | bsd, |
818 | all( |
819 | linux_kernel, |
820 | not(any(target_arch = "powerpc" , target_arch = "powerpc64" )) |
821 | ) |
822 | )))] |
823 | pub(crate) const fn decode(encoded_speed: c::speed_t) -> Option<u32> { |
824 | match encoded_speed { |
825 | c::B0 => Some(0), |
826 | c::B50 => Some(50), |
827 | c::B75 => Some(75), |
828 | c::B110 => Some(110), |
829 | c::B134 => Some(134), |
830 | c::B150 => Some(150), |
831 | c::B200 => Some(200), |
832 | c::B300 => Some(300), |
833 | c::B600 => Some(600), |
834 | c::B1200 => Some(1200), |
835 | c::B1800 => Some(1800), |
836 | c::B2400 => Some(2400), |
837 | c::B4800 => Some(4800), |
838 | c::B9600 => Some(9600), |
839 | c::B19200 => Some(19200), |
840 | c::B38400 => Some(38400), |
841 | #[cfg (not(target_os = "aix" ))] |
842 | c::B57600 => Some(57600), |
843 | #[cfg (not(target_os = "aix" ))] |
844 | c::B115200 => Some(115_200), |
845 | #[cfg (not(any(target_os = "aix" , target_os = "nto" )))] |
846 | c::B230400 => Some(230_400), |
847 | #[cfg (not(any( |
848 | apple, |
849 | target_os = "aix" , |
850 | target_os = "dragonfly" , |
851 | target_os = "haiku" , |
852 | target_os = "nto" , |
853 | target_os = "openbsd" |
854 | )))] |
855 | c::B460800 => Some(460_800), |
856 | #[cfg (not(any( |
857 | bsd, |
858 | solarish, |
859 | target_os = "aix" , |
860 | target_os = "haiku" , |
861 | target_os = "nto" |
862 | )))] |
863 | c::B500000 => Some(500_000), |
864 | #[cfg (not(any( |
865 | bsd, |
866 | solarish, |
867 | target_os = "aix" , |
868 | target_os = "haiku" , |
869 | target_os = "nto" |
870 | )))] |
871 | c::B576000 => Some(576_000), |
872 | #[cfg (not(any( |
873 | apple, |
874 | target_os = "aix" , |
875 | target_os = "dragonfly" , |
876 | target_os = "haiku" , |
877 | target_os = "nto" , |
878 | target_os = "openbsd" |
879 | )))] |
880 | c::B921600 => Some(921_600), |
881 | #[cfg (not(any( |
882 | bsd, |
883 | target_os = "aix" , |
884 | target_os = "haiku" , |
885 | target_os = "nto" , |
886 | target_os = "solaris" |
887 | )))] |
888 | c::B1000000 => Some(1_000_000), |
889 | #[cfg (not(any( |
890 | bsd, |
891 | target_os = "aix" , |
892 | target_os = "haiku" , |
893 | target_os = "nto" , |
894 | target_os = "solaris" |
895 | )))] |
896 | c::B1152000 => Some(1_152_000), |
897 | #[cfg (not(any( |
898 | bsd, |
899 | target_os = "aix" , |
900 | target_os = "haiku" , |
901 | target_os = "nto" , |
902 | target_os = "solaris" |
903 | )))] |
904 | c::B1500000 => Some(1_500_000), |
905 | #[cfg (not(any( |
906 | bsd, |
907 | target_os = "aix" , |
908 | target_os = "haiku" , |
909 | target_os = "nto" , |
910 | target_os = "solaris" |
911 | )))] |
912 | c::B2000000 => Some(2_000_000), |
913 | #[cfg (not(any( |
914 | target_arch = "sparc" , |
915 | target_arch = "sparc64" , |
916 | bsd, |
917 | target_os = "aix" , |
918 | target_os = "haiku" , |
919 | target_os = "nto" , |
920 | target_os = "solaris" , |
921 | )))] |
922 | c::B2500000 => Some(2_500_000), |
923 | #[cfg (not(any( |
924 | target_arch = "sparc" , |
925 | target_arch = "sparc64" , |
926 | bsd, |
927 | target_os = "aix" , |
928 | target_os = "haiku" , |
929 | target_os = "nto" , |
930 | target_os = "solaris" , |
931 | )))] |
932 | c::B3000000 => Some(3_000_000), |
933 | #[cfg (not(any( |
934 | target_arch = "sparc" , |
935 | target_arch = "sparc64" , |
936 | bsd, |
937 | target_os = "aix" , |
938 | target_os = "haiku" , |
939 | target_os = "nto" , |
940 | target_os = "solaris" , |
941 | )))] |
942 | c::B3500000 => Some(3_500_000), |
943 | #[cfg (not(any( |
944 | target_arch = "sparc" , |
945 | target_arch = "sparc64" , |
946 | bsd, |
947 | target_os = "aix" , |
948 | target_os = "haiku" , |
949 | target_os = "nto" , |
950 | target_os = "solaris" , |
951 | )))] |
952 | c::B4000000 => Some(4_000_000), |
953 | _ => None, |
954 | } |
955 | } |
956 | |
957 | /// Translate from an arbitrary `u32` arbitrary integer speed value to a |
958 | /// `c::speed_t` code. |
959 | #[cfg (not(bsd))] |
960 | pub(crate) const fn encode(speed: u32) -> Option<c::speed_t> { |
961 | match speed { |
962 | 0 => Some(c::B0), |
963 | 50 => Some(c::B50), |
964 | 75 => Some(c::B75), |
965 | 110 => Some(c::B110), |
966 | 134 => Some(c::B134), |
967 | 150 => Some(c::B150), |
968 | 200 => Some(c::B200), |
969 | 300 => Some(c::B300), |
970 | 600 => Some(c::B600), |
971 | 1200 => Some(c::B1200), |
972 | 1800 => Some(c::B1800), |
973 | 2400 => Some(c::B2400), |
974 | 4800 => Some(c::B4800), |
975 | 9600 => Some(c::B9600), |
976 | 19200 => Some(c::B19200), |
977 | 38400 => Some(c::B38400), |
978 | #[cfg (not(target_os = "aix" ))] |
979 | 57600 => Some(c::B57600), |
980 | #[cfg (not(target_os = "aix" ))] |
981 | 115_200 => Some(c::B115200), |
982 | #[cfg (not(any(target_os = "aix" , target_os = "nto" )))] |
983 | 230_400 => Some(c::B230400), |
984 | #[cfg (not(any( |
985 | apple, |
986 | target_os = "aix" , |
987 | target_os = "dragonfly" , |
988 | target_os = "haiku" , |
989 | target_os = "nto" , |
990 | target_os = "openbsd" , |
991 | )))] |
992 | 460_800 => Some(c::B460800), |
993 | #[cfg (not(any( |
994 | bsd, |
995 | solarish, |
996 | target_os = "aix" , |
997 | target_os = "haiku" , |
998 | target_os = "nto" |
999 | )))] |
1000 | 500_000 => Some(c::B500000), |
1001 | #[cfg (not(any( |
1002 | bsd, |
1003 | solarish, |
1004 | target_os = "aix" , |
1005 | target_os = "haiku" , |
1006 | target_os = "nto" |
1007 | )))] |
1008 | 576_000 => Some(c::B576000), |
1009 | #[cfg (not(any( |
1010 | apple, |
1011 | target_os = "aix" , |
1012 | target_os = "dragonfly" , |
1013 | target_os = "haiku" , |
1014 | target_os = "nto" , |
1015 | target_os = "openbsd" |
1016 | )))] |
1017 | 921_600 => Some(c::B921600), |
1018 | #[cfg (not(any( |
1019 | bsd, |
1020 | target_os = "aix" , |
1021 | target_os = "haiku" , |
1022 | target_os = "nto" , |
1023 | target_os = "solaris" |
1024 | )))] |
1025 | 1_000_000 => Some(c::B1000000), |
1026 | #[cfg (not(any( |
1027 | bsd, |
1028 | target_os = "aix" , |
1029 | target_os = "haiku" , |
1030 | target_os = "nto" , |
1031 | target_os = "solaris" |
1032 | )))] |
1033 | 1_152_000 => Some(c::B1152000), |
1034 | #[cfg (not(any( |
1035 | bsd, |
1036 | target_os = "aix" , |
1037 | target_os = "haiku" , |
1038 | target_os = "nto" , |
1039 | target_os = "solaris" |
1040 | )))] |
1041 | 1_500_000 => Some(c::B1500000), |
1042 | #[cfg (not(any( |
1043 | bsd, |
1044 | target_os = "aix" , |
1045 | target_os = "haiku" , |
1046 | target_os = "nto" , |
1047 | target_os = "solaris" |
1048 | )))] |
1049 | 2_000_000 => Some(c::B2000000), |
1050 | #[cfg (not(any( |
1051 | target_arch = "sparc" , |
1052 | target_arch = "sparc64" , |
1053 | bsd, |
1054 | target_os = "aix" , |
1055 | target_os = "haiku" , |
1056 | target_os = "nto" , |
1057 | target_os = "solaris" , |
1058 | )))] |
1059 | 2_500_000 => Some(c::B2500000), |
1060 | #[cfg (not(any( |
1061 | target_arch = "sparc" , |
1062 | target_arch = "sparc64" , |
1063 | bsd, |
1064 | target_os = "aix" , |
1065 | target_os = "haiku" , |
1066 | target_os = "nto" , |
1067 | target_os = "solaris" , |
1068 | )))] |
1069 | 3_000_000 => Some(c::B3000000), |
1070 | #[cfg (not(any( |
1071 | target_arch = "sparc" , |
1072 | target_arch = "sparc64" , |
1073 | bsd, |
1074 | target_os = "aix" , |
1075 | target_os = "haiku" , |
1076 | target_os = "nto" , |
1077 | target_os = "solaris" , |
1078 | )))] |
1079 | 3_500_000 => Some(c::B3500000), |
1080 | #[cfg (not(any( |
1081 | target_arch = "sparc" , |
1082 | target_arch = "sparc64" , |
1083 | bsd, |
1084 | target_os = "aix" , |
1085 | target_os = "haiku" , |
1086 | target_os = "nto" , |
1087 | target_os = "solaris" , |
1088 | )))] |
1089 | 4_000_000 => Some(c::B4000000), |
1090 | _ => None, |
1091 | } |
1092 | } |
1093 | } |
1094 | |
1095 | /// An array indexed by [`SpecialCodeIndex`] indicating the current values |
1096 | /// of various special control codes. |
1097 | #[repr (transparent)] |
1098 | #[derive (Clone, Debug)] |
1099 | pub struct SpecialCodes(pub(crate) [c::cc_t; c::NCCS as usize]); |
1100 | |
1101 | impl core::ops::Index<SpecialCodeIndex> for SpecialCodes { |
1102 | type Output = c::cc_t; |
1103 | |
1104 | fn index(&self, index: SpecialCodeIndex) -> &Self::Output { |
1105 | &self.0[index.0] |
1106 | } |
1107 | } |
1108 | |
1109 | impl core::ops::IndexMut<SpecialCodeIndex> for SpecialCodes { |
1110 | fn index_mut(&mut self, index: SpecialCodeIndex) -> &mut Self::Output { |
1111 | &mut self.0[index.0] |
1112 | } |
1113 | } |
1114 | |
1115 | /// Indices for use with [`Termios::special_codes`]. |
1116 | pub struct SpecialCodeIndex(usize); |
1117 | |
1118 | #[rustfmt::skip] |
1119 | impl SpecialCodeIndex { |
1120 | /// `VINTR` |
1121 | pub const VINTR: Self = Self(c::VINTR as usize); |
1122 | |
1123 | /// `VQUIT` |
1124 | pub const VQUIT: Self = Self(c::VQUIT as usize); |
1125 | |
1126 | /// `VERASE` |
1127 | pub const VERASE: Self = Self(c::VERASE as usize); |
1128 | |
1129 | /// `VKILL` |
1130 | pub const VKILL: Self = Self(c::VKILL as usize); |
1131 | |
1132 | /// `VEOF` |
1133 | pub const VEOF: Self = Self(c::VEOF as usize); |
1134 | |
1135 | /// `VTIME` |
1136 | pub const VTIME: Self = Self(c::VTIME as usize); |
1137 | |
1138 | /// `VMIN` |
1139 | pub const VMIN: Self = Self(c::VMIN as usize); |
1140 | |
1141 | /// `VSWTC` |
1142 | #[cfg (not(any( |
1143 | bsd, |
1144 | solarish, |
1145 | target_os = "aix" , |
1146 | target_os = "haiku" , |
1147 | target_os = "hurd" , |
1148 | target_os = "nto" , |
1149 | )))] |
1150 | pub const VSWTC: Self = Self(c::VSWTC as usize); |
1151 | |
1152 | /// `VSTART` |
1153 | pub const VSTART: Self = Self(c::VSTART as usize); |
1154 | |
1155 | /// `VSTOP` |
1156 | pub const VSTOP: Self = Self(c::VSTOP as usize); |
1157 | |
1158 | /// `VSUSP` |
1159 | pub const VSUSP: Self = Self(c::VSUSP as usize); |
1160 | |
1161 | /// `VEOL` |
1162 | pub const VEOL: Self = Self(c::VEOL as usize); |
1163 | |
1164 | /// `VREPRINT` |
1165 | #[cfg (not(target_os = "haiku" ))] |
1166 | pub const VREPRINT: Self = Self(c::VREPRINT as usize); |
1167 | |
1168 | /// `VDISCARD` |
1169 | #[cfg (not(any(target_os = "aix" , target_os = "haiku" )))] |
1170 | pub const VDISCARD: Self = Self(c::VDISCARD as usize); |
1171 | |
1172 | /// `VWERASE` |
1173 | #[cfg (not(any(target_os = "aix" , target_os = "haiku" )))] |
1174 | pub const VWERASE: Self = Self(c::VWERASE as usize); |
1175 | |
1176 | /// `VLNEXT` |
1177 | #[cfg (not(target_os = "haiku" ))] |
1178 | pub const VLNEXT: Self = Self(c::VLNEXT as usize); |
1179 | |
1180 | /// `VEOL2` |
1181 | pub const VEOL2: Self = Self(c::VEOL2 as usize); |
1182 | } |
1183 | |
1184 | /// `TCSA*` values for use with [`tcsetattr`]. |
1185 | /// |
1186 | /// [`tcsetattr`]: crate::termios::tcsetattr |
1187 | #[derive (Debug, Clone, Copy, Eq, PartialEq, Hash)] |
1188 | #[repr (u32)] |
1189 | pub enum OptionalActions { |
1190 | /// `TCSANOW`—Make the change immediately. |
1191 | #[doc (alias = "TCSANOW" )] |
1192 | Now = c::TCSANOW as u32, |
1193 | |
1194 | /// `TCSADRAIN`—Make the change after all output has been transmitted. |
1195 | #[doc (alias = "TCSADRAIN" )] |
1196 | Drain = c::TCSADRAIN as u32, |
1197 | |
1198 | /// `TCSAFLUSH`—Discard any pending input and then make the change |
1199 | /// after all output has been transmitted. |
1200 | #[doc (alias = "TCSAFLUSH" )] |
1201 | Flush = c::TCSAFLUSH as u32, |
1202 | } |
1203 | |
1204 | /// `TC*` values for use with [`tcflush`]. |
1205 | /// |
1206 | /// [`tcflush`]: crate::termios::tcflush |
1207 | #[derive (Debug, Clone, Copy, Eq, PartialEq, Hash)] |
1208 | #[repr (u32)] |
1209 | pub enum QueueSelector { |
1210 | /// `TCIFLUSH`—Flush data received but not read. |
1211 | #[doc (alias = "TCIFLUSH" )] |
1212 | IFlush = c::TCIFLUSH as u32, |
1213 | |
1214 | /// `TCOFLUSH`—Flush data written but not transmitted. |
1215 | #[doc (alias = "TCOFLUSH" )] |
1216 | OFlush = c::TCOFLUSH as u32, |
1217 | |
1218 | /// `TCIOFLUSH`—`IFlush` and `OFlush` combined. |
1219 | #[doc (alias = "TCIOFLUSH" )] |
1220 | IOFlush = c::TCIOFLUSH as u32, |
1221 | } |
1222 | |
1223 | /// `TC*` values for use with [`tcflow`]. |
1224 | /// |
1225 | /// [`tcflow`]: crate::termios::tcflow |
1226 | #[derive (Debug, Clone, Copy, Eq, PartialEq, Hash)] |
1227 | #[repr (u32)] |
1228 | pub enum Action { |
1229 | /// `TCOOFF`—Suspend output. |
1230 | #[doc (alias = "TCOOFF" )] |
1231 | OOff = c::TCOOFF as u32, |
1232 | |
1233 | /// `TCOON`—Restart suspended output. |
1234 | #[doc (alias = "TCOON" )] |
1235 | OOn = c::TCOON as u32, |
1236 | |
1237 | /// `TCIOFF`—Transmits a STOP byte. |
1238 | #[doc (alias = "TCIOFF" )] |
1239 | IOff = c::TCIOFF as u32, |
1240 | |
1241 | /// `TCION`—Transmits a START byte. |
1242 | #[doc (alias = "TCION" )] |
1243 | IOn = c::TCION as u32, |
1244 | } |
1245 | |
1246 | /// `struct winsize` for use with [`tcgetwinsize`]. |
1247 | /// |
1248 | /// [`tcgetwinsize`]: crate::termios::tcgetwinsize |
1249 | #[doc (alias = "winsize" )] |
1250 | pub type Winsize = c::winsize; |
1251 | |
1252 | #[test ] |
1253 | fn termios_layouts() { |
1254 | check_renamed_type!(InputModes, tcflag_t); |
1255 | check_renamed_type!(OutputModes, tcflag_t); |
1256 | check_renamed_type!(ControlModes, tcflag_t); |
1257 | check_renamed_type!(LocalModes, tcflag_t); |
1258 | |
1259 | // On platforms with a termios/termios2 split, check `termios`. |
1260 | #[cfg (linux_raw)] |
1261 | { |
1262 | check_renamed_type!(Termios, termios2); |
1263 | check_renamed_struct_renamed_field!(Termios, termios2, input_modes, c_iflag); |
1264 | check_renamed_struct_renamed_field!(Termios, termios2, output_modes, c_oflag); |
1265 | check_renamed_struct_renamed_field!(Termios, termios2, control_modes, c_cflag); |
1266 | check_renamed_struct_renamed_field!(Termios, termios2, local_modes, c_lflag); |
1267 | check_renamed_struct_renamed_field!(Termios, termios2, line_discipline, c_line); |
1268 | check_renamed_struct_renamed_field!(Termios, termios2, special_codes, c_cc); |
1269 | check_renamed_struct_renamed_field!(Termios, termios2, input_speed, c_ispeed); |
1270 | check_renamed_struct_renamed_field!(Termios, termios2, output_speed, c_ospeed); |
1271 | |
1272 | // We assume that `termios` has the same layout as `termios2` minus the |
1273 | // `c_ispeed` and `c_ospeed` fields. |
1274 | check_renamed_struct_renamed_field!(Termios, termios, input_modes, c_iflag); |
1275 | check_renamed_struct_renamed_field!(Termios, termios, output_modes, c_oflag); |
1276 | check_renamed_struct_renamed_field!(Termios, termios, control_modes, c_cflag); |
1277 | check_renamed_struct_renamed_field!(Termios, termios, local_modes, c_lflag); |
1278 | check_renamed_struct_renamed_field!(Termios, termios, special_codes, c_cc); |
1279 | |
1280 | // On everything except PowerPC, `termios` matches `termios2` except |
1281 | // for the addition of `c_ispeed` and `c_ospeed`. |
1282 | #[cfg (not(any(target_arch = "powerpc" , target_arch = "powerpc64" )))] |
1283 | const_assert_eq!( |
1284 | memoffset::offset_of!(Termios, input_speed), |
1285 | core::mem::size_of::<c::termios>() |
1286 | ); |
1287 | |
1288 | // On PowerPC, `termios2` is `termios`. |
1289 | #[cfg (any(target_arch = "powerpc" , target_arch = "powerpc64" ))] |
1290 | assert_eq_size!(c::termios2, c::termios); |
1291 | } |
1292 | |
1293 | #[cfg (not(linux_raw))] |
1294 | { |
1295 | // On Mips, Sparc, and Android, the libc lacks the ospeed and ispeed |
1296 | // fields. |
1297 | #[cfg (all( |
1298 | not(all( |
1299 | target_env = "gnu" , |
1300 | any( |
1301 | target_arch = "mips" , |
1302 | target_arch = "mips32r6" , |
1303 | target_arch = "mips64" , |
1304 | target_arch = "mips64r6" , |
1305 | target_arch = "sparc" , |
1306 | target_arch = "sparc64" |
1307 | ) |
1308 | )), |
1309 | not(all(libc, target_os = "android" )) |
1310 | ))] |
1311 | check_renamed_type!(Termios, termios); |
1312 | #[cfg (not(all( |
1313 | not(all( |
1314 | target_env = "gnu" , |
1315 | any( |
1316 | target_arch = "mips" , |
1317 | target_arch = "mips32r6" , |
1318 | target_arch = "mips64" , |
1319 | target_arch = "mips64r6" , |
1320 | target_arch = "sparc" , |
1321 | target_arch = "sparc64" |
1322 | ) |
1323 | )), |
1324 | not(all(libc, target_os = "android" )) |
1325 | )))] |
1326 | const_assert!(core::mem::size_of::<Termios>() >= core::mem::size_of::<c::termios>()); |
1327 | |
1328 | check_renamed_struct_renamed_field!(Termios, termios, input_modes, c_iflag); |
1329 | check_renamed_struct_renamed_field!(Termios, termios, output_modes, c_oflag); |
1330 | check_renamed_struct_renamed_field!(Termios, termios, control_modes, c_cflag); |
1331 | check_renamed_struct_renamed_field!(Termios, termios, local_modes, c_lflag); |
1332 | #[cfg (any( |
1333 | linux_like, |
1334 | target_env = "newlib" , |
1335 | target_os = "fuchsia" , |
1336 | target_os = "haiku" , |
1337 | target_os = "redox" |
1338 | ))] |
1339 | check_renamed_struct_renamed_field!(Termios, termios, line_discipline, c_line); |
1340 | check_renamed_struct_renamed_field!(Termios, termios, special_codes, c_cc); |
1341 | #[cfg (not(any( |
1342 | linux_kernel, |
1343 | solarish, |
1344 | target_os = "emscripten" , |
1345 | target_os = "fuchsia" |
1346 | )))] |
1347 | { |
1348 | check_renamed_struct_renamed_field!(Termios, termios, input_speed, c_ispeed); |
1349 | check_renamed_struct_renamed_field!(Termios, termios, output_speed, c_ospeed); |
1350 | } |
1351 | #[cfg (any(target_env = "musl" , target_os = "fuchsia" ))] |
1352 | { |
1353 | check_renamed_struct_renamed_field!(Termios, termios, input_speed, __c_ispeed); |
1354 | check_renamed_struct_renamed_field!(Termios, termios, output_speed, __c_ospeed); |
1355 | } |
1356 | } |
1357 | |
1358 | check_renamed_type!(OptionalActions, c_int); |
1359 | check_renamed_type!(QueueSelector, c_int); |
1360 | check_renamed_type!(Action, c_int); |
1361 | } |
1362 | |
1363 | #[test ] |
1364 | #[cfg (not(any( |
1365 | solarish, |
1366 | target_os = "emscripten" , |
1367 | target_os = "haiku" , |
1368 | target_os = "redox" |
1369 | )))] |
1370 | fn termios_legacy() { |
1371 | // Check that our doc aliases above are correct. |
1372 | const_assert_eq!(c::EXTA, c::B19200); |
1373 | const_assert_eq!(c::EXTB, c::B38400); |
1374 | } |
1375 | |
1376 | #[cfg (bsd)] |
1377 | #[test ] |
1378 | fn termios_bsd() { |
1379 | // On BSD platforms we can assume that the `B*` constants have their |
1380 | // arbitrary integer speed value. Confirm this. |
1381 | const_assert_eq!(c::B0, 0); |
1382 | const_assert_eq!(c::B50, 50); |
1383 | const_assert_eq!(c::B19200, 19200); |
1384 | const_assert_eq!(c::B38400, 38400); |
1385 | } |
1386 | |
1387 | #[test ] |
1388 | #[cfg (not(bsd))] |
1389 | fn termios_speed_encoding() { |
1390 | assert_eq!(speed::encode(0), Some(c::B0)); |
1391 | assert_eq!(speed::encode(50), Some(c::B50)); |
1392 | assert_eq!(speed::encode(19200), Some(c::B19200)); |
1393 | assert_eq!(speed::encode(38400), Some(c::B38400)); |
1394 | assert_eq!(speed::encode(1), None); |
1395 | assert_eq!(speed::encode(!0), None); |
1396 | |
1397 | #[cfg (not(linux_kernel))] |
1398 | { |
1399 | assert_eq!(speed::decode(c::B0), Some(0)); |
1400 | assert_eq!(speed::decode(c::B50), Some(50)); |
1401 | assert_eq!(speed::decode(c::B19200), Some(19200)); |
1402 | assert_eq!(speed::decode(c::B38400), Some(38400)); |
1403 | } |
1404 | } |
1405 | |
1406 | #[cfg (linux_kernel)] |
1407 | #[test ] |
1408 | fn termios_ioctl_contiguity() { |
1409 | // When using `termios2`, we assume that we can add the optional actions |
1410 | // value to the ioctl request code. Test this assumption. |
1411 | |
1412 | const_assert_eq!(c::TCSETS2, c::TCSETS2 + 0); |
1413 | const_assert_eq!(c::TCSETSW2, c::TCSETS2 + 1); |
1414 | const_assert_eq!(c::TCSETSF2, c::TCSETS2 + 2); |
1415 | |
1416 | const_assert_eq!(c::TCSANOW - c::TCSANOW, 0); |
1417 | const_assert_eq!(c::TCSADRAIN - c::TCSANOW, 1); |
1418 | const_assert_eq!(c::TCSAFLUSH - c::TCSANOW, 2); |
1419 | |
1420 | // MIPS is different here. |
1421 | #[cfg (any( |
1422 | target_arch = "mips" , |
1423 | target_arch = "mips32r6" , |
1424 | target_arch = "mips64" , |
1425 | target_arch = "mips64r6" |
1426 | ))] |
1427 | { |
1428 | assert_eq!(i128::from(c::TCSANOW) - i128::from(c::TCSETS), 0); |
1429 | assert_eq!(i128::from(c::TCSADRAIN) - i128::from(c::TCSETS), 1); |
1430 | assert_eq!(i128::from(c::TCSAFLUSH) - i128::from(c::TCSETS), 2); |
1431 | } |
1432 | #[cfg (not(any( |
1433 | target_arch = "mips" , |
1434 | target_arch = "mips32r6" , |
1435 | target_arch = "mips64" , |
1436 | target_arch = "mips64r6" |
1437 | )))] |
1438 | { |
1439 | const_assert_eq!(c::TCSANOW, 0); |
1440 | const_assert_eq!(c::TCSADRAIN, 1); |
1441 | const_assert_eq!(c::TCSAFLUSH, 2); |
1442 | } |
1443 | } |
1444 | |
1445 | #[cfg (linux_kernel)] |
1446 | #[test ] |
1447 | fn termios_cibaud() { |
1448 | // Test an assumption. |
1449 | const_assert_eq!(c::CIBAUD, c::CBAUD << c::IBSHIFT); |
1450 | } |
1451 | |