/*****************************************************************************
 * Copyright (c) 2005  Daniel Lerch Hostalot <http://daniellerch.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a 
 * copy of this software and associated documentation files (the "Software"), 
 * to deal in the Software without restriction, including without limitation 
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 
 * and/or sell copies of the Software, and to permit persons to whom the 
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in 
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 * DEALINGS IN THE SOFTWARE.
 ****************************************************************************/


#include "serial.h"

#include <stdlib.h>
#include <stdio.h>

serial_t* serial_new(char* device) 
{
   int status=0;

   /* Reservamos memoria para el objeto */
   serial_t* obj = malloc(sizeof(serial_t));
   if (!obj) {

      fprintf(stderr, "malloc(): no es posible reservar memoria\n");
      exit(EXIT_FAILURE);
   }

   /* Abrimos el dispositivo */
   obj->fd = open(device, O_RDWR | O_NDELAY);
   if (obj->fd < 0) {

      free(obj);
      fprintf(stderr, "Error al abrir el dispositivo %s\n", device);
      exit(EXIT_FAILURE);
   }

   /* Inicializamos todos los pines del puerto serie a cero */
   ioctl(obj->fd, TIOCMSET, &status);

   return obj;
}


void serial_free(serial_t* obj)
{
   if (obj) free(obj);
}

int serial_get_DCD_status(serial_t* obj)
{
   int state;

   ioctl(obj->fd, TIOCMGET, &state);

   if (state & TIOCM_CAR) return (1);
   else return (0);
}

int serial_get_DSR_status(serial_t* obj)
{
   int state;

   ioctl(obj->fd, TIOCMGET, &state);

   if (state & TIOCM_DSR) return (1);
   else return (0);
}

int serial_get_CTS_status(serial_t* obj)
{
   int state;

   ioctl(obj->fd, TIOCMGET, &state);

   if (state & TIOCM_CTS) return (1);
   else return (0);
}


void serial_set_TXD_status(serial_t* obj, int value) /* ST */
{
   int status;

   /*
    * Este pin funciona la reves de los demas. Cuando se hace SET se pone
    * a voltaje negativo y cuando se hace clear a voltaje positivo. Por lo
    * que igualamos el funcionamiento al de los demas pines realizando SET
    * cuando value=0 y clear cuando value=1.
    */   
   if (value==0) ioctl(obj->fd, TIOCSBRK, &status);
   else ioctl(obj->fd, TIOCCBRK, &status);
}

void serial_set_DTR_status(serial_t* obj, int value) 
{
   int status;

   status = 0;
   status |= TIOCM_DTR;

   if (value==0) ioctl(obj->fd, TIOCMBIC, &status);
   else ioctl(obj->fd, TIOCMBIS, &status);
}

void serial_set_RTS_status(serial_t* obj, int value)
{
   int status;

   status = 0;
   status |= TIOCM_RTS;

   if (value==0) ioctl(obj->fd, TIOCMBIC, &status);
   else ioctl(obj->fd, TIOCMBIS, &status);
}






