Simplify lua line manipulation API

Collapses lua high(), low(), toggle(), config_high(), config_low(),
config_apply() into one simple function:

set{<line>=<state>, ...}

Line can be any of DTR, RTS, CTS, DSR, CD, RI.

State is high, low, or toggle.

Example:
script = set{DTR=high, RTS=low}; msleep(100); set{DTR=low, RTS=high}; msleep(100); set{RTS=low}

Notice the use of {} instad of () when calling the set function. This is
required to pass parameters by name in lua.
This commit is contained in:
Martin Lund 2024-04-29 14:45:36 +02:00
parent eef0a15194
commit 6d77201ba0
6 changed files with 112 additions and 211 deletions

View file

@ -343,17 +343,12 @@ read(size, timeout)
Returns number of bytes read on success, 0 on timeout, or -1 on error.
exit(code)
Exit with exit code.
set{line=state, ...}
Set state of one or multiple tty modem lines.
high(line)
Set tty line high.
Line can be any of DTR, RTS, CTS, DSR, CD, RI
low(line)
Set tty line low.
toggle(line)
Toggle the tty line.
State is high, low, or toggle.
sleep(seconds)
Sleep for seconds.
@ -361,18 +356,8 @@ sleep(seconds)
msleep(ms)
Sleep for miliseconds.
config_high(line)
Set tty line state configuration to high.
config_low(line)
Set tty line state configuration to low.
apply_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.
Note: Line can be any of DTR, RTS, CTS, DSR, CD, RI
exit(code)
Exit with exit code.
```
### 3.4 Configuration file

View file

@ -1,7 +1,5 @@
high(DTR)
low(RTS)
set{DTR=high, RTS=low}
msleep(100)
low(DTR)
high(RTS)
set{DTR=low, RTS=high}
msleep(100)
low(RTS)
set{RTS=toggle}

View file

@ -457,29 +457,19 @@ until data is ready to read.
Returns number of bytes read on success, 0 on timeout, or -1 on error.
.IP "\fBexit(code)"
Exit with exit code.
.IP "\fBhigh(line)"
Set tty line high.
.IP "\fBlow(line)"
Set tty line low.
.IP "\fBtoggle(line)"
Toggle the tty line.
.IP "\fBset{line=state, ...}"
Set state of one or multiple tty modem lines.
Line can be any of DTR, RTS, CTS, DSR, CD, RI
State is high, low, or toggle.
.IP "\fBsleep(seconds)"
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
.IP "\fBexit(code)"
Exit with exit code.
.SH "CONFIGURATION FILE"
.PP

View file

@ -45,8 +45,16 @@ static char circular_buffer[MAX_BUFFER_SIZE];
static char match_string[MAX_BUFFER_SIZE];
static int buffer_size = 0;
static char init_script[] =
"\n";
static char script_init[] =
"function set(arg)\n"
" local dtr = arg.DTR or -1\n"
" local rts = arg.RTS or -1\n"
" local cts = arg.CTS or -1\n"
" local dsr = arg.DSR or -1\n"
" local cd = arg.CD or -1\n"
" local ri = arg.RI or -1\n"
" line_set(dtr, rts, cts, dsr, cd, ri)\n"
"end\n";
// lua: sleep(seconds)
static int sleep_(lua_State *L)
@ -82,87 +90,56 @@ static int msleep(lua_State *L)
return 0;
}
// lua: high(line)
static int high(lua_State *L)
// lua: line_set(dtr,rts,cts,dsr,cd,ri)
static int line_set(lua_State *L)
{
long line = lua_tointeger(L, 1);
tty_line_config_t line_config[6] = { };
if (line < 0)
int dtr = lua_tointeger(L, 1);
int rts = lua_tointeger(L, 2);
int cts = lua_tointeger(L, 3);
int dsr = lua_tointeger(L, 4);
int cd = lua_tointeger(L, 5);
int ri = lua_tointeger(L, 6);
if (dtr != -1)
{
return 0;
line_config[0].mask = TIOCM_DTR;
line_config[0].value = dtr;
line_config[0].reserved = true;
}
if (rts != -1)
{
line_config[1].mask = TIOCM_RTS;
line_config[1].value = rts;
line_config[1].reserved = true;
}
if (cts != -1)
{
line_config[2].mask = TIOCM_CTS;
line_config[2].value = cts;
line_config[2].reserved = true;
}
if (dsr != -1)
{
line_config[3].mask = TIOCM_DSR;
line_config[3].value = dsr;
line_config[3].reserved = true;
}
if (cd != -1)
{
line_config[4].mask = TIOCM_CD;
line_config[4].value = cd;
line_config[4].reserved = true;
}
if (ri != -1)
{
line_config[5].mask = TIOCM_RI;
line_config[5].value = ri;
line_config[5].reserved = true;
}
tty_line_set(device_fd, 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;
}
tty_line_set(device_fd, 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;
}
tty_line_toggle(device_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();
tty_line_set(device_fd, line_config);
return 0;
}
@ -472,12 +449,7 @@ static const struct luaL_Reg tio_lib[] =
{
{ "sleep", sleep_},
{ "msleep", msleep},
{ "high", high},
{ "low", low},
{ "toggle", toggle},
{ "config_high", config_high},
{ "config_low", config_low},
{ "config_apply", config_apply},
{ "line_set", line_set},
{ "modem_send", modem_send},
{ "send", send},
{ "read", read_string},
@ -506,11 +478,11 @@ static void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup)
}
#endif
static void load_init_script(lua_State *L)
static void script_load(lua_State *L)
{
int error;
error = luaL_loadbuffer(L, init_script, strlen(init_script), "tio") || lua_pcall(L, 0, 0, 0);
error = luaL_loadbuffer(L, script_init, strlen(script_init), "tio") || lua_pcall(L, 0, 0, 0);
if (error)
{
tio_error_print("%s\n", lua_tostring(L, -1));
@ -525,7 +497,8 @@ int lua_register_tio(lua_State *L)
luaL_setfuncs(L, tio_lib, 0);
lua_pop(L, 1);
load_init_script(L);
// Load lua init script
script_load(L);
return 0;
}
@ -554,12 +527,9 @@ void script_set_global(lua_State *L, const char *name, long value)
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);
script_set_global(L, "toggle", 2);
script_set_global(L, "high", 1);
script_set_global(L, "low", 0);
script_set_global(L, "XMODEM_CRC", XMODEM_CRC);
script_set_global(L, "XMODEM_1K", XMODEM_1K);
script_set_global(L, "YMODEM", YMODEM);

View file

@ -137,13 +137,6 @@ typedef enum
SUBCOMMAND_XMODEM,
} sub_command_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,
@ -190,7 +183,6 @@ 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)
{
@ -483,28 +475,12 @@ static const char *tty_line_name(int mask)
}
}
void tty_line_config(int mask, bool value)
void tty_line_set(int fd, tty_line_config_t line_config[])
{
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;
int i = 0;
if (ioctl(device_fd, TIOCMGET, &state) < 0)
if (ioctl(fd, TIOCMGET, &state) < 0)
{
tio_warning_printf("Could not get line state (%s)", strerror(errno));
return;
@ -514,55 +490,33 @@ void tty_line_config_apply(void)
{
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
if (line_config[i].value == 0)
{
// 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(device_fd, TIOCMSET, &state) < 0)
else if (line_config[i].value == 1)
{
tio_warning_printf("Could not set line state configuration (%s)", strerror(errno));
// High
state &= ~line_config[i].mask;
tio_printf("Setting %s to HIGH", tty_line_name(line_config[i].mask));
}
// Reset configuration
for (i=0; i<6; i++)
else if (line_config[i].value == 2)
{
line_config[i].reserved = false;
line_config[i].mask = -1;
}
}
// Toggle
state ^= line_config[i].mask;
void tty_line_set(int fd, int mask, bool value)
{
int state;
if (ioctl(fd, TIOCMGET, &state) < 0)
if (state & line_config[i].mask)
{
tio_warning_printf("Could not get line state (%s)", strerror(errno));
return;
}
if (value)
{
state &= ~mask;
tio_printf("Setting %s to HIGH", tty_line_name(mask));
tio_printf("Setting %s to LOW", tty_line_name(line_config[i].mask));
}
else
{
state |= mask;
tio_printf("Setting %s to LOW", tty_line_name(mask));
tio_printf("Setting %s to HIGH", tty_line_name(line_config[i].mask));
}
}
}
}
if (ioctl(fd, TIOCMSET, &state) < 0)

View file

@ -46,6 +46,13 @@ typedef struct
char *description;
} device_t;
typedef struct
{
int mask;
int value;
bool reserved;
} tty_line_config_t;
extern const char *device_name;
extern bool interactive_mode;
extern bool map_i_nl_cr;
@ -60,9 +67,6 @@ 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, 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);
void tty_line_set(int fd, tty_line_config_t line_config[]);
void tty_search(void);
GList *tty_search_for_serial_devices(void);