title: Serial ports writing/reading in linux
body: <p>I need to implement communication between two devices through serial ports on Raspberry Pi (with last Raspbian on board). Both uses CP2102 controller and connected to the Pi.</p>
  
  <p><a href="https://i.stack.imgur.com/USV7S.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/USV7S.jpg" alt="Data flow"></a></p>
  
  <p><strong>Terminal:</strong></p>
  
  <pre><code>pi@pi ~ $ ls -l /dev/serial/by-id
  total 0
  Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0 -&gt; ../../ttyUSB2
  
  pi@pi ~ $ ls -l /dev/serial/by-path
  total 0
  platform-bcm2708_usb-usb-0:1.2.1:1.0-port0 -&gt; ../../ttyUSB1
  platform-bcm2708_usb-usb-0:1.2.4:1.0-port0 -&gt; ../../ttyUSB2
  platform-bcm2708_usb-usb-0:1.3:1.0-port0 -&gt; ../../ttyUSB0
  </code></pre>
  
  <p>Normally when I send command to SERIAL A, Device A replies through SERIAL A and sends data through SERIAL B. After that I need to retranslate this data to Device B (SERIAL C) and receive answer from SERIAL C.</p>
  
  <p>The problem is that SERIAL A reply appears on SERIAL B and SERIAL B data appears on SERIAL A.</p>
  
  <p>I've tried different languages and serial libraries but the result is the same. So the questions are: why is it happening when using Raspberry Pi? How can I implement this functionality on Raspberry Pi?</p>
  
  <p>P.S. Both devices are working properly. My C# code works perfect. I used System.IO.Ports.SerialPort class for that implementation and it looks like Pi4J and RXTX solutions.</p>
  
  <p>P.P.S. Some code that I tried to use on RPi:</p>
  
  <p><strong><a href="http://wjwwood.io/serial/" rel="nofollow noreferrer">Serial</a>, C++:</strong> (very bad piece of code)</p>
  
  <pre><code>Serial port("/dev/ttyUSB2", 115200U);
  Serial port1("/dev/ttyUSB1", 115200U);
  port1.setTimeout(Timeout::max(), 250, 0, 250, 0);
  port.setTimeout(Timeout::max(), 250, 0, 250, 0);
  
  cout &lt;&lt; "Is the serial port open?";
  if (port1.isOpen()) {
      cout &lt;&lt; " Yes." &lt;&lt; endl;
      uint8_t data[2] = { 0xAA, 0x00 };
      port1.write(data, 2);
      data[1] = 0xFF;
      sleep(1);
      port1.write(data, 2);
      while (port.available() &lt; 7);
      int av = port.available();
      string ss;
      port.read(ss, av);
      for (int i = 0; i &lt; av; i++){
          cout &lt;&lt; (uint)ss.at(i) &lt;&lt; " ";
      }
      cout &lt;&lt; "av: " + (uint)av &lt;&lt; endl;
  }
  </code></pre>
  
  <p><strong>RXTX, Java:</strong></p>
  
  <pre><code>    public class Bridge_rxtx {
          public static final int baudrate = 115200;
  
          protected SerialPort spDevB_Data;
          SerialReader devB_DataListener;
  
          protected SerialPort spDevA_Data;
          SerialReader DevA_DataListener;
  
          protected SerialPort spDevA_Control;
          SerialPortEventListener DevA_ControlListener;
  
          public Bridge_rxtx(String comDevB_Data, String comDevA_Data, String comDevA_Control) {
              try {
              spDevB_Data = setupPort(comDevB_Data);
              spDevA_Data = setupPort(comDevA_Data);
              spDevA_Control = setupPort(comDevA_Control);
              } catch (Exception ignored){
                  ignored.printStackTrace();
              }
  
              try {
                  devB_DataListener = new SerialReader(spDevB_Data.getInputStream(), spDevA_Data.getOutputStream(), "B-A");
                  DevA_DataListener = new SerialReader(spDevA_Data.getInputStream(), spDevB_Data.getOutputStream(), "A-B");
                  DevA_ControlListener = new SerialPortEventListener() {
  
                      @Override
                      public void serialEvent(SerialPortEvent spe) {
                          throw new UnsupportedOperationException("Not supported yet.");
                      }
                  };
  
              spDevB_Data.notifyOnDataAvailable(true);
              spDevA_Data.notifyOnDataAvailable(true);
              spDevA_Control.notifyOnDataAvailable(true);
  
              } catch (IOException ex) {
                  Logger.getLogger(Bridge_rxtx.class.getName()).log(Level.SEVERE, null, ex);
              }
  
          }
  
          public void launchBridge(){
              System.out.println("Starting...");
              try {
                  spDevA_Control.getOutputStream().write(new byte[] {(byte)0xAA, (byte) 0x00}, 0, 2);
              } catch (IOException ex) {
                  Logger.getLogger(Bridge_rxtx.class.getName()).log(Level.SEVERE, null, ex);
              }
              try {
                  Thread.sleep(200);
              } catch (InterruptedException ex) {
                  Logger.getLogger(Bridge_rxtx.class.getName()).log(Level.SEVERE, null, ex);
              }
              try {
                  spDevA_Control.getOutputStream().write(new byte[] {(byte)0xAA, (byte) 0xFF}, 0, 2);
              } catch (IOException ex) {
                  Logger.getLogger(Bridge_rxtx.class.getName()).log(Level.SEVERE, null, ex);
              }
              System.out.println("Started");
          }
  
          SerialPort setupPort(String portName) throws Exception {
              SerialPort serialPort = null;
              CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
              if (portIdentifier.isCurrentlyOwned()) {
                  System.out.println("Error: Port is currently in use");
              } else {
                  CommPort commPort = portIdentifier.open(this.getClass().getName(), 2000);
                  if (commPort instanceof SerialPort) {
                      serialPort = (SerialPort) commPort;
                      serialPort.setSerialPortParams(baudrate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
                  } else {
                      System.out.println("Error: Only serial ports are handled by this code.");
                  }
              }
              return serialPort;
          }
  
          public static void main(String[] args) {
              Bridge_rxtx bridge = new Bridge_rxtx("/dev/ttyUSB0", "/dev/ttyUSB2", "/dev/ttyUSB1");
              bridge.launchBridge();
          }
      }
  </code></pre>
  
  <p><strong>Pi4J, Java:</strong></p>
  
  <pre><code>public class Bridge {
      public static Bridge instance;
  
      public static final int baudrate = 115200;
  
      protected Serial spDevB_Data;
      SerialDataListener devB_DataListener;
  
      protected Serial spDevA_Data;
      SerialDataListener devA_DataListener;
  
      protected Serial spDevA_Control;
      SerialDataListener devA_ControlListener;
  
      private Bridge() {
  
      }
      public Bridge(String comDevB_Data, String comDevA_Data, String comDevA_Control) {
          instance = this;
  
          devA_ControlListener = new SerialDataListener() {
          //SerialDataEvent in Pi4J doesn't support binary
          //data by default. I implemented this myself.
              public void dataReceived(SerialDataEvent event) {
                  System.out.println(bytesToHex(toPrimitives(event.getBinaryData())));
              }
  
          };
          devB_DataListener = new SerialDataListener() {
              public void dataReceived(SerialDataEvent event) {
                  byte[] data = toPrimitives(event.getBinaryData());
                  instance.spDevA_Data.write(data);
                  System.out.println("B -&gt; A: " + bytesToHex(data));
              }
  
          };
          devA_DataListener = new SerialDataListener() {
              public void dataReceived(SerialDataEvent event) {
                  byte[] data = toPrimitives(event.getBinaryData());
                  instance.spDevB_Data.write(data);
                  try {
                      Thread.sleep(15);
                  } catch (InterruptedException ex) {
                      Logger.getLogger(Bridge.class.getName()).log(Level.SEVERE, null, ex);
                  }
                  System.out.println("B &lt;- A: " + bytesToHex(data));
              }
  
          };
  
          spDevB_Data = SerialFactory.createInstance();
          spDevB_Data.addListener(devB_DataListener);
  
          spDevA_Data = SerialFactory.createInstance();
          spDevA_Data.addListener(devA_ControlListener);
  
          spDevA_Control = SerialFactory.createInstance();
          spDevA_Control.addListener(devA_DataListener);
  
  
          spDevB_Data.setMonitorInterval(40);
          spDevA_Data.setMonitorInterval(80);
          spDevA_Control.setMonitorInterval(25);
  
          spDevB_Data.open(comDevB_Data, baudrate);
  
          spDevA_Data.open(comDevA_Data, baudrate);
          spDevA_Control.open(comDevA_Control, baudrate);
  
      }
  
      public void SetupBridge() {
          spDevA_Control.write(new byte[]{(byte) 0xAA, (byte) 0x00});
          try {
              Thread.sleep(20);
          } catch (InterruptedException ex) {
              Logger.getLogger(Bridge.class.getName()).log(Level.SEVERE, null, ex);
          }
          spDevA_Control.write(new byte[]{(byte) 0xAA, (byte) 0xFF});
      }
  }
  </code></pre>