]> git.sur5r.net Git - tio/blobdiff - src/tty.c
Update upstream source from tag 'upstream/2.0'
[tio] / src / tty.c
index 43cfb9125cb32981fafc13ee22d61ca7a70f7810..4165017b93e0204e9ba4d8fc8bbec51310015158 100644 (file)
--- a/src/tty.c
+++ b/src/tty.c
 #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
 {
@@ -92,12 +99,25 @@ 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;
@@ -445,6 +465,10 @@ void handle_command_sequence(char input_char, char previous_char, char *output_c
                 tio_printf("Configuration:");
                 config_file_print();
                 options_print();
+                if (option.rs485)
+                {
+                    rs485_print_config();
+                }
                 break;
 
             case KEY_E:
@@ -454,16 +478,16 @@ void handle_command_sequence(char input_char, char previous_char, char *output_c
 
             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;
@@ -517,6 +541,10 @@ void handle_command_sequence(char input_char, char previous_char, char *output_c
                 tio_printf("tio v%s", VERSION);
                 break;
 
+            case KEY_Z:
+                tio_printf_array(random_array);
+                break;
+
             default:
                 /* Ignore unknown ctrl-t escaped keys */
                 break;
@@ -925,6 +953,9 @@ void tty_disconnect(void)
         flock(fd, LOCK_UN);
         close(fd);
         connected = false;
+
+        /* Fire alert action */
+        alert_disconnect();
     }
 }
 
@@ -932,6 +963,12 @@ void tty_restore(void)
 {
     tcsetattr(fd, TCSANOW, &tio_old);
 
+    if (option.rs485)
+    {
+        /* Restore original RS-485 mode */
+        rs485_mode_restore(fd);
+    }
+
     if (connected)
     {
         tty_disconnect();
@@ -969,7 +1006,7 @@ void forward_to_tty(int fd, char output_char)
     }
     else
     {
-        if (print_mode == HEX)
+        if (option.hex_mode)
         {
             output_hex(output_char);
         }
@@ -1000,6 +1037,9 @@ int tty_connect(void)
     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);
@@ -1032,6 +1072,9 @@ int tty_connect(void)
     connected = true;
     print_tainted = false;
 
+    /* Fire alert action */
+    alert_connect();
+
     if (option.timestamp)
     {
         next_timestamp = true;
@@ -1041,12 +1084,10 @@ int tty_connect(void)
     if (option.hex_mode)
     {
         print = print_hex;
-        print_mode = HEX;
     }
     else
     {
         print = print_normal;
-        print_mode = NORMAL;
     }
 
     /* Save current port settings */
@@ -1065,6 +1106,12 @@ int tty_connect(void)
     }
 #endif
 
+    /* Manage RS-485 mode */
+    if (option.rs485)
+    {
+        rs485_mode_enable(fd);
+    }
+
     /* Make sure we restore tty settings on exit */
     if (first)
     {
@@ -1095,12 +1142,28 @@ int tty_connect(void)
     {
         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;
@@ -1126,7 +1189,7 @@ int tty_connect(void)
                     /* 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);
@@ -1168,6 +1231,15 @@ int tty_connect(void)
                     {
                         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))
@@ -1182,8 +1254,21 @@ int tty_connect(void)
                 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 */
@@ -1209,7 +1294,7 @@ int tty_connect(void)
                         /* Save previous key */
                         previous_char = input_char;
 
-                        if ((print_mode == HEX) && (forward))
+                        if ((option.hex_mode) && (forward))
                         {
                             if (!is_valid_hex(input_char))
                             {
@@ -1244,6 +1329,11 @@ int tty_connect(void)
             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;
@@ -1267,11 +1357,10 @@ void list_serial_devices(void)
         {
             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);