]> git.sur5r.net Git - tio/commitdiff
New upstream version 2.2 upstream/2.2
authorJakob Haufe <sur5r@debian.org>
Sun, 23 Oct 2022 19:10:29 +0000 (21:10 +0200)
committerJakob Haufe <sur5r@debian.org>
Sun, 23 Oct 2022 19:10:29 +0000 (21:10 +0200)
17 files changed:
AUTHORS
NEWS
README.md
example/tiorc
man/tio.1.in
man/tio.1.txt
meson.build
src/bash-completion/tio.in
src/configfile.c
src/configfile.h
src/error.c
src/main.c
src/options.c
src/options.h
src/print.c
src/print.h
src/tty.c

diff --git a/AUTHORS b/AUTHORS
index 762ce18fd8a00ad1874c7432d2ec3feb90973651..8f5cada3d161800fe84dac11ffa77a64e1150609 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -40,5 +40,6 @@ Robert Snell <rcsnell@ncf.ca>
 Rui Chen <rui@chenrui.dev>
 Ralph Siemsen <ralphs@netwinder.org>
 Victor Oliveira <rhapsodyv@gmail.com>
+Attila Veghelyi <aveghelyi@dension.com>
 
 Thanks to everyone who has contributed to this project.
diff --git a/NEWS b/NEWS
index 544f8a1c7ce12958b2bd0c507c4a6b1637316469..1a1cc4dbb151e0eaf923a66ad27e15e35670a80c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,52 @@
 
-=== tio v2.0 ===
+=== tio v2.2 ===
+
+
+
+Changes since tio v2.1:
+
+ * Add shell completion of sub-configuration names
+
+   Does not work with sub configuration names that contains one or more
+   white spaces.
+
+ * Beautify help
+
+ * Fix error message
+
+ * Simplify configfile implementation
+
+
+
+Changes since tio v2.0:
+
+ * Fix output line delay
+
+   Apply output line delay on lines ending with \n.
+
+   On most systems lines ends with \n or \r\n.
+
+ * Do not print timestamps in hex mode
+
+ * Improve input mechanism in hex mode
+
+   Print the 2 character hex code that you input in hex mode but then
+   delete it before sending. This way it is easier to keep track of what
+   you are inputting. It basically mimics the ctrl-shift-u input mechanism
+   that is used to input unicode.
+
+ * Add support for sending prefix character to serial device
+
+   Do so by inputting prefix key twice, e.g. input ctrl-t ctrl-t to send
+   ctrl-t character to serial device.
+
+ * Clean up indentation
+
+ * Update example tiorc
+
+Attila Veghelyi:
+
+ * Add bit reverse order feature
 
 
 
index 8861b68819f92473d99395a201a673561b75e860..1c87aa0c75e133c161b9e9dd37f1963848611892 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,8 +1,9 @@
 # tio - a simple serial device I/O tool
 
