diff --git a/man/tio.1.in b/man/tio.1.in index d36c56a..3757f1b 100644 --- a/man/tio.1.in +++ b/man/tio.1.in @@ -383,6 +383,14 @@ Toggle the tty line. Sleep for seconds. .IP "\fBmsleep(ms)" Sleep for miliseconds. +.IP "\fBconfig_high(line)" +Set tty line state configuration to high. +.IP "\fBconfig_low(line)" +Set tty line state configuration to low. +.IP "\fBapply_config()" +Apply tty line state configuration. Using the line state configuration API +instead of high()/low() will help to make the lines physically switch as +simultaneously as possible. This may solve timing issues on some platforms. .TP 0n Note: Line can be any of DTR, RTS, CTS, DSR, CD, RI diff --git a/src/script.c b/src/script.c index c736a50..c06e93e 100644 --- a/src/script.c +++ b/src/script.c @@ -27,6 +27,7 @@ #include #include #include +#include "misc.h" #include "print.h" #include "options.h" #include "tty.h" @@ -67,60 +68,6 @@ static int msleep(lua_State *L) return 0; } -static void script_line_set(int line, bool value) -{ - switch (line) - { - case TIOCM_DTR: - tty_line_set(serial_fd, "DTR", line, value); - break; - case TIOCM_RTS: - tty_line_set(serial_fd, "RTS", line, value); - break; - case TIOCM_CTS: - tty_line_set(serial_fd, "CTS", line, value); - break; - case TIOCM_DSR: - tty_line_set(serial_fd, "DSR", line, value); - break; - case TIOCM_CD: - tty_line_set(serial_fd, "CD", line, value); - break; - case TIOCM_RI: - tty_line_set(serial_fd, "RI", line, value); - break; - default: - break; - } -} - -static void script_line_toggle(int line) -{ - switch (line) - { - case TIOCM_DTR: - tty_line_toggle(serial_fd, "DTR", line); - break; - case TIOCM_RTS: - tty_line_toggle(serial_fd, "RTS", line); - break; - case TIOCM_CTS: - tty_line_toggle(serial_fd, "CTS", line); - break; - case TIOCM_DSR: - tty_line_toggle(serial_fd, "DSR", line); - break; - case TIOCM_CD: - tty_line_toggle(serial_fd, "CD", line); - break; - case TIOCM_RI: - tty_line_toggle(serial_fd, "RI", line); - break; - default: - break; - } -} - // lua: high(line) static int high(lua_State *L) { @@ -131,7 +78,7 @@ static int high(lua_State *L) return 0; } - script_line_set(line, LINE_HIGH); + tty_line_set(serial_fd, line, LINE_HIGH); return 0; } @@ -146,7 +93,7 @@ static int low(lua_State *L) return 0; } - script_line_set(line, LINE_LOW); + tty_line_set(serial_fd, line, LINE_LOW); return 0; } @@ -161,7 +108,47 @@ static int toggle(lua_State *L) return 0; } - script_line_toggle(line); + tty_line_toggle(serial_fd, line); + + return 0; +} + +// lua: config_high(line) +static int config_high(lua_State *L) +{ + long line = lua_tointeger(L, 1); + + if (line < 0) + { + return 0; + } + + tty_line_config(line, true); + + return 0; +} + +// lua: config_low(line) +static int config_low(lua_State *L) +{ + long line = lua_tointeger(L, 1); + + if (line < 0) + { + return 0; + } + + tty_line_config(line, false); + + return 0; +} + +// lua: config_apply(line) +static int config_apply(lua_State *L) +{ + UNUSED(L); + + tty_line_config_apply(); return 0; } @@ -186,6 +173,9 @@ static const struct luaL_Reg tio_lib[] = { "high", high}, { "low", low}, { "toggle", toggle}, + { "config_high", config_high}, + { "config_low", config_low}, + { "config_apply", config_apply}, {NULL, NULL} }; diff --git a/src/tty.c b/src/tty.c index 38bf1ef..af36ae1 100644 --- a/src/tty.c +++ b/src/tty.c @@ -120,6 +120,13 @@ typedef enum LINE_PULSE } tty_line_mode_t; +typedef struct +{ + int mask; + bool value; + bool reserved; +} tty_line_config_t; + const char random_array[] = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x20, 0x28, 0x0A, 0x20, @@ -164,6 +171,7 @@ static pthread_t thread; static int pipefd[2]; static pthread_mutex_t mutex_input_ready = PTHREAD_MUTEX_INITIALIZER; static char line[LINE_SIZE_MAX]; +static tty_line_config_t line_config[6] = { }; static void optional_local_echo(char c) { @@ -427,7 +435,89 @@ static void output_hex(char c) } } -void tty_line_set(int fd, const char *name, int mask, bool value) +static const char *tty_line_name(int mask) +{ + switch (mask) + { + case TIOCM_DTR: + return "DTR"; + case TIOCM_RTS: + return "RTS"; + case TIOCM_CTS: + return "CTS"; + case TIOCM_DSR: + return "DSR"; + case TIOCM_CD: + return "CD"; + case TIOCM_RI: + return "RI"; + default: + return NULL; + } +} + +void tty_line_config(int mask, bool value) +{ + int i = 0; + + for (i=0; i<6; i++) + { + if ((line_config[i].mask == mask) || (line_config[i].reserved == false)) + { + line_config[i].mask = mask; + line_config[i].value = value; + line_config[i].reserved = true; + break; + } + } +} + +void tty_line_config_apply(void) +{ + int i = 0; + static int state; + + if (ioctl(fd, TIOCMGET, &state) < 0) + { + tio_warning_printf("Could not get line state (%s)", strerror(errno)); + return; + } + + for (i=0; i<6; i++) + { + if (line_config[i].reserved) + { + if (line_config[i].value) + { + // High + state &= ~line_config[i].mask; + tio_printf("Setting %s to HIGH", tty_line_name(line_config[i].mask)); + } + else + { + // Low + state |= line_config[i].mask; + tio_printf("Setting %s to LOW", tty_line_name(line_config[i].mask)); + } + + line_config[i].reserved = true; + } + } + + if (ioctl(fd, TIOCMSET, &state) < 0) + { + tio_warning_printf("Could not set line state configuration (%s)", strerror(errno)); + } + + // Reset configuration + for (i=0; i<6; i++) + { + line_config[i].reserved = false; + line_config[i].mask = -1; + } +} + +void tty_line_set(int fd, int mask, bool value) { int state; @@ -440,12 +530,12 @@ void tty_line_set(int fd, const char *name, int mask, bool value) if (value) { state &= ~mask; - tio_printf("Setting %s to HIGH", name); + tio_printf("Setting %s to HIGH", tty_line_name(mask)); } else { state |= mask; - tio_printf("Setting %s to LOW", name); + tio_printf("Setting %s to LOW", tty_line_name(mask)); } if (ioctl(fd, TIOCMSET, &state) < 0) @@ -454,7 +544,7 @@ void tty_line_set(int fd, const char *name, int mask, bool value) } } -void tty_line_toggle(int fd, const char *line_name, int mask) +void tty_line_toggle(int fd, int mask) { int state; @@ -467,12 +557,12 @@ void tty_line_toggle(int fd, const char *line_name, int mask) if (state & mask) { state &= ~mask; - tio_printf("Setting %s to HIGH", line_name); + tio_printf("Setting %s to HIGH", tty_line_name(mask)); } else { state |= mask; - tio_printf("Setting %s to LOW", line_name); + tio_printf("Setting %s to LOW", tty_line_name(mask)); } if (ioctl(fd, TIOCMSET, &state) < 0) @@ -481,9 +571,9 @@ void tty_line_toggle(int fd, const char *line_name, int mask) } } -static void tty_line_pulse(int fd, const char *line_name, int mask, unsigned int duration) +static void tty_line_pulse(int fd, int mask, unsigned int duration) { - tty_line_toggle(fd, line_name, mask); + tty_line_toggle(fd, mask); if (duration > 0) { @@ -491,19 +581,19 @@ static void tty_line_pulse(int fd, const char *line_name, int mask, unsigned int delay(duration); } - tty_line_toggle(fd, line_name, mask); + tty_line_toggle(fd, mask); } -static void tty_line_poke(int fd, const char *name, int mask, tty_line_mode_t mode, unsigned int duration) +static void tty_line_poke(int fd, int mask, tty_line_mode_t mode, unsigned int duration) { switch (mode) { case LINE_TOGGLE: - tty_line_toggle(fd, name, mask); + tty_line_toggle(fd, mask); break; case LINE_PULSE: - tty_line_pulse(fd, name, mask, duration); + tty_line_pulse(fd, mask, duration); break; case LINE_OFF: @@ -564,22 +654,22 @@ void handle_command_sequence(char input_char, char *output_char, bool *forward) switch (input_char) { case KEY_0: - tty_line_poke(fd, "DTR", TIOCM_DTR, line_mode, option.dtr_pulse_duration); + tty_line_poke(fd, TIOCM_DTR, line_mode, option.dtr_pulse_duration); break; case KEY_1: - tty_line_poke(fd, "RTS", TIOCM_RTS, line_mode, option.rts_pulse_duration); + tty_line_poke(fd, TIOCM_RTS, line_mode, option.rts_pulse_duration); break; case KEY_2: - tty_line_poke(fd, "CTS", TIOCM_CTS, line_mode, option.cts_pulse_duration); + tty_line_poke(fd, TIOCM_CTS, line_mode, option.cts_pulse_duration); break; case KEY_3: - tty_line_poke(fd, "DSR", TIOCM_DSR, line_mode, option.dsr_pulse_duration); + tty_line_poke(fd, TIOCM_DSR, line_mode, option.dsr_pulse_duration); break; case KEY_4: - tty_line_poke(fd, "DCD", TIOCM_CD, line_mode, option.dcd_pulse_duration); + tty_line_poke(fd, TIOCM_CD, line_mode, option.dcd_pulse_duration); break; case KEY_5: - tty_line_poke(fd, "RI", TIOCM_RI, line_mode, option.ri_pulse_duration); + tty_line_poke(fd, TIOCM_RI, line_mode, option.ri_pulse_duration); break; default: tio_warning_printf("Invalid line number"); diff --git a/src/tty.h b/src/tty.h index 4c667ef..eb4b3bb 100644 --- a/src/tty.h +++ b/src/tty.h @@ -39,5 +39,7 @@ void tty_wait_for_device(void); void list_serial_devices(void); void tty_input_thread_create(void); void tty_input_thread_wait_ready(void); -void tty_line_set(int fd, const char *name, int mask, bool value); -void tty_line_toggle(int fd, const char *name, int mask); +void tty_line_set(int fd, int mask, bool value); +void tty_line_toggle(int fd, int mask); +void tty_line_config(int mask, bool value); +void tty_line_config_apply(void);