10f66f451Sopenharmony_ci/* microcom.c - Simple serial console. 20f66f451Sopenharmony_ci * 30f66f451Sopenharmony_ci * Copyright 2017 The Android Open Source Project. 40f66f451Sopenharmony_ci 50f66f451Sopenharmony_ciUSE_MICROCOM(NEWTOY(microcom, "<1>1s:X", TOYFLAG_USR|TOYFLAG_BIN)) 60f66f451Sopenharmony_ci 70f66f451Sopenharmony_ciconfig MICROCOM 80f66f451Sopenharmony_ci bool "microcom" 90f66f451Sopenharmony_ci default y 100f66f451Sopenharmony_ci help 110f66f451Sopenharmony_ci usage: microcom [-s SPEED] [-X] DEVICE 120f66f451Sopenharmony_ci 130f66f451Sopenharmony_ci Simple serial console. 140f66f451Sopenharmony_ci 150f66f451Sopenharmony_ci -s Set baud rate to SPEED 160f66f451Sopenharmony_ci -X Ignore ^@ (send break) and ^] (exit) 170f66f451Sopenharmony_ci*/ 180f66f451Sopenharmony_ci 190f66f451Sopenharmony_ci#define FOR_microcom 200f66f451Sopenharmony_ci#include "toys.h" 210f66f451Sopenharmony_ci 220f66f451Sopenharmony_ciGLOBALS( 230f66f451Sopenharmony_ci char *s; 240f66f451Sopenharmony_ci 250f66f451Sopenharmony_ci int fd; 260f66f451Sopenharmony_ci struct termios original_stdin_state, original_fd_state; 270f66f451Sopenharmony_ci) 280f66f451Sopenharmony_ci 290f66f451Sopenharmony_ci// TODO: tty_sigreset outputs ansi escape sequences, how to disable? 300f66f451Sopenharmony_cistatic void restore_states(int i) 310f66f451Sopenharmony_ci{ 320f66f451Sopenharmony_ci tcsetattr(0, TCSAFLUSH, &TT.original_stdin_state); 330f66f451Sopenharmony_ci tcsetattr(TT.fd, TCSAFLUSH, &TT.original_fd_state); 340f66f451Sopenharmony_ci} 350f66f451Sopenharmony_ci 360f66f451Sopenharmony_civoid microcom_main(void) 370f66f451Sopenharmony_ci{ 380f66f451Sopenharmony_ci struct pollfd fds[2]; 390f66f451Sopenharmony_ci int i, speed; 400f66f451Sopenharmony_ci 410f66f451Sopenharmony_ci if (!TT.s) speed = 115200; 420f66f451Sopenharmony_ci else speed = atoi(TT.s); 430f66f451Sopenharmony_ci 440f66f451Sopenharmony_ci // Open with O_NDELAY, but switch back to blocking for reads. 450f66f451Sopenharmony_ci TT.fd = xopen(*toys.optargs, O_RDWR | O_NOCTTY | O_NDELAY); 460f66f451Sopenharmony_ci if (-1==(i = fcntl(TT.fd, F_GETFL, 0)) || fcntl(TT.fd, F_SETFL, i&~O_NDELAY)) 470f66f451Sopenharmony_ci perror_exit_raw(*toys.optargs); 480f66f451Sopenharmony_ci 490f66f451Sopenharmony_ci // Set both input and output to raw mode. 500f66f451Sopenharmony_ci xset_terminal(TT.fd, 1, speed, &TT.original_fd_state); 510f66f451Sopenharmony_ci set_terminal(0, 1, 0, &TT.original_stdin_state); 520f66f451Sopenharmony_ci // ...and arrange to restore things, however we may exit. 530f66f451Sopenharmony_ci sigatexit(restore_states); 540f66f451Sopenharmony_ci 550f66f451Sopenharmony_ci fds[0].fd = TT.fd; 560f66f451Sopenharmony_ci fds[0].events = POLLIN; 570f66f451Sopenharmony_ci fds[1].fd = 0; 580f66f451Sopenharmony_ci fds[1].events = POLLIN; 590f66f451Sopenharmony_ci 600f66f451Sopenharmony_ci while (poll(fds, 2, -1) > 0) { 610f66f451Sopenharmony_ci char buf[BUFSIZ]; 620f66f451Sopenharmony_ci 630f66f451Sopenharmony_ci // Read from connection, write to stdout. 640f66f451Sopenharmony_ci if (fds[0].revents) { 650f66f451Sopenharmony_ci ssize_t n = read(TT.fd, buf, sizeof(buf)); 660f66f451Sopenharmony_ci if (n > 0) xwrite(0, buf, n); 670f66f451Sopenharmony_ci else break; 680f66f451Sopenharmony_ci } 690f66f451Sopenharmony_ci 700f66f451Sopenharmony_ci // Read from stdin, write to connection. 710f66f451Sopenharmony_ci if (fds[1].revents) { 720f66f451Sopenharmony_ci if (read(0, buf, 1) != 1) break; 730f66f451Sopenharmony_ci if (!(toys.optflags & FLAG_X)) { 740f66f451Sopenharmony_ci if (!*buf) { 750f66f451Sopenharmony_ci tcsendbreak(TT.fd, 0); 760f66f451Sopenharmony_ci continue; 770f66f451Sopenharmony_ci } else if (*buf == (']'-'@')) break; 780f66f451Sopenharmony_ci } 790f66f451Sopenharmony_ci xwrite(TT.fd, buf, 1); 800f66f451Sopenharmony_ci } 810f66f451Sopenharmony_ci } 820f66f451Sopenharmony_ci} 83