haitest/bspsvs/tools/java/UartEchoServer/src/UartEchoServer.java
changeset 0 cec860690d41
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/haitest/bspsvs/tools/java/UartEchoServer/src/UartEchoServer.java	Tue Feb 02 01:39:10 2010 +0200
@@ -0,0 +1,814 @@
+/*
+* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+import gnu.io.CommPort;
+import gnu.io.CommPortIdentifier;
+import gnu.io.SerialPort;
+import gnu.io.SerialPortEvent;
+import gnu.io.SerialPortEventListener;
+
+import java.util.logging.Logger;
+
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.PosixParser;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.HelpFormatter;
+
+public class UartEchoServer implements SerialPortEventListener
+	{
+	//	Command line options
+	private static final String	OPTION_HELP			="help";
+	private static final String	OPTION_PORT			="port";
+	private static final String	OPTION_BAUD			="baud_rate";
+	private static final String	OPTION_DATA			="data_bits";
+	private static final String	OPTION_STOP			="stop_bits";
+	private static final String	OPTION_PARITY		="parity";
+	private static final String	OPTION_FLOW			="flow_control";
+
+	//	Default settings for serial port
+	private static final String	DEFAULT_PORT_NAME	= "COM1";
+	private static final int	DEFAULT_BAUD_RATE	= 9600;
+	private static final int	DEFAULT_DATA_BITS	= SerialPort.DATABITS_8;
+	private static final int	DEFAULT_STOP_BITS	= SerialPort.STOPBITS_1;
+	private static final int	DEFAULT_PARITY		= SerialPort.PARITY_NONE;
+	private static final int	DEFAULT_FLOW_CONTROL= SerialPort.FLOWCONTROL_NONE;
+
+	//	Command format limiters
+	private static final byte	BYTE_IGNORE			= '\0'; // Null
+	private static final byte	BYTE_CLEARBI		= '\1'; // Ctrl A
+	private static final byte	BYTE_QUERYBI		= '\2'; // Ctrl B
+	private static final byte	BYTE_RESET			= '\3'; // Ctrl C
+	private static final byte	BYTE_BLOCK_START	= '[';
+	private static final byte	BYTE_BLOCK_END		= ']';
+	private static final String	BLOCK_ASSIGN		= "=";
+	private static final String	BLOCK_SEPERATOR		= ",";
+
+	//	Supported commands
+	private static final String	CMD_BAUD_RATE		= "baud_rate";
+	private static final String	CMD_DATA_BITS		= "data_bits";
+	private static final String	CMD_DELAY			= "delay";
+	private static final String	CMD_DISCONNECT		= "disconnect";
+	private static final String	CMD_ECHO			= "echo";
+	private static final String	CMD_FLOW_CONTROL	= "flow_control";
+	private static final String	CMD_LOG				= "log";
+	private static final String	CMD_PARITY			= "parity";
+	private static final String	CMD_STOP_BITS		= "stop_bits";
+
+	//	Supported data bits
+	private static final String	DATA_BITS_5			= "5";
+	private static final String	DATA_BITS_6			= "6";
+	private static final String	DATA_BITS_7			= "7";
+	private static final String	DATA_BITS_8			= "8";
+
+	//	Supported flow control
+	private static final String	FLOWCONTROL_NONE	= "none";
+	private static final String	FLOWCONTROL_RTSCTS	= "rtscts";
+	private static final String	FLOWCONTROL_XONXOFF	= "xonxoff";
+
+	//	Supported parity
+	private static final String	PARITY_NONE			= "none";
+	private static final String	PARITY_EVEN			= "even";
+	private static final String	PARITY_ODD			= "odd";
+	private static final String	PARITY_MARK			= "mark";
+	private static final String	PARITY_SPACE		= "space";
+
+	//	Supported stop bits
+	private static final String	STOP_BITS_1			= "1";
+	private static final String	STOP_BITS_1_5		= "1.5";
+	private static final String	STOP_BITS_2			= "2";
+
+	//	Constants
+	private static final int	BUFFER_SIZE			= 1024;
+	private static final int	SLEEP_PERIOD		= 200000;
+
+	private enum EStatus
+		{
+		EStatusEcho,
+		EStatusCommandStart,
+		};
+
+	private Thread				iMainThread;
+	private int					iRestartingDelay;
+	private boolean				iRestarting;
+	private boolean				iRunning;
+	private Logger				iLogger;
+	private byte[]				iBuffer;
+	private EStatus				iStatus;
+	private String				iCommand;
+	private String				iPortName;
+	private byte				iBI;
+
+	private int					iBaudRate;
+	private int					iDataBits;
+	private int					iStopBits;
+	private int					iParity;
+	private int					iFlowControl;
+
+	private int					iStartupBaudRate;
+	private int					iStartupDataBits;
+	private int					iStartupStopBits;
+	private int					iStartupParity;
+	private int					iStartupFlowControl;
+
+	private CommPortIdentifier	iPortIdentifier;
+	private SerialPort			iSerialPort;
+
+	/*
+	 *	Constructor
+	 */
+	protected UartEchoServer() throws Exception
+		{
+		iRestartingDelay=0;
+		iRestarting=true;
+		iRunning=true;
+		iLogger=Logger.getLogger("UartEchoServer");
+		iBuffer=new byte[BUFFER_SIZE];
+		iStatus = EStatus.EStatusEcho;
+		iCommand = "";
+		iBI=0;
+		iPortName=DEFAULT_PORT_NAME;
+		iBaudRate=DEFAULT_BAUD_RATE;
+		iDataBits=DEFAULT_DATA_BITS;
+		iStopBits=DEFAULT_STOP_BITS;
+		iParity=DEFAULT_PARITY;
+		iFlowControl=DEFAULT_FLOW_CONTROL;
+		}
+
+	/*
+	 *	Second pahse constructor
+	 *
+	 *	@param	aCommandLine	Command line parameters
+	 */
+	protected void Construct(final CommandLine aCommandLine) throws Exception
+		{
+		/*
+		 *	Set port name if passed in command line
+		 */
+		if ( aCommandLine.hasOption(OPTION_PORT) )
+			{
+			iPortName=aCommandLine.getOptionValue(OPTION_PORT);
+			iLogger.info("PortName:" + iPortName);
+			}
+
+		/*
+		 *	Set baud rate if passed in command line
+		 */
+		if ( aCommandLine.hasOption(OPTION_BAUD) )
+			{
+			setBaudRate(aCommandLine.getOptionValue(OPTION_BAUD));
+			iLogger.info("Baud Rate:" + iBaudRate);
+			}
+
+		/*
+		 *	Set data bits if passed in command line
+		 */
+		if ( aCommandLine.hasOption(OPTION_DATA) )
+			{
+			setDataBits(aCommandLine.getOptionValue(OPTION_DATA));
+			iLogger.info("Data Bits:" + iDataBits);
+			}
+
+		/*
+		 *	Set stop bits if passed in command line
+		 */
+		if ( aCommandLine.hasOption(OPTION_STOP) )
+			{
+			setStopBits(aCommandLine.getOptionValue(OPTION_STOP));
+			iLogger.info("Stop Bits:" + iStopBits);
+			}
+
+		/*
+		 *	Set parity if passed in command line
+		 */
+		if ( aCommandLine.hasOption(OPTION_PARITY) )
+			{
+			setParity(aCommandLine.getOptionValue(OPTION_PARITY));
+			iLogger.info("Parity:" + iParity);
+			}
+
+		/*
+		 *	Set flow control if passed in command line
+		 */
+		if ( aCommandLine.hasOption(OPTION_FLOW) )
+			{
+			setFlowControl(aCommandLine.getOptionValue(OPTION_FLOW));
+			iLogger.info("Flow Control:" + iFlowControl);
+			}
+
+		/*
+		 *	Save startup values. Used by reset command
+		 */
+		iStartupBaudRate=iBaudRate;
+		iStartupDataBits=iDataBits;
+		iStartupStopBits=iStopBits;
+		iStartupParity=iParity;
+		iStartupFlowControl=iFlowControl;
+
+		/*
+		 *	Make sure port is not in use
+		 */
+		iPortIdentifier=CommPortIdentifier.getPortIdentifier(iPortName);
+		if ( iPortIdentifier.isCurrentlyOwned() )
+			{
+			throw new Exception("Error: Port is currently in use");
+			}
+
+		/*
+		 *	Port not in use so open it
+		 */
+		CommPort	commPort=iPortIdentifier.open(this.getClass().getName(), 2000);
+
+		/*
+		 *	Save thread
+		 */
+		iMainThread=Thread.currentThread();
+
+		/*
+		 *	Make sure the port is of type serial
+		 */
+		if ( commPort instanceof SerialPort )
+			{
+			iSerialPort = (SerialPort) commPort;
+			iFlowControl=iSerialPort.getFlowControlMode();
+			while ( iRunning )
+				{
+				initPort();
+
+				iRestarting=false;
+				while ( iRunning && !iRestarting )
+					{
+					try
+						{
+						iMainThread.sleep(SLEEP_PERIOD);
+						}
+					catch ( InterruptedException e )
+						{
+						}
+					}
+				iSerialPort.close();
+				if ( iRestarting )
+					{
+					iLogger.finest("Restarting");
+					iMainThread.sleep(iRestartingDelay);
+					commPort=iPortIdentifier.open(this.getClass().getName(), 2000);
+					iSerialPort = (SerialPort) commPort;
+					}
+				}
+			}
+		else
+			{
+			throw new Exception("Error: Only serial ports are handled by this example.");
+			}
+		}
+
+	/*
+	 *	Initialise the port
+	 */
+	private void initPort() throws Exception
+		{
+		iSerialPort.setSerialPortParams(iBaudRate, iDataBits, iStopBits, iParity);
+		iSerialPort.setFlowControlMode(iFlowControl);
+		iSerialPort.addEventListener(this);
+		iSerialPort.notifyOnBreakInterrupt(true);
+		iSerialPort.notifyOnCarrierDetect(true);
+		iSerialPort.notifyOnCTS(true);
+		iSerialPort.notifyOnDataAvailable(true);
+		iSerialPort.notifyOnDSR(true);
+		iSerialPort.notifyOnFramingError(true);
+		iSerialPort.notifyOnOutputEmpty(true);
+		iSerialPort.notifyOnOverrunError(true);
+		iSerialPort.notifyOnParityError(true);
+		iSerialPort.notifyOnRingIndicator(true);
+		iSerialPort.setInputBufferSize(BUFFER_SIZE);
+		}
+
+	/*
+	 *	Set the baud rate
+	 *
+	 *	@param	aValue	String representation of the baud rate
+	 */
+	private void setBaudRate(final String aValue)
+		{
+		try
+			{
+			iBaudRate=Integer.parseInt(aValue);
+			}
+		catch (Exception e)
+			{
+			iLogger.severe("convertToBaudRate(" + aValue + "):exception" + e);
+			}
+		}
+
+	/*
+	 *	Set the data bits
+	 *
+	 *	@param	aValue	String representation of the data bits
+	 */
+	private void setDataBits(final String aValue)
+		{
+		try
+			{
+			if ( aValue.compareTo(DATA_BITS_5)==0 )
+				{
+				iDataBits=SerialPort.DATABITS_5;
+				}
+			else if ( aValue.compareTo(DATA_BITS_6)==0 )
+				{
+				iDataBits=SerialPort.DATABITS_6;
+				}
+			else if ( aValue.compareTo(DATA_BITS_7)==0 )
+				{
+				iDataBits=SerialPort.DATABITS_7;
+				}
+			else if ( aValue.compareTo(DATA_BITS_8)==0 )
+				{
+				iDataBits=SerialPort.DATABITS_8;
+				}
+			else
+				{
+				iLogger.severe("setDataBits(" + aValue + ")");
+				}
+			}
+		catch (Exception e)
+			{
+			iLogger.severe("setDataBits(" + aValue + "):excpetion" + e);
+			}
+		}
+
+	/*
+	 *	Set the flow control
+	 *
+	 *	@param	aValue	String representation of the flow control
+	 */
+	private void setFlowControl(final String aValue)
+		{
+		try
+			{
+			if ( aValue.compareTo(FLOWCONTROL_NONE)==0 )
+				{
+				iFlowControl=SerialPort.FLOWCONTROL_NONE;
+				}
+			else if ( aValue.compareTo(FLOWCONTROL_RTSCTS)==0 )
+				{
+				iFlowControl=SerialPort.FLOWCONTROL_RTSCTS_IN | SerialPort.FLOWCONTROL_RTSCTS_OUT;
+				}
+			else if ( aValue.compareTo(FLOWCONTROL_XONXOFF)==0 )
+				{
+				iFlowControl=SerialPort.FLOWCONTROL_XONXOFF_IN | SerialPort.FLOWCONTROL_XONXOFF_OUT;
+				}
+			else
+				{
+				iLogger.severe("setFlowControl(" + aValue + ")");
+				}
+			}
+		catch (Exception e)
+			{
+			iLogger.severe("setFlowControl(" + aValue + "):exception" + e);
+			}
+		}
+
+	/*
+	 *	Set the parity
+	 *
+	 *	@param	aValue	String representation of the parity
+	 */
+	private void setParity(final String aValue)
+		{
+		try
+			{
+			if ( aValue.compareTo(PARITY_NONE)==0 )
+				{
+				iParity=SerialPort.PARITY_NONE;
+				}
+			else if ( aValue.compareTo(PARITY_EVEN)==0 )
+				{
+				iParity=SerialPort.PARITY_EVEN;
+				}
+			else if ( aValue.compareTo(PARITY_ODD)==0 )
+				{
+				iParity=SerialPort.PARITY_ODD;
+				}
+			else if ( aValue.compareTo(PARITY_MARK)==0 )
+				{
+				iParity=SerialPort.PARITY_MARK;
+				}
+			else if ( aValue.compareTo(PARITY_SPACE)==0 )
+				{
+				iParity=SerialPort.PARITY_SPACE;
+				}
+			else
+				{
+				iLogger.severe("setParity(" + aValue + ")");
+				}
+			}
+		catch (Exception e)
+			{
+			iLogger.severe("setParity(" + aValue + "):exception" + e);
+			}
+		}
+
+	/*
+	 *	Set the stop bits
+	 *
+	 *	@param	aValue	String representation of the stop bits
+	 */
+	private void setStopBits(final String aValue)
+		{
+		try
+			{
+			if ( aValue.compareTo(STOP_BITS_1)==0 )
+				{
+				iStopBits=SerialPort.STOPBITS_1;
+				}
+			else if ( aValue.compareTo(STOP_BITS_1_5)==0 )
+				{
+				iStopBits=SerialPort.STOPBITS_1_5;
+				}
+			else if ( aValue.compareTo(STOP_BITS_2)==0 )
+				{
+				iStopBits=SerialPort.STOPBITS_2;
+				}
+			else
+				{
+				iLogger.severe("setStopBits(" + aValue + ")");
+				}
+			}
+		catch (Exception e)
+			{
+			iLogger.severe("setStopBits(" + aValue + "):exception" + e);
+			}
+		}
+
+	/*
+	 *	Process a command from the input
+	 */
+	private void processCommand() throws Exception
+		{
+		final String	values[] = iCommand.split(BLOCK_SEPERATOR);
+
+		iSerialPort.getOutputStream().flush();
+		for ( int i=0; i<values.length; i++ )
+			{
+			/*
+			 *	Commands should be of the type variable=value
+			 */
+			final String	parts[]=values[i].split(BLOCK_ASSIGN);
+
+			if ( parts.length==2 )
+				{
+				/*
+				 *	Set baud rate command
+				 */
+				if ( parts[0].compareTo(CMD_BAUD_RATE)==0 )
+					{
+					setBaudRate(parts[1]);
+					iSerialPort.setSerialPortParams(iBaudRate, iDataBits, iStopBits, iParity);
+					}
+				/*
+				 *	Set data bits command
+				 */
+				else if ( parts[0].compareTo(CMD_DATA_BITS)==0 )
+					{
+					setDataBits(parts[1]);
+					iSerialPort.setSerialPortParams(iBaudRate, iDataBits, iStopBits, iParity);
+					}
+				/*
+				 *	Delay command
+				 */
+				else if ( parts[0].compareTo(CMD_DELAY)==0 )
+					{
+					final int	delay=Integer.parseInt(parts[1]);
+					Thread.sleep(delay);
+					}
+				/*
+				 *	Disconnect command
+				 */
+				else if ( parts[0].compareTo(CMD_DISCONNECT)==0 )
+					{
+					iRestartingDelay=Integer.parseInt(parts[1]);
+					iRestarting=true;
+					}
+				/*
+				 *	Echo command
+				 */
+				else if ( parts[0].compareTo(CMD_ECHO)==0 )
+					{
+					final int		length=parts[1].length();
+					for ( int index=0; index<length; ++index )
+						{
+						final byte	out=(byte)(parts[1].charAt(index));
+						iLogger.finest("<< " + out);
+						iSerialPort.getOutputStream().write(out);
+						}
+					}
+				/*
+				 *	Set flow control command
+				 */
+				else if ( parts[0].compareTo(CMD_FLOW_CONTROL)==0 )
+					{
+					setFlowControl(parts[1]);
+					iSerialPort.setFlowControlMode(iFlowControl);
+					}
+				/*
+				 *	Log command
+				 */
+				else if ( parts[0].compareTo(CMD_LOG)==0 )
+					{
+					iLogger.info(parts[1]);
+					}
+				/*
+				 *	Set parity command
+				 */
+				else if ( parts[0].compareTo(CMD_PARITY)==0 )
+					{
+					setParity(parts[1]);
+					iSerialPort.setSerialPortParams(iBaudRate, iDataBits, iStopBits, iParity);
+					}
+				/*
+				 *	Set stop bits command
+				 */
+				else if ( parts[0].compareTo(CMD_STOP_BITS)==0 )
+					{
+					setStopBits(parts[1]);
+					iSerialPort.setSerialPortParams(iBaudRate, iDataBits, iStopBits, iParity);
+					}
+				/*
+				 *	Error command
+				 */
+				else
+					{
+					iLogger.severe("Bad command(" + parts[0] + ")");
+					}
+				}
+			else
+				{
+				iLogger.severe("Bad data");
+				}
+			}
+		}
+
+	/*
+	 *	Process data read from input stream
+	 *
+	 *	@param	aLength	Length of the data in the buffer
+	 */
+	private void processInput(final int aLength) throws Exception
+		{
+		final String	buffer=new String(iBuffer, 0, aLength);
+		iLogger.finest(">> " + buffer);
+		for ( int index=0; index<aLength; ++index )
+			{
+			switch ( iBuffer[index] )
+				{
+			/*
+			 *	Ignored data
+			 */
+			case BYTE_IGNORE:
+				break;
+			/*
+			 *	Clear the break interrupt count
+			 */
+			case BYTE_CLEARBI:
+				iBI=0;
+				break;
+			/*
+			 *	Query the break interrupt count
+			 */
+			case BYTE_QUERYBI:
+				iLogger.finest("BI Count=" + iBI);
+				iLogger.finest("<< " + iBI);
+				iSerialPort.getOutputStream().write(iBI);
+				break;
+			/*
+			 *	Reset port setting to startup values
+			 */
+			case BYTE_RESET:
+				iBaudRate=iStartupBaudRate;
+				iDataBits=iStartupDataBits;
+				iStopBits=iStartupStopBits;
+				iParity=iStartupParity;
+				iFlowControl=iStartupFlowControl;
+				iSerialPort.setFlowControlMode(iFlowControl);
+				iSerialPort.setSerialPortParams(iBaudRate, iDataBits, iStopBits, iParity);
+				iStatus=EStatus.EStatusEcho;
+				break;
+			default:
+				/*
+				 *	If in command mode add the byte to the command buffer
+				 *	unless we read the end of command block character
+				 */
+				if ( iStatus==EStatus.EStatusCommandStart ) 
+					{
+					if ( iBuffer[index]==BYTE_BLOCK_END )
+						{
+						processCommand();
+						iStatus=EStatus.EStatusEcho;
+						}
+					else
+						{
+						iCommand += buffer.charAt(index);
+						}
+					}
+				/*
+				 *	If in echo mode, echo the character unless we read the
+				 *	start of command block character
+				 */
+				else if ( iStatus==EStatus.EStatusEcho )
+					{
+					if ( iBuffer[index]==BYTE_BLOCK_START )
+						{
+						iCommand="";
+						iStatus=EStatus.EStatusCommandStart;
+						}
+					else
+						{
+						iLogger.finest("<< " + iBuffer[index]);
+						iSerialPort.getOutputStream().write(iBuffer[index]);
+						}
+					}
+				break;
+				}
+			}
+		}
+
+	/*
+	 *	Serial port event received
+	 *
+	 *	@param	aEvent	Event received
+	 */
+	public void serialEvent(SerialPortEvent aEvent)
+		{
+		switch ( aEvent.getEventType() )
+			{
+		case SerialPortEvent.DATA_AVAILABLE:
+			/*
+			 *	Process data in input buffer
+			 */
+			try
+				{
+				final int	length = iSerialPort.getInputStream().read(iBuffer);
+
+				if ( length>0 )
+					{
+					processInput(length);
+					}
+				}
+			catch (Exception e)
+				{
+				e.printStackTrace();
+				}
+			if ( iRestarting )
+				{
+				iMainThread.interrupt();
+				}
+			break;
+		case SerialPortEvent.BI:
+			/*
+			 *	Increment break interrupt count
+			 */
+			++iBI;
+			iLogger.finest("Break Interrupt");
+			break;
+		case SerialPortEvent.CD:
+			/*
+			 *	Ignore
+			 */
+			iLogger.finest("Carrier Detect");
+			break;
+		case SerialPortEvent.CTS:
+			/*
+			 *	Ignore
+			 */
+			iLogger.finest("Clear To Send");
+			break;
+		case SerialPortEvent.DSR:
+			/*
+			 *	Ignore
+			 */
+			iLogger.finest("Data Set Ready");
+			break;
+		case SerialPortEvent.FE:
+			/*
+			 *	Ignore
+			 */
+			iLogger.finest("Framing Error");
+			break;
+		case SerialPortEvent.OE:
+			/*
+			 *	Ignore
+			 */
+			iLogger.finest("Overflow Error");
+			break;
+		case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
+			/*
+			 *	Ignore
+			 */
+			iLogger.finest("Output Buffer Empty");
+			break;
+		case SerialPortEvent.PE:
+			/*
+			 *	Ignore
+			 */
+			iLogger.finest("Parity Error");
+			break;
+		case SerialPortEvent.RI:
+			/*
+			 *	Ignore
+			 */
+			iLogger.finest("Ring Interrupt");
+			break;
+		default:
+			iLogger.finest("Unknown event");
+			break;
+			}
+		}
+
+	/*
+	 *	Application entry point
+	 *
+	 *	@param	aArgs	COmmand line arguments
+	 */
+	public static void main(String[] aArgs)
+		{
+		final Options	options = new Options();
+
+		options.addOption(new Option(OPTION_HELP, "print this message"));
+
+		OptionBuilder.withLongOpt(OPTION_PORT);
+		OptionBuilder.withDescription("set port COMx");
+		OptionBuilder.withValueSeparator( '=' );
+		OptionBuilder.hasArg();
+		options.addOption(OptionBuilder.create());
+
+		OptionBuilder.withLongOpt(OPTION_BAUD);
+		OptionBuilder.withDescription("set the baud rate");
+		OptionBuilder.withValueSeparator( '=' );
+		OptionBuilder.hasArg();
+		options.addOption(OptionBuilder.create());
+
+		OptionBuilder.withLongOpt(OPTION_DATA);
+		OptionBuilder.withDescription("set the data bits [" + DATA_BITS_5 +"|" + DATA_BITS_6 + "|" + DATA_BITS_7 + "|" + DATA_BITS_8 + "]");
+		OptionBuilder.withValueSeparator( '=' );
+		OptionBuilder.hasArg();
+		options.addOption(OptionBuilder.create());
+
+		OptionBuilder.withLongOpt(OPTION_STOP);
+		OptionBuilder.withDescription("set the stop bits [" + STOP_BITS_1 + "|" + STOP_BITS_1_5 + "|" + STOP_BITS_2 + "]");
+		OptionBuilder.withValueSeparator( '=' );
+		OptionBuilder.hasArg();
+		options.addOption(OptionBuilder.create());
+
+		OptionBuilder.withLongOpt(OPTION_PARITY);
+		OptionBuilder.withDescription("set the parity [" + PARITY_NONE + "|" + PARITY_EVEN + "|" + PARITY_ODD + "|" + PARITY_MARK + "|" + PARITY_SPACE + "]");
+		OptionBuilder.withValueSeparator( '=' );
+		OptionBuilder.hasArg();
+		options.addOption(OptionBuilder.create());
+
+		OptionBuilder.withLongOpt(OPTION_FLOW);
+		OptionBuilder.withDescription("set the flow control [" + FLOWCONTROL_NONE + "|" + FLOWCONTROL_RTSCTS + "|" + FLOWCONTROL_XONXOFF + "]");
+		OptionBuilder.withValueSeparator( '=' );
+		OptionBuilder.hasArg();
+		options.addOption(OptionBuilder.create());
+
+		final CommandLineParser	parser = new PosixParser();
+
+		try
+			{
+			// parse the command line arguments
+			final CommandLine	commandLine = parser.parse(options, aArgs);
+
+			if ( commandLine.hasOption(OPTION_HELP) )
+				{
+				final HelpFormatter	formatter = new HelpFormatter();
+				formatter.printHelp("UartEchoServer", options);
+				}
+			else
+				{
+				final UartEchoServer	echoServer=new UartEchoServer();
+				echoServer.Construct(commandLine);
+				}
+			}
+		catch ( Exception e )
+			{
+			e.printStackTrace();
+			}
+		}
+	}