/***************************************************************************
                          bootstrap555.cc  -  description
                             -------------------
    begin                : lun déc 22 2003
    copyright            : (C) 2003 by Alain Gibaud
    email                : alain.gibaud@univ-valenciennes.fr
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#include "bootstrap555.hh"
#include "hardware.hh"

#include <errno.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

bootstrap555::bootstrap555(): fd(-1)
{
}
bootstrap555::~bootstrap555()
{
    close() ;
}
/** Allocate and open the serial port
The status of this operation can be tested with isok() */
void bootstrap555::setport(const char *device)
{
    fd = open (device, O_RDWR|O_NOCTTY|O_NONBLOCK) ;
    if(fd == -1 )
    {
        char buf[300] ;
        sprintf(buf,"serial port %.150s must be RW enabled.", device) ;
        perror(buf) ;
        return ;
    }

    tcgetattr (fd, &current_state);
    old_state = current_state ;
    current_state.c_iflag = IGNBRK | IGNPAR;
    current_state.c_oflag = 0;
    current_state.c_cflag = B4800 | CS8 | CREAD | CLOCAL;
    current_state.c_lflag = 0;
    tcsetattr(fd, TCSANOW, &current_state);

}
/** No descriptions */
bool bootstrap555::isok()
{
    return fd != -1 ;
}
/** No descriptions */
void bootstrap555::close()
{
    if(fd != -1)
    {
        ioctl (fd, TIOCCBRK, 0);
        hardware::waitus (1);
        tcsetattr (fd, TCSANOW, &old_state);

        ::close(fd) ; fd = -1 ;
    }
}
/** set the specified pin low */
void bootstrap555::bitoff(int pin)
{
    unsigned char c=0xc0;

    if( pin < 0)
    {
        biton(-pin) ;
        return ;
    }
    int the_bit ;
    if(pin == 3) // TX
    {
        write(fd,&c,1);
        read(fd,&c,1) ;
        fprintf(stderr,"bitoff: read %02x\n",c);
        return ;
    }
    else if(pin == 4)  // DTR
    {
        the_bit = TIOCM_DTR;
    }
    else if(pin == 6)  // DSR
    {
        the_bit = TIOCM_DSR;
    }
    else if(pin == 7)  // DSR
    {
        the_bit = TIOCM_RTS;
    }
    else
    {
        return ; // not an output pin .
    }
    if( ioctl (fd, TIOCMBIC, &the_bit) == -1)
    {
        perror("void bootstrap555::bitoff(int pin)") ;
    }
}
/** See bitoff(int) */
void bootstrap555::biton(int pin)
{
    unsigned char c=0xc0;
    if( pin < 0)
    {
        bitoff(-pin) ;
        return ;
    }
    int the_bit ;
    if(pin == 3) // TX
    {
        write(fd,&c,1);
        read(fd,&c,1)  ;
        fprintf(stderr,"bitoff: read %02x\n",c);
        ; return ;
    }
    else if(pin == 4)  // DTR
    {
        the_bit = TIOCM_DTR;
    }
    else if(pin == 6)  // DSR
    {
        the_bit = TIOCM_DSR;
    }
    else if(pin == 7)  // DSR
    {
        the_bit = TIOCM_RTS;
    }
    else
    {
        return ; // not an output pin .
    }
    if( ioctl (fd, TIOCMBIS, &the_bit) == -1)
    {
        perror("void bootstrap555::bitoff(int pin)") ;
    }
}
/** No descriptions */
int bootstrap555::readbit(int rpin)
{
    unsigned char c=0xff;

    int bits , mask, pin  = rpin < 0 ? -rpin : rpin ;

    if(pin == 1)
        mask =  TIOCM_CD ;
    else if(pin == 2) {
        write(fd,&c,1);
        read(fd,&c,1) ;
        fprintf(stderr,"bitoff: read %02x\n",c);
        return c;
    }
    else if(pin == 8)
        mask =  TIOCM_CTS ;
    else if(pin == 9)
        mask =  TIOCM_RI ;
    else
        mask = 0 ;

    if( 	ioctl (fd, TIOCMGET, &bits) == -1)
    {
        perror("int bootstrap555::readbit(int pin)") ; return 0 ;
    }
    return ( ((rpin<0) ? ~bits : bits) & mask) ;
}

/** No descriptions */
const char * bootstrap555::inputPinsList()
{
    return "1 (CD),2 (RX),8 (CTS),9 (RI)" ;
}
/** No descriptions */
const char * bootstrap555::outputPinsList()
{
    return "3 (TX),4 (DTR),6 (DSR),7 (RTS),5 (NA)" ;
}
/** Probes the port pname

\return
0 = the port is present on the system and is RW enabled
-1 = port present but not RW enabled
-2 = not present
  */
int bootstrap555::probePort(const char *device)
{
    int id ;
    id = open (device, O_RDONLY|O_NOCTTY|O_NONBLOCK) ;
    if(id == -1 )
    {
        return -2 ;
    }
    ::close(id) ;

    id = open (device, O_RDWR|O_NOCTTY|O_NONBLOCK) ;
    if(id == -1 )
    {
        return -1 ;
    }
    ::close(id) ;
    return 0 ;
}
