#include <stdio.h>
#include <fcntl.h>  /* manipulate file descriptor (POSIX) */
#include <unistd.h> /* for optget & write */
#include <stdlib.h> /* for atoi */
#include <string.h>
#include <signal.h>
#include <termios.h>

/* Bytes and float union */
union uchar_float_t {
  float f_data;
  unsigned char uc_data[4];
};

/* Default values */
const char * defport = "/dev/ttyUSB0";
const int defbaud = 115200;

/* Function prototypes */
void ctrc_handler(int);
int set_serial(int , int , struct termios * );

/* global variables */
unsigned char running = 1;

int main(int argc, char* argv[])
{
  char port[1024];
  int baudrate = defbaud;
  strcpy(port, defport);

  int opt;
  while((opt = getopt(argc, argv, "p:b:h")) != -1)
  {
    switch(opt)
    {
      case 'p':
        strcpy(port, optarg);
        break;
      case 'b':
        baudrate = atoi(optarg);
        break;
      case 'h':
        printf("USAGE: %s [option <argument>]\n", argv[0]);
        printf("  Where [option] can be:\n");
        printf("     -p <port>     : serial port device (default: %s)\n", defport);
        printf("     -b <baudrate> : serial port baudrate (default: %d)\n", defbaud);
        printf("     -h            : this help\n");
        return 0;
        break;
    }
  }

	signal(SIGINT, ctrc_handler);

  /* Open serial port */
  int fd = open(port, O_WRONLY | O_NOCTTY | O_SYNC);
  if(fd == -1)
  {
    printf("ERROR: opening serial port.\n");
    return -1;
  }

  struct termios tty;
  if(set_serial(fd, baudrate, &tty) == -1)
  {
    printf("ERROR: setting tty.\n");
    return -1;
  }

  while(running)
  {
  }

  printf("Closing the port...\n");
  close(fd);
  return 0;
}

void ctrc_handler(int sig)
{
  running = 0;
}

int set_serial(int fd, int baudrate, struct termios * tty)
{
  switch(baudrate)
  {
    case 115200: baudrate = B115200;
                 break;
    case 57600:  baudrate = B57600;
                 break;
    case 38400:  baudrate = B38400;
                 break;
    case 19200:  baudrate = B19200;
                 break;
    case 9600:   baudrate = B9600;
                 break;
    default:     baudrate = B115200;
                 break;
  }

  if(tcgetattr(fd, tty) != 0)
  {
    printf("ERROR: tcgetattr\n");
    return -1;
  }

  cfsetospeed(tty, baudrate);
  cfsetispeed(tty, baudrate);

  tty->c_cflag = (tty->c_cflag & ~CSIZE) | CS8;   // 8bits
  tty->c_iflag &= ~IGNBRK;                        // disable break processing
  tty->c_lflag = 0;                               // no signaling chars, no echo,
  tty->c_oflag = 0;                               // no remapping, no delays
  tty->c_cc[VMIN]  = 0;                           // read doesn't block
  tty->c_cc[VTIME] = 100;                         // read timeout

  tty->c_iflag &= ~(IXON | IXOFF | IXANY);        // shut off xon/xoff ctrl
  tty->c_cflag |= (CLOCAL | CREAD);               // ignore modem controls,
  tty->c_cflag &= ~(PARENB | PARODD);             // shut off parity
  tty->c_cflag |= 0;
  tty->c_cflag &= ~CSTOPB;
  tty->c_cflag &= ~CRTSCTS;

  if(tcsetattr(fd, TCSANOW, tty) != 0)
  {
    printf("ERROR: tcsetattr\n");
    return -1;
  }

  return 0;
}

