#include "error.h"
#include "socket.h"
#include "setspeed.h"
+#include "rs485.h"
+#include "alert.h"
+#include "timestamp.h"
+#include "misc.h"
-#ifdef __APPLE__
+#if 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/"
+#define PREFIX_TTY_DEVICES ""
#endif
#ifndef CMSPAR
#define KEY_G 0x67
#define KEY_H 0x68
#define KEY_L 0x6C
+#define KEY_SHIFT_L 0x4C
#define KEY_P 0x70
#define KEY_Q 0x71
#define KEY_S 0x73
#define KEY_T 0x74
#define KEY_U 0x55
#define KEY_V 0x76
-#define KEY_SHIFT_L 0x4C
-
-#define NORMAL 0
-#define HEX 1
+#define KEY_Z 0x7a
enum line_mode_t
{
LINE_PULSE
};
+const char random_array[] =
+{
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x20, 0x28, 0x0A, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x29, 0x0A, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
+0x2E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7C, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x7C, 0x5D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x5C, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2F, 0x0A, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x60, 0x2D, 0x2D, 0x2D, 0x2D, 0x27, 0x0A, 0x0A, 0x54,
+0x69, 0x6D, 0x65, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x61, 0x20, 0x63, 0x6F, 0x66,
+0x66, 0x65, 0x65, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6B, 0x21, 0x0A, 0x20, 0x0A,
+0x00
+};
+
bool interactive_mode = true;
static struct termios tio, tio_old, stdout_new, stdout_old, stdin_new, stdin_old;
static unsigned long rx_total = 0, tx_total = 0;
static bool connected = false;
-static bool print_mode = NORMAL;
static bool standard_baudrate = true;
static void (*print)(char c);
static int fd;
tio_printf("Configuration:");
config_file_print();
options_print();
+ if (option.rs485)
+ {
+ rs485_print_config();
+ }
break;
case KEY_E:
case KEY_H:
/* Toggle hexadecimal printing mode */
- if (print_mode == NORMAL)
+ if (!option.hex_mode)
{
print = print_hex;
- print_mode = HEX;
+ option.hex_mode = true;
tio_printf("Switched to hexadecimal mode");
}
else
{
print = print_normal;
- print_mode = NORMAL;
+ option.hex_mode = false;
tio_printf("Switched to normal mode");
}
break;
tio_printf("tio v%s", VERSION);
break;
+ case KEY_Z:
+ tio_printf_array(random_array);
+ break;
+
default:
/* Ignore unknown ctrl-t escaped keys */
break;
flock(fd, LOCK_UN);
close(fd);
connected = false;
+
+ /* Fire alert action */
+ alert_disconnect();
}
}
{
tcsetattr(fd, TCSANOW, &tio_old);
+ if (option.rs485)
+ {
+ /* Restore original RS-485 mode */
+ rs485_mode_restore(fd);
+ }
+
if (connected)
{
tty_disconnect();
}
else
{
- if (print_mode == HEX)
+ if (option.hex_mode)
{
output_hex(output_char);
}
int status;
bool next_timestamp = false;
char* now = NULL;
+ struct timeval tv;
+ struct timeval *tv_p = &tv;
+ bool ignore_stdin = false;
/* Open tty device */
fd = open(option.tty_device, O_RDWR | O_NOCTTY | O_NONBLOCK);
connected = true;
print_tainted = false;
+ /* Fire alert action */
+ alert_connect();
+
if (option.timestamp)
{
next_timestamp = true;
if (option.hex_mode)
{
print = print_hex;
- print_mode = HEX;
}
else
{
print = print_normal;
- print_mode = NORMAL;
}
/* Save current port settings */
}
#endif
+ /* Manage RS-485 mode */
+ if (option.rs485)
+ {
+ rs485_mode_enable(fd);
+ }
+
/* Make sure we restore tty settings on exit */
if (first)
{
{
FD_ZERO(&rdfs);
FD_SET(fd, &rdfs);
- FD_SET(STDIN_FILENO, &rdfs);
+ if (!ignore_stdin)
+ {
+ FD_SET(STDIN_FILENO, &rdfs);
+ }
maxfd = MAX(fd, STDIN_FILENO);
maxfd = MAX(maxfd, socket_add_fds(&rdfs, true));
+ /* Manage timeout */
+ if ((option.response_wait) && (option.response_timeout != 0))
+ {
+ // Set response timeout
+ tv_p->tv_sec = 0;
+ tv_p->tv_usec = option.response_timeout * 1000;
+ }
+ else
+ {
+ // No timeout
+ tv_p = NULL;
+ }
+
/* Block until input becomes available */
- status = select(maxfd + 1, &rdfs, NULL, NULL, NULL);
+ status = select(maxfd + 1, &rdfs, NULL, NULL, tv_p);
if (status > 0)
{
bool forward = false;
/* Print timestamp on new line if enabled */
if (next_timestamp && input_char != '\n' && input_char != '\r')
{
- now = current_time();
+ now = timestamp_current_time();
if (now)
{
ansi_printf_raw("[%s] ", now);
{
next_timestamp = true;
}
+
+ if (option.response_wait)
+ {
+ if ((input_char == '\r') || (input_char == '\n'))
+ {
+ tty_sync(fd);
+ exit(EXIT_SUCCESS);
+ }
+ }
}
}
else if (FD_ISSET(STDIN_FILENO, &rdfs))
else if (bytes_read == 0)
{
/* Reached EOF (when piping to stdin) */
- tty_sync(fd);
- exit(EXIT_SUCCESS);
+ if (option.response_wait)
+ {
+ /* Stdin pipe closed but not blocking so stop listening
+ * to stdin in response mode.
+ *
+ * Note: select() really indicates not if data is ready
+ * but if file descriptor is non-blocking for I/O
+ * operation. */
+ ignore_stdin = true;
+ }
+ else
+ {
+ tty_sync(fd);
+ exit(EXIT_SUCCESS);
+ }
}
/* Process input byte by byte */
/* Save previous key */
previous_char = input_char;
- if ((print_mode == HEX) && (forward))
+ if ((option.hex_mode) && (forward))
{
if (!is_valid_hex(input_char))
{
tio_error_printf("select() failed (%s)", strerror(errno));
exit(EXIT_FAILURE);
}
+ else
+ {
+ // Timeout (only happens in response wait mode)
+ exit(EXIT_FAILURE);
+ }
}
return TIO_SUCCESS;
{
if ((strcmp(dir->d_name, ".")) && (strcmp(dir->d_name, "..")))
{
-#ifdef __APPLE__
-#define TTY_DEVICES_PREFIX "tty."
- if (!strncmp(dir->d_name, TTY_DEVICES_PREFIX, sizeof(TTY_DEVICES_PREFIX) - 1))
-#endif
- printf("%s%s\n", PATH_SERIAL_DEVICES, dir->d_name);
+ if (!strncmp(dir->d_name, PREFIX_TTY_DEVICES, sizeof(PREFIX_TTY_DEVICES) - 1))
+ {
+ printf("%s%s\n", PATH_SERIAL_DEVICES, dir->d_name);
+ }
}
}
closedir(d);