-[![CircleCI](https://circleci.com/gh/tio/tio/tree/master.svg?style=shield)](https://circleci.com/gh/tio/tio/tree/master)
-[![tio](https://snapcraft.io/tio/badge.svg)](https://snapcraft.io/tio)
-[![Packaging status](https://repology.org/badge/tiny-repos/tio.svg)](https://repology.org/project/tio/versions)
+[![](https://img.shields.io/circleci/build/gh/tio/tio?token=da7e7fd0d0ee99b9f986f8877dcdbe28f73d9e06)](https://circleci.com/gh/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/tokei/lines/github/tio/tio)](https://github.com/tio/tio)
+[![](https://img.shields.io/repology/repositories/tio)](https://repology.org/project/tio/versions)
 
 ## 1. Introduction
 
@@ -31,12 +32,13 @@ when used in combination with [tmux](https://tmux.github.io).
  * Sensible defaults
  * Support for non-standard baud rates
  * Support for RS-485 mode
+ * Support for mark and space parity
  * List available serial devices by ID
  * Show RX/TX statistics
  * Toggle serial lines
  * Pulse serial lines with configurable pulse duration
  * Local echo support
- * Map characters (nl, cr-nl, bs, lowercase to uppercase, etc.)
+ * Remapping of characters (nl, cr-nl, bs, lowercase to uppercase, etc.)
  * Line timestamps
  * Support for delayed output per character
  * Support for delayed output per line
@@ -48,8 +50,8 @@ when used in combination with [tmux](https://tmux.github.io).
  * Redirect I/O to UNIX socket or IPv4/v6 network socket for scripting or TTY sharing
  * Pipe input and/or output
  * Support for simple line request/response handling
- * Bash completion
- * Color support
+ * Bash completion on options, serial device names, and sub-configuration names
+ * Configurable text color
  * Visual or audible alert on connect/disconnect
  * Remapping of prefix key
  * Man page documentation
@@ -65,42 +67,42 @@ For more usage details please see the man page documentation
 The command-line interface is straightforward as reflected in the output from
 'tio --help':
 ```
 Usage: tio [<options>] <tty-device|sub-config>
-
 Connect to tty device directly or via sub-configuration.
-
 Options:
-    -b, --baudrate <bps>                   Baud rate (default: 115200)
-    -d, --databits 5|6|7|8                 Data bits (default: 8)
-    -f, --flow hard|soft|none              Flow control (default: none)
-    -s, --stopbits 1|2                     Stop bits (default: 1)
-    -p, --parity odd|even|none|mark|space  Parity (default: none)
-    -o, --output-delay <ms>                Output character delay (default: 0)
-    -O, --output-line-delay <ms>           Output line delay (default: 0)
-        --line-pulse-duration <duration>   Set line pulse duration
-    -n, --no-autoconnect                   Disable automatic connect
-    -e, --local-echo                       Enable local echo
-    -t, --timestamp                        Enable line timestamp
-        --timestamp-format <format>        Set timestamp format (default: 24hour)
-    -L, --list-devices                     List available serial devices
-    -l, --log                              Enable log to file
-        --log-file <filename>              Set log filename
-        --log-strip                        Strip control characters and escape sequences
-    -m, --map <flags>                      Map characters
-    -c, --color 0..255|bold|none|list      Colorize tio text (default: bold)
-    -S, --socket <socket>                  Redirect I/O to socket
-    -x, --hexadecimal                      Enable hexadecimal mode
-    -r, --response-wait                    Wait for line response then quit
-        --response-timeout <ms>            Response timeout (default: 100)
-        --rs-485                           Enable RS-485 mode
-        --rs-485-config <config>           Set RS-485 configuration
-        --alert bell|blink|none            Alert on connect/disconnect (default: none)
-    -v, --version                          Display version
-    -h, --help                             Display help
-
 Options and sub-configurations may be set via configuration file.
-
 See the man page for more details.
+ Usage: tio [<options>] <tty-device|sub-config>
+
+ Connect to tty device directly or via sub-configuration.
+
+ Options:
+   -b, --baudrate <bps>                   Baud rate (default: 115200)
+   -d, --databits 5|6|7|8                 Data bits (default: 8)
+   -f, --flow hard|soft|none              Flow control (default: none)
+   -s, --stopbits 1|2                     Stop bits (default: 1)
+   -p, --parity odd|even|none|mark|space  Parity (default: none)
+   -o, --output-delay <ms>                Output character delay (default: 0)
+   -O, --output-line-delay <ms>           Output line delay (default: 0)
+       --line-pulse-duration <duration>   Set line pulse duration
+   -n, --no-autoconnect                   Disable automatic connect
+   -e, --local-echo                       Enable local echo
+   -t, --timestamp                        Enable line timestamp
+       --timestamp-format <format>        Set timestamp format (default: 24hour)
+   -L, --list-devices                     List available serial devices
+   -l, --log                              Enable log to file
+       --log-file <filename>              Set log filename
+       --log-strip                        Strip control characters and escape sequences
+   -m, --map <flags>                      Map characters
+   -c, --color 0..255|bold|none|list      Colorize tio text (default: bold)
+   -S, --socket <socket>                  Redirect I/O to socket
+   -x, --hexadecimal                      Enable hexadecimal mode
+   -r, --response-wait                    Wait for line response then quit
+       --response-timeout <ms>            Response timeout (default: 100)
+       --rs-485                           Enable RS-485 mode
+       --rs-485-config <config>           Set RS-485 configuration
+       --alert bell|blink|none            Alert on connect/disconnect (default: none)
+   -v, --version                          Display version
+   -h, --help                             Display help
+
+ Options and sub-configurations may be set via configuration file.
+
+ See the man page for more details.
 
 ```
 
@@ -113,6 +115,7 @@ established connection is lost.
 
 tio features full bash autocompletion.
 
+#### 3.1.1 Examples
 
 Typical use is without options:
 ```
@@ -131,6 +134,27 @@ $ tio /dev/serial/by-id/usb-FTDI_TTL232R-3V3_FTGQVXBL-if00-port0
 Using serial devices by ID ensures that tio automatically reconnects to the
 correct serial device if it is disconnected and then reconnected.
 
+List available serial devices by ID:
+```
+$ tio --list-devices
+```
+Note: One can also use tio shell completion on /dev which will automatically
+list all available serial tty devices.
+
+Log to file with autogenerated filename:
+```
+$ tio --log /dev/ttyUSB0
+```
+
+Enable ISO8601 timestamps per line:
+```
+$ tio --timestamp --timestamp-format iso8601 /dev/ttyUSB0
+```
+
+Redirect I/O to IPv4 network socket on port 4242:
+```
+$ tio --socket inet:4242 /dev/ttyUSB0
+```
 
 Inject data to the serial device:
 ```
@@ -150,20 +174,21 @@ ctrl-t ? to list the available key commands.
 
 ```
 [20:19:12.040] Key commands:
-[20:19:12.040]  ctrl-t ?   List available key commands
-[20:19:12.040]  ctrl-t b   Send break
-[20:19:12.040]  ctrl-t c   Show configuration
-[20:19:12.040]  ctrl-t e   Toggle local echo mode
-[20:19:12.040]  ctrl-t g   Toggle serial port line
-[20:19:12.040]  ctrl-t h   Toggle hexadecimal mode
-[20:19:12.040]  ctrl-t l   Clear screen
-[20:19:12.040]  ctrl-t L   Show line states
-[20:19:12.040]  ctrl-t p   Pulse serial port line
-[20:19:12.040]  ctrl-t q   Quit
-[20:19:12.041]  ctrl-t s   Show statistics
-[20:19:12.041]  ctrl-t T   Toggle line timestamp mode
-[20:19:12.041]  ctrl-t U   Toggle conversion to uppercase
-[20:19:12.041]  ctrl-t v   Show version
+[20:19:12.040]  ctrl-t ?       List available key commands
+[20:19:12.040]  ctrl-t b       Send break
+[20:19:12.040]  ctrl-t c       Show configuration
+[20:19:12.040]  ctrl-t e       Toggle local echo mode
+[20:19:12.040]  ctrl-t g       Toggle serial port line
+[20:19:12.040]  ctrl-t h       Toggle hexadecimal mode
+[20:19:12.040]  ctrl-t l       Clear screen
+[20:19:12.040]  ctrl-t L       Show line states
+[20:19:12.040]  ctrl-t p       Pulse serial port line
+[20:19:12.040]  ctrl-t q       Quit
+[20:19:12.041]  ctrl-t s       Show statistics
+[20:19:12.041]  ctrl-t t       Toggle line timestamp mode
+[20:19:12.041]  ctrl-t U       Toggle conversion to uppercase
+[20:19:12.041]  ctrl-t v       Show version
+[20:19:12.041]  ctrl-t ctrl-t  Send ctrl-t character
 ```
 
 If needed, the prefix key (ctrl-t) can be remapped via configuration file.
@@ -214,7 +239,7 @@ Or by pattern match:
 $ tio usb12
 ```
 
-Another configuration file example is available [here](example/tiorc).
+Another more elaborate configuration file example is available [here](example/tiorc).
 
 ## 4. Installation
 
@@ -230,21 +255,21 @@ reach out to its package maintainers team.
 
 Install latest stable version:
 ```
-    $ snap install tio
+$ snap install tio
 ```
 
 ### 4.3 Installation using brew (MacOS, Linux)
 
 If you have [brew](http://brew.sh) installed:
 ```
-    $ brew install tio
+$ brew install tio
 ```
 
 ### 4.4 Installation using MSYS2 (Windows)
 
 If you have [MSYS2](https://www.msys2.org) installed:
 ```
-    $ pacman -S tio
+$ pacman -S tio
 ```
 
 ### 4.5 Installation from source
@@ -253,9 +278,9 @@ The latest source releases can be found [here](https://github.com/tio/tio/releas
 
 Install steps:
 ```
-    $ meson build
-    $ meson compile -C build
-    $ meson install -C build
+$ meson build
+$ meson compile -C build
+$ meson install -C build
 ```
 
 See meson\_options.txt for tio specific build options.
index c555df1b834e28da7912bb572cfa42f1e54dd4bf..525a982eb60260a7c433e5b4046c5022f96e037d 100644 (file)
@@ -18,8 +18,10 @@ hexadecimal = disable
 timestamp = disable
 log = disable
 log-strip = disable
+local-echo = disable
 color = bold
 rs-485 = disable
+response-wait = disable
 alert = none
 
 # Sub-configuraions
index de87ea33478a64fe210c8e49cb122f7817b8ad43..936ab5c85e02843c09ea279e23f9b1c232bac223 100644 (file)
@@ -167,6 +167,8 @@ Map DEL to BS on output
 Map NL to CR-NL on output
 .IP "\fBOLTU"
 Map lowercase characters to uppercase on output
+.IP "\fBMSB2LSB"
+Map MSB bit order to LSB on output
 .P
 If defining more than one flag, the flags must be comma separated.
 .RE
@@ -307,6 +309,8 @@ Toggle line timestamp mode
 Toggle conversion to uppercase on output
 .IP "\fBctrl-t v"
 Show version
+.IP "\fBctrl-t ctrl-t"
+Send ctrl-t character
 
 .SH "HEXADECIMAL MODE"
 .PP
index 0399b635a6707ce81e07d972849213248a3b5530..1874c65dcd871cfb877b3d79ff9bcbd29a6e21d2 100644 (file)
@@ -1,4 +1,4 @@
-tio(1)                                                                                    User Commands                                                                                   tio(1)
+tio(1)                                                                                                                              User Commands                                                                                                                             tio(1)
 
 NAME
        tio - a simple serial device I/O tool
@@ -66,8 +66,7 @@ OPTIONS
 
               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.
 
@@ -131,6 +130,8 @@ OPTIONS
 
               OLTU        Map lowercase characters to uppercase on output
 
+              MSB2LSB     Map MSB bit order to LSB on output
+
               If defining more than one flag, the flags must be comma separated.
 
        -x, --hexadecimal
@@ -149,8 +150,8 @@ OPTIONS
 
               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.
 
@@ -243,6 +244,8 @@ KEYS
 
        ctrl-t v        Show version
 
+       ctrl-t ctrl-t   Send ctrl-t character
+
 HEXADECIMAL MODE
        In hexadecimal mode each incoming byte is printed out as a hexadecimal value.
 
@@ -436,4 +439,4 @@ WEBSITE
 AUTHOR
        Created by Martin Lund <martin.lund@keep-it-simple.com>.
 
-tio 2.0                                                                                    2022-09-11                                                                                     tio(1)
+tio 2.2                                                                                                                              2022-10-18                                                                                                                               tio(1)
index 0291474a0e24b1e378b916934c0aec42083e74c2..9a91e851a53f24fd1cb1d9b9b7df1f8b4323750b 100644 (file)
@@ -1,12 +1,12 @@
 project('tio', 'c',
-    version : '2.0',
+    version : '2.2',
     license : [ 'GPL-2'],
     meson_version : '>= 0.53.2',
     default_options : [ 'warning_level=2', 'buildtype=release', 'c_std=gnu99' ]
 )
 
 # The tag date of the project_version(), update when the version bumps.
-version_date = '2022-09-11'
+version_date = '2022-10-18'
 
 # Test for dynamic baudrate configuration interface
 compiler = meson.get_compiler('c')
index ca115e600cbbcba25c7f562f1e0c41bc0105c311..82cb649964f54863791cfca21593ca0eaad797ed 100644 (file)
@@ -94,7 +94,7 @@ _tio()
             return 0
             ;;
         -m | --map)
-            COMPREPLY=( $(compgen -W "ICRNL IGNCR INLCR INLCRNL OCRNL ODELBS ONLCRNL" -- ${cur}) )
+            COMPREPLY=( $(compgen -W "ICRNL IGNCR INLCR INLCRNL OCRNL ODELBS ONLCRNL MSB2LSB" -- ${cur}) )
             return 0
             ;;
         -t | --timestamp)
@@ -159,12 +159,14 @@ _tio()
             ;;
     esac
 
+    sub_configs="`tio --complete-sub-configs`"
+
     if [ -d /dev/serial/by-id ]; then
         ttys=$(printf '%s\n' /dev/tty* /dev/serial/by-id/*)
     else
         ttys=$(printf '%s\n' /dev/tty*)
     fi
-    COMPREPLY=( $(compgen -W "${ttys}" -- ${cur}) )
+    COMPREPLY=( $(compgen -W "${ttys} ${sub_configs}" -- ${cur}) )
     return 0
 }
 
index 864380e04a79d3235a5e12e1acc30cdde6c19836..e749e4b49f9453a362d2f50ea790f5bc0545e662 100644 (file)
 #include "timestamp.h"
 #include "alert.h"
 
-static struct config_t *c;
+struct config_t
+{
+    const char *user;
+
+    char *path;
+    char *section_name;
+    char *match;
+
+    char *tty;
+    char *flow;
+    char *parity;
+    char *log_filename;
+    char *socket;
+    char *map;
+};
+
+static struct config_t c;
 
 static int get_match(const char *input, const char *pattern, char **match)
 {
@@ -93,13 +109,13 @@ static int data_handler(void *user, const char *section, const char *name,
     UNUSED(user);
 
     // If section matches current section being parsed
-    if (!strcmp(section, c->section_name))
+    if (!strcmp(section, c.section_name))
     {
         // Set configuration parameter if found
         if (!strcmp(name, "tty"))
         {
-            asprintf(&c->tty, value, c->match);
-            option.tty_device = c->tty;
+            asprintf(&c.tty, value, c.match);
+            option.tty_device = c.tty;
         }
         else if (!strcmp(name, "baudrate"))
         {
@@ -111,8 +127,8 @@ static int data_handler(void *user, const char *section, const char *name,
         }
         else if (!strcmp(name, "flow"))
         {
-            asprintf(&c->flow, "%s", value);
-            option.flow = c->flow;
+            asprintf(&c.flow, "%s", value);
+            option.flow = c.flow;
         }
         else if (!strcmp(name, "stopbits"))
         {
@@ -120,8 +136,8 @@ static int data_handler(void *user, const char *section, const char *name,
         }
         else if (!strcmp(name, "parity"))
         {
-            asprintf(&c->parity, "%s", value);
-            option.parity = c->parity;
+            asprintf(&c.parity, "%s", value);
+            option.parity = c.parity;
         }
         else if (!strcmp(name, "output-delay"))
         {
@@ -159,8 +175,8 @@ static int data_handler(void *user, const char *section, const char *name,
         }
         else if (!strcmp(name, "log-file"))
         {
-            asprintf(&c->log_filename, "%s", value);
-            option.log_filename = c->log_filename;
+            asprintf(&c.log_filename, "%s", value);
+            option.log_filename = c.log_filename;
         }
         else if (!strcmp(name, "log-strip"))
         {
@@ -212,8 +228,8 @@ static int data_handler(void *user, const char *section, const char *name,
         }
         else if (!strcmp(name, "map"))
         {
-            asprintf(&c->map, "%s", value);
-            option.map = c->map;
+            asprintf(&c.map, "%s", value);
+            option.map = c.map;
         }
         else if (!strcmp(name, "color"))
         {
@@ -241,8 +257,8 @@ static int data_handler(void *user, const char *section, const char *name,
         }
         else if (!strcmp(name, "socket"))
         {
-            asprintf(&c->socket, "%s", value);
-            option.socket = c->socket;
+            asprintf(&c.socket, "%s", value);
+            option.socket = c.socket;
         }
         else if (!strcmp(name, "prefix-ctrl-key"))
         {
@@ -306,15 +322,15 @@ static int section_pattern_search_handler(void *user, const char *section, const
     if (strcmp(varname, "pattern"))
         return 0;
 
-    if (!strcmp(varval, c->user))
+    if (!strcmp(varval, c.user))
     {
         /* pattern matches as plain text */
-        asprintf(&c->section_name, "%s", section);
+        asprintf(&c.section_name, "%s", section);
     }
-    else if (get_match(c->user, varval, &c->match) > 0)
+    else if (get_match(c.user, varval, &c.match) > 0)
     {
         /* pattern matches as regex */
-        asprintf(&c->section_name, "%s", section);
+        asprintf(&c.section_name, "%s", section);
     }
 
     return 0;
@@ -333,10 +349,28 @@ static int section_name_search_handler(void *user, const char *section, const ch
     UNUSED(varname);
     UNUSED(varval);
 
-    if (!strcmp(section, c->user))
+    if (!strcmp(section, c.user))
     {
         /* section name matches as plain text */
-        asprintf(&c->section_name, "%s", section);
+        asprintf(&c.section_name, "%s", section);
+    }
+
+    return 0;
+}
+
+static int section_name_print_handler(void *user, const char *section, const char *varname,
+                                       const char *varval)
+{
+    UNUSED(user);
+    UNUSED(varname);
+    UNUSED(varval);
+
+    static char *section_previous = "";
+
+    if (strcmp(section, section_previous) != 0)
+    {
+        printf("%s ", section);
+        section_previous = strdup(section);
     }
 
     return 0;
@@ -344,46 +378,54 @@ static int section_name_search_handler(void *user, const char *section, const ch
 
 static int resolve_config_file(void)
 {
-    asprintf(&c->path, "%s/tio/tiorc", getenv("XDG_CONFIG_HOME"));
-    if (!access(c->path, F_OK))
+    asprintf(&c.path, "%s/tio/tiorc", getenv("XDG_CONFIG_HOME"));
+    if (!access(c.path, F_OK))
     {
         return 0;
     }
 
-    free(c->path);
+    free(c.path);
 
-    asprintf(&c->path, "%s/.config/tio/tiorc", getenv("HOME"));
-    if (!access(c->path, F_OK))
+    asprintf(&c.path, "%s/.config/tio/tiorc", getenv("HOME"));
+    if (!access(c.path, F_OK))
     {
         return 0;
     }
 
-    free(c->path);
+    free(c.path);
 
-    asprintf(&c->path, "%s/.tiorc", getenv("HOME"));
-    if (!access(c->path, F_OK))
+    asprintf(&c.path, "%s/.tiorc", getenv("HOME"));
+    if (!access(c.path, F_OK))
     {
         return 0;
     }
 
-    free(c->path);
+    free(c.path);
 
-    c->path = NULL;
+    c.path = NULL;
 
     return -EINVAL;
 }
 
+void config_file_show_sub_configurations(void)
+{
+    memset(&c, 0, sizeof(struct config_t));
+
+    // Find config file
+    if (resolve_config_file() != 0)
+    {
+        // None found - stop parsing
+        return;
+    }
+
+    ini_parse(c.path, section_name_print_handler, NULL);
+}
+
 void config_file_parse(void)
 {
     int ret;
 
-    c = malloc(sizeof(struct config_t));
-    if (!c)
-    {
-        tio_error_printf("Insufficient memory allocation");
-        exit(EXIT_FAILURE);
-    } 
-    memset(c, 0, sizeof(struct config_t));
+    memset(&c, 0, sizeof(struct config_t));
 
     // Find config file
     if (resolve_config_file() != 0)
@@ -393,30 +435,30 @@ void config_file_parse(void)
     }
 
     // Set user input which may be tty device or sub config
-    c->user = option.tty_device;
+    c.user = option.tty_device;
 
-    if (!c->user)
+    if (!c.user)
     {
         return;
     }
 
     // Parse default (unnamed) settings
-    asprintf(&c->section_name, "%s", "");
-    ret = ini_parse(c->path, data_handler, NULL);
+    asprintf(&c.section_name, "%s", "");
+    ret = ini_parse(c.path, data_handler, NULL);
     if (ret < 0)
     {
         tio_error_printf("Unable to parse configuration file (%d)", ret);
         exit(EXIT_FAILURE);
     }
-    free(c->section_name);
-    c->section_name = NULL;
+    free(c.section_name);
+    c.section_name = NULL;
 
     // Find matching section
-    ret = ini_parse(c->path, section_pattern_search_handler, NULL);
-    if (!c->section_name)
+    ret = ini_parse(c.path, section_pattern_search_handler, NULL);
+    if (!c.section_name)
     {
-        ret = ini_parse(c->path, section_name_search_handler, NULL);
-        if (!c->section_name)
+        ret = ini_parse(c.path, section_name_search_handler, NULL);
+        if (!c.section_name)
         {
             tio_debug_printf("Unable to match user input to configuration section (%d)", ret);
             return;
@@ -424,7 +466,7 @@ void config_file_parse(void)
     }
 
     // Parse settings of found section (sub config)
-    ret = ini_parse(c->path, data_handler, NULL);
+    ret = ini_parse(c.path, data_handler, NULL);
     if (ret < 0)
     {
         tio_error_printf("Unable to parse configuration file (%d)", ret);
@@ -436,27 +478,25 @@ void config_file_parse(void)
 
 void config_exit(void)
 {
-    free(c->tty);
-    free(c->flow);
-    free(c->parity);
-    free(c->log_filename);
-    free(c->map);
-
-    free(c->match);
-    free(c->section_name);
-    free(c->path);
-
-    free(c);
+    free(c.tty);
+    free(c.flow);
+    free(c.parity);
+    free(c.log_filename);
+    free(c.map);
+
+    free(c.match);
+    free(c.section_name);
+    free(c.path);
 }
 
 void config_file_print(void)
 {
-    if (c->path != NULL)
+    if (c.path != NULL)
     {
-        tio_printf(" Path: %s", c->path);
-        if (c->section_name != NULL)
+        tio_printf(" Path: %s", c.path);
+        if (c.section_name != NULL)
         {
-            tio_printf(" Active sub-configuration: %s", c->section_name);
+            tio_printf(" Active sub-configuration: %s", c.section_name);
         }
     }
 }
index 8fbea07cb5132ab1f45fb1bdea23a700db8be131..74e1b6ec251e8aca3e65ac967977ad386c8eaac0 100644 (file)
 
 #pragma once
 
-struct config_t
-{
-       const char *user;
-
-       char *path;
-       char *section_name;
-       char *match;
-
-       char *tty;
-       char *flow;
-       char *parity;
-       char *log_filename;
-       char *socket;
-       char *map;
-};
-
 void config_file_print(void);
 void config_file_parse(void);
 void config_exit(void);
+void config_file_show_sub_configurations(void);
index 43da8dd728f74b2a9517ce2c5809a11ede67d6f0..dfe32aa8787e03441ddcf971cabdfa080a42e08f 100644 (file)
@@ -38,64 +38,64 @@ static bool in_session = false;
 
 void error_enter_session_mode(void)
 {
-  in_session = true;
+    in_session = true;
 }
 
 void error_printf_(const char *format, ...)
 {
-  va_list args;
-  char *line;
+    va_list args;
+    char *line;
 
-  va_start(args, format);
-  vasprintf(&line, format, args);
+    va_start(args, format);
+    vasprintf(&line, format, args);
 
-  if (in_session)
-  {
-    if (print_tainted)
+    if (in_session)
     {
-      putchar('\n');
+        if (print_tainted)
+        {
+            putchar('\n');
+        }
+        ansi_error_printf("[%s] %s", timestamp_current_time(), line);
+    }
+    else
+    {
+        fprintf(stderr, "%s\n", line);
     }
-    ansi_error_printf("[%s] %s", timestamp_current_time(), line);
-  }
-  else
-  {
-    fprintf(stderr, "%s\n", line);
-  }
 
-  va_end(args);
+    va_end(args);
 
-  print_tainted = false;
-  free(line);
+    print_tainted = false;
+    free(line);
 }
 
 void tio_error_printf(const char *format, ...)
 {
-  va_list args;
+    va_list args;
 
-  va_start(args, format);
-  vsnprintf(error[0], 1000, format, args);
-  va_end(args);
+    va_start(args, format);
+    vsnprintf(error[0], 1000, format, args);
+    va_end(args);
 }
 
 void tio_error_printf_silent(const char *format, ...)
 {
-  va_list args;
+    va_list args;
 
-  va_start(args, format);
-  vsnprintf(error[1], 1000, format, args);
-  va_end(args);
+    va_start(args, format);
+    vsnprintf(error[1], 1000, format, args);
+    va_end(args);
 }
 
 void error_exit(void)
 {
-  if (error[0][0] != 0)
-  {
-    /* Print error */
-    error_printf_("Error: %s", error[0]);
-  }
-  else if ((error[1][0] != 0) && (option.no_autoconnect))
-  {
-    /* Print silent error */
-    error_printf_("Error: %s", error[1]);
-  }
+    if (error[0][0] != 0)
+    {
+        /* Print error */
+        error_printf_("Error: %s", error[0]);
+    }
+    else if ((error[1][0] != 0) && (option.no_autoconnect))
+    {
+        /* Print silent error */
+        error_printf_("Error: %s", error[1]);
+    }
 }
index 02f8a47f9ebb399cc6a32010f9876c0b23978201..d2b1c0d063dfc9fabe0ecba402719a5356d72a0c 100644 (file)
@@ -45,6 +45,12 @@ int main(int argc, char *argv[])
     /* Parse command-line options (1st pass) */
     options_parse(argc, argv);
 
+    if (option.complete_sub_configs)
+    {
+        config_file_show_sub_configurations();
+        return status;
+    }
+
     /* Parse configuration file */
     config_file_parse();
 
index d21ed87d87beb148a1c655d19b2b5d5bc0d965e6..7b61fd810adabc8bf98ca0c6ac111421d38b4105 100644 (file)
@@ -50,6 +50,7 @@ enum opt_t
     OPT_RS485,
     OPT_RS485_CONFIG,
     OPT_ALERT,
+    OPT_COMPLETE_SUB_CONFIGS,
 };
 
 /* Default options */
@@ -89,11 +90,14 @@ struct option_t option =
     .rs485_delay_rts_before_send = -1,
     .rs485_delay_rts_after_send = -1,
     .alert = ALERT_NONE,
+    .complete_sub_configs = false,
 };
 
 void print_help(char *argv[])
 {
-    printf("Usage: %s [<options>] <tty-device|sub-config>\n", argv[0]);
+    UNUSED(argv);
+
+    printf("Usage: tio [<options>] <tty-device|sub-config>\n");
     printf("\n");
     printf("Connect to tty device directly or via sub-configuration.\n");
     printf("\n");
@@ -229,34 +233,35 @@ void options_parse(int argc, char *argv[])
     {
         static struct option long_options[] =
         {
-            {"baudrate",            required_argument, 0, 'b'                    },
-            {"databits",            required_argument, 0, 'd'                    },
-            {"flow",                required_argument, 0, 'f'                    },
-            {"stopbits",            required_argument, 0, 's'                    },
-            {"parity",              required_argument, 0, 'p'                    },
-            {"output-delay",        required_argument, 0, 'o'                    },
-            {"output-line-delay" ,  required_argument, 0, 'O'                    },
-            {"line-pulse-duration", required_argument, 0, OPT_LINE_PULSE_DURATION},
-            {"no-autoconnect",      no_argument,       0, 'n'                    },
-            {"local-echo",          no_argument,       0, 'e'                    },
-            {"timestamp",           no_argument,       0, 't'                    },
-            {"timestamp-format",    required_argument, 0, OPT_TIMESTAMP_FORMAT   },
-            {"list-devices",        no_argument,       0, 'L'                    },
-            {"log",                 no_argument,       0, 'l'                    },
-            {"log-file",            required_argument, 0, OPT_LOG_FILE           },
-            {"log-strip",           no_argument,       0, OPT_LOG_STRIP          },
-            {"socket",              required_argument, 0, 'S'                    },
-            {"map",                 required_argument, 0, 'm'                    },
-            {"color",               required_argument, 0, 'c'                    },
-            {"hexadecimal",         no_argument,       0, 'x'                    },
-            {"response-wait",       no_argument,       0, 'r'                    },
-            {"response-timeout",    required_argument, 0, OPT_RESPONSE_TIMEOUT   },
-            {"rs-485",              no_argument,       0, OPT_RS485              },
-            {"rs-485-config",       required_argument, 0, OPT_RS485_CONFIG       },
-            {"alert",               required_argument, 0, OPT_ALERT              },
-            {"version",             no_argument,       0, 'v'                    },
-            {"help",                no_argument,       0, 'h'                    },
-            {0,                     0,                 0,  0                     }
+            {"baudrate",             required_argument, 0, 'b'                     },
+            {"databits",             required_argument, 0, 'd'                     },
+            {"flow",                 required_argument, 0, 'f'                     },
+            {"stopbits",             required_argument, 0, 's'                     },
+            {"parity",               required_argument, 0, 'p'                     },
+            {"output-delay",         required_argument, 0, 'o'                     },
+            {"output-line-delay" ,   required_argument, 0, 'O'                     },
+            {"line-pulse-duration",  required_argument, 0, OPT_LINE_PULSE_DURATION },
+            {"no-autoconnect",       no_argument,       0, 'n'                     },
+            {"local-echo",           no_argument,       0, 'e'                     },
+            {"timestamp",            no_argument,       0, 't'                     },
+            {"timestamp-format",     required_argument, 0, OPT_TIMESTAMP_FORMAT    },
+            {"list-devices",         no_argument,       0, 'L'                     },
+            {"log",                  no_argument,       0, 'l'                     },
+            {"log-file",             required_argument, 0, OPT_LOG_FILE            },
+            {"log-strip",            no_argument,       0, OPT_LOG_STRIP           },
+            {"socket",               required_argument, 0, 'S'                     },
+            {"map",                  required_argument, 0, 'm'                     },
+            {"color",                required_argument, 0, 'c'                     },
+            {"hexadecimal",          no_argument,       0, 'x'                     },
+            {"response-wait",        no_argument,       0, 'r'                     },
+            {"response-timeout",     required_argument, 0, OPT_RESPONSE_TIMEOUT    },
+            {"rs-485",               no_argument,       0, OPT_RS485               },
+            {"rs-485-config",        required_argument, 0, OPT_RS485_CONFIG        },
+            {"alert",                required_argument, 0, OPT_ALERT               },
+            {"version",              no_argument,       0, 'v'                     },
+            {"help",                 no_argument,       0, 'h'                     },
+            {"complete-sub-configs", no_argument,       0, OPT_COMPLETE_SUB_CONFIGS},
+            {0,                      0,                 0,  0                      }
         };
 
         /* getopt_long stores the option index here */
@@ -418,6 +423,10 @@ void options_parse(int argc, char *argv[])
                 exit(EXIT_SUCCESS);
                 break;
 
+            case OPT_COMPLETE_SUB_CONFIGS:
+                option.complete_sub_configs = true;
+                break;
+
             case '?':
                 /* getopt_long already printed an error message */
                 exit(EXIT_FAILURE);
@@ -434,6 +443,11 @@ void options_parse(int argc, char *argv[])
     else if (optind < argc)
         option.tty_device = argv[optind++];
 
+    if (option.complete_sub_configs)
+    {
+        return;
+    }
+
     if (strlen(option.tty_device) == 0)
     {
         tio_error_printf("Missing tty device or sub-configuration name");
@@ -445,7 +459,9 @@ void options_parse(int argc, char *argv[])
     {
         fprintf(stderr, "Error: Unknown argument ");
         while (optind < argc)
-            printf("%s ", argv[optind++]);
+        {
+            fprintf(stderr, "%s ", argv[optind++]);
+        }
         fprintf(stderr, "\n");
         exit(EXIT_FAILURE);
     }
index 22ec236b7b7fc2dfe7cced64bbab6cb5d446d42b..8ae556d5271ae748af8f8ac3e7104d166e94baf6 100644 (file)
@@ -66,6 +66,7 @@ struct option_t
     int32_t rs485_delay_rts_before_send;
     int32_t rs485_delay_rts_after_send;
     enum alert_t alert;
+    bool complete_sub_configs;
 };
 
 extern struct option_t option;
index cf130f0afee1208df5f6a1dea75507d4bf0a6806..b5ad48c14fadbdb62a53f413c8683686d0e8e1c8 100644 (file)
@@ -31,45 +31,45 @@ char ansi_format[30];
 
 void print_hex(char c)
 {
-  printf("%02x ", (unsigned char) c);
+    printf("%02x ", (unsigned char) c);
 }
 
 void print_normal(char c)
 {
-  putchar(c);
+    putchar(c);
 }
 
 void print_init_ansi_formatting()
 {
-  if (option.color == 256)
-  {
-    // Set bold text with no color changes
-    sprintf(ansi_format, "\e[1m");
-  }
-  else
-  {
-    // Set bold text with user defined ANSI color
-    sprintf(ansi_format, "\e[1;38;5;%dm", option.color);
-  }
+    if (option.color == 256)
+    {
+        // Set bold text with no color changes
+        sprintf(ansi_format, "\e[1m");
+    }
+    else
+    {
+        // Set bold text with user defined ANSI color
+        sprintf(ansi_format, "\e[1;38;5;%dm", option.color);
+    }
 }
 
 void tio_printf_array(const char *array)
 {
-  int i = 0, j = 0;
+    int i = 0, j = 0;
 
-  tio_printf("");
+    tio_printf("");
 
-  while (array[i])
-  {
-    if (array[i] == '\n')
+    while (array[i])
     {
-      const char *line = &array[j];
-      char *line_copy = strndup(line, i-j);
-      tio_printf_raw("%s\r", line_copy);
-      free(line_copy);
-      j = i;
+        if (array[i] == '\n')
+        {
+            const char *line = &array[j];
+            char *line_copy = strndup(line, i-j);
+            tio_printf_raw("%s\r", line_copy);
+            free(line_copy);
+            j = i;
+        }
+        i++;
     }
-    i++;
-  }
-  tio_printf("");
+    tio_printf("");
 }
index e3f61939f32a7ecad9347465373be03f0bbc5bed..c870f1746a9f494fedd79eaf061039a581bfaea3 100644 (file)
@@ -35,72 +35,78 @@ extern char ansi_format[];
 
 #define ansi_printf(format, args...) \
 { \
-  if (!option.mute) { \
-  if (option.color < 0) \
-    fprintf (stdout, "\r" format "\r\n", ## args); \
-  else \
-    fprintf (stdout, "\r%s" format ANSI_RESET "\r\n", ansi_format, ## args); \
-  } \
+    if (!option.mute) \
+    { \
+        if (option.color < 0) \
+        fprintf (stdout, "\r" format "\r\n", ## args); \
+        else \
+        fprintf (stdout, "\r%s" format ANSI_RESET "\r\n", ansi_format, ## args); \
+    } \
 }
 
 #define ansi_error_printf(format, args...) \
 { \
-  if (!option.mute) { \
-  if (option.color < 0) \
-    fprintf (stderr, "\r" format "\r\n", ## args); \
-  else \
-    fprintf (stderr, "\r%s" format ANSI_RESET "\r\n", ansi_format, ## args); \
-  fflush(stderr); \
-  } \
+    if (!option.mute) \
+    { \
+        if (option.color < 0) \
+        fprintf (stderr, "\r" format "\r\n", ## args); \
+        else \
+        fprintf (stderr, "\r%s" format ANSI_RESET "\r\n", ansi_format, ## args); \
+        fflush(stderr); \
+    } \
 }
 
 #define ansi_printf_raw(format, args...) \
 { \
-  if (!option.mute) { \
-  if (option.color < 0) \
-    fprintf (stdout, format, ## args); \
-  else \
-    fprintf (stdout, "%s" format ANSI_RESET, ansi_format, ## args); \
-  } \
+    if (!option.mute) \
+    { \
+        if (option.color < 0) \
+        fprintf (stdout, format, ## args); \
+        else \
+        fprintf (stdout, "%s" format ANSI_RESET, ansi_format, ## args); \
+    } \
 }
 
 #define tio_warning_printf(format, args...) \
 { \
-  if (!option.mute) { \
-  if (print_tainted) \
-    putchar('\n'); \
-  if (option.color < 0) \
-    fprintf (stdout, "\r[%s] Warning: " format "\r\n", timestamp_current_time(), ## args); \
-  else \
-    ansi_printf("[%s] Warning: " format, timestamp_current_time(), ## args); \
-  } \
+    if (!option.mute) \
+    { \
+        if (print_tainted) \
+        putchar('\n'); \
+        if (option.color < 0) \
+        fprintf (stdout, "\r[%s] Warning: " format "\r\n", timestamp_current_time(), ## args); \
+        else \
+        ansi_printf("[%s] Warning: " format, timestamp_current_time(), ## args); \
+    } \
 }
 
 #define tio_printf(format, args...) \
 { \
-  if (!option.mute) { \
-  if (print_tainted) \
-    putchar('\n'); \
-  ansi_printf("[%s] " format, timestamp_current_time(), ## args); \
-  print_tainted = false; \
-  } \
+    if (!option.mute) \
+    { \
+        if (print_tainted) \
+        putchar('\n'); \
+        ansi_printf("[%s] " format, timestamp_current_time(), ## args); \
+        print_tainted = false; \
+    } \
 }
 
 #define tio_printf_raw(format, args...) \
 { \
-  if (!option.mute) { \
-  if (print_tainted) \
-    putchar('\n'); \
-  ansi_printf_raw("[%s] " format, timestamp_current_time(), ## args); \
-  print_tainted = false; \
-  } \
+    if (!option.mute) \
+    { \
+        if (print_tainted) \
+        putchar('\n'); \
+        ansi_printf_raw("[%s] " format, timestamp_current_time(), ## args); \
+        print_tainted = false; \
+    } \
 }
 
 #ifdef DEBUG
 #define tio_debug_printf(format, args...) \
-  fprintf (stdout, "[debug] " format, ## args)
+    fprintf(stdout, "[debug] " format, ## args)
 #define tio_debug_printf_raw(format, args...) \
-  fprintf (stdout, "" format, ## args)
+    fprintf(stdout, "" format, ## args)
 #else
 #define tio_debug_printf(format, args...)
 #define tio_debug_printf_raw(format, args...)
index 4165017b93e0204e9ba4d8fc8bbec51310015158..75c724230b34de2f0fad913bfbb2354892292af7 100644 (file)
--- a/src/tty.c
+++ b/src/tty.c
@@ -84,6 +84,7 @@
 #define KEY_H 0x68
 #define KEY_L 0x6C
 #define KEY_SHIFT_L 0x4C
+#define KEY_M 0x6D
 #define KEY_P 0x70
 #define KEY_Q 0x71
 #define KEY_S 0x73
@@ -126,6 +127,7 @@ static bool map_o_cr_nl = false;
 static bool map_o_nl_crnl = false;
 static bool map_o_del_bs = false;
 static bool map_o_ltu = false;
+static bool map_o_msblsb = false;
 static char hex_chars[2];
 static unsigned char hex_char_index = 0;
 static char tty_buffer[BUFSIZ*2];
@@ -221,7 +223,7 @@ ssize_t tty_write(int fd, const void *buffer, size_t count)
             }
             bytes_written += retval;
 
-            if (option.output_line_delay && *(unsigned char*)buffer == '\r')
+            if (option.output_line_delay && *(unsigned char*)buffer == '\n')
             {
                 delay(option.output_line_delay);
             }
@@ -257,8 +259,14 @@ static void output_hex(char c)
 {
     hex_chars[hex_char_index++] = c;
 
+    printf("%c", c);
+
     if (hex_char_index == 2)
     {
+        usleep(100*1000);
+        printf("\b \b");
+        printf("\b \b");
+
         unsigned char hex_value = char_to_nibble(hex_chars[0]) << 4 | (char_to_nibble(hex_chars[1]) & 0x0F);
         hex_char_index = 0;
 
@@ -402,20 +410,22 @@ void handle_command_sequence(char input_char, char previous_char, char *output_c
         {
             case KEY_QUESTION:
                 tio_printf("Key commands:");
-                tio_printf(" ctrl-%c ?   List available key commands", option.prefix_key);
-                tio_printf(" ctrl-%c b   Send break", option.prefix_key);
-                tio_printf(" ctrl-%c c   Show configuration", option.prefix_key);
-                tio_printf(" ctrl-%c e   Toggle local echo mode", option.prefix_key);
-                tio_printf(" ctrl-%c g   Toggle serial port line", option.prefix_key);
-                tio_printf(" ctrl-%c h   Toggle hexadecimal mode", option.prefix_key);
-                tio_printf(" ctrl-%c l   Clear screen", option.prefix_key);
-                tio_printf(" ctrl-%c L   Show line states", 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 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);
-                tio_printf(" ctrl-%c v   Show version", option.prefix_key);
+                tio_printf(" ctrl-%c ?       List available key commands", option.prefix_key);
+                tio_printf(" ctrl-%c b       Send break", option.prefix_key);
+                tio_printf(" ctrl-%c c       Show configuration", option.prefix_key);
+                tio_printf(" ctrl-%c e       Toggle local echo mode", option.prefix_key);
+                tio_printf(" ctrl-%c g       Toggle serial port line", option.prefix_key);
+                tio_printf(" ctrl-%c h       Toggle hexadecimal mode", option.prefix_key);
+                tio_printf(" ctrl-%c l       Clear screen", option.prefix_key);
+                tio_printf(" ctrl-%c L       Show line states", option.prefix_key);
+                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 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);
+                tio_printf(" ctrl-%c v       Show version", option.prefix_key);
+                tio_printf(" ctrl-%c ctrl-%c  Send ctrl-%c character", option.prefix_key, option.prefix_key, option.prefix_key);
                 break;
 
             case KEY_SHIFT_L:
@@ -497,6 +507,20 @@ void handle_command_sequence(char input_char, char previous_char, char *output_c
                 printf("\033c");
                 break;
 
+            case KEY_M:
+                /* Toggle bit order */
+                if (!map_o_msblsb)
+                {
+                    map_o_msblsb = true;
+                    tio_printf("Switched to reverse bit order");
+                }
+                else
+                {
+                    map_o_msblsb = false;
+                    tio_printf("Switched to normal bit order");
+                }
+                break;
+
             case KEY_Q:
                 /* Exit upon ctrl-t q sequence */
                 exit(EXIT_SUCCESS);
@@ -546,6 +570,23 @@ void handle_command_sequence(char input_char, char previous_char, char *output_c
                 break;
 
             default:
+                /* Handle double prefix key input case */
+                if (input_char == option.prefix_code)
+                {
+                    static int count = 0;
+                    if (count++ == 1)
+                    {
+                        // Do not forward prefix characters excessively
+                        count = 0;
+                        break;
+                    }
+
+                    /* Forward prefix character to tty */
+                    *output_char = option.prefix_code;
+                    *forward = true;
+                    break;
+                }
+
                 /* Ignore unknown ctrl-t escaped keys */
                 break;
         }
@@ -842,6 +883,10 @@ void tty_configure(void)
             {
                 map_o_ltu = true;
             }
+            else if (strcmp(token, "MSB2LSB") == 0)
+            {
+                map_o_msblsb = true;
+            }
             else
             {
                 printf("Error: Unknown mapping flag %s\n", token);
@@ -1187,7 +1232,7 @@ int tty_connect(void)
                     input_char = input_buffer[i];
 
                     /* Print timestamp on new line if enabled */
-                    if (next_timestamp && input_char != '\n' && input_char != '\r')
+                    if ((next_timestamp && input_char != '\n' && input_char != '\r') && !option.hex_mode)
                     {
                         now = timestamp_current_time();
                         if (now)
@@ -1201,8 +1246,19 @@ int tty_connect(void)
                         }
                     }
 
+                    /* Convert MSB to LSB bit order */
+                    if (map_o_msblsb)
+                    {
+                        char ch = input_char;
+                        input_char = 0;
+                        for (int j = 0; j < 8; ++j)
+                        {
+                            input_char |= ((1 << j) & ch) ? (1 << (7 - j)) : 0;
+                        }
+                    }
+
                     /* Map input character */
-                    if ((input_char == '\n') && (map_i_nl_crnl))
+                    if ((input_char == '\n') && (map_i_nl_crnl) && (!map_o_msblsb))
                     {
                         print('\r');
                         print('\n');