mirror of
https://github.com/tio/tio.git
synced 2026-05-01 14:57:59 +02:00
Add Lua scripting feature
Add support for running Lua scripts that can manipulate the tty control lines. Script is activated automatically on connect or manually via in session key command. The Lua scripting feature opens up for many posibilities in the future such as adding expect like functionality to easily and programatically interact with the connected device.
This commit is contained in:
parent
6fee8514f4
commit
0becfa3274
12 changed files with 590 additions and 72 deletions
|
|
@ -37,6 +37,9 @@ _tio()
|
|||
--rs-485-config \
|
||||
--alert \
|
||||
--mute \
|
||||
--script \
|
||||
--script-file \
|
||||
--script-run \
|
||||
-v --version \
|
||||
-h --help"
|
||||
|
||||
|
|
@ -151,6 +154,18 @@ _tio()
|
|||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
return 0
|
||||
;;
|
||||
--script)
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
return 0
|
||||
;;
|
||||
--script-file)
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
return 0
|
||||
;;
|
||||
--script-run)
|
||||
COMPREPLY=( $(compgen -W "once always never" -- ${cur}) )
|
||||
return 0
|
||||
;;
|
||||
-v | --version)
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
return 0
|
||||
|
|
|
|||
|
|
@ -60,6 +60,9 @@ struct config_t
|
|||
char *log_filename;
|
||||
char *socket;
|
||||
char *map;
|
||||
char *script;
|
||||
char *script_filename;
|
||||
bool script_run;
|
||||
};
|
||||
|
||||
static struct config_t c;
|
||||
|
|
@ -297,6 +300,20 @@ static int data_handler(void *user, const char *section, const char *name,
|
|||
{
|
||||
// Do nothing
|
||||
}
|
||||
else if (!strcmp(name, "script"))
|
||||
{
|
||||
asprintf(&c.script, "%s", value);
|
||||
option.script = c.script;
|
||||
}
|
||||
else if (!strcmp(name, "script-file"))
|
||||
{
|
||||
asprintf(&c.script_filename, "%s", value);
|
||||
option.script_filename = c.script_filename;
|
||||
}
|
||||
else if (!strcmp(name, "script-run"))
|
||||
{
|
||||
option.script_run = script_run_option_parse(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
tio_warning_printf("Unknown option '%s' in configuration file, ignored", name);
|
||||
|
|
|
|||
|
|
@ -18,14 +18,27 @@ tio_sources = [
|
|||
'rs485.c',
|
||||
'timestamp.c',
|
||||
'alert.c',
|
||||
'xymodem.c'
|
||||
'xymodem.c',
|
||||
'script.c'
|
||||
]
|
||||
|
||||
|
||||
foreach name: ['lua-5.4', 'lua-5.3', 'lua-5.2', 'lua-5.1', 'lua']
|
||||
lua_dep = dependency(name, version: '>=5.1', required: false)
|
||||
if lua_dep.found()
|
||||
break
|
||||
endif
|
||||
endforeach
|
||||
if not lua_dep.found()
|
||||
error('Lua could not be found!')
|
||||
endif
|
||||
|
||||
tio_dep = [
|
||||
dependency('threads', required: true),
|
||||
dependency('inih', required: true,
|
||||
fallback : ['libinih', 'inih_dep'],
|
||||
default_options: ['default_library=static', 'distro_install=false'])
|
||||
default_options: ['default_library=static', 'distro_install=false']),
|
||||
lua_dep
|
||||
]
|
||||
|
||||
tio_c_args = ['-Wno-unused-result']
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#include "timestamp.h"
|
||||
#include "alert.h"
|
||||
#include "log.h"
|
||||
#include "script.h"
|
||||
|
||||
enum opt_t
|
||||
{
|
||||
|
|
@ -54,6 +55,9 @@ enum opt_t
|
|||
OPT_ALERT,
|
||||
OPT_COMPLETE_SUB_CONFIGS,
|
||||
OPT_MUTE,
|
||||
OPT_SCRIPT,
|
||||
OPT_SCRIPT_FILE,
|
||||
OPT_SCRIPT_RUN,
|
||||
};
|
||||
|
||||
/* Default options */
|
||||
|
|
@ -96,6 +100,9 @@ struct option_t option =
|
|||
.rs485_delay_rts_after_send = -1,
|
||||
.alert = ALERT_NONE,
|
||||
.complete_sub_configs = false,
|
||||
.script = NULL,
|
||||
.script_filename = NULL,
|
||||
.script_run = SCRIPT_RUN_ALWAYS,
|
||||
};
|
||||
|
||||
void print_help(char *argv[])
|
||||
|
|
@ -134,6 +141,9 @@ void print_help(char *argv[])
|
|||
printf(" --rs-485-config <config> Set RS-485 configuration\n");
|
||||
printf(" --alert bell|blink|none Alert on connect/disconnect (default: none)\n");
|
||||
printf(" --mute Mute tio\n");
|
||||
printf(" --script <string> Run script from string\n");
|
||||
printf(" --script-file <filename> Run script from file\n");
|
||||
printf(" --script-run once|always|never Run script on connect (default: always)\n");
|
||||
printf(" -v, --version Display version\n");
|
||||
printf(" -h, --help Display help\n");
|
||||
printf("\n");
|
||||
|
|
@ -202,6 +212,27 @@ void line_pulse_duration_option_parse(const char *arg)
|
|||
free(buffer);
|
||||
}
|
||||
|
||||
enum script_run_t script_run_option_parse(const char *arg)
|
||||
{
|
||||
if (strcmp("once", arg) == 0)
|
||||
{
|
||||
return SCRIPT_RUN_ONCE;
|
||||
}
|
||||
else if (strcmp("always", arg) == 0)
|
||||
{
|
||||
return SCRIPT_RUN_ALWAYS;
|
||||
}
|
||||
else if (strcmp("never", arg) == 0)
|
||||
{
|
||||
return SCRIPT_RUN_NEVER;
|
||||
}
|
||||
else
|
||||
{
|
||||
tio_error_printf("Invalid script run option");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void options_print()
|
||||
{
|
||||
tio_printf(" Device: %s", option.tty_device);
|
||||
|
|
@ -276,6 +307,9 @@ void options_parse(int argc, char *argv[])
|
|||
{"rs-485-config", required_argument, 0, OPT_RS485_CONFIG },
|
||||
{"alert", required_argument, 0, OPT_ALERT },
|
||||
{"mute", no_argument, 0, OPT_MUTE },
|
||||
{"script", required_argument, 0, OPT_SCRIPT },
|
||||
{"script-file", required_argument, 0, OPT_SCRIPT_FILE },
|
||||
{"script-run", required_argument, 0, OPT_SCRIPT_RUN },
|
||||
{"version", no_argument, 0, 'v' },
|
||||
{"help", no_argument, 0, 'h' },
|
||||
{"complete-sub-configs", no_argument, 0, OPT_COMPLETE_SUB_CONFIGS},
|
||||
|
|
@ -439,6 +473,18 @@ void options_parse(int argc, char *argv[])
|
|||
option.mute = true;
|
||||
break;
|
||||
|
||||
case OPT_SCRIPT:
|
||||
option.script = optarg;
|
||||
break;
|
||||
|
||||
case OPT_SCRIPT_FILE:
|
||||
option.script_filename = optarg;
|
||||
break;
|
||||
|
||||
case OPT_SCRIPT_RUN:
|
||||
option.script_run = script_run_option_parse(optarg);
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
printf("tio v%s\n", VERSION);
|
||||
exit(EXIT_SUCCESS);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <limits.h>
|
||||
#include <termios.h>
|
||||
#include <sys/param.h>
|
||||
#include "script.h"
|
||||
#include "timestamp.h"
|
||||
#include "alert.h"
|
||||
|
||||
|
|
@ -69,6 +70,9 @@ struct option_t
|
|||
int32_t rs485_delay_rts_after_send;
|
||||
enum alert_t alert;
|
||||
bool complete_sub_configs;
|
||||
const char *script;
|
||||
const char *script_filename;
|
||||
enum script_run_t script_run;
|
||||
};
|
||||
|
||||
extern struct option_t option;
|
||||
|
|
@ -78,3 +82,4 @@ void options_parse(int argc, char *argv[]);
|
|||
void options_parse_final(int argc, char *argv[]);
|
||||
|
||||
void line_pulse_duration_option_parse(const char *arg);
|
||||
enum script_run_t script_run_option_parse(const char *arg);
|
||||
|
|
|
|||
280
src/script.c
Normal file
280
src/script.c
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
* tio - a simple serial terminal I/O tool
|
||||
*
|
||||
* Copyright (c) 2014-2024 Martin Lund
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <lauxlib.h>
|
||||
#include <lualib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include "print.h"
|
||||
#include "options.h"
|
||||
#include "tty.h"
|
||||
|
||||
static int serial_fd;
|
||||
|
||||
// lua: sleep(seconds)
|
||||
static int sleep_(lua_State *L)
|
||||
{
|
||||
long seconds = lua_tointeger(L, 1);
|
||||
|
||||
if (seconds < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
tio_printf("Sleeping %ld seconds", seconds);
|
||||
|
||||
sleep(seconds);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// lua: msleep(miliseconds)
|
||||
static int msleep(lua_State *L)
|
||||
{
|
||||
long mseconds = lua_tointeger(L, 1);
|
||||
long useconds = mseconds * 1000;
|
||||
|
||||
if (useconds < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
tio_printf("Sleeping %ld ms", mseconds);
|
||||
usleep(useconds);
|
||||
|
||||
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)
|
||||
{
|
||||
long line = lua_tointeger(L, 1);
|
||||
|
||||
if (line < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
script_line_set(line, LINE_HIGH);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// lua: low(line)
|
||||
static int low(lua_State *L)
|
||||
{
|
||||
long line = lua_tointeger(L, 1);
|
||||
|
||||
if (line < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
script_line_set(line, LINE_LOW);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// lua: toggle(line)
|
||||
static int toggle(lua_State *L)
|
||||
{
|
||||
long line = lua_tointeger(L, 1);
|
||||
|
||||
if (line < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
script_line_toggle(line);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void script_buffer_run(lua_State *L, const char *script_buffer)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = luaL_loadbuffer(L, script_buffer, strlen(script_buffer), "tio") ||
|
||||
lua_pcall(L, 0, 0, 0);
|
||||
if (error)
|
||||
{
|
||||
tio_warning_printf("%s\n", lua_tostring(L, -1));
|
||||
lua_pop(L, 1); /* pop error message from the stack */
|
||||
}
|
||||
}
|
||||
|
||||
static const struct luaL_Reg tio_lib[] =
|
||||
{
|
||||
{ "sleep", sleep_},
|
||||
{ "msleep", msleep},
|
||||
{ "high", high},
|
||||
{ "low", low},
|
||||
{ "toggle", toggle},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
#if !defined LUA_VERSION_NUM || LUA_VERSION_NUM==501
|
||||
/*
|
||||
** Adapted from Lua 5.2.0 (for backwards compatibility)
|
||||
*/
|
||||
static void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup)
|
||||
{
|
||||
luaL_checkstack(L, nup+1, "too many upvalues");
|
||||
for (; l->name != NULL; l++) { /* fill the table with given functions */
|
||||
int i;
|
||||
lua_pushstring(L, l->name);
|
||||
for (i = 0; i < nup; i++) /* copy upvalues to the top */
|
||||
lua_pushvalue(L, -(nup+1));
|
||||
lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */
|
||||
lua_settable(L, -(nup + 3));
|
||||
}
|
||||
lua_pop(L, nup); /* remove upvalues */
|
||||
}
|
||||
#endif
|
||||
|
||||
int lua_register_tio(lua_State *L)
|
||||
{
|
||||
// Register lxi functions
|
||||
lua_getglobal(L, "_G");
|
||||
luaL_setfuncs(L, tio_lib, 0);
|
||||
lua_pop(L, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void script_file_run(lua_State *L, const char *filename)
|
||||
{
|
||||
if (strlen(filename) == 0)
|
||||
{
|
||||
tio_warning_printf("Missing script filename\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (luaL_dofile(L, filename))
|
||||
{
|
||||
tio_warning_printf("%s\n", lua_tostring(L, -1));
|
||||
lua_pop(L, 1); /* pop error message from the stack */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void script_set_global(lua_State *L, const char *name, long value)
|
||||
{
|
||||
lua_pushnumber(L, value);
|
||||
lua_setglobal(L, name);
|
||||
}
|
||||
|
||||
void script_set_globals(lua_State *L)
|
||||
{
|
||||
script_set_global(L, "DTR", TIOCM_DTR);
|
||||
script_set_global(L, "RTS", TIOCM_RTS);
|
||||
script_set_global(L, "CTS", TIOCM_CTS);
|
||||
script_set_global(L, "DSR", TIOCM_DSR);
|
||||
script_set_global(L, "CD", TIOCM_CD);
|
||||
script_set_global(L, "RI", TIOCM_RI);
|
||||
}
|
||||
|
||||
void script_run(int fd)
|
||||
{
|
||||
lua_State *L;
|
||||
|
||||
serial_fd = fd;
|
||||
|
||||
L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
|
||||
// Bind tio functions
|
||||
lua_register_tio(L);
|
||||
|
||||
// Initialize globals
|
||||
script_set_globals(L);
|
||||
|
||||
if (option.script_filename != NULL)
|
||||
{
|
||||
tio_printf("Running script %s", option.script_filename);
|
||||
script_file_run(L, option.script_filename);
|
||||
}
|
||||
else if (option.script != NULL)
|
||||
{
|
||||
tio_printf("Running script");
|
||||
script_buffer_run(L, option.script);
|
||||
}
|
||||
|
||||
lua_close(L);
|
||||
}
|
||||
32
src/script.h
Normal file
32
src/script.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* tio - a simple serial terminal I/O tool
|
||||
*
|
||||
* Copyright (c) 2014-2024 Martin Lund
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
enum script_run_t
|
||||
{
|
||||
SCRIPT_RUN_ONCE,
|
||||
SCRIPT_RUN_ALWAYS,
|
||||
SCRIPT_RUN_NEVER,
|
||||
SCRIPT_RUN_END,
|
||||
};
|
||||
|
||||
void script_run(int fd);
|
||||
171
src/tty.c
171
src/tty.c
|
|
@ -55,6 +55,7 @@
|
|||
#include "alert.h"
|
||||
#include "timestamp.h"
|
||||
#include "misc.h"
|
||||
#include "script.h"
|
||||
|
||||
/* tty device listing configuration */
|
||||
|
||||
|
|
@ -103,6 +104,7 @@
|
|||
#define KEY_M 0x6D
|
||||
#define KEY_P 0x70
|
||||
#define KEY_Q 0x71
|
||||
#define KEY_R 0x72
|
||||
#define KEY_S 0x73
|
||||
#define KEY_T 0x74
|
||||
#define KEY_U 0x55
|
||||
|
|
@ -111,12 +113,12 @@
|
|||
#define KEY_Y 0x79
|
||||
#define KEY_Z 0x7a
|
||||
|
||||
enum line_mode_t
|
||||
typedef enum
|
||||
{
|
||||
LINE_OFF,
|
||||
LINE_TOGGLE,
|
||||
LINE_PULSE
|
||||
};
|
||||
} tty_line_mode_t;
|
||||
|
||||
const char random_array[] =
|
||||
{
|
||||
|
|
@ -424,67 +426,87 @@ static void output_hex(char c)
|
|||
}
|
||||
}
|
||||
|
||||
static void toggle_line(const char *line_name, int mask, enum line_mode_t line_mode)
|
||||
void tty_line_set(int fd, const char *name, int mask, bool value)
|
||||
{
|
||||
int state;
|
||||
|
||||
if (line_mode == LINE_TOGGLE)
|
||||
if (ioctl(fd, TIOCMGET, &state) < 0)
|
||||
{
|
||||
// Toggle line
|
||||
if (ioctl(fd, TIOCMGET, &state) < 0)
|
||||
{
|
||||
tio_warning_printf("Could not get line state (%s)", strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (state & mask)
|
||||
{
|
||||
state &= ~mask;
|
||||
tio_printf("Setting %s to HIGH", line_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
state |= mask;
|
||||
tio_printf("Setting %s to LOW", line_name);
|
||||
}
|
||||
if (ioctl(fd, TIOCMSET, &state) < 0)
|
||||
tio_warning_printf("Could not set line state (%s)", strerror(errno));
|
||||
}
|
||||
} else if (line_mode == LINE_PULSE)
|
||||
tio_warning_printf("Could not get line state (%s)", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
if (value)
|
||||
{
|
||||
int duration = 0;
|
||||
// Pulse line
|
||||
toggle_line(line_name, mask, LINE_TOGGLE);
|
||||
switch (mask)
|
||||
{
|
||||
case TIOCM_DTR:
|
||||
duration = option.dtr_pulse_duration;
|
||||
break;
|
||||
case TIOCM_RTS:
|
||||
duration = option.rts_pulse_duration;
|
||||
break;
|
||||
case TIOCM_CTS:
|
||||
duration = option.cts_pulse_duration;
|
||||
break;
|
||||
case TIOCM_DSR:
|
||||
duration = option.dsr_pulse_duration;
|
||||
break;
|
||||
case TIOCM_CD:
|
||||
duration = option.dcd_pulse_duration;
|
||||
break;
|
||||
case TIOCM_RI:
|
||||
duration = option.ri_pulse_duration;
|
||||
break;
|
||||
default:
|
||||
duration = 0;
|
||||
break;
|
||||
}
|
||||
if (duration > 0)
|
||||
{
|
||||
tio_printf("Waiting %d ms", duration);
|
||||
delay(duration);
|
||||
}
|
||||
toggle_line(line_name, mask, LINE_TOGGLE);
|
||||
state &= ~mask;
|
||||
tio_printf("Setting %s to HIGH", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
state |= mask;
|
||||
tio_printf("Setting %s to LOW", name);
|
||||
}
|
||||
|
||||
if (ioctl(fd, TIOCMSET, &state) < 0)
|
||||
{
|
||||
tio_warning_printf("Could not set line state (%s)", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
void tty_line_toggle(int fd, const char *line_name, int mask)
|
||||
{
|
||||
int state;
|
||||
|
||||
if (ioctl(fd, TIOCMGET, &state) < 0)
|
||||
{
|
||||
tio_warning_printf("Could not get line state (%s)", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
if (state & mask)
|
||||
{
|
||||
state &= ~mask;
|
||||
tio_printf("Setting %s to HIGH", line_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
state |= mask;
|
||||
tio_printf("Setting %s to LOW", line_name);
|
||||
}
|
||||
|
||||
if (ioctl(fd, TIOCMSET, &state) < 0)
|
||||
{
|
||||
tio_warning_printf("Could not set line state (%s)", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
static void tty_line_pulse(int fd, const char *line_name, int mask, unsigned int duration)
|
||||
{
|
||||
tty_line_toggle(fd, line_name, mask);
|
||||
|
||||
if (duration > 0)
|
||||
{
|
||||
tio_printf("Waiting %d ms", duration);
|
||||
delay(duration);
|
||||
}
|
||||
|
||||
tty_line_toggle(fd, line_name, mask);
|
||||
}
|
||||
|
||||
static void tty_line_poke(int fd, const char *name, int mask, tty_line_mode_t mode, unsigned int duration)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case LINE_TOGGLE:
|
||||
tty_line_toggle(fd, name, mask);
|
||||
break;
|
||||
|
||||
case LINE_PULSE:
|
||||
tty_line_pulse(fd, name, mask, duration);
|
||||
break;
|
||||
|
||||
case LINE_OFF:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -520,7 +542,7 @@ void handle_command_sequence(char input_char, char *output_char, bool *forward)
|
|||
char unused_char;
|
||||
bool unused_bool;
|
||||
int state;
|
||||
static enum line_mode_t line_mode = LINE_OFF;
|
||||
static tty_line_mode_t line_mode = LINE_OFF;
|
||||
static char previous_char = 0;
|
||||
|
||||
/* Ignore unused arguments */
|
||||
|
|
@ -534,29 +556,29 @@ void handle_command_sequence(char input_char, char *output_char, bool *forward)
|
|||
forward = &unused_bool;
|
||||
}
|
||||
|
||||
// Handle tty line toggle and pulse action
|
||||
if (line_mode)
|
||||
{
|
||||
// Handle line toggle number action
|
||||
*forward = false;
|
||||
switch (input_char)
|
||||
{
|
||||
case KEY_0:
|
||||
toggle_line("DTR", TIOCM_DTR, line_mode);
|
||||
tty_line_poke(fd, "DTR", TIOCM_DTR, line_mode, option.dtr_pulse_duration);
|
||||
break;
|
||||
case KEY_1:
|
||||
toggle_line("RTS", TIOCM_RTS, line_mode);
|
||||
tty_line_poke(fd, "RTS", TIOCM_RTS, line_mode, option.rts_pulse_duration);
|
||||
break;
|
||||
case KEY_2:
|
||||
toggle_line("CTS", TIOCM_CTS, line_mode);
|
||||
tty_line_poke(fd, "CTS", TIOCM_CTS, line_mode, option.cts_pulse_duration);
|
||||
break;
|
||||
case KEY_3:
|
||||
toggle_line("DSR", TIOCM_DSR, line_mode);
|
||||
tty_line_poke(fd, "DSR", TIOCM_DSR, line_mode, option.dsr_pulse_duration);
|
||||
break;
|
||||
case KEY_4:
|
||||
toggle_line("DCD", TIOCM_CD, line_mode);
|
||||
tty_line_poke(fd, "DCD", TIOCM_CD, line_mode, option.dcd_pulse_duration);
|
||||
break;
|
||||
case KEY_5:
|
||||
toggle_line("RI", TIOCM_RI, line_mode);
|
||||
tty_line_poke(fd, "RI", TIOCM_RI, line_mode, option.ri_pulse_duration);
|
||||
break;
|
||||
default:
|
||||
tio_warning_printf("Invalid line number");
|
||||
|
|
@ -601,6 +623,7 @@ void handle_command_sequence(char input_char, char *output_char, bool *forward)
|
|||
tio_printf(" ctrl-%c m Toggle MSB to LSB bit order", option.prefix_key);
|
||||
tio_printf(" ctrl-%c p Pulse serial port line", option.prefix_key);
|
||||
tio_printf(" ctrl-%c q Quit", option.prefix_key);
|
||||
tio_printf(" ctrl-%c r Run script", option.prefix_key);
|
||||
tio_printf(" ctrl-%c s Show statistics", option.prefix_key);
|
||||
tio_printf(" ctrl-%c t Toggle line timestamp mode", option.prefix_key);
|
||||
tio_printf(" ctrl-%c U Toggle conversion to uppercase on output", option.prefix_key);
|
||||
|
|
@ -726,6 +749,11 @@ void handle_command_sequence(char input_char, char *output_char, bool *forward)
|
|||
/* Exit upon ctrl-t q sequence */
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
case KEY_R:
|
||||
/* Run script */
|
||||
script_run(fd);
|
||||
break;
|
||||
|
||||
case KEY_S:
|
||||
/* Show tx/rx statistics upon ctrl-t s sequence */
|
||||
tio_printf("Statistics:");
|
||||
|
|
@ -1383,6 +1411,17 @@ int tty_connect(void)
|
|||
}
|
||||
}
|
||||
|
||||
/* Manage script activation */
|
||||
if (option.script_run != SCRIPT_RUN_NEVER)
|
||||
{
|
||||
script_run(fd);
|
||||
|
||||
if (option.script_run == SCRIPT_RUN_ONCE)
|
||||
{
|
||||
option.script_run = SCRIPT_RUN_NEVER;
|
||||
}
|
||||
}
|
||||
|
||||
/* Input loop */
|
||||
while (true)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define LINE_HIGH true
|
||||
#define LINE_LOW false
|
||||
|
||||
extern bool interactive_mode;
|
||||
extern bool map_i_nl_cr;
|
||||
extern bool map_i_cr_nl;
|
||||
|
|
@ -36,3 +39,5 @@ 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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue