title: Reading and writing binary data over serial port
body: <p>So I searched around, and couldn't exactly find what I needed. I need help reading and writing binary data over a serial port, and would appreciate any advice you may have. Please note, I asked a question similar to this earlier when I was at a different stage of this project.</p>
  
  <p>Below are programs. The first program opens a file "test.jpg", reads it in binary mode and stores the result in a buffer. It then closes the file, and is supposed to send that file over a serial port.</p>
  
  <p>The second program creates a file called "testout.jpg", and is supposed to read in the data sent from the previous program.</p>
  
  <p>I have a hunch that the problem in my code lies in the second program. Perhaps I need to use fread for that too? I tried, but I cannot figure out how to implement it for a serial port as I am relatively new to programming.</p>
  
  <p>Many thanks for your time.</p>
  
  <p>Serial write:</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 */
      #include &lt;stdlib.h&gt;
  
      int main()
          {
                  //writing
                  int writeport = open_port("/dev/ttyUSB0");
  
                  //open file
  
                  FILE *file;
                  char *buffer;
                  int fileLen;
  
                  file = fopen("test.jpg", "rb");
  
                  //get file size
  
                  fseek(file, 0, SEEK_END);
                  fileLen = ftell(file);
                  fseek(file, 0, SEEK_SET);
  
                  buffer = (char *)malloc(fileLen + 1);
  
                  //read file contents
  
                  fread(buffer, fileLen, 1, file);
                  fclose(file);
  
                  int n = write(writeport, buffer, fileLen + 1);
                  if (n &lt; 0)
                          fputs("write() of bytes failed!\n", stderr);
  
                  //closing ports
                  close(writeport);
          }
  
          int open_port(char str[])
      {
          int fd = open(str, O_RDWR | O_NOCTTY | O_NONBLOCK); // ?? NDELAY or NONBLOCK?
  
        if (fd == -1)
        {
                          perror("open_port: Unable to open /dev/ttyS0 - ");
        }
        else
                          fcntl(fd, F_SETFL, 0);
  
            struct termios options;
            tcgetattr(fd, &amp;options); //this gets the current options set for the port
  
            // setting the options
  
            cfsetispeed(&amp;options, B9600); //input baudrate
            cfsetospeed(&amp;options, B9600); // output baudrate
            options.c_cflag |= (CLOCAL | CREAD); // ?? enable receicer and set local mode
            //options.c_cflag &amp;= ~CSIZE; /* mask the character size bits */
            options.c_cflag |= CS8;    /* select 8 data bits */
            options.c_lflag &amp;= ~(ICANON | ECHO | ECHOE | ISIG); // choosing raw input
            options.c_iflag &amp;= ~INPCK; // disable parity check
            options.c_iflag &amp;= ~(IXON | IXOFF | IXANY); // disable software flow control
            options.c_oflag |= OPOST; // ?? choosing processed output
            options.c_cc[VMIN] = 0; // Wait until x bytes read (blocks!)
            options.c_cc[VTIME] = 0; // Wait x * 0.1s for input (unblocks!)
  
            // settings for no parity bit
            options.c_cflag &amp;= ~PARENB;
            options.c_cflag &amp;= ~CSTOPB;
            options.c_cflag &amp;= ~CSIZE;
            options.c_cflag |= CS8;
  
            tcsetattr(fd, TCSANOW, &amp;options); //set the new options ... TCSANOW specifies all option changes to occur immediately
  
        return (fd);
      }
  </code></pre>
  
  <p>Serial read:</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 main()
          {
                  //reading      
                  int readport = open_port("/dev/ttyUSB1");
  
          //open resultant file
  
          FILE *file;
          //system("rm testout.jpg");
          file = fopen("testout.jpg", "wb");
  
                  //trying to read one character at a time
                  char buff;
                  int n = 1;
  
             while (n &gt; 0)
             {
                  n = read(readport, &amp;buff, 1);
                  //printf("%c", buff, buff);
  
                  **//I tried these three methods, with little success**
  
                  //fprintf(file, "%c", buff);
                  //fwrite(&amp;buff, 1, 1, file);
                  //write(file, &amp;buff, 1);
             }
  
                  //closing ports
                  close(readport);
                  fclose(file);
          }
  
          int open_port(char str[])
      {
          int fd = open(str, O_RDWR | O_NOCTTY | O_NONBLOCK); // ?? NDELAY or NONBLOCK?
  
        if (fd == -1)
        {
                          perror("open_port: Unable to open /dev/ttyS0 - ");
        }
        else
                          fcntl(fd, F_SETFL, 0);
  
            struct termios options;
            tcgetattr(fd, &amp;options); //this gets the current options set for the port
  
            // setting the options
  
            cfsetispeed(&amp;options, B9600); //input baudrate
            cfsetospeed(&amp;options, B9600); // output baudrate
            options.c_cflag |= (CLOCAL | CREAD); // ?? enable receicer and set local mode
            //options.c_cflag &amp;= ~CSIZE; /* mask the character size bits */
            options.c_cflag |= CS8;    /* select 8 data bits */
            options.c_lflag &amp;= ~(ICANON | ECHO | ECHOE | ISIG); // choosing raw input
            options.c_iflag &amp;= ~INPCK; // disable parity check
            options.c_iflag &amp;= ~(IXON | IXOFF | IXANY); // disable software flow control
            options.c_oflag |= OPOST; // ?? choosing processed output
            options.c_cc[VMIN] = 0; // Wait until x bytes read (blocks!)
            options.c_cc[VTIME] = 0; // Wait x * 0.1s for input (unblocks!)
  
            // settings for no parity bit
            options.c_cflag &amp;= ~PARENB;
            options.c_cflag &amp;= ~CSTOPB;
            options.c_cflag &amp;= ~CSIZE;
            options.c_cflag |= CS8;
  
            tcsetattr(fd, TCSANOW, &amp;options); //set the new options ... TCSANOW specifies all option changes to occur immediately
  
        return (fd);
      }
  </code></pre>