/***************************************************************************
                          serialport.cpp  -  description
                             -------------------
    begin                : Thu May 2 2002
    copyright            : (C) 2002 by Argo Vessmann (ARTEC Design)
    email                : 
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 "serialport.h"

#include <stdlib.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

#include <qstringlist.h>

SerialPort::SerialPort(){
	_isnetmosport = FALSE;
	_systemport = FALSE;
	detected = FALSE;
}
SerialPort::~SerialPort(){
}

/** Set's all values to NULL */
void SerialPort::clean()
{
	io = 0;
	irq = 0;
	uart = "";
	baud = 0;
	port = 0;
	_isnetmosport = FALSE;
}

/** Creats a listview item into listview parent */
void SerialPort::newListViewItem( QListView *parent )
{
	QString lname, dname;

	dname.sprintf( "COM%i", port+1 );
	lname.sprintf( "/dev/ttyS%02i", port );
	new QListViewItem( parent, lname, dname, QString::number( io, 16 ).upper(), \
			QString::number( irq ), QString::number( baud ) );
}

QString SerialPort::InfoStrForNewt()
{
	QString lname, dname;
	QString resp;

	dname.sprintf( "COM%-2i   ", port+1 );
	lname.sprintf( "/dev/ttyS%02i   ", port );
	resp = lname;
	resp += dname;
	resp += QString::number( io, 16 ).upper();
	resp += "   ";
	resp += QString::number( irq );
	resp += "   ";
	resp += QString::number( baud );

	return resp;
}

/** Returns serial ports device name "/dev/ttySx" */
QString SerialPort::DevName()
{
	QString dname;

	dname.sprintf( "/dev/ttyS%i", port );

	return( dname );
}

/** Mark this prot as used by NetMos Card */
void SerialPort::setNetmosCard( bool v )
{
	_isnetmosport = v;
}

/** Return's true when this port is on Netmos Card. */
bool SerialPort::isNetmosPort()
{
	return( _isnetmosport );
}

/** Return's seriaports speed( baud ) */
int SerialPort::Speed()
{
	return baud;
}

/** Set's a new baud rate. */
void SerialPort::setSpeed( int speed )
{
	baud = speed;
}

/** Test if device file for this serial port exists. If not creates it. Writes log about actions into str. */
bool SerialPort::testDeviceFile( QString *str, const char *owner, const char *group )
{
	QString tmp;
	if ( str ) {
		tmp.sprintf( "\t%s -- ", (const char *)DevName() );
		str->append( tmp );
	}
	struct stat statbuf;
	int resp = stat( (const char*)DevName(), &statbuf );
	if ( resp == 0 ) {
		if ( str )
			str->append( "OK<BR>\n" );
		return TRUE;
	}
	if ( str )
		str->append( "creating -- " );
	resp = mknod( (const char*)DevName(), S_IFCHR, (4<<8)|64+port );
	if ( resp == -1 ) {
		str->append( strerror( errno ) );
		return FALSE;
	}
	chmod( (const char *)DevName(), S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP );
	tmp.sprintf( "chown %s:%s %s", owner, group, (const char *)DevName() );
	system( tmp );
	if ( str )
		str->append( "OK<BR>\n" );
	return TRUE;

}

/** Saves current serial port into Suse's rc script. */
void SerialPort::saveForSuse73( QStringList *list, QString *log )
{
	QString sdef;

	QString dname = DevName();
	sdef.sprintf( "    run_setserial %s uart 16550A port 0x%X irq %i baud_base %i", \
		(const char *)dname, io, irq, baud );

#if ( QT_VERSION >= 300 )
	QStringList::iterator it;
#else
	QStringList::Iterator it;
#endif

	for ( it = list->begin(); it != list->end(); ++it ) {
		QString tmp = (*it).stripWhiteSpace();
		if ( tmp[0] == '#' )
			continue;
		if ( tmp.find( dname ) != -1 ) {
			(*it) = sdef;
			return;
		}
		
	}
	for ( it = list->begin(); it != list->end(); ++it ) {
		QString tmp = (*it).stripWhiteSpace();
		if ( tmp.find( "MANUAL CONFIGURATION" ) != -1 )
			break;
	}
	for ( ; it != list->end(); ++it ) {
		QString tmp = (*it).stripWhiteSpace();
		if ( tmp[0] == '#' )
			continue;
		break;
	}
	it++;
	list->insert( it, sdef );		
}

/** Saves serial configuration into RedHat/Mandrake serial configuration file. */
void SerialPort::saveForMandrakeRedHat( QStringList *list, QString *log )
{
	QString sdef;

	QString dname = DevName();
	sdef.sprintf( "%s uart 16550A port 0x%X irq %i baud_base %i", \
		(const char *)dname, io, irq, baud );

#if ( QT_VERSION >= 300 )
	QStringList::iterator it;
#else
	QStringList::Iterator it;
#endif

	bool found = FALSE;
	QString fstr;
	fstr.sprintf( "port 0x%x", io );
	for ( it = list->begin(); it != list->end(); ++it ) {
		QString tmp = (*it).stripWhiteSpace();
		if ( tmp[0] == '#' )
			continue;
		if ( tmp.find( dname ) != -1 ) {
			(*it) = sdef;
			found = TRUE;
			continue;
		}
		if ( tmp.find( fstr, 0, FALSE ) != -1 ) {
			it = list->remove( it );
			it--;
		}
		
	}
	if ( !found )
		list->append( sdef );
}

/** Set's wether this is detected port. */
void SerialPort::setDetected( bool b )
{
	detected = b;
}

/** Returns true if this is detected port. */
bool SerialPort::isDetected()
{
	return detected;
}


void SerialPort::setSystemPort( bool v )
{
	_systemport = v;
}

bool SerialPort::isSystemPort()
{
	return _systemport;
}
