title: Serial port loopback/duplex test, in Bash or C? (process substitution)
body: <p>I have a serial device set up as loopback (meaning it will simply echo back any character it receives), and I'd like to measure effective throughput speed. For this, I hoped I could use <code>time</code>, as in</p>
  
  <pre><code>time bash -c '...'
  </code></pre>
  
  <p>where '<code>...</code>' would be some command I could run. </p>
  
  <p>Now, the first problem is that I want to use the device at 2000000 bps, so I cannot use  <a href="http://man.gnusquad.org/ttylog/section-8/en/" rel="noreferrer">ttylog</a> or <a href="http://www.manpagez.com/man/1/screen/" rel="noreferrer">screen</a> (they both seem to go up to 115200 bps only). However, working with <code>/dev/ttyUSB0</code> as a file (using file redirection and <code>cat</code>) seems to work fine:</p>
  
  <pre><code># initialize serial port
  stty 2000000 -ixon icanon &lt;/dev/ttyUSB0
  
  # check settings
  stty -a -F /dev/ttyUSB0
  
  # in one terminal - read from serial port
  while (true) do cat -A /dev/ttyUSB0 ; done
  
  # in other terminal - write to serial port
  echo "1234567890" &gt; /dev/ttyUSB0
  
  # back to first terminal, I now have:
  # $ while (true) do cat -A /dev/ttyUSB0 ; done
  # 1234567890$
  # ...
  </code></pre>
  
  <p>Now, I'd like to do something similar - I'd like to <code>cat</code> a file to a serial port, and have the serial port read back - but from a single terminal command (so I could use it as argument to <code>time</code>). </p>
  
  <p>I thought that I could use a Bash process substitution, to have the "writing" and "reading" part go, sort of, in "parallel" - if I try it with named pipes, it works:</p>
  
  <pre><code># mkfifo my.pipe # same as below:
  $ mknod my.pipe p
  
  $ comm &lt;(echo -e "test\ntest\ntest\n" &gt; my.pipe) &lt;(cat my.pipe)
      test
      test
      test
  comm: file 2 is not in sorted order
  </code></pre>
  
  <p>Up there, I'm not using <code>comm</code> for any other purpose, than to (sort of) merge the two processes into a single command (I guess, I could have just as well used <code>echo</code> instead). </p>
  
  <p>Unfortunately, that trick does not seem to work with a serial port, because when I try it, I sometimes get:</p>
  
  <pre><code>$ comm &lt;(echo "1234567890" &gt; /dev/ttyUSB0) &lt;(while (true) do cat -A /dev/ttyUSB0 ; done)
  cat: /dev/ttyUSB0: Invalid argument
  </code></pre>
  
  <p>..., however, usually I just get no output whatsoever. This tells me that: either there is no control of which process starts first, and so <code>cat</code> may start reading before the port is ready (however, that doesn't seem to be a problem in the first example above); or in Linux/Bash, you cannot both read and write to a serial port at the same time, and so the "<code>Invalid argument</code>" would occur in those moments when both read and write seem to happen at the same time. </p>
  
  <p>So my questions are:</p>
  
  <ul>
  <li>Is there a way to do something like this (<code>cat</code> a file to a serial port configured as loopback; read it back and see how long it takes) only in Bash, without resorting to writing a dedicated C program? </li>
  <li>If I need a dedicated C program, any source examples out there on the net I could use? </li>
  </ul>
  
  <p>Thanks a lot for any responses, </p>
  
  <p>Cheers! </p>
  
  <p>&nbsp;</p>
  
  <p>EDIT: I am aware that the <code>while</code> loop written above does not exit; that command line was for preliminary testing, and I interrupt it using Ctrl-C. ( <em>I could in principle interrupt it with something like <code>timeout -9 0.1 bash -c 'while (true) do echo AA ; done'</code>, but that would defeat the purpose of <code>time</code>, then :)</em> )</p>
  
  <p>The reason that <code>while</code> is there, is that for the time being, reading via <code>cat</code> from the device exits immediately; at times, I <em>have</em> set up the device, so that when <code>cat</code> is issued, it in fact blocks and waits for incoming data; but I cannot as of yet figure what's going on (and partially that is why I'm looking for a way to test from the command line). </p>
  
  <p>In case I didn't use the <code>while</code>, I imagine for timing, I'd use something like:</p>
  
  <p><code>time bash -c 'comm &lt;(echo "1234567890" &gt; /dev/ttyUSB0) &lt;(cat -A /dev/ttyUSB0)'</code></p>
  
  <p>... however for this to be working, sort of, assumes that <code>cat -A /dev/ttyUSB0</code> starts first and blocks; then the <code>echo</code> writes to the serial port (and exits); and then <code>cat -A</code> outputs whatever it read from the serial port - and then exits. (<em>And I'm not really sure neither if a serial port can behave this way at all, nor if <code>cat</code> can be made to block and exit arbitrarily like that</em>). </p>
  
  <p>The exact method really doesn't matter; if at all possible, I'd just like to avoid coding my own C program to do this kind of testing - which is why my primary interest is if it is somehow possible to run such a "full-duplex test" using basic Bash/Linux (i.e. <code>coreutils</code>); (<em>and if not, if there is a ready-made code I can use for something like this</em>). </p>
  
  <p>EDIT2: Also possibly relevant:</p>
  
  <ul>
  <li><a href="http://ubuntuforums.org/showthread.php?t=31339" rel="noreferrer">Parallel processes in Bash - Ubuntu Forums</a></li>
  </ul>