1use crate::backend::c;
2use crate::backend::termios::types;
3#[cfg(target_os = "nto")]
4use crate::ffi;
5use crate::{backend, io};
6use bitflags::bitflags;
7
8#[repr(C)]
13#[derive(Clone)]
14pub struct Termios {
15 #[doc(alias = "c_iflag")]
17 pub input_modes: InputModes,
18
19 #[doc(alias = "c_oflag")]
21 pub output_modes: OutputModes,
22
23 #[doc(alias = "c_cflag")]
25 pub control_modes: ControlModes,
26
27 #[doc(alias = "c_lflag")]
29 pub local_modes: LocalModes,
30
31 #[doc(alias = "c_line")]
33 #[cfg(not(all(linux_raw, any(target_arch = "powerpc", target_arch = "powerpc64"))))]
34 #[cfg(any(
35 linux_like,
36 target_env = "newlib",
37 target_os = "fuchsia",
38 target_os = "haiku",
39 target_os = "redox"
40 ))]
41 pub line_discipline: u8,
42
43 #[doc(alias = "c_cc")]
45 #[cfg(not(target_os = "haiku"))]
46 pub special_codes: SpecialCodes,
47
48 #[cfg(target_os = "nto")]
49 pub(crate) __reserved: [ffi::c_uint; 3],
50
51 #[doc(alias = "c_line")]
54 #[cfg(all(linux_raw, any(target_arch = "powerpc", target_arch = "powerpc64")))]
55 pub line_discipline: c::cc_t,
56
57 #[cfg(not(any(solarish, all(libc, target_env = "newlib"), target_os = "aix")))]
62 pub(crate) input_speed: c::speed_t,
63
64 #[cfg(not(any(solarish, all(libc, target_env = "newlib"), target_os = "aix")))]
69 pub(crate) output_speed: c::speed_t,
70
71 #[doc(alias = "c_cc")]
73 #[cfg(target_os = "haiku")]
74 pub special_codes: SpecialCodes,
75}
76
77impl Termios {
78 #[cfg(not(target_os = "nto"))]
83 #[doc(alias = "cfmakeraw")]
84 #[inline]
85 pub fn make_raw(&mut self) {
86 backend::termios::syscalls::cfmakeraw(self)
87 }
88
89 #[doc(alias = "c_ispeed")]
95 #[doc(alias = "cfgetispeed")]
96 #[doc(alias = "cfgetspeed")]
97 #[inline]
98 pub fn input_speed(&self) -> u32 {
99 #[cfg(any(linux_kernel, bsd))]
101 {
102 debug_assert!(u32::try_from(self.input_speed).is_ok());
103 self.input_speed as u32
104 }
105
106 #[cfg(any(solarish, all(libc, target_env = "newlib"), target_os = "aix"))]
108 unsafe {
109 speed::decode(c::cfgetispeed(crate::utils::as_ptr(self).cast())).unwrap()
110 }
111
112 #[cfg(not(any(
114 linux_kernel,
115 bsd,
116 solarish,
117 all(libc, target_env = "newlib"),
118 target_os = "aix"
119 )))]
120 {
121 speed::decode(self.input_speed).unwrap()
122 }
123 }
124
125 #[inline]
131 pub fn output_speed(&self) -> u32 {
132 #[cfg(any(linux_kernel, bsd))]
134 {
135 debug_assert!(u32::try_from(self.output_speed).is_ok());
136 self.output_speed as u32
137 }
138
139 #[cfg(any(solarish, all(libc, target_env = "newlib"), target_os = "aix"))]
141 unsafe {
142 speed::decode(c::cfgetospeed(crate::utils::as_ptr(self).cast())).unwrap()
143 }
144
145 #[cfg(not(any(
147 linux_kernel,
148 bsd,
149 solarish,
150 all(libc, target_env = "newlib"),
151 target_os = "aix"
152 )))]
153 {
154 speed::decode(self.output_speed).unwrap()
155 }
156 }
157
158 #[cfg(not(target_os = "nto"))]
166 #[doc(alias = "cfsetspeed")]
167 #[doc(alias = "CBAUD")]
168 #[doc(alias = "CBAUDEX")]
169 #[doc(alias = "CIBAUD")]
170 #[doc(alias = "CIBAUDEX")]
171 #[inline]
172 pub fn set_speed(&mut self, new_speed: u32) -> io::Result<()> {
173 backend::termios::syscalls::set_speed(self, new_speed)
174 }
175
176 #[doc(alias = "c_ispeed")]
186 #[doc(alias = "cfsetispeed")]
187 #[doc(alias = "CIBAUD")]
188 #[doc(alias = "CIBAUDEX")]
189 #[inline]
190 pub fn set_input_speed(&mut self, new_speed: u32) -> io::Result<()> {
191 backend::termios::syscalls::set_input_speed(self, new_speed)
192 }
193
194 #[doc(alias = "c_ospeed")]
204 #[doc(alias = "cfsetospeed")]
205 #[doc(alias = "CBAUD")]
206 #[doc(alias = "CBAUDEX")]
207 #[inline]
208 pub fn set_output_speed(&mut self, new_speed: u32) -> io::Result<()> {
209 backend::termios::syscalls::set_output_speed(self, new_speed)
210 }
211}
212
213impl core::fmt::Debug for Termios {
214 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
215 let mut d = f.debug_struct("Termios");
216 d.field("input_modes", &self.input_modes);
217 d.field("output_modes", &self.output_modes);
218
219 d.field("control_modes", &self.control_modes);
226
227 d.field("local_modes", &self.local_modes);
228 #[cfg(any(
229 linux_like,
230 target_env = "newlib",
231 target_os = "fuchsia",
232 target_os = "haiku",
233 target_os = "redox"
234 ))]
235 {
236 d.field("line_discipline", &SpecialCode(self.line_discipline));
237 }
238 d.field("special_codes", &self.special_codes);
239 d.field("input_speed", &self.input_speed());
240 d.field("output_speed", &self.output_speed());
241 d.finish()
242 }
243}
244
245bitflags! {
246 #[repr(transparent)]
248 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
249 pub struct InputModes: types::tcflag_t {
250 const IGNBRK = c::IGNBRK;
252
253 const BRKINT = c::BRKINT;
255
256 const IGNPAR = c::IGNPAR;
258
259 const PARMRK = c::PARMRK;
261
262 const INPCK = c::INPCK;
264
265 const ISTRIP = c::ISTRIP;
267
268 const INLCR = c::INLCR;
270
271 const IGNCR = c::IGNCR;
273
274 const ICRNL = c::ICRNL;
276
277 #[cfg(any(linux_kernel, solarish, target_os = "aix", target_os = "haiku", target_os = "nto"))]
279 const IUCLC = c::IUCLC;
280
281 const IXON = c::IXON;
283
284 #[cfg(not(target_os = "redox"))]
286 const IXANY = c::IXANY;
287
288 const IXOFF = c::IXOFF;
290
291 #[cfg(not(any(target_os = "haiku", target_os = "redox")))]
293 const IMAXBEL = c::IMAXBEL;
294
295 #[cfg(not(any(
297 freebsdlike,
298 netbsdlike,
299 solarish,
300 target_os = "aix",
301 target_os = "emscripten",
302 target_os = "haiku",
303 target_os = "hurd",
304 target_os = "redox",
305 )))]
306 const IUTF8 = c::IUTF8;
307
308 const _ = !0;
310 }
311}
312
313bitflags! {
314 #[repr(transparent)]
316 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
317 pub struct OutputModes: types::tcflag_t {
318 const OPOST = c::OPOST;
320
321 #[cfg(not(any(
323 apple,
324 freebsdlike,
325 target_os = "aix",
326 target_os = "netbsd",
327 target_os = "redox",
328 )))]
329 const OLCUC = c::OLCUC;
330
331 const ONLCR = c::ONLCR;
333
334 const OCRNL = c::OCRNL;
336
337 const ONOCR = c::ONOCR;
339
340 const ONLRET = c::ONLRET;
342
343 #[cfg(not(bsd))]
345 const OFILL = c::OFILL;
346
347 #[cfg(not(bsd))]
349 const OFDEL = c::OFDEL;
350
351 #[cfg(not(any(bsd, solarish, target_os = "redox")))]
353 const NLDLY = c::NLDLY;
354
355 #[cfg(not(any(bsd, solarish, target_os = "fuchsia", target_os = "redox")))]
357 const NL0 = c::NL0;
358
359 #[cfg(not(any(bsd, solarish, target_os = "fuchsia", target_os = "redox")))]
361 const NL1 = c::NL1;
362
363 #[cfg(not(any(bsd, solarish, target_os = "redox")))]
365 const CRDLY = c::CRDLY;
366
367 #[cfg(not(any(bsd, solarish, target_os = "fuchsia", target_os = "redox")))]
369 const CR0 = c::CR0;
370
371 #[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 CR1 = c::CR1;
381
382 #[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 CR2 = c::CR2;
392
393 #[cfg(not(any(
395 target_env = "musl",
396 bsd,
397 solarish,
398 target_os = "emscripten",
399 target_os = "fuchsia",
400 target_os = "redox",
401 )))]
402 const CR3 = c::CR3;
403
404 #[cfg(not(any(
406 netbsdlike,
407 solarish,
408 target_os = "dragonfly",
409 target_os = "redox",
410 )))]
411 const TABDLY = c::TABDLY;
412
413 #[cfg(not(any(
415 netbsdlike,
416 solarish,
417 target_os = "dragonfly",
418 target_os = "fuchsia",
419 target_os = "redox",
420 )))]
421 const TAB0 = c::TAB0;
422
423 #[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 TAB1 = c::TAB1;
433
434 #[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 TAB2 = c::TAB2;
444
445 #[cfg(not(any(
447 target_env = "musl",
448 bsd,
449 solarish,
450 target_os = "emscripten",
451 target_os = "fuchsia",
452 target_os = "redox",
453 )))]
454 const TAB3 = c::TAB3;
455
456 #[cfg(not(any(
458 bsd,
459 solarish,
460 target_os = "aix",
461 target_os = "haiku",
462 target_os = "redox",
463 )))]
464 const XTABS = c::XTABS;
465
466 #[cfg(not(any(bsd, solarish, target_os = "redox")))]
468 const BSDLY = c::BSDLY;
469
470 #[cfg(not(any(bsd, solarish, target_os = "fuchsia", target_os = "redox")))]
472 const BS0 = c::BS0;
473
474 #[cfg(not(any(
476 target_env = "musl",
477 bsd,
478 solarish,
479 target_os = "emscripten",
480 target_os = "fuchsia",
481 target_os = "redox",
482 )))]
483 const BS1 = c::BS1;
484
485 #[cfg(not(any(bsd, solarish, target_os = "redox")))]
487 const FFDLY = c::FFDLY;
488
489 #[cfg(not(any(bsd, solarish, target_os = "fuchsia", target_os = "redox")))]
491 const FF0 = c::FF0;
492
493 #[cfg(not(any(
495 target_env = "musl",
496 bsd,
497 solarish,
498 target_os = "emscripten",
499 target_os = "fuchsia",
500 target_os = "redox",
501 )))]
502 const FF1 = c::FF1;
503
504 #[cfg(not(any(bsd, solarish, target_os = "redox")))]
506 const VTDLY = c::VTDLY;
507
508 #[cfg(not(any(bsd, solarish, target_os = "fuchsia", target_os = "redox")))]
510 const VT0 = c::VT0;
511
512 #[cfg(not(any(
514 target_env = "musl",
515 bsd,
516 solarish,
517 target_os = "emscripten",
518 target_os = "fuchsia",
519 target_os = "redox",
520 )))]
521 const VT1 = c::VT1;
522
523 const _ = !0;
525 }
526}
527
528bitflags! {
529 #[repr(transparent)]
537 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
538 pub struct ControlModes: types::tcflag_t {
539 const CSIZE = c::CSIZE;
541
542 const CS5 = c::CS5;
544
545 const CS6 = c::CS6;
547
548 const CS7 = c::CS7;
550
551 const CS8 = c::CS8;
553
554 const CSTOPB = c::CSTOPB;
556
557 const CREAD = c::CREAD;
559
560 const PARENB = c::PARENB;
562
563 const PARODD = c::PARODD;
565
566 const HUPCL = c::HUPCL;
568
569 const CLOCAL = c::CLOCAL;
571
572 #[cfg(not(any(target_os = "aix", target_os = "nto", target_os = "redox")))]
574 const CRTSCTS = c::CRTSCTS;
575
576 #[cfg(not(any(
578 bsd,
579 solarish,
580 target_os = "aix",
581 target_os = "emscripten",
582 target_os = "haiku",
583 target_os = "hurd",
584 target_os = "nto",
585 target_os = "redox",
586 )))]
587 const CMSPAR = c::CMSPAR;
588
589 const _ = !0;
591 }
592}
593
594bitflags! {
595 #[repr(transparent)]
597 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
598 pub struct LocalModes: types::tcflag_t {
599 #[cfg(any(linux_kernel, target_arch = "s390x", target_os = "haiku"))]
601 const XCASE = c::XCASE;
602
603 #[cfg(not(target_os = "redox"))]
605 const ECHOCTL = c::ECHOCTL;
606
607 #[cfg(not(any(target_os = "cygwin", target_os = "nto", target_os = "redox")))]
609 const ECHOPRT = c::ECHOPRT;
610
611 #[cfg(not(target_os = "redox"))]
613 const ECHOKE = c::ECHOKE;
614
615 #[cfg(not(any(target_os = "nto", target_os = "redox")))]
617 const FLUSHO = c::FLUSHO;
618
619 #[cfg(not(any(target_os = "cygwin", target_os = "nto", target_os = "redox")))]
621 const PENDIN = c::PENDIN;
622
623 #[cfg(not(any(
625 target_os = "aix",
626 target_os = "cygwin",
627 target_os = "haiku",
628 target_os = "nto",
629 target_os = "redox",
630 )))]
631 const EXTPROC = c::EXTPROC;
632
633 const ISIG = c::ISIG;
635
636 const ICANON = c::ICANON;
639
640 const ECHO = c::ECHO;
642
643 const ECHOE = c::ECHOE;
645
646 const ECHOK = c::ECHOK;
648
649 const ECHONL = c::ECHONL;
651
652 const NOFLSH = c::NOFLSH;
654
655 const TOSTOP = c::TOSTOP;
657
658 const IEXTEN = c::IEXTEN;
660
661 const _ = !0;
663 }
664}
665
666pub mod speed {
675 #[cfg(not(bsd))]
676 use crate::backend::c;
677
678 pub const B0: u32 = 0;
680
681 pub const B50: u32 = 50;
683
684 pub const B75: u32 = 75;
686
687 pub const B110: u32 = 110;
689
690 pub const B134: u32 = 134;
692
693 pub const B150: u32 = 150;
695
696 pub const B200: u32 = 200;
698
699 pub const B300: u32 = 300;
701
702 pub const B600: u32 = 600;
704
705 pub const B1200: u32 = 1200;
707
708 pub const B1800: u32 = 1800;
710
711 pub const B2400: u32 = 2400;
713
714 pub const B4800: u32 = 4800;
716
717 pub const B9600: u32 = 9600;
719
720 #[doc(alias = "EXTA")]
722 pub const B19200: u32 = 19200;
723
724 #[doc(alias = "EXTB")]
726 pub const B38400: u32 = 38400;
727
728 #[cfg(not(target_os = "aix"))]
730 pub const B57600: u32 = 57600;
731
732 #[cfg(not(target_os = "aix"))]
734 pub const B115200: u32 = 115_200;
735
736 #[cfg(not(target_os = "aix"))]
738 pub const B230400: u32 = 230_400;
739
740 #[cfg(not(any(
742 apple,
743 target_os = "aix",
744 target_os = "dragonfly",
745 target_os = "haiku",
746 target_os = "openbsd"
747 )))]
748 pub const B460800: u32 = 460_800;
749
750 #[cfg(not(any(bsd, solarish, target_os = "aix", target_os = "haiku")))]
752 pub const B500000: u32 = 500_000;
753
754 #[cfg(not(any(bsd, solarish, target_os = "aix", target_os = "haiku")))]
756 pub const B576000: u32 = 576_000;
757
758 #[cfg(not(any(
760 apple,
761 target_os = "aix",
762 target_os = "dragonfly",
763 target_os = "haiku",
764 target_os = "openbsd"
765 )))]
766 pub const B921600: u32 = 921_600;
767
768 #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))]
770 pub const B1000000: u32 = 1_000_000;
771
772 #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))]
774 pub const B1152000: u32 = 1_152_000;
775
776 #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))]
778 pub const B1500000: u32 = 1_500_000;
779
780 #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))]
782 pub const B2000000: u32 = 2_000_000;
783
784 #[cfg(not(any(
786 target_arch = "sparc",
787 target_arch = "sparc64",
788 bsd,
789 target_os = "aix",
790 target_os = "haiku",
791 target_os = "solaris",
792 )))]
793 pub const B2500000: u32 = 2_500_000;
794
795 #[cfg(not(any(
797 target_arch = "sparc",
798 target_arch = "sparc64",
799 bsd,
800 target_os = "aix",
801 target_os = "haiku",
802 target_os = "solaris",
803 )))]
804 pub const B3000000: u32 = 3_000_000;
805
806 #[cfg(not(any(
808 target_arch = "sparc",
809 target_arch = "sparc64",
810 bsd,
811 target_os = "aix",
812 target_os = "haiku",
813 target_os = "solaris",
814 )))]
815 pub const B3500000: u32 = 3_500_000;
816
817 #[cfg(not(any(
819 target_arch = "sparc",
820 target_arch = "sparc64",
821 bsd,
822 target_os = "aix",
823 target_os = "haiku",
824 target_os = "solaris",
825 )))]
826 pub const B4000000: u32 = 4_000_000;
827
828 #[cfg(not(any(
841 bsd,
842 all(linux_kernel, any(target_arch = "powerpc", target_arch = "powerpc64"))
843 )))]
844 pub(crate) const fn decode(encoded_speed: c::speed_t) -> Option<u32> {
845 match encoded_speed {
846 c::B0 => Some(0),
847 c::B50 => Some(50),
848 c::B75 => Some(75),
849 c::B110 => Some(110),
850 c::B134 => Some(134),
851 c::B150 => Some(150),
852 c::B200 => Some(200),
853 c::B300 => Some(300),
854 c::B600 => Some(600),
855 c::B1200 => Some(1200),
856 c::B1800 => Some(1800),
857 c::B2400 => Some(2400),
858 c::B4800 => Some(4800),
859 c::B9600 => Some(9600),
860 c::B19200 => Some(19200),
861 c::B38400 => Some(38400),
862 #[cfg(not(target_os = "aix"))]
863 c::B57600 => Some(57600),
864 #[cfg(not(target_os = "aix"))]
865 c::B115200 => Some(115_200),
866 #[cfg(not(any(target_os = "aix", target_os = "nto")))]
867 c::B230400 => Some(230_400),
868 #[cfg(not(any(
869 apple,
870 target_os = "aix",
871 target_os = "dragonfly",
872 target_os = "haiku",
873 target_os = "nto",
874 target_os = "openbsd"
875 )))]
876 c::B460800 => Some(460_800),
877 #[cfg(not(any(
878 bsd,
879 solarish,
880 target_os = "aix",
881 target_os = "haiku",
882 target_os = "nto"
883 )))]
884 c::B500000 => Some(500_000),
885 #[cfg(not(any(
886 bsd,
887 solarish,
888 target_os = "aix",
889 target_os = "haiku",
890 target_os = "nto"
891 )))]
892 c::B576000 => Some(576_000),
893 #[cfg(not(any(
894 apple,
895 target_os = "aix",
896 target_os = "dragonfly",
897 target_os = "haiku",
898 target_os = "nto",
899 target_os = "openbsd"
900 )))]
901 c::B921600 => Some(921_600),
902 #[cfg(not(any(
903 bsd,
904 target_os = "aix",
905 target_os = "haiku",
906 target_os = "nto",
907 target_os = "solaris"
908 )))]
909 c::B1000000 => Some(1_000_000),
910 #[cfg(not(any(
911 bsd,
912 target_os = "aix",
913 target_os = "haiku",
914 target_os = "nto",
915 target_os = "solaris"
916 )))]
917 c::B1152000 => Some(1_152_000),
918 #[cfg(not(any(
919 bsd,
920 target_os = "aix",
921 target_os = "haiku",
922 target_os = "nto",
923 target_os = "solaris"
924 )))]
925 c::B1500000 => Some(1_500_000),
926 #[cfg(not(any(
927 bsd,
928 target_os = "aix",
929 target_os = "haiku",
930 target_os = "nto",
931 target_os = "solaris"
932 )))]
933 c::B2000000 => Some(2_000_000),
934 #[cfg(not(any(
935 target_arch = "sparc",
936 target_arch = "sparc64",
937 bsd,
938 target_os = "aix",
939 target_os = "haiku",
940 target_os = "nto",
941 target_os = "solaris",
942 )))]
943 c::B2500000 => Some(2_500_000),
944 #[cfg(not(any(
945 target_arch = "sparc",
946 target_arch = "sparc64",
947 bsd,
948 target_os = "aix",
949 target_os = "haiku",
950 target_os = "nto",
951 target_os = "solaris",
952 )))]
953 c::B3000000 => Some(3_000_000),
954 #[cfg(not(any(
955 target_arch = "sparc",
956 target_arch = "sparc64",
957 bsd,
958 target_os = "aix",
959 target_os = "cygwin",
960 target_os = "haiku",
961 target_os = "nto",
962 target_os = "solaris",
963 )))]
964 c::B3500000 => Some(3_500_000),
965 #[cfg(not(any(
966 target_arch = "sparc",
967 target_arch = "sparc64",
968 bsd,
969 target_os = "aix",
970 target_os = "cygwin",
971 target_os = "haiku",
972 target_os = "nto",
973 target_os = "solaris",
974 )))]
975 c::B4000000 => Some(4_000_000),
976 _ => None,
977 }
978 }
979
980 #[cfg(not(bsd))]
983 pub(crate) const fn encode(speed: u32) -> Option<c::speed_t> {
984 match speed {
985 0 => Some(c::B0),
986 50 => Some(c::B50),
987 75 => Some(c::B75),
988 110 => Some(c::B110),
989 134 => Some(c::B134),
990 150 => Some(c::B150),
991 200 => Some(c::B200),
992 300 => Some(c::B300),
993 600 => Some(c::B600),
994 1200 => Some(c::B1200),
995 1800 => Some(c::B1800),
996 2400 => Some(c::B2400),
997 4800 => Some(c::B4800),
998 9600 => Some(c::B9600),
999 19200 => Some(c::B19200),
1000 38400 => Some(c::B38400),
1001 #[cfg(not(target_os = "aix"))]
1002 57600 => Some(c::B57600),
1003 #[cfg(not(target_os = "aix"))]
1004 115_200 => Some(c::B115200),
1005 #[cfg(not(any(target_os = "aix", target_os = "nto")))]
1006 230_400 => Some(c::B230400),
1007 #[cfg(not(any(
1008 apple,
1009 target_os = "aix",
1010 target_os = "dragonfly",
1011 target_os = "haiku",
1012 target_os = "nto",
1013 target_os = "openbsd",
1014 )))]
1015 460_800 => Some(c::B460800),
1016 #[cfg(not(any(
1017 bsd,
1018 solarish,
1019 target_os = "aix",
1020 target_os = "haiku",
1021 target_os = "nto"
1022 )))]
1023 500_000 => Some(c::B500000),
1024 #[cfg(not(any(
1025 bsd,
1026 solarish,
1027 target_os = "aix",
1028 target_os = "haiku",
1029 target_os = "nto"
1030 )))]
1031 576_000 => Some(c::B576000),
1032 #[cfg(not(any(
1033 apple,
1034 target_os = "aix",
1035 target_os = "dragonfly",
1036 target_os = "haiku",
1037 target_os = "nto",
1038 target_os = "openbsd"
1039 )))]
1040 921_600 => Some(c::B921600),
1041 #[cfg(not(any(
1042 bsd,
1043 target_os = "aix",
1044 target_os = "haiku",
1045 target_os = "nto",
1046 target_os = "solaris"
1047 )))]
1048 1_000_000 => Some(c::B1000000),
1049 #[cfg(not(any(
1050 bsd,
1051 target_os = "aix",
1052 target_os = "haiku",
1053 target_os = "nto",
1054 target_os = "solaris"
1055 )))]
1056 1_152_000 => Some(c::B1152000),
1057 #[cfg(not(any(
1058 bsd,
1059 target_os = "aix",
1060 target_os = "haiku",
1061 target_os = "nto",
1062 target_os = "solaris"
1063 )))]
1064 1_500_000 => Some(c::B1500000),
1065 #[cfg(not(any(
1066 bsd,
1067 target_os = "aix",
1068 target_os = "haiku",
1069 target_os = "nto",
1070 target_os = "solaris"
1071 )))]
1072 2_000_000 => Some(c::B2000000),
1073 #[cfg(not(any(
1074 target_arch = "sparc",
1075 target_arch = "sparc64",
1076 bsd,
1077 target_os = "aix",
1078 target_os = "haiku",
1079 target_os = "nto",
1080 target_os = "solaris",
1081 )))]
1082 2_500_000 => Some(c::B2500000),
1083 #[cfg(not(any(
1084 target_arch = "sparc",
1085 target_arch = "sparc64",
1086 bsd,
1087 target_os = "aix",
1088 target_os = "haiku",
1089 target_os = "nto",
1090 target_os = "solaris",
1091 )))]
1092 3_000_000 => Some(c::B3000000),
1093 #[cfg(not(any(
1094 target_arch = "sparc",
1095 target_arch = "sparc64",
1096 bsd,
1097 target_os = "aix",
1098 target_os = "cygwin",
1099 target_os = "haiku",
1100 target_os = "nto",
1101 target_os = "solaris",
1102 )))]
1103 3_500_000 => Some(c::B3500000),
1104 #[cfg(not(any(
1105 target_arch = "sparc",
1106 target_arch = "sparc64",
1107 bsd,
1108 target_os = "aix",
1109 target_os = "cygwin",
1110 target_os = "haiku",
1111 target_os = "nto",
1112 target_os = "solaris",
1113 )))]
1114 4_000_000 => Some(c::B4000000),
1115 _ => None,
1116 }
1117 }
1118}
1119
1120#[repr(transparent)]
1123#[derive(Clone)]
1124pub struct SpecialCodes(pub(crate) [c::cc_t; c::NCCS as usize]);
1125
1126impl core::ops::Index<SpecialCodeIndex> for SpecialCodes {
1127 type Output = u8;
1128
1129 fn index(&self, index: SpecialCodeIndex) -> &Self::Output {
1130 &self.0[index.0]
1131 }
1132}
1133
1134impl core::ops::IndexMut<SpecialCodeIndex> for SpecialCodes {
1135 fn index_mut(&mut self, index: SpecialCodeIndex) -> &mut Self::Output {
1136 &mut self.0[index.0]
1137 }
1138}
1139
1140impl core::fmt::Debug for SpecialCodes {
1141 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1142 write!(f, "SpecialCodes {{")?;
1143 let mut first = true;
1144 for i in 0..self.0.len() {
1145 if first {
1146 write!(f, " ")?;
1147 } else {
1148 write!(f, ", ")?;
1149 }
1150 first = false;
1151 let index = SpecialCodeIndex(i);
1152 write!(f, "{:?}: {:?}", index, SpecialCode(self[index]))?;
1153 }
1154 if !first {
1155 write!(f, " ")?;
1156 }
1157 write!(f, "}}")
1158 }
1159}
1160
1161struct SpecialCode(u8);
1163
1164impl core::fmt::Debug for SpecialCode {
1165 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1166 if self.0 == 0 {
1167 write!(f, "<undef>")
1168 } else if self.0 < 0x20 {
1169 write!(f, "^{}", (self.0 + 0x40) as char)
1170 } else if self.0 == 0x7f {
1171 write!(f, "^?")
1172 } else if self.0 >= 0x80 {
1173 write!(f, "M-")?;
1174 SpecialCode(self.0 - 0x80).fmt(f)
1175 } else {
1176 write!(f, "{}", (self.0 as char))
1177 }
1178 }
1179}
1180
1181#[derive(Copy, Clone, Eq, PartialEq, Hash)]
1183pub struct SpecialCodeIndex(usize);
1184
1185#[rustfmt::skip]
1186impl SpecialCodeIndex {
1187 pub const VINTR: Self = Self(c::VINTR as usize);
1189
1190 pub const VQUIT: Self = Self(c::VQUIT as usize);
1192
1193 pub const VERASE: Self = Self(c::VERASE as usize);
1195
1196 pub const VKILL: Self = Self(c::VKILL as usize);
1198
1199 pub const VEOF: Self = Self(c::VEOF as usize);
1201
1202 pub const VTIME: Self = Self(c::VTIME as usize);
1204
1205 pub const VMIN: Self = Self(c::VMIN as usize);
1207
1208 #[cfg(not(any(
1210 bsd,
1211 solarish,
1212 target_os = "aix",
1213 target_os = "haiku",
1214 target_os = "hurd",
1215 target_os = "nto",
1216 )))]
1217 pub const VSWTC: Self = Self(c::VSWTC as usize);
1218
1219 pub const VSTART: Self = Self(c::VSTART as usize);
1221
1222 pub const VSTOP: Self = Self(c::VSTOP as usize);
1224
1225 pub const VSUSP: Self = Self(c::VSUSP as usize);
1227
1228 pub const VEOL: Self = Self(c::VEOL as usize);
1230
1231 #[cfg(not(target_os = "haiku"))]
1233 pub const VREPRINT: Self = Self(c::VREPRINT as usize);
1234
1235 #[cfg(not(any(target_os = "aix", target_os = "haiku")))]
1237 pub const VDISCARD: Self = Self(c::VDISCARD as usize);
1238
1239 #[cfg(not(any(target_os = "aix", target_os = "haiku")))]
1241 pub const VWERASE: Self = Self(c::VWERASE as usize);
1242
1243 #[cfg(not(target_os = "haiku"))]
1245 pub const VLNEXT: Self = Self(c::VLNEXT as usize);
1246
1247 pub const VEOL2: Self = Self(c::VEOL2 as usize);
1249
1250 #[cfg(any(solarish, target_os = "haiku", target_os = "nto"))]
1252 pub const VSWTCH: Self = Self(c::VSWTCH as usize);
1253
1254 #[cfg(any(
1256 bsd,
1257 solarish,
1258 target_os = "aix",
1259 target_os = "hurd",
1260 target_os = "nto"
1261 ))]
1262 pub const VDSUSP: Self = Self(c::VDSUSP as usize);
1263
1264 #[cfg(any(bsd, target_os = "hurd", target_os = "illumos"))]
1266 pub const VSTATUS: Self = Self(c::VSTATUS as usize);
1267
1268 #[cfg(any(freebsdlike, target_os = "illumos"))]
1270 pub const VERASE2: Self = Self(c::VERASE2 as usize);
1271}
1272
1273impl core::fmt::Debug for SpecialCodeIndex {
1274 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1275 match *self {
1276 Self::VINTR => write!(f, "VINTR"),
1277 Self::VQUIT => write!(f, "VQUIT"),
1278 Self::VERASE => write!(f, "VERASE"),
1279 Self::VKILL => write!(f, "VKILL"),
1280 #[cfg(not(any(
1281 solarish,
1282 all(linux_kernel, any(target_arch = "sparc", target_arch = "sparc64")),
1283 target_os = "aix",
1284 target_os = "haiku",
1285 )))]
1286 Self::VEOF => write!(f, "VEOF"),
1287 #[cfg(not(any(
1288 solarish,
1289 all(linux_kernel, any(target_arch = "sparc", target_arch = "sparc64")),
1290 target_os = "aix",
1291 target_os = "haiku",
1292 )))]
1293 Self::VTIME => write!(f, "VTIME"),
1294 #[cfg(not(any(
1295 solarish,
1296 all(linux_kernel, any(target_arch = "sparc", target_arch = "sparc64")),
1297 target_os = "aix",
1298 target_os = "haiku",
1299 )))]
1300 Self::VMIN => write!(f, "VMIN"),
1301
1302 #[cfg(any(
1305 solarish,
1306 all(linux_kernel, any(target_arch = "sparc", target_arch = "sparc64")),
1307 target_os = "aix",
1308 target_os = "haiku",
1309 ))]
1310 Self::VMIN => write!(f, "VMIN/VEOF"),
1311 #[cfg(any(
1312 solarish,
1313 all(linux_kernel, any(target_arch = "sparc", target_arch = "sparc64")),
1314 target_os = "aix",
1315 target_os = "haiku",
1316 ))]
1317 Self::VTIME => write!(f, "VTIME/VEOL"),
1318
1319 #[cfg(not(any(
1320 bsd,
1321 solarish,
1322 target_os = "aix",
1323 target_os = "haiku",
1324 target_os = "hurd",
1325 target_os = "nto",
1326 )))]
1327 Self::VSWTC => write!(f, "VSWTC"),
1328 Self::VSTART => write!(f, "VSTART"),
1329 Self::VSTOP => write!(f, "VSTOP"),
1330 Self::VSUSP => write!(f, "VSUSP"),
1331 #[cfg(not(any(
1332 solarish,
1333 all(linux_kernel, any(target_arch = "sparc", target_arch = "sparc64")),
1334 target_os = "aix",
1335 target_os = "haiku",
1336 )))]
1337 Self::VEOL => write!(f, "VEOL"),
1338 #[cfg(not(target_os = "haiku"))]
1339 Self::VREPRINT => write!(f, "VREPRINT"),
1340 #[cfg(not(any(target_os = "aix", target_os = "haiku")))]
1341 Self::VDISCARD => write!(f, "VDISCARD"),
1342 #[cfg(not(any(target_os = "aix", target_os = "haiku")))]
1343 Self::VWERASE => write!(f, "VWERASE"),
1344 #[cfg(not(target_os = "haiku"))]
1345 Self::VLNEXT => write!(f, "VLNEXT"),
1346 Self::VEOL2 => write!(f, "VEOL2"),
1347 #[cfg(any(solarish, target_os = "haiku", target_os = "nto"))]
1348 Self::VSWTCH => write!(f, "VSWTCH"),
1349 #[cfg(any(
1350 bsd,
1351 solarish,
1352 target_os = "aix",
1353 target_os = "hurd",
1354 target_os = "nto"
1355 ))]
1356 Self::VDSUSP => write!(f, "VDSUSP"),
1357 #[cfg(any(bsd, target_os = "hurd", target_os = "illumos"))]
1358 Self::VSTATUS => write!(f, "VSTATUS"),
1359 #[cfg(any(freebsdlike, target_os = "illumos"))]
1360 Self::VERASE2 => write!(f, "VERASE2"),
1361
1362 _ => write!(f, "unknown"),
1363 }
1364 }
1365}
1366
1367#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
1371#[repr(u32)]
1372pub enum OptionalActions {
1373 #[doc(alias = "TCSANOW")]
1375 Now = c::TCSANOW as u32,
1376
1377 #[doc(alias = "TCSADRAIN")]
1379 Drain = c::TCSADRAIN as u32,
1380
1381 #[doc(alias = "TCSAFLUSH")]
1384 Flush = c::TCSAFLUSH as u32,
1385}
1386
1387#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
1391#[repr(u32)]
1392pub enum QueueSelector {
1393 #[doc(alias = "TCIFLUSH")]
1395 IFlush = c::TCIFLUSH as u32,
1396
1397 #[doc(alias = "TCOFLUSH")]
1399 OFlush = c::TCOFLUSH as u32,
1400
1401 #[doc(alias = "TCIOFLUSH")]
1403 IOFlush = c::TCIOFLUSH as u32,
1404}
1405
1406#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
1410#[repr(u32)]
1411pub enum Action {
1412 #[doc(alias = "TCOOFF")]
1414 OOff = c::TCOOFF as u32,
1415
1416 #[doc(alias = "TCOON")]
1418 OOn = c::TCOON as u32,
1419
1420 #[doc(alias = "TCIOFF")]
1422 IOff = c::TCIOFF as u32,
1423
1424 #[doc(alias = "TCION")]
1426 IOn = c::TCION as u32,
1427}
1428
1429#[doc(alias = "winsize")]
1433#[repr(C)]
1434#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
1435#[allow(missing_docs)]
1436pub struct Winsize {
1437 pub ws_row: u16,
1439 pub ws_col: u16,
1441
1442 pub ws_xpixel: u16,
1443 pub ws_ypixel: u16,
1444}
1445
1446#[cfg(test)]
1447mod tests {
1448 use super::*;
1449
1450 #[test]
1451 fn termios_layouts() {
1452 check_renamed_type!(InputModes, tcflag_t);
1453 check_renamed_type!(OutputModes, tcflag_t);
1454 check_renamed_type!(ControlModes, tcflag_t);
1455 check_renamed_type!(LocalModes, tcflag_t);
1456 assert_eq_size!(u8, libc::cc_t);
1457 assert_eq_size!(types::tcflag_t, libc::tcflag_t);
1458
1459 check_renamed_struct!(Winsize, winsize, ws_row, ws_col, ws_xpixel, ws_ypixel);
1460
1461 #[cfg(linux_raw)]
1463 {
1464 check_renamed_type!(Termios, termios2);
1465 check_renamed_struct_renamed_field!(Termios, termios2, input_modes, c_iflag);
1466 check_renamed_struct_renamed_field!(Termios, termios2, output_modes, c_oflag);
1467 check_renamed_struct_renamed_field!(Termios, termios2, control_modes, c_cflag);
1468 check_renamed_struct_renamed_field!(Termios, termios2, local_modes, c_lflag);
1469 check_renamed_struct_renamed_field!(Termios, termios2, line_discipline, c_line);
1470 check_renamed_struct_renamed_field!(Termios, termios2, special_codes, c_cc);
1471 check_renamed_struct_renamed_field!(Termios, termios2, input_speed, c_ispeed);
1472 check_renamed_struct_renamed_field!(Termios, termios2, output_speed, c_ospeed);
1473
1474 check_renamed_struct_renamed_field!(Termios, termios, input_modes, c_iflag);
1477 check_renamed_struct_renamed_field!(Termios, termios, output_modes, c_oflag);
1478 check_renamed_struct_renamed_field!(Termios, termios, control_modes, c_cflag);
1479 check_renamed_struct_renamed_field!(Termios, termios, local_modes, c_lflag);
1480 check_renamed_struct_renamed_field!(Termios, termios, special_codes, c_cc);
1481
1482 #[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
1485 const_assert_eq!(
1486 memoffset::offset_of!(Termios, input_speed),
1487 core::mem::size_of::<c::termios>()
1488 );
1489
1490 #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
1492 assert_eq_size!(c::termios2, c::termios);
1493 }
1494
1495 #[cfg(not(linux_raw))]
1496 {
1497 #[cfg(all(
1500 not(all(
1501 target_env = "gnu",
1502 any(
1503 target_arch = "mips",
1504 target_arch = "mips32r6",
1505 target_arch = "mips64",
1506 target_arch = "mips64r6",
1507 target_arch = "sparc",
1508 target_arch = "sparc64"
1509 )
1510 )),
1511 not(all(libc, target_os = "android"))
1512 ))]
1513 check_renamed_type!(Termios, termios);
1514 #[cfg(not(all(
1515 not(all(
1516 target_env = "gnu",
1517 any(
1518 target_arch = "mips",
1519 target_arch = "mips32r6",
1520 target_arch = "mips64",
1521 target_arch = "mips64r6",
1522 target_arch = "sparc",
1523 target_arch = "sparc64"
1524 )
1525 )),
1526 not(all(libc, target_os = "android"))
1527 )))]
1528 const_assert!(core::mem::size_of::<Termios>() >= core::mem::size_of::<c::termios>());
1529
1530 check_renamed_struct_renamed_field!(Termios, termios, input_modes, c_iflag);
1531 check_renamed_struct_renamed_field!(Termios, termios, output_modes, c_oflag);
1532 check_renamed_struct_renamed_field!(Termios, termios, control_modes, c_cflag);
1533 check_renamed_struct_renamed_field!(Termios, termios, local_modes, c_lflag);
1534 #[cfg(any(
1535 linux_like,
1536 target_env = "newlib",
1537 target_os = "fuchsia",
1538 target_os = "haiku",
1539 target_os = "redox"
1540 ))]
1541 check_renamed_struct_renamed_field!(Termios, termios, line_discipline, c_line);
1542 check_renamed_struct_renamed_field!(Termios, termios, special_codes, c_cc);
1543 #[cfg(not(any(
1544 linux_kernel,
1545 solarish,
1546 target_os = "emscripten",
1547 target_os = "fuchsia"
1548 )))]
1549 {
1550 check_renamed_struct_renamed_field!(Termios, termios, input_speed, c_ispeed);
1551 check_renamed_struct_renamed_field!(Termios, termios, output_speed, c_ospeed);
1552 }
1553 #[cfg(any(target_env = "musl", target_os = "fuchsia"))]
1554 {
1555 check_renamed_struct_renamed_field!(Termios, termios, input_speed, __c_ispeed);
1556 check_renamed_struct_renamed_field!(Termios, termios, output_speed, __c_ospeed);
1557 }
1558 }
1559
1560 check_renamed_type!(OptionalActions, c_int);
1561 check_renamed_type!(QueueSelector, c_int);
1562 check_renamed_type!(Action, c_int);
1563 }
1564
1565 #[test]
1566 #[cfg(not(any(
1567 solarish,
1568 target_os = "cygwin",
1569 target_os = "emscripten",
1570 target_os = "haiku",
1571 target_os = "redox",
1572 )))]
1573 fn termios_legacy() {
1574 const_assert_eq!(c::EXTA, c::B19200);
1576 const_assert_eq!(c::EXTB, c::B38400);
1577 }
1578
1579 #[cfg(bsd)]
1580 #[test]
1581 fn termios_bsd() {
1582 const_assert_eq!(c::B0, 0);
1585 const_assert_eq!(c::B50, 50);
1586 const_assert_eq!(c::B19200, 19200);
1587 const_assert_eq!(c::B38400, 38400);
1588 }
1589
1590 #[test]
1591 #[cfg(not(bsd))]
1592 fn termios_speed_encoding() {
1593 assert_eq!(speed::encode(0), Some(c::B0));
1594 assert_eq!(speed::encode(50), Some(c::B50));
1595 assert_eq!(speed::encode(19200), Some(c::B19200));
1596 assert_eq!(speed::encode(38400), Some(c::B38400));
1597 assert_eq!(speed::encode(1), None);
1598 assert_eq!(speed::encode(!0), None);
1599
1600 #[cfg(not(linux_kernel))]
1601 {
1602 assert_eq!(speed::decode(c::B0), Some(0));
1603 assert_eq!(speed::decode(c::B50), Some(50));
1604 assert_eq!(speed::decode(c::B19200), Some(19200));
1605 assert_eq!(speed::decode(c::B38400), Some(38400));
1606 }
1607 }
1608
1609 #[cfg(linux_kernel)]
1610 #[test]
1611 fn termios_ioctl_contiguity() {
1612 const_assert_eq!(c::TCSETS2, c::TCSETS2 + 0);
1616 const_assert_eq!(c::TCSETSW2, c::TCSETS2 + 1);
1617 const_assert_eq!(c::TCSETSF2, c::TCSETS2 + 2);
1618
1619 const_assert_eq!(c::TCSANOW - c::TCSANOW, 0);
1620 const_assert_eq!(c::TCSADRAIN - c::TCSANOW, 1);
1621 const_assert_eq!(c::TCSAFLUSH - c::TCSANOW, 2);
1622
1623 #[cfg(any(
1625 target_arch = "mips",
1626 target_arch = "mips32r6",
1627 target_arch = "mips64",
1628 target_arch = "mips64r6"
1629 ))]
1630 {
1631 assert_eq!(i128::from(c::TCSANOW) - i128::from(c::TCSETS), 0);
1632 assert_eq!(i128::from(c::TCSADRAIN) - i128::from(c::TCSETS), 1);
1633 assert_eq!(i128::from(c::TCSAFLUSH) - i128::from(c::TCSETS), 2);
1634 }
1635 #[cfg(not(any(
1636 target_arch = "mips",
1637 target_arch = "mips32r6",
1638 target_arch = "mips64",
1639 target_arch = "mips64r6"
1640 )))]
1641 {
1642 const_assert_eq!(c::TCSANOW, 0);
1643 const_assert_eq!(c::TCSADRAIN, 1);
1644 const_assert_eq!(c::TCSAFLUSH, 2);
1645 }
1646 }
1647
1648 #[cfg(linux_kernel)]
1649 #[test]
1650 fn termios_cibaud() {
1651 const_assert_eq!(c::CIBAUD, c::CBAUD << c::IBSHIFT);
1653 }
1654}