1use crate::backend::c;
2use crate::{backend, io};
3use 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)]
11pub 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
74impl 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
210impl 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
234bitflags! {
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/*/bitflags/#externally-defined-flags>
298 const _ = !0;
299 }
300}
301
302bitflags! {
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/*/bitflags/#externally-defined-flags>
513 const _ = !0;
514 }
515}
516
517bitflags! {
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/*/bitflags/#externally-defined-flags>
577 const _ = !0;
578 }
579}
580
581bitflags! {
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/*/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.
655pub 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)]
1099pub struct SpecialCodes(pub(crate) [c::cc_t; c::NCCS as usize]);
1100
1101impl 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
1109impl 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`].
1116pub struct SpecialCodeIndex(usize);
1117
1118#[rustfmt::skip]
1119impl 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)]
1189pub 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)]
1209pub 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)]
1228pub 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")]
1250pub type Winsize = c::winsize;
1251
1252#[test]
1253fn 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)))]
1370fn 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]
1378fn 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))]
1389fn 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]
1408fn 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]
1447fn termios_cibaud() {
1448 // Test an assumption.
1449 const_assert_eq!(c::CIBAUD, c::CBAUD << c::IBSHIFT);
1450}
1451