/* ======================================================================
**
** GeoMag Generic I/O Communications
**	open_io_port
**
** io.c - SL 12/2001
**
** History:
**       Date     Who      Description
**       ------   ---      --------------------------------------------
**      12/2000   SL       Create - wrapper for opening serial/network IO
**      04/2001   JCH      Added IO_TYPE_BOTH
**   07/06/2003   SL       Update for GeoMag - stripped-out network IO and
**                         renamed to serial_io.c
** ======================================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>    /* UNIX standard function definitions */
#include <fcntl.h>     /* file control definitions           */
#include <termios.h>   /* POSIX terminal control definitions */

#include "serial_io.h"
#include "debug.h"


//---------------------------------------------------------------------------
//
// void init_io_cfg() -- zero's out data structure and sets default
//                       values
//
//---------------------------------------------------------------------------
void init_io_cfg(io_cfg_t *io)
{
  memset(io,0,sizeof(io_cfg_t));

  strcpy(io->port_str,"**NOT initialized***");
  io->port       = '\0';
  io->port_fd    = -1; 
  io->block      = 1;    // 0 for non-blocking
  io->baud       = 9600;
  io->parity     = 'N';
  io->nbits      = 8;
  io->sbits      = 1;
  io->flowctl    = 0;    //0-none
  io->canonical  = 1;    //1-canonical, 0-raw
  io->terminator = '\n'; //not implemented yet
  io->vtime      = 0;    //time to wait - tenths of a second
  io->vmin       = 1;    //min chars to read
  io->vlevel     = ERR;  //ERR,WNG,MSG,DBG,DBG1,DBG2,DBG3

  return;
}


//---------------------------------------------------------------------------
//
// int open_io_port() -- Open serial io port (stripped-out network stuff).Sets 
//                       port characteristics. Updates io_cfg structure (ie; fd)
//                       and Returns 1-OK, 0-error
//
//---------------------------------------------------------------------------
int open_io_port(io_cfg_t *io)
{
   int flags = O_RDWR | O_NOCTTY;

     /*--------------------------------------------------------------------*
      * O_RDWR:    open port for reading and writing                       *
      * O_NOCTTY:  specifies program won't be controlling entity for port  *
      * O_NDELAY:  open() cmd doesn't block, (doesn't care if other port   *
      *            is opened or not)                                       *
      *--------------------------------------------------------------------*/
      if (io->block == 0) flags |= (O_NONBLOCK | O_NDELAY);
      io->port_fd = open(io->port, flags);
      if (io->port_fd == -1)
        {char err_str[80];
         sprintf(err_str,"open_port failed: Unable to open %s",io->port);
         DPRINTF(ERR,io->vlevel,err_print(errno,err_str));
         return(0);
         }

      //If not blocking, set to non-blocking via fctl call
      if (io->block == 0) fcntl(io->port_fd, F_SETFL, FNDELAY);
      DPRINTF(MSG,io->vlevel,printf("Opened port %s [fd=%d]\t\t\t\t\t\t[serial.c]\n",
             io->port, io->port_fd));

      sprintf(io->port_str, "Type: SERIAL  Port: %s  fd=%d",io->port,io->port_fd);
      
      //Now set port characteristics
      set_serial_port(io);

   return(1);
  
}



//---------------------------------------------------------------------------
//
// int read_io_port() -- read serial io port (stripped-out UDP network stuff)
//                       Returns n-bytes read or -1 if error
//
//---------------------------------------------------------------------------
int read_io_port(io_cfg_t *io, char *buf, int buf_len, int vlevel)
{
  return(read_port(io->port_fd, buf, buf_len, vlevel));
}


//---------------------------------------------------------------------------
//
// int write_io_port() -- write serial io port (stripped-out UDP network stuff)
//                        Returns n-bytes written or -1 if error
//
//---------------------------------------------------------------------------
int write_io_port(io_cfg_t *io, char *buf, int buf_len, int vlevel)
{
  return(write_to_port(io->port_fd, buf, buf_len, vlevel));

}


//---------------------------------------------------------------------------
//
// int close_io_port() -- close serial io port (stripped-out network stuff)
//                        Returns results from close()
//
//---------------------------------------------------------------------------
int close_io_port(io_cfg_t *io)
{
  close_port(io->port_fd, io->vlevel);
  return(1);
}



//---------------------------------------------------------------------------
//
// int valid_io_descriptor() -- Depending on IO type, checks that fd or 
//                              sock is valid (ie; not -1). Stripped-out 
//				network stuff
//                        Returns 1-OK, 0-error
//
//---------------------------------------------------------------------------
int valid_io_descriptor(io_cfg_t *io)
{
  if (io->port_fd == -1) return 0;
                    else return 1;
}


