From fcd3937d7c5fa57fe996f443c10c3f5cefbb231c Mon Sep 17 00:00:00 2001 From: Oleg Evseev Date: Thu, 13 Aug 2020 00:10:37 +0300 Subject: [PATCH] system/cu: refactor, add option -c to disable \n -> \r\n conversion option -c will disable \n -> \r\n conversion both for serial device and console if it is a tty refactor: use only one function to set termios parameters, use termious related code and options only if CONFIG_SERIAL_TERMIOS is defined --- system/cu/cu_main.c | 165 +++++++++++++++++++++++++++++++------------- 1 file changed, 116 insertions(+), 49 deletions(-) diff --git a/system/cu/cu_main.c b/system/cu/cu_main.c index 469063db2..b053d2801 100644 --- a/system/cu/cu_main.c +++ b/system/cu/cu_main.c @@ -81,6 +81,11 @@ enum parity_mode ****************************************************************************/ static struct cu_globals_s g_cu; +#ifdef CONFIG_SERIAL_TERMIOS +int fd_std_tty; +static struct termios g_tio_std; +static struct termios g_tio_dev; +#endif /**************************************************************************** * Public Data @@ -129,52 +134,17 @@ static void sigint(int sig) exit(0); } -static int enable_crlf_conversion(int fd) -{ #ifdef CONFIG_SERIAL_TERMIOS +static int set_termios(int fd, int rate, enum parity_mode parity, + int rtscts, int nocrlf) +{ int rc = 0; int ret; struct termios tio; - /* enable \n -> \r\n conversion during write */ + tio = g_tio_dev; - ret = tcgetattr(fd, &tio); - if (ret) - { - fprintf(stderr, "en_crlf_conv: ERROR during tcgetattr(): %d\n", errno); - rc = -1; - } - - tio.c_oflag = OPOST | ONLCR; - ret = tcsetattr(fd, TCSANOW, &tio); - if (ret) - { - fprintf(stderr, "en_crlf_conv: ERROR during tcsetattr(): %d\n", errno); - rc = -1; - } - - return rc; -#else - return -1; -#endif -} - -static int set_baudrate(int fd, int rate, enum parity_mode parity, - int rtscts) -{ -#ifdef CONFIG_SERIAL_TERMIOS - int rc = 0; - int ret; - struct termios tio; - - /* enable \n -> \r\n conversion during write */ - - ret = tcgetattr(fd, &tio); - if (ret) - { - fprintf(stderr, "set_baudrate: ERROR during tcgetattr(): %d\n", errno); - rc = -1; - } + /* set baudrate */ if (rate != 0) { @@ -200,36 +170,81 @@ static int set_baudrate(int fd, int rate, enum parity_mode parity, tio.c_cflag |= CRTS_IFLOW | CCTS_OFLOW; } + tio.c_oflag = OPOST; + + /* enable or disable \n -> \r\n conversion during write */ + + if (nocrlf == 0) + { + tio.c_oflag |= ONLCR; + } + ret = tcsetattr(fd, TCSANOW, &tio); if (ret) { - fprintf(stderr, "set_baudrate: ERROR during tcsetattr(): %d\n", errno); + fprintf(stderr, "set_termios: ERROR during tcsetattr(): %d\n", errno); rc = -1; + goto errout; } + /* for tty stdout force enable or disable \n -> \r\n conversion */ + + if (fd_std_tty >= 0) + { + tio = g_tio_std; + if (nocrlf == 0) + { + tio.c_oflag |= ONLCR; + } + else + { + tio.c_oflag &= ~ONLCR; + } + + ret = tcsetattr(fd_std_tty, TCSANOW, &tio); + if (ret) + { + fprintf(stderr, "set_termios: ERROR during tcsetattr(): %d\n", + errno); + rc = -1; + } + } + +errout: return rc; -#else - if (rate == 0) +} + +static int retrive_termios(int fd) +{ + tcsetattr(fd, TCSANOW, &g_tio_dev); + if (fd_std_tty >= 0) { - return 0; + tcsetattr(fd_std_tty, TCSANOW, &g_tio_std); } - return -1; -#endif + return 0; } +#endif static void print_help(void) { printf("Usage: cu [options]\n" " -l: Use named device (default %s)\n" +#ifdef CONFIG_SERIAL_TERMIOS " -e: Set even parity\n" " -o: Set odd parity\n" " -s: Use given speed (default %d)\n" " -r: Disable RTS/CTS flow control (default: on)\n" + " -c: Disable lf -> crlf conversion (default: off)\n" +#endif " -f: Enable endless mode without escape sequence (default: off)\n" " -?: This help\n", +#ifdef CONFIG_SERIAL_TERMIOS CONFIG_SYSTEM_CUTERM_DEFAULT_DEVICE, CONFIG_SYSTEM_CUTERM_DEFAULT_BAUD); +#else + CONFIG_SYSTEM_CUTERM_DEFAULT_DEVICE); +#endif } static void print_escape_help(void) @@ -273,9 +288,12 @@ int main(int argc, FAR char *argv[]) pthread_attr_t attr; struct sigaction sa; FAR char *devname = CONFIG_SYSTEM_CUTERM_DEFAULT_DEVICE; +#ifdef CONFIG_SERIAL_TERMIOS int baudrate = CONFIG_SYSTEM_CUTERM_DEFAULT_BAUD; enum parity_mode parity = PARITY_NONE; int rtscts = 1; + int nocrlf = 0; +#endif int nobreak = 0; int option; int ret; @@ -294,7 +312,7 @@ int main(int argc, FAR char *argv[]) sigaction(SIGKILL, &sa, NULL); optind = 0; /* global that needs to be reset in FLAT mode */ - while ((option = getopt(argc, argv, "l:s:efhor?")) != ERROR) + while ((option = getopt(argc, argv, "l:s:cefhor?")) != ERROR) { switch (option) { @@ -302,6 +320,7 @@ int main(int argc, FAR char *argv[]) devname = optarg; break; +#ifdef CONFIG_SERIAL_TERMIOS case 's': baudrate = atoi(optarg); break; @@ -318,6 +337,11 @@ int main(int argc, FAR char *argv[]) rtscts = 0; break; + case 'c': + nocrlf = 1; + break; +#endif + case 'f': nobreak = 1; break; @@ -342,8 +366,47 @@ int main(int argc, FAR char *argv[]) goto errout_with_devinit; } - enable_crlf_conversion(g_cu.outfd); - set_baudrate(g_cu.outfd, baudrate, parity, rtscts); +#ifdef CONFIG_SERIAL_TERMIOS + /* remember serial device termios attributes */ + + ret = tcgetattr(g_cu.outfd, &g_tio_dev); + if (ret) + { + fprintf(stderr, "cu_main: ERROR during tcgetattr(): %d\n", errno); + goto errout_with_outfd; + } + + /* remember std termios attributes if it is a tty. Try to select + * right descriptor that is used to refer to tty + */ + + if (isatty(fileno(stderr))) + { + fd_std_tty = fileno(stderr); + } + else if (isatty(fileno(stdout))) + { + fd_std_tty = fileno(stdout); + } + else if (isatty(fileno(stdin))) + { + fd_std_tty = fileno(stdin); + } + else + { + fd_std_tty = -1; + } + + if (fd_std_tty >= 0) + { + tcgetattr(fd_std_tty, &g_tio_std); + } + + if (set_termios(g_cu.outfd, baudrate, parity, rtscts, nocrlf) != 0) + { + goto errout_with_outfd_retrieve; + } +#endif /* Open the serial device for reading. Since we are already connected, * this should not fail. @@ -443,6 +506,10 @@ int main(int argc, FAR char *argv[]) errout_with_fds: close(g_cu.infd); +#ifdef CONFIG_SERIAL_TERMIOS +errout_with_outfd_retrieve: + retrive_termios(g_cu.outfd); +#endif errout_with_outfd: close(g_cu.outfd); errout_with_devinit: