#include <aspoutil.h>
#include <aspoprotocol.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

#define LOG_BUFSZ 200
const size_t log_bufsz = LOG_BUFSZ;
char log_buffer[LOG_BUFSZ];

/****************************/

#define TIME 100000

uint8_t req[S6400_MAXREQLEN];
#define RESSZ 4000
uint8_t res[RESSZ];
struct termios ttysave;
int fd = -1;
char *dev;
static uint32_t reader;
static struct openraw_t opts = { 8, 0, 1, 1, 0, };

/****************************/

static void Usage(void) {
  printf("Usage:\n\t%s serial_port\n", cmdline_pgm);
  exit(1);
}

static void Close(void) {
  /*NOTICE("Stopping %s", cmdline_pgm); */
  LOG_VIF( (fd = tty_close(fd, &ttysave, dev, opts.pid)) < 0, LOG_ERR, " dev = %s fd = %d", dev, fd) { }
}

static int doio(const void *obuf, size_t olen, void *ibuf, ssize_t ilen ) {
  ssize_t ret;
  uint16_t code;
  const char *err1;
  const char *err2;

  LOG_IF( tcflush(fd, TCIOFLUSH) < 0, LOG_ERR) { }
  LOG_IF( (ret = tty_write(fd, obuf, olen) != (ssize_t) olen), LOG_NOTICE) return -1;
  /*s6400_prpkg("out ", obuf, olen); */
  /* sending 15 bytes and receiving 22 bytes takes about 1ms, so the delay is for reader tag processing */
  usleep(TIME); /* this don't check for signal interruptions */
  bzero( ibuf, ilen);  
  LOG_IF( (ret = tty_read(fd, ibuf, ilen)) < 0, LOG_ERR) return -1;
  /*s6400_prpkg("in  ", ibuf, ret); */

  if (!ret) {
    /*s6400_prpkg("no response for", obuf, olen); */
    return 0;
  }
  if (s6400_validate(ibuf, ret)   < 0) goto doio_err;
  if (s6400_check_error_res(ibuf, &code, &err1, &err2) < 0 || code) {
    if (code == 0x0201) return 0; /* no transponder found */
    if (code == 0x0206) return 0; /* for some reasons, sometimes tag crc error is reported */
    (void) s6400_check_error_report(code, err1, err2);
    goto doio_err;
  }

  return ret;

doio_err:
  s6400_prpkg("doio req: ", obuf, olen);
  s6400_prpkg("doio res: ", ibuf, ret);
  return -1;
}

int main(int argc, char *argv[]) {
  int val;
  int baudrate = B38400;
  /*sigset_t unblock_set; */

  (void) cmdline_extrpgm(argv);
  log_open("", LOG_PRIO | 2, 0); /* log to stdout */
  if (argc != 2) Usage();
  dev = argv[1];

  LOG_VIF( (fd = tty_openraw(&ttysave, dev, baudrate, &opts)) < 0, LOG_ERR, " dev = %s", dev ) Usage();
  LOG_IF( setvbuf(stdout, (char *) NULL, _IOLBF, 0), LOG_NOTICE) { } /* too bad, but we'll continue */

  if (argc == 2) {
    val = s6400_reader_version_req( req, S6400_MAXREQLEN, 0);
    LOG_IF( doio(req, (size_t) val, res, RESSZ) < 0, LOG_ERR) return -1;
    LOG_IF( s6400_reader_version_res(res, NULL, NULL, &reader), LOG_ERR) return -1;
    printf("%07u\n", reader);
    fflush(stdout);
  }

  Close();
  return 1;
}
