title: How to properly set up serial communication on Linux
body: <p>I'm attempting to read and write data from and to an FPGA board. The board itself came with a driver that create a terminal device called ttyUSB0 whenever the board is plugged in. On the FPGA, an asynchronous receiver and transmitter were implemented, and they seem to work.</p>
  
  <p>However, there seems to be an issue on C side of things. I've been using some test vectors to test if the FPGA is outputting the proper information. I've noticed a few things things:</p>
  
  <ol>
  <li>The device sometimes does not open correctly</li>
  <li>The terminal attributes sometimes fail to be retrieved or set.</li>
  <li>The read is sometimes non-blocking and doesn't retrieve the proper value.</li>
  </ol>
  
  <p>Below is how I set up terminal and file descriptor options. Much of it was taken from here: <a href="http://slackware.osuosl.org/slackware-3.3/docs/mini/Serial-Port-Programming">http://slackware.osuosl.org/slackware-3.3/docs/mini/Serial-Port-Programming</a></p>
  
  <p>Any advice or comments as to why the program may be failing would be greatly helpful.</p>
  
  <pre><code>#include &lt;stdio.h&gt;   // Standard input/output definitions
  #include &lt;string.h&gt;  // String function definitions
  #include &lt;unistd.h&gt;  // UNIX standard function definitions
  #include &lt;fcntl.h&gt;   // File control definitions
  #include &lt;errno.h&gt;   // Error number definitions
  #include &lt;termios.h&gt; // POSIX terminal control definitions
  
  int open_port(void){
  
      int fd;    // File descriptor for the port
      fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY);
  
      if (fd == -1){
          fprintf(stderr, "open_port: Unable to open /dev/ttyUSB0 %s\n",strerror(errno));
          exit(EXIT_FAILURE);
      }
  
      return (fd);
  }
  
  int main(void){
  
      int fd = 0;              // File descriptor
      struct termios options;  // Terminal options
  
      fd = open_port();    // Open tty device for RD and WR
  
      fcntl(fd, F_SETFL);            // Configure port reading
      tcgetattr(fd, &amp;options);       // Get the current options for the port
      cfsetispeed(&amp;options, B230400);    // Set the baud rates to 230400
      cfsetospeed(&amp;options, B230400);
  
      options.c_cflag |= (CLOCAL | CREAD);    // Enable the receiver and set local mode
      options.c_cflag &amp;= ~PARENB;             // No parity bit
      options.c_cflag &amp;= ~CSTOPB;             // 1 stop bit
      options.c_cflag &amp;= ~CSIZE;              // Mask data size
      options.c_cflag |=  CS8;                // Select 8 data bits
      options.c_cflag &amp;= ~CRTSCTS;            // Disable hardware flow control  
  
      // Enable data to be processed as raw input
      options.c_lflag &amp;= ~(ICANON | ECHO | ISIG);
  
      // Set the new attributes
      tcsetattr(fd, TCSANOW, &amp;options);
  
      ////////////////////////////////////
      // Simple read and write code here//
      ////////////////////////////////////
  
      // Close file descriptor &amp; exit
      close(fd)
      return EXIT_SUCCESS
  }  
  </code></pre>
  
  <p><strong>UPDATE</strong>
  I've modified my code based on the first answer. This is what I have now:</p>
  
  <pre><code>#include &lt;errno.h&gt;      // Error number definitions
  #include &lt;stdint.h&gt;     // C99 fixed data types
  #include &lt;stdio.h&gt;      // Standard input/output definitions
  #include &lt;stdlib.h&gt;     // C standard library
  #include &lt;string.h&gt;     // String function definitions
  #include &lt;unistd.h&gt;     // UNIX standard function definitions
  #include &lt;fcntl.h&gt;      // File control definitions
  #include &lt;termios.h&gt;    // POSIX terminal control definitions
  
  // Open usb-serial port for reading &amp; writing
  int open_port(void){
  
      int fd;    // File descriptor for the port
      fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY);
  
      if (fd == -1){
          fprintf(stderr, "open_port: Unable to open /dev/ttyUSB0 %s\n",strerror(errno));
          exit(EXIT_FAILURE);
      }
  
      return fd;
  }
  
  int main(void){
  
      int              fd = 0;     // File descriptor
      struct termios   options;    // Terminal options
      int              rc;         // Return value
  
      fd = open_port();            // Open tty device for RD and WR
  
      // Get the current options for the port
      if((rc = tcgetattr(fd, &amp;options)) &lt; 0){
          fprintf(stderr, "failed to get attr: %d, %s\n", fd, strerror(errno));
          exit(EXIT_FAILURE);
      }
  
      // Set the baud rates to 230400
      cfsetispeed(&amp;options, B230400);
  
      // Set the baud rates to 230400
      cfsetospeed(&amp;options, B230400);
  
      cfmakeraw(&amp;options);
      options.c_cflag |= (CLOCAL | CREAD);   // Enable the receiver and set local mode
      options.c_cflag &amp;= ~CSTOPB;            // 1 stop bit
      options.c_cflag &amp;= ~CRTSCTS;           // Disable hardware flow control
      options.c_cc[VMIN]  = 1;
      options.c_cc[VTIME] = 2;
  
      // Set the new attributes
      if((rc = tcsetattr(fd, TCSANOW, &amp;options)) &lt; 0){
          fprintf(stderr, "failed to set attr: %d, %s\n", fd, strerror(errno));
          exit(EXIT_FAILURE);
      }
  
      ////////////////////////////////
          // Simple Read/Write Code Here//
          ////////////////////////////////
  
      // Close file descriptor &amp; exit
      close(fd);
      return EXIT_SUCCESS;
  } 
  </code></pre>
  
  <p>Just to clarify, the receiver and transmitter use 8 data bits, 1 stop bit, and no parity bit.</p>