/*
 * $Id: phase3.c,v 1.2 2001/01/10 20:46:31 oe1kib Exp $
 *
 * Copyright (C) 1994-2000 Klaus Kudielka
 *
 * Read telemetry blocks from serial line and write them to stdout.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */


#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <string.h>
#include "crc16.h"


/* Compile-time constants */

#define CC_VMIN  200     /* chars to receive before read is satisfied */


/* Global variables */

int block_length, tty, ok = 0, badlen = 0, badcrc = 0;


/* Function declarations */

void handler(int);
int open_tty(char *name);
void close_tty(int fd);
int main(int argc, char **argv);


/* Signal handler */

void handler(int s) {
  time_t t;

  close_tty(tty);

  time(&t);
  fprintf(stderr, "%d ok, %d bad length", ok, badlen);
  if (block_length == 514) fprintf(stderr, ", %d bad crc", badcrc);
  fprintf(stderr, "\nend %s\n", ctime(&t));

  exit(0);
}


int open_tty(char *name) {
  int fd, line;
  struct termios tios;

  fd = open(name, O_RDONLY | O_NOCTTY);
  if (fd == -1) {
    fprintf(stderr, "error: could not open %s for reading.\n", name);
    return -1;
  }
  if (ioctl(fd, TCGETS, &tios)) {
    fprintf(stderr, "error: could not get terminal parameters.\n");
    close(fd);
    return -1;
  }
  tios.c_iflag = 0;
  tios.c_cflag = B1200 | CS8 | CREAD | CLOCAL;
  tios.c_lflag = 0;
  tios.c_cc[VMIN] = CC_VMIN;
  tios.c_cc[VTIME] = 5;
  if (ioctl(fd, TCSETS, &tios)) {
    fprintf(stderr, "error: could not set terminal parameters.\n");
    close(fd);
    return -1;
  }
  line = TIOCM_DTR | TIOCM_RTS;
  if (ioctl(fd, TIOCMBIS, &line)) {
    fprintf(stderr, "error: could not set modem control lines.\n");
    close(fd);
    return -1;
  }
  return fd;
}


void close_tty(int fd) {
    int line = TIOCM_DTR | TIOCM_RTS;

    if (ioctl(fd, TIOCMBIC, &line)) {
      fprintf(stderr, "warning: could not clear modem control lines.\n");
    }
    close(fd);
}


/* Main program */

int main(int argc, char **argv) {
  size_t	n = 0, bytes_read = 0;
  char		block[1024];
  time_t	t;
  crc16_t       crc;
  crc16_table_t table;

  signal(SIGINT, handler);
  signal(SIGTERM, handler);

  if (argc == 2) {
    block_length = 514;
    crc16_init(CCITT_CRC16, table);
  } else if (argc == 3 && !strcmp(argv[1], "--no-crc")) {
    block_length = 512;
  } else {
    fprintf(stderr,
	    "usage: %s [--no-crc] <device>\n",
	    argv[0]);
    return 1;
  }
   
  tty = open_tty(argv[argc-1]);
  if (tty == -1) return 2;

  time(&t);
  fprintf(stderr, "start %s", ctime(&t));

  while (1) {
    if (bytes_read > 0 && n < CC_VMIN) {
      time(&t);
      if (bytes_read == block_length) {
	if (block_length == 514) {
	  crc = crc16(block, 514, 0xffff, table);
	} else {
	  crc = 0;
	  block[0] |= 0x80;
	  block[1] |= 0x80;
	}
        if (crc == 0) {
	  ok++;
	  fprintf(stderr, "ok %s", ctime(&t));
	} else {
	  badcrc++;
	  fprintf(stderr, "crc=0x%04X %s", (int) crc, ctime(&t));
	  block[0] |= 0x80;
	}
	fwrite(block, 512, 1, stdout);
	fflush(stdout);
      } else {
	badlen++;
        fprintf(stderr, "length=%d %s", bytes_read, ctime(&t));
      }
      bytes_read = 0;
    }  
    n = read(tty, block+bytes_read, sizeof(block)-bytes_read);
    bytes_read += n;
  }

}

