/***********************************
 ** Aleksander Adamowski (s1869)  **
 ** pon lip 5 14:29:12 CEST 2004  **
 ***********************************/

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h> /* File control definitions */
#include <errno.h>
#include <termios.h> /* POSIX terminal control definitions */
#include <sys/ioctl.h>

/*#define DEBUG*/
/*#undef DEBUG*/

#define BUFSIZE 256
char* devname;
int uchwytp; /* Deskryptor pliku dla portu */
size_t bufsize = BUFSIZE;
/* Bufor odczytu */
char rbuf[BUFSIZE];
/* Bufor zapisu */
char wbuf[BUFSIZE];
struct termios stareustawienia;
/* int baud = B57600;*/
int baud = B9600;

int otworzport(void) {
   uchwytp = open(devname, O_RDWR | O_NOCTTY | O_NDELAY);

   return uchwytp;
}

int skonfigurujport() {
  struct termios noweustawienia;
  int databits = CS8;

  /* Wylaczyc blokujace Wejscie/wyjscie: */
  fcntl(uchwytp, F_SETFL, FNDELAY);
  /* fcntl(uchwytp, F_SETFL, FASYNC);*/

  tcgetattr(uchwytp, &stareustawienia); 

  memset(&noweustawienia, 0, sizeof(noweustawienia));
  noweustawienia.c_cflag = baud | databits | CLOCAL | CREAD ;
  noweustawienia.c_iflag = IGNPAR;
  /* Brak przetwarzania wyjscia: */
  noweustawienia.c_oflag = 0;
  noweustawienia.c_lflag = 0;

  tcflush(uchwytp, TCIFLUSH);
  tcsetattr(uchwytp, TCSANOW, &noweustawienia);

}

int zdekonfigurujport() {
  tcflush(uchwytp, TCIFLUSH);
  tcsetattr(uchwytp, TCSANOW, &stareustawienia);
}

/* Obsluz odczyt z portu */
ssize_t obsluzOdczyt(void) {
  ssize_t readcount = 0;
  ssize_t writtencount;
  int iloscRBuf;

  ioctl(uchwytp, FIONREAD, &iloscRBuf);
  if (iloscRBuf > 0) {
    readcount = read(uchwytp, &rbuf, bufsize);
    if (readcount > 0) {
#ifdef DEBUG
      fprintf(stderr, "Odczytano z portu: %d\n", readcount);
#endif
      writtencount = write(1, &rbuf, readcount);
#ifdef DEBUG
      fprintf(stderr, "Zapisano na std wyjscie: %d\n", writtencount);
#endif
    }
  }
  return readcount;
}

/* Obsluz zapis do portu */
void obsluzZapis(void) {
  ssize_t readcount;
  ssize_t writtencount;
  int iloscWBuf;

  ioctl(uchwytp, TIOCOUTQ, &iloscWBuf);
  /* Zaczynamy pisac dalsze dane tylko jesli bufor wyjscia juz jest pusty: */
  if (iloscWBuf <= 0) {
    /* Czytanie z STDIN: */
    readcount = read(0, &wbuf, bufsize);
    if (readcount > 0) {
#ifdef DEBUG
      fprintf(stderr, "Odczytano z std wejscia: %d\n", readcount);
#endif
      writtencount = write(uchwytp, &wbuf, readcount);
      /* writtencount = zapiszDoPortu(&wbuf, readcount); */
#ifdef DEBUG
      fprintf(stderr, "Zapisano do portu: %d\n", writtencount);
#endif
    }
  }
}

ssize_t zapiszDoPortu(char* wbuf, ssize_t bufcount) {
  ssize_t checkcount = 0;
  ssize_t writtencount;
  /* Zapisuj do portu az oprozni sie bufor */
  while (checkcount < bufcount) {
    writtencount = write(uchwytp, wbuf + checkcount, bufcount - checkcount);
    checkcount += writtencount;
  }
  return checkcount;
}

int main(int argc, char* argv[]) {
  char* baudname;

  if (argc < 2) {
    devname = "/dev/ttyS0";
  } else {
    devname = argv[1];
  }
#ifdef DEBUG
  fprintf(stderr, "Nazwa urzadzenia: %s\n", devname);
#endif
  if (argc > 2) {
    baudname = argv[2];
#ifdef DEBUG
    fprintf(stderr, "baudname: %s\n", baudname);
#endif
    if (strncmp(baudname, "300", 8) == 0) {
      baud = B300;
    } else if (strncmp(baudname, "600", 8) == 0) {
      baud = B600;
    } else if (strncmp(baudname, "1200", 8) == 0) {
      baud = B1200;
    } else if (strncmp(baudname, "2400", 8) == 0) {
      baud = B2400;
    } else if (strncmp(baudname, "4800", 8) == 0) {
      baud = B4800;
    } else if (strncmp(baudname, "9600", 8) == 0) {
      baud = B9600;
#ifdef DEBUG
      fprintf(stderr, "ustawiam B9600: %d\n", baud);
#endif
    } else if (strncmp(baudname, "19200", 8) == 0) {
      baud = B19200;
#ifdef DEBUG
      fprintf(stderr, "ustawiam B19200: %d\n", baud);
#endif
    } else if (strncmp(baudname, "38400", 8) == 0) {
      baud = B38400;
    } else if (strncmp(baudname, "57600", 8) == 0) {
      baud = B57600;
    } else if (strncmp(baudname, "115200", 8) == 0) {
      baud = B115200;
    } else {
      fprintf(stderr, "nieznana szybkosc portu: %s\n", baudname);
    }
  }
  uchwytp = otworzport();
  skonfigurujport();
  fcntl(0, F_SETFL, FNDELAY);

  while (1) {
    obsluzOdczyt();
    obsluzZapis();
    /* Uspienie na 1/100 sek. */
    usleep(10000);
  }
  /* printf("%s\n", rbuf); */
  /* Tu reszta... */
  zdekonfigurujport();
  close(uchwytp);
  return 0;
}

