commit 4c2d5ff1162be816f0498f79804333a802a75a70
parent 6507fa604db4cb304daaa6ba2f3ae86e3706557c
Author: Alexey Yerin <yyp@disroot.org>
Date: Thu, 25 Nov 2021 20:50:27 +0300
unix::tty: add termios support on +freebsd
Signed-off-by: Alexey Yerin <yyp@disroot.org>
Diffstat:
2 files changed, 164 insertions(+), 2 deletions(-)
diff --git a/rt/+freebsd/types.ha b/rt/+freebsd/types.ha
@@ -118,6 +118,110 @@ export type winsize = struct {
ws_ypixel: u16,
};
+export type termios = struct {
+ c_iflag: tcflag,
+ c_oflag: tcflag,
+ c_cflag: tcflag,
+ c_lflag: tcflag,
+ c_cc: [NCCS]cc,
+};
+
+export def NCCS: size = 20;
+
+export type tcflag = enum uint {
+ // c_iflag bits
+ IGNBRK = 0x00000001,
+ BRKINT = 0x00000002,
+ IGNPAR = 0x00000004,
+ PARMRK = 0x00000008,
+ INPCK = 0x00000010,
+ ISTRIP = 0x00000020,
+ INLCR = 0x00000040,
+ IGNCR = 0x00000080,
+ ICRNL = 0x00000100,
+ IXON = 0x00000200,
+ IXOFF = 0x00000400,
+ IXANY = 0x00000800,
+ IMAXBEL = 0x00002000,
+
+ // c_oflag bits
+ OPOST = 0x00000001,
+ ONLCR = 0x00000002,
+ TABDLY = 0x00000004,
+ TAB0 = 0x00000000,
+ TAB3 = 0x00000004,
+ ONOEOT = 0x00000008,
+ OCRNL = 0x00000010,
+ ONOCR = 0x00000020,
+ ONLRET = 0x00000040,
+
+ // c_cflag bits
+ CIGNORE = 0x00000001,
+ CSIZE = 0x00000300,
+ CS5 = 0x00000000,
+ CS6 = 0x00000100,
+ CS7 = 0x00000200,
+ CS8 = 0x00000300,
+ CSTOPB = 0x00000400,
+ CREAD = 0x00000800,
+ PARENB = 0x00001000,
+ PARODD = 0x00002000,
+ HUPCL = 0x00004000,
+ CLOCAL = 0x00008000,
+ CCTS_OFLOW = 0x00010000,
+ CRTS_IFLOW = 0x00020000,
+ CRTSCTS = (CCTS_OFLOW | CRTS_IFLOW),
+ CDTR_IFLOW = 0x00040000,
+ CDSR_OFLOW = 0x00080000,
+ CCAR_OFLOW = 0x00100000,
+ CNO_RTSDTR = 0x00200000,
+
+ // c_lflag bits
+ ECHOKE = 0x00000001,
+ ECHOE = 0x00000002,
+ ECHOK = 0x00000004,
+ ECHO = 0x00000008,
+ ECHONL = 0x00000010,
+ ECHOPRT = 0x00000020,
+ ECHOCTL = 0x00000040,
+ ISIG = 0x00000080,
+ ICANON = 0x00000100,
+ ALTWERASE = 0x00000200,
+ IEXTEN = 0x00000400,
+ EXTPROC = 0x00000800,
+ TOSTOP = 0x00400000,
+ FLUSHO = 0x00800000,
+ NOKERNINFO = 0x02000000,
+ PENDIN = 0x20000000,
+ NOFLSH = 0x80000000,
+};
+
+export type cc = enum char {
+ VEOF = 0,
+ VEOL = 1,
+ VEOL2 = 2,
+ VERASE = 3,
+ VWERASE = 4,
+ VKILL = 5,
+ VREPRINT = 6,
+ VERASE2 = 7,
+ VINTR = 8,
+ VQUIT = 9,
+ VSUSP = 10,
+ VDSUSP = 11,
+ VSTART = 12,
+ VSTOP = 13,
+ VLNEXT = 14,
+ VDISCARD = 15,
+ VMIN = 16,
+ VTIME = 17,
+ VSTATUS = 18,
+};
+
+export def TIOCGWINSZ: u64 = 0x40087468;
+export def TIOCGETA: u64 = 0x402c7413;
+export def TIOCSETA: u64 = 0x802c7414;
+
export type rusage = struct {
ru_utime: timeval,
ru_stime: timeval,
@@ -137,8 +241,6 @@ export type rusage = struct {
ru_nivcsw: i64,
};
-export def TIOCGWINSZ: u64 = 0x40087468;
-
export def DT_UNKNOWN: u8 = 0;
export def DT_FIFO: u8 = 1;
export def DT_CHR: u8 = 2;
diff --git a/unix/tty/+freebsd/termios.ha b/unix/tty/+freebsd/termios.ha
@@ -0,0 +1,60 @@
+use io;
+use rt;
+use errors;
+
+export type termios = struct {
+ file: io::file,
+ saved: rt::termios,
+ current: rt::termios,
+};
+
+// Retrieves serial port settings of the given terminal.
+export fn termios_query(file: io::file) (termios | errors::error) = {
+ let settings = rt::termios { ... };
+
+ match (rt::ioctl(file, rt::TIOCGETA, &settings)) {
+ case int => void;
+ case err: rt::errno =>
+ return errors::errno(err);
+ };
+
+ return termios {
+ file = file,
+ saved = settings,
+ current = settings,
+ };
+};
+
+// Restores original serial port settings.
+export fn termios_restore(termios: *const termios) void = {
+ rt::ioctl(termios.file, rt::TIOCSETA, &termios.saved): void;
+};
+
+// Sets serial port settings.
+export fn termios_set(termios: *const termios) (void | errors::error) = {
+ match (rt::ioctl(termios.file, rt::TIOCSETA, &termios.current)) {
+ case int => void;
+ case err: rt::errno =>
+ return errors::errno(err);
+ };
+};
+
+// Enables "raw" mode for this terminal, disabling echoing, line
+// editing, and signal handling. Users should call [[termios_query]]
+// prior to this to save the previous terminal settings, and
+// [[termios_restore]] to restore them before exiting.
+export fn makeraw(termios: *termios) (void | errors::error) = {
+ // Disable break signal and CR<->LF processing
+ termios.current.c_iflag &= ~(rt::tcflag::IGNBRK | rt::tcflag::BRKINT
+ | rt::tcflag::INLCR | rt::tcflag::IGNCR
+ | rt::tcflag::ICRNL);
+ // Disable output post-processing
+ termios.current.c_oflag &= ~rt::tcflag::OPOST;
+ // Disable character echo, canonical mode, implementation defined
+ // extensions and INTR/QUIT/SUSP characters
+ termios.current.c_lflag &= ~(rt::tcflag::ECHO | rt::tcflag::ECHONL
+ | rt::tcflag::ICANON | rt::tcflag::IEXTEN
+ | rt::tcflag::ISIG);
+
+ termios_set(termios)?;
+};