/*
 *
 *
 *    serialios.cc
 *
 *    C++ source code for class my::serialios member functions and/or static
 *    member data.
 *
 *    =========================================================================
 *
 *    Copyright (C) 1999-2003 by Matt Roberts, KK5JY.
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License as published by the Free Software Foundation; either
 *    version 2.1 of the License, or (at your option) any later version.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *    =========================================================================
 *
 *
 */


#include <my++/serialios.h>


/*
 *
 *   serialios::init ()
 *
 *   This does what it says: it loads default values into the fields of
 *   the IOS structure, values that are reasonable for a serial device.
 *
 */

void my::serialios::init (void) {
	/* first allow the base class to initialize */
	my::termios::init();

	/* clear all flags */
	clearLocalFlags ();
	clearCommFlags ();
	clearInputFlags ();
	clearOutputFlags ();

	/*
	 *   set some reasonable defaults:
	 *     + 9600bps, N81
	 *     + No hard or soft flow ctl
	 *     + ignore modem control lines
	 */

	optionCommReceiver(true);
	optionCommHardHangup (true);
	setParity (no_parity);
	setStopBits (1);
	setCharSize (8);
	setSpeed (9600);
	setHWflow (false);
	setSWflow (false);
	setLocal (true);
}


/*
 *
 *   serialios::setParity (...)
 *
 *   NOTE: the default for any party setting is to IGNORE parity errors.
 *   If the user wishes to override this behaviour, he should use the
 *   functions in the base class termios to do so.
 *
 */

bool my::serialios::setParity (parity_values p) {
	int wlen;

	switch (p) {
		case no_parity:
			optionCommParity (false);
			optionCommOddParity (false);
			optionInputIgnoreParity (true);
			optionInputParityCheck (false);
			optionInputStripBitEight (false);
			break;

		case even_parity:
			optionCommParity (true);
			optionCommOddParity (false);
			getCharSize (wlen);
			if (wlen == 8)
				setCharSize (7);
			optionInputIgnoreParity (false);
			optionInputParityCheck (true);
			optionInputStripBitEight (true);
			break;

		case odd_parity:
			optionCommParity (true);
			optionCommOddParity (true);
			getCharSize (wlen);
			if (wlen == 8)
				setCharSize (7);
			optionInputIgnoreParity (false);
			optionInputParityCheck (true);
			optionInputStripBitEight (true);
			break;

/*
		case mark_parity:           // FIXME
			optionCommParity (false);
			optionCommCharSize (7);
			optionCommStopBits (2);
			break;
		case space_parity:          // FIXME
			optionCommParity (false);
			optionCommCharSize (7);
			optionCommStopBits (2);
			break;
*/
		default:
			return false;
	}

	return true;
}


bool my::serialios::setParity (char c) {
	switch (c) {
		case 'N':
		case 'n':
			setParity (no_parity);
			break;
		case 'O':
		case 'o':
			setParity (odd_parity);
			break;
		case 'E':
		case 'e':
			setParity (even_parity);
			break;
		case 'M':
		case 'm':
			setParity (mark_parity);
			break;
		case 'S':
		case 's':
			setParity (space_parity);
			break;
		default:
			return false;
	}

	return true;
}


bool my::serialios::setCharSize (int i) {
	if (i == 8) {
		setParity (no_parity);
		setStopBits (1);
	}
	optionCommCharSize (i);
	return true;
}


bool my::serialios::setStopBits (int i) {
	optionCommStopBits (i);
	return true;
}


bool my::serialios::setSpeed (int i) {
	optionCommSpeed (i);
	return true;
}


bool my::serialios::setHWflow (bool i) {
	optionCommHardFlowCtl(i);
	optionCommHardHangup(i);
	//optionCommIgnoreModemCtl (!i);
	return true;
}


bool my::serialios::setSWflow (bool i) {
	optionInputXFlow (i);
	optionInputOutputXFlow (i);
	return true;
}


bool my::serialios::setLocal (bool i) {
	optionCommIgnoreModemCtl (i);
	return true;
}

bool my::serialios::getParity (parity_values &p) {
	if (optionCommParity ()) {
		if (optionCommOddParity ())
			p = odd_parity;
		else
			p = even_parity;
	} else {
		p = no_parity;  // FIXME -- for mark_ and space_parity
	}

	return true;
}


bool my::serialios::getParity (char &p) {
	if (optionCommParity ()) {
		if (optionCommOddParity ())
			p = 'O';
		else
			p = 'E';
	} else {
		p = 'N';  // FIXME -- for mark_ and space_parity
	}

	return true;
}


bool my::serialios::getStopBits (int &i) {
	i = optionCommStopBits ();
	return true;
}


bool my::serialios::getCharSize (int &i) {
	i = optionCommCharSize ();
	return true;
}


bool my::serialios::getSpeed (int &i) {
	i = optionCommSpeed ();
	return true;
}


bool my::serialios::getHWflow (bool &i) {
	i = optionCommHardFlowCtl ();
	return true;
}


bool my::serialios::getSWflow (bool &i) {
	i = (optionInputXFlow () || optionInputOutputXFlow ());
	return true;
}


bool my::serialios::getLocal (bool &i) {
	i = optionCommIgnoreModemCtl ();
	return i;
}

my::serialios::parity_values my::serialios::getParity (void) {
	parity_values pv;
	getParity(pv);
	return pv;
}

int my::serialios::getStopBits (void) {
	int sb;
	getStopBits(sb);
	return sb;
}

int my::serialios::getCharSize (void) {
	int cs;
	getCharSize(cs);
	return cs;
}

int my::serialios::getSpeed (void) {
	int s;
	getSpeed(s);
	return s;
}

bool my::serialios::getHWflow (void) {
	bool hw;
	getHWflow(hw);
	return hw;
}

bool my::serialios::getSWflow (void) {
	bool sw;
	getSWflow(sw);
	return sw;
}

bool my::serialios::getLocal (void) {
	bool l;
	getLocal(l);
	return l;
}

