diff options
-rw-r--r-- | lib/lib.h | 1 | ||||
-rw-r--r-- | lib/tty.c | 14 | ||||
-rw-r--r-- | toys/net/microcom.c | 19 |
3 files changed, 27 insertions, 7 deletions
@@ -337,6 +337,7 @@ int terminal_probesize(unsigned *xx, unsigned *yy); #define KEY_ALT (1<<18) int scan_key(char *scratch, int timeout_ms); int scan_key_getsize(char *scratch, int timeout_ms, unsigned *xx, unsigned *yy); +void xsetspeed(struct termios *tio, int speed); int set_terminal(int fd, int raw, int speed, struct termios *old); void xset_terminal(int fd, int raw, int speed, struct termios *old); void tty_esc(char *s); @@ -61,6 +61,20 @@ int terminal_probesize(unsigned *xx, unsigned *yy) return 0; } +void xsetspeed(struct termios *tio, int speed) +{ + int i, speeds[] = {50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, + 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, + 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000, + 2500000, 3000000, 3500000, 4000000}; + + // Find speed in table, adjust to constant + for (i = 0; i < ARRAY_LEN(speeds); i++) if (speeds[i] == speed) break; + if (i == ARRAY_LEN(speeds)) error_exit("unknown speed: %d", speed); + cfsetspeed(tio, i+1+4081*(i>15)); +} + + // Reset terminal to known state, saving copy of old state if old != NULL. int set_terminal(int fd, int raw, int speed, struct termios *old) { diff --git a/toys/net/microcom.c b/toys/net/microcom.c index 62b020f2..963445c2 100644 --- a/toys/net/microcom.c +++ b/toys/net/microcom.c @@ -22,30 +22,35 @@ config MICROCOM GLOBALS( long s; - int fd; - struct termios original_stdin_state, original_fd_state; + int fd, stok; + struct termios old_stdin, old_fd; ) // TODO: tty_sigreset outputs ansi escape sequences, how to disable? static void restore_states(int i) { - tcsetattr(0, TCSAFLUSH, &TT.original_stdin_state); - tcsetattr(TT.fd, TCSAFLUSH, &TT.original_fd_state); + if (TT.stok) tcsetattr(0, TCSAFLUSH, &TT.old_stdin); + tcsetattr(TT.fd, TCSAFLUSH, &TT.old_fd); } void microcom_main(void) { + struct termios tio; struct pollfd fds[2]; int i; // Open with O_NDELAY, but switch back to blocking for reads. TT.fd = xopen(*toys.optargs, O_RDWR | O_NOCTTY | O_NDELAY); - if (-1==(i = fcntl(TT.fd, F_GETFL, 0)) || fcntl(TT.fd, F_SETFL, i&~O_NDELAY)) + if (-1==(i = fcntl(TT.fd, F_GETFL, 0)) || fcntl(TT.fd, F_SETFL, i&~O_NDELAY) + || tcgetattr(TT.fd, &TT.old_fd)) perror_exit_raw(*toys.optargs); // Set both input and output to raw mode. - xset_terminal(TT.fd, 1, TT.s, &TT.original_fd_state); - set_terminal(0, 1, 0, &TT.original_stdin_state); + memcpy(&tio, &TT.old_fd, sizeof(struct termios)); + cfmakeraw(&tio); + xsetspeed(&tio, TT.s); + if (tcsetattr(TT.fd, TCSAFLUSH, &tio)) perror_exit("set speed"); + if (!set_terminal(0, 1, 0, &TT.old_stdin)) TT.stok++; // ...and arrange to restore things, however we may exit. sigatexit(restore_states); |