/*
 * rawserial.c -- Machine/OS dependent serial I/O code
 *
 *  Copyright 1997 (unix code)  John E. Stone (j.stone@acm.org)
 *
 *  $Id: rawserial.c,v 1.4 1998/02/18 13:20:08 johns Exp $
 *
 */

/*
 * Unix serial I/O code by John Stone
 */

#define _POSIX_SOURCE 1

#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include "rawserial.h" /* protos and types for this file */

typedef struct {
  int fd;        /* serial port device file descriptor */
} commstruct;


int comm_open(char * commname, int speed, CommHandle * commhandleptr, int *iofd) {
  struct termios orbtermio;
  commstruct * comm;
  speed_t speedflag;

  *commhandleptr = NULL;
  *iofd = -1;

  switch (speed) {
    case 38400: 
      speedflag = B38400;
      break;

    case 19200:
      speedflag = B19200;
      break;

    case 9600:
      speedflag = B9600;
      break;
   
    default: 
      return -1;
  }

  comm = malloc(sizeof(commstruct));
  if (comm == NULL)
    return -1;

  comm->fd = open(commname, O_RDWR | O_NOCTTY);

  if (comm->fd == -1) {
    free(comm);
    return -1;  /* failed open of comm port */
  }
  tcgetattr(comm->fd, &orbtermio);

  orbtermio.c_lflag = 0;
  orbtermio.c_lflag = NOFLSH;
  orbtermio.c_iflag = IGNBRK | IGNPAR;
  orbtermio.c_oflag = 0;
  orbtermio.c_cflag =  CREAD | CSIZE | CS8 | CLOCAL | HUPCL;
  orbtermio.c_cc[VEOL] = '\r';
  orbtermio.c_cc[VERASE] = 0;
  orbtermio.c_cc[VKILL] = 0;
  orbtermio.c_cc[VMIN] = 0;
  orbtermio.c_cc[VTIME] = 0;

  cfsetispeed(&orbtermio, speedflag);
  cfsetospeed(&orbtermio, speedflag);

  tcsetattr(comm->fd, TCSAFLUSH, &orbtermio);

  *commhandleptr = (CommHandle) comm;

  *iofd = comm->fd; 

printf("comm iofd: %d\n", comm->fd);

  return 0;
}


int comm_write(CommHandle commhandle, char * buf, int sz) {
  commstruct * comm = (commstruct *) commhandle;

  return write(comm->fd, buf, sz);
}


int comm_read(CommHandle commhandle, char * buf, int sz) {
  commstruct * comm = (commstruct *) commhandle;

  return read(comm->fd, buf, sz);
}


int comm_close(CommHandle * commhandleptr) {
  commstruct * comm = (commstruct *) (*commhandleptr);

  if (comm == NULL)
    return -1;

  close(comm->fd);

  free(*commhandleptr);
  *commhandleptr = NULL;

  return 0;
}


