Victor Oliveira <rhapsodyv@gmail.com>
Attila Veghelyi <aveghelyi@dension.com>
Vyacheslav Patkov <slava@patkov.ru>
+Bill Hass <billhass@umich.edu>
+Peter van Dijk <peter@7bits.nl>
+Braden Young <braden@somewearlabs.com>
Thanks to everyone who has contributed to this project.
-=== tio v2.5 ===
+=== tio v2.6 ===
+
+
+
+Changes since tio v2.5:
+
+ * Remove warning when using pattern option
+
+ * Add --log-append option
+
+ Add --log-append option which makes tio append to any existing log file.
+
+ This also changes the default behaviour of tio from appending to
+ overwriting any existing log file. Now you have to use this new option
+ to make tio append.
+
+ * Update man page
+
+ * Update README
+
+ * Fix line termination for response wait feature
+
+ The response wait feature waited for a line response, a string
+ terminated with either CR or NL. However, some devices may send a CR and
+ then their line content and then NL. This means tio will quit before
+ receiving and printing the line response. To solve this we simply ignore
+ the CR character and only consider lines terminated with a NL character.
+
+ This should work for all devices as lines are AFAIK always terminated
+ with either CRNL or a NL.
+
+ * Update tty device listing configuration
+
+ Cleanup and add FreeBSD tty device listing support.
+
+Braden Young:
+
+ * Move map variables to tty to keep them all in one spot
+
+ * Configure socket mapping flags from tty parsing logic. Remove duplicate parsing logic in socket
+
+ * Support input mapping modes for sockets
+
+Josh Soref:
+
+ * Various spelling fixes
+
+Peter van Dijk:
+
+ * avoid "warning: unused parameter" on setspeed stub
+
+ * use right /dev/ path on Haiku
+
+Bill Hass:
+
+ * Update README with details on snap confinement
pipe data to tio which then forwards the data to the connected serial
device.
- Non ineractive means that tio does not react to interactive key commands
+ Non interactive means that tio does not react to interactive key commands
in the incoming stream. This allows users to pipe binary data directly
to the connected serial device.
inherently inconsistent with how you define required arguments.
To avoid confusion we decide to avoid this inconsistency by replacing
- optional options with additional options with required argmuments.
+ optional options with additional options with required arguments.
* Replace '1' with 'enable' in config files
* Fix out of tree builds
Out of tree builds are currently broken because $(top_srcdir)src/include
- is not in the search path. In tree builds are working because autconf add
+ is not in the search path. In tree builds are working because autoconf adds
$(top_builddir)/src/include to the search path for the generated config.h.
As $(top_builddir) and $(top_srcdir) are identical during in tree builds
- the search path still end up beeing somehow correct.
+ the search path still end up being somehow correct.
To fix this add -I$(srcdir)/include to the CPPFLAGS in Makefile.am.
+
+[![tio](images/tio-icon.png)]()
+
# tio - a simple serial device I/O tool
-[![](https://img.shields.io/circleci/build/gh/tio/tio?token=da7e7fd0d0ee99b9f986f8877dcdbe28f73d9e06)](https://circleci.com/gh/tio/tio/tree/master)
+[![](https://img.shields.io/circleci/build/github/tio/tio)](https://circleci.com/github/tio/tio/tree/master)
[![](https://img.shields.io/github/v/release/tio/tio?sort=semver)](https://github.com/tio/tio/releases)
[![](https://img.shields.io/repology/repositories/tio)](https://repology.org/project/tio/versions)
[![](https://img.shields.io/tokei/lines/github/tio/tio)](https://github.com/tio/tio)
* Easily connect to serial TTY devices
* Automatic connect and reconnect
- * Sensible defaults
+ * Sensible defaults (115200 8n1)
* Support for non-standard baud rates
* Support for RS-485 mode
* Support for mark and space parity
* Visual or audible alert on connect/disconnect
* Remapping of prefix key
* Man page documentation
+ * Binary size less than 80kB
* Plays nicely with [tmux](https://tmux.github.io)
## 3. Usage
Install latest stable version:
```
-$ snap install tio
+$ snap install tio --classic
```
+Note: Classic confinement is currently required due to limitations of the snapcraft framework.
+See [Issue #187](https://github.com/tio/tio/issues/187) for discussion.
+
### 4.3 Installation using brew (MacOS, Linux)
If you have [brew](http://brew.sh) installed:
Install steps:
```
-$ meson build
+$ meson setup build
$ meson compile -C build
$ meson install -C build
```
Note: The meson install steps may differ depending on your specific system.
+### 4.6 Known issues
+
+Getting permission access errors trying to open your serial device?
+
+Add your user to the group which allows serial device access. For example, to add your user to the 'dialout' group do:
+```
+$ sudo usermod -a -G dialout <username>
+```
+
## 5. Contributing
+ * Support for interaction using simple autoresponse strings
+
+ Add support for simple autoresponse strings in the configuration file. For
+ example:
+
+ autoresponse = expect:'localhost login: ', send:'root\n',
+ expect:'Password: ', send:'abcd1234\n'
+
+ When expect line is matched tio will respond by writing the send string.
+
+ When parsing the autoresponse variable make sure matching expect/send pairs
+ else provide warning.
+
+ Maybe support regex matching in expect string to make feature more powerful.
+
+ This is mostly a convenience feature. For more powerful scripted interaction
+ users can continue use the socket feature in combination with the expect tool
+ as described in the man page.
+
+ Maybe provide a mechanism to disable autoresponse feature. Maybe by defining
+ maximum match count and/or in session key command to toggle feature.
+
+ * Support for running external command
+
+ Add key command e.g. 'ctrl-t r' which prompts user to run external command.
+ The command will be run in a process which stdin/stdout is redirected to the
+ serial port.
+
+ This is the first step towards maybe also adding automatic support for
+ x/y/zmodem data transfer protocols by calling external programs such as
+ rb/sb, rx/sx, rz/sz, etc.
* Allow tio to connect to socket
hexadecimal = disable
timestamp = disable
log = disable
+log-append = disable
log-strip = disable
local-echo = disable
color = bold
response-wait = disable
alert = none
-# Sub-configuraions
+# Sub-configurations
[rpi3]
baudrate = 115200
Enable log to file.
-If no filename is provided the filename will be automatically generated.
+The filename will be automatically generated using the following format
+tio_DEVICE_YYYY-MM-DDTHH:MM:SS.log.
+
+The filename can be manually set using the \-\-log-file option.
.TP
.BR " \-\-log-file \fI<filename>
Set log filename.
+.TP
+.BR " \-\-log-append
+
+Append to log file.
+
.TP
.BR " \-\-log-strip
.TP
.BR \-r ", " \-\-response-wait
-Wait for line response then quit. A line is considered any string ending with
-either CR or NL character. If no line is received tio will quit after response
+Wait for line response then quit. A line is considered any string terminated
+with a NL character. If no line is received tio will quit after response
timeout.
Any tio text is automatically muted when piping a string to tio while in
.SH "KEYS"
.PP
.TP 16n
-In session, the following key sequences, a prefix key (default: ctrl-t) followed by a command key, are intercepted as tio commands:
+In session, all key strokes are forwarded to the serial device except the following key sequence: a prefix key (default: ctrl-t) followed by a command key. These sequences are intercepted as tio commands:
.IP "\fBctrl-t ?"
List available key commands
.IP "\fBctrl-t b"
.TP
Redirect serial device I/O to Unix file socket for scripting:
-$ tio -S unix:/tmp/tmux-socket0 /dev/ttyUSB0
+$ tio -S unix:/tmp/tio-socket0 /dev/ttyUSB0
.TP
Then, to issue a command via the file socket simply do:
-$ echo "ls -la" | nc -UN /tmp/tmux-socket0 > /dev/null
+$ echo "ls -la" | nc -UN /tmp/tio-socket0 > /dev/null
.TP
Or use the expect command to script an interaction:
-tio(1) User Commands tio(1)
+tio(1) User Commands tio(1)
NAME
tio - a simple serial device I/O tool
Disable automatic connect.
- By default tio automatically connects to the provided device if present. If the device is not present, it will wait for it to appear and then connect. If the connection is lost (eg. device disconnects), it will wait for the device to
- reappear and then reconnect.
+ By default tio automatically connects to the provided device if present. If the device is not present, it will wait for it to appear and then connect. If the connection is lost (eg. device disconnects), it will wait for the device to reappear and then reconnect.
However, if the --no-autoconnect option is provided, tio will exit if the device is not present or an established connection is lost.
Enable log to file.
- If no filename is provided the filename will be automatically generated.
+ The filename will be automatically generated using the following format tio_DEVICE_YYYY-MM-DDTHH:MM:SS.log.
+
+ The filename can be manually set using the --log-file option.
--log-file <filename>
Set log filename.
+ --log-append
+
+ Append to log file.
+
--log-strip
Strip control characters and escape sequences from log.
Redirect I/O to socket.
- Any input from clients connected to the socket is sent on the serial port as if entered at the terminal where tio is running (except that ctrl-t sequences are not recognized), and any input from the serial port is multiplexed to the
- terminal and all connected clients.
+ Any input from clients connected to the socket is sent on the serial port as if entered at the terminal where tio is running (except that ctrl-t sequences are not recognized), and any input from the serial port is multiplexed to the terminal and all connected clients.
Sockets remain open while the serial port is disconnected, and writes will block.
-r, --response-wait
- Wait for line response then quit. A line is considered any string ending with either CR or NL character. If no line is received tio will quit after response timeout.
+ Wait for line response then quit. A line is considered any string terminated with a NL character. If no line is received tio will quit after response timeout.
Any tio text is automatically muted when piping a string to tio while in response mode to make it easy to parse the response.
Display help.
KEYS
- In session, the following key sequences, a prefix key (default: ctrl-t) followed by a command key, are intercepted as tio commands:
+ In session, all key strokes are forwarded to the serial device except the following key sequence: a prefix key (default: ctrl-t) followed by a command key. These sequences are intercepted as tio commands:
ctrl-t ? List available key commands
Redirect serial device I/O to Unix file socket for scripting:
- $ tio -S unix:/tmp/tmux-socket0 /dev/ttyUSB0
+ $ tio -S unix:/tmp/tio-socket0 /dev/ttyUSB0
Then, to issue a command via the file socket simply do:
- $ echo "ls -la" | nc -UN /tmp/tmux-socket0 > /dev/null
+ $ echo "ls -la" | nc -UN /tmp/tio-socket0 > /dev/null
Or use the expect command to script an interaction:
AUTHOR
Created by Martin Lund <martin.lund@keep-it-simple.com>.
-tio 2.5 2022-11-02 tio(1)
+tio 2.6 2022-12-17 tio(1)
project('tio', 'c',
- version : '2.5',
+ version : '2.6',
license : [ 'GPL-2'],
meson_version : '>= 0.53.2',
default_options : [ 'warning_level=2', 'buildtype=release', 'c_std=gnu99' ]
asprintf(&c.log_filename, "%s", value);
option.log_filename = c.log_filename;
}
+ else if (!strcmp(name, "log-append"))
+ {
+ option.log_append = read_boolean(value, name);
+ }
else if (!strcmp(name, "log-strip"))
{
option.log_strip = read_boolean(value, name);
{
option.mute = read_boolean(value, name);
}
+ else if (!strcmp(name, "pattern"))
+ {
+ // Do nothing
+ }
else
{
tio_warning_printf("Unknown option '%s' in configuration file, ignored", name);
log_filename = filename;
- // Open log file in append write mode
- fp = fopen(filename, "a+");
+ // Open log file
+ if (option.log_append)
+ {
+ // Appends to existing log file
+ fp = fopen(filename, "a+");
+ }
+ else
+ {
+ // Truncates existing log file
+ fp = fopen(filename, "w+");
+ }
if (fp == NULL)
{
tio_warning_printf("Could not open log file %s (%s)", filename, strerror(errno));
.ri_pulse_duration = 100,
.no_autoconnect = false,
.log = false,
+ .log_append = false,
.log_filename = NULL,
.log_strip = false,
.local_echo = false,
printf(" -L, --list-devices List available serial devices by ID\n");
printf(" -l, --log Enable log to file\n");
printf(" --log-file <filename> Set log filename\n");
+ printf(" --log-append Append to log file\n");
printf(" --log-strip Strip control characters and escape sequences\n");
printf(" -m, --map <flags> Map characters\n");
printf(" -c, --color 0..255|bold|none|list Colorize tio text (default: bold)\n");
unsigned int ri_pulse_duration;
bool no_autoconnect;
bool log;
+ bool log_append;
bool log_strip;
bool local_echo;
enum timestamp_t timestamp;
#include <IOKit/serial/ioss.h>
#endif
+#include "misc.h"
#ifdef HAVE_TERMIOS2
int setspeed(int fd, int baudrate)
#else
int setspeed(int fd, int baudrate)
{
+ UNUSED(fd);
+ UNUSED(baudrate);
+
errno = EINVAL;
return -1;
}
#include "socket.h"
#include "options.h"
#include "print.h"
+#include "tty.h"
#define MAX_SOCKET_CLIENTS 16
#define SOCKET_PORT_DEFAULT 3333
clientfds[i] = -1;
continue;
}
- /* match the behavior of a terminal in raw mode */
- if (*output_char == '\n')
+
+ /* If INLCR is set, a received NL character shall be translated into a CR character */
+ if (*output_char == '\n' && map_i_nl_cr)
{
*output_char = '\r';
}
+ else if (*output_char == '\r')
+ {
+ /* If IGNCR is set, a received CR character shall be ignored (not read). */
+ if (map_ign_cr)
+ {
+ return false;
+ }
+
+ /* If IGNCR is not set and ICRNL is set, a received CR character shall be translated into an NL character. */
+ if (map_i_cr_nl)
+ {
+ *output_char = '\n';
+ }
+ }
return true;
}
}
first = false;
}
- // Add formatted timestap
+ // Add formatted timestamp
switch (option.timestamp)
{
case TIMESTAMP_NONE:
#include "timestamp.h"
#include "misc.h"
-#if defined(__APPLE__)
+/* tty device listing configuration */
+
+#if defined(__linux__)
+#define PATH_SERIAL_DEVICES "/dev/serial/by-id/"
+#define PREFIX_TTY_DEVICES ""
+#elif defined(__FreeBSD__)
+#define PATH_SERIAL_DEVICES "/dev/"
+#define PREFIX_TTY_DEVICES "cua"
+#elif defined(__APPLE__)
#define PATH_SERIAL_DEVICES "/dev/"
#define PREFIX_TTY_DEVICES "tty."
#elif defined(__CYGWIN__)
#define PATH_SERIAL_DEVICES "/dev/"
#define PREFIX_TTY_DEVICES "ttyS"
-#else
-#define PATH_SERIAL_DEVICES "/dev/serial/by-id/"
+#elif defined(__HAIKU__)
+#define PATH_SERIAL_DEVICES "/dev/ports/"
#define PREFIX_TTY_DEVICES ""
+#else
+#define PATH_SERIAL_DEVICES "/dev/"
+#define PREFIX_TTY_DEVICES "tty"
#endif
#ifndef CMSPAR
};
bool interactive_mode = true;
+bool map_i_nl_cr = false;
+bool map_i_cr_nl = false;
+bool map_ign_cr = false;
static struct termios tio, tio_old, stdout_new, stdout_old, stdin_new, stdin_old;
static unsigned long rx_total = 0, tx_total = 0;
if (strcmp(token,"INLCR") == 0)
{
tio.c_iflag |= INLCR;
+ map_i_nl_cr = true;
}
else if (strcmp(token,"IGNCR") == 0)
{
tio.c_iflag |= IGNCR;
+ map_ign_cr = true;
}
else if (strcmp(token,"ICRNL") == 0)
{
tio.c_iflag |= ICRNL;
+ map_i_cr_nl = true;
}
else if (strcmp(token,"OCRNL") == 0)
{
if (option.response_wait)
{
- if ((input_char == '\r') || (input_char == '\n'))
+ if (input_char == '\n')
{
tty_sync(fd);
exit(EXIT_SUCCESS);
#include <stdbool.h>
extern bool interactive_mode;
+extern bool map_i_nl_cr;
+extern bool map_i_cr_nl;
+extern bool map_ign_cr;
void stdout_configure(void);
void stdin_configure(void);