Update contrib.
2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
4 * This component and the accompanying materials are made available
5 * under the terms of "Eclipse Public License v1.0"
6 * which accompanies this distribution, and is available
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
19 import gnu.io.CommPort;
20 import gnu.io.CommPortIdentifier;
21 import gnu.io.SerialPort;
22 import gnu.io.SerialPortEvent;
23 import gnu.io.SerialPortEventListener;
25 import java.util.logging.Logger;
27 import org.apache.commons.cli.Options;
28 import org.apache.commons.cli.Option;
29 import org.apache.commons.cli.OptionBuilder;
30 import org.apache.commons.cli.CommandLineParser;
31 import org.apache.commons.cli.PosixParser;
32 import org.apache.commons.cli.CommandLine;
33 import org.apache.commons.cli.HelpFormatter;
35 public class UartEchoServer implements SerialPortEventListener
37 // Command line options
38 private static final String OPTION_HELP ="help";
39 private static final String OPTION_PORT ="port";
40 private static final String OPTION_BAUD ="baud_rate";
41 private static final String OPTION_DATA ="data_bits";
42 private static final String OPTION_STOP ="stop_bits";
43 private static final String OPTION_PARITY ="parity";
44 private static final String OPTION_FLOW ="flow_control";
46 // Default settings for serial port
47 private static final String DEFAULT_PORT_NAME = "COM1";
48 private static final int DEFAULT_BAUD_RATE = 9600;
49 private static final int DEFAULT_DATA_BITS = SerialPort.DATABITS_8;
50 private static final int DEFAULT_STOP_BITS = SerialPort.STOPBITS_1;
51 private static final int DEFAULT_PARITY = SerialPort.PARITY_NONE;
52 private static final int DEFAULT_FLOW_CONTROL= SerialPort.FLOWCONTROL_NONE;
54 // Command format limiters
55 private static final byte BYTE_IGNORE = '\0'; // Null
56 private static final byte BYTE_CLEARBI = '\1'; // Ctrl A
57 private static final byte BYTE_QUERYBI = '\2'; // Ctrl B
58 private static final byte BYTE_RESET = '\3'; // Ctrl C
59 private static final byte BYTE_BLOCK_START = '[';
60 private static final byte BYTE_BLOCK_END = ']';
61 private static final String BLOCK_ASSIGN = "=";
62 private static final String BLOCK_SEPERATOR = ",";
65 private static final String CMD_BAUD_RATE = "baud_rate";
66 private static final String CMD_DATA_BITS = "data_bits";
67 private static final String CMD_DELAY = "delay";
68 private static final String CMD_DISCONNECT = "disconnect";
69 private static final String CMD_ECHO = "echo";
70 private static final String CMD_FLOW_CONTROL = "flow_control";
71 private static final String CMD_LOG = "log";
72 private static final String CMD_PARITY = "parity";
73 private static final String CMD_STOP_BITS = "stop_bits";
75 // Supported data bits
76 private static final String DATA_BITS_5 = "5";
77 private static final String DATA_BITS_6 = "6";
78 private static final String DATA_BITS_7 = "7";
79 private static final String DATA_BITS_8 = "8";
81 // Supported flow control
82 private static final String FLOWCONTROL_NONE = "none";
83 private static final String FLOWCONTROL_RTSCTS = "rtscts";
84 private static final String FLOWCONTROL_XONXOFF = "xonxoff";
87 private static final String PARITY_NONE = "none";
88 private static final String PARITY_EVEN = "even";
89 private static final String PARITY_ODD = "odd";
90 private static final String PARITY_MARK = "mark";
91 private static final String PARITY_SPACE = "space";
93 // Supported stop bits
94 private static final String STOP_BITS_1 = "1";
95 private static final String STOP_BITS_1_5 = "1.5";
96 private static final String STOP_BITS_2 = "2";
99 private static final int BUFFER_SIZE = 1024;
100 private static final int SLEEP_PERIOD = 200000;
108 private Thread iMainThread;
109 private int iRestartingDelay;
110 private boolean iRestarting;
111 private boolean iRunning;
112 private Logger iLogger;
113 private byte[] iBuffer;
114 private EStatus iStatus;
115 private String iCommand;
116 private String iPortName;
119 private int iBaudRate;
120 private int iDataBits;
121 private int iStopBits;
123 private int iFlowControl;
125 private int iStartupBaudRate;
126 private int iStartupDataBits;
127 private int iStartupStopBits;
128 private int iStartupParity;
129 private int iStartupFlowControl;
131 private CommPortIdentifier iPortIdentifier;
132 private SerialPort iSerialPort;
137 protected UartEchoServer() throws Exception
142 iLogger=Logger.getLogger("UartEchoServer");
143 iBuffer=new byte[BUFFER_SIZE];
144 iStatus = EStatus.EStatusEcho;
147 iPortName=DEFAULT_PORT_NAME;
148 iBaudRate=DEFAULT_BAUD_RATE;
149 iDataBits=DEFAULT_DATA_BITS;
150 iStopBits=DEFAULT_STOP_BITS;
151 iParity=DEFAULT_PARITY;
152 iFlowControl=DEFAULT_FLOW_CONTROL;
156 * Second pahse constructor
158 * @param aCommandLine Command line parameters
160 protected void Construct(final CommandLine aCommandLine) throws Exception
163 * Set port name if passed in command line
165 if ( aCommandLine.hasOption(OPTION_PORT) )
167 iPortName=aCommandLine.getOptionValue(OPTION_PORT);
168 iLogger.info("PortName:" + iPortName);
172 * Set baud rate if passed in command line
174 if ( aCommandLine.hasOption(OPTION_BAUD) )
176 setBaudRate(aCommandLine.getOptionValue(OPTION_BAUD));
177 iLogger.info("Baud Rate:" + iBaudRate);
181 * Set data bits if passed in command line
183 if ( aCommandLine.hasOption(OPTION_DATA) )
185 setDataBits(aCommandLine.getOptionValue(OPTION_DATA));
186 iLogger.info("Data Bits:" + iDataBits);
190 * Set stop bits if passed in command line
192 if ( aCommandLine.hasOption(OPTION_STOP) )
194 setStopBits(aCommandLine.getOptionValue(OPTION_STOP));
195 iLogger.info("Stop Bits:" + iStopBits);
199 * Set parity if passed in command line
201 if ( aCommandLine.hasOption(OPTION_PARITY) )
203 setParity(aCommandLine.getOptionValue(OPTION_PARITY));
204 iLogger.info("Parity:" + iParity);
208 * Set flow control if passed in command line
210 if ( aCommandLine.hasOption(OPTION_FLOW) )
212 setFlowControl(aCommandLine.getOptionValue(OPTION_FLOW));
213 iLogger.info("Flow Control:" + iFlowControl);
217 * Save startup values. Used by reset command
219 iStartupBaudRate=iBaudRate;
220 iStartupDataBits=iDataBits;
221 iStartupStopBits=iStopBits;
222 iStartupParity=iParity;
223 iStartupFlowControl=iFlowControl;
226 * Make sure port is not in use
228 iPortIdentifier=CommPortIdentifier.getPortIdentifier(iPortName);
229 if ( iPortIdentifier.isCurrentlyOwned() )
231 throw new Exception("Error: Port is currently in use");
235 * Port not in use so open it
237 CommPort commPort=iPortIdentifier.open(this.getClass().getName(), 2000);
242 iMainThread=Thread.currentThread();
245 * Make sure the port is of type serial
247 if ( commPort instanceof SerialPort )
249 iSerialPort = (SerialPort) commPort;
250 iFlowControl=iSerialPort.getFlowControlMode();
256 while ( iRunning && !iRestarting )
260 iMainThread.sleep(SLEEP_PERIOD);
262 catch ( InterruptedException e )
269 iLogger.finest("Restarting");
270 iMainThread.sleep(iRestartingDelay);
271 commPort=iPortIdentifier.open(this.getClass().getName(), 2000);
272 iSerialPort = (SerialPort) commPort;
278 throw new Exception("Error: Only serial ports are handled by this example.");
283 * Initialise the port
285 private void initPort() throws Exception
287 iSerialPort.setSerialPortParams(iBaudRate, iDataBits, iStopBits, iParity);
288 iSerialPort.setFlowControlMode(iFlowControl);
289 iSerialPort.addEventListener(this);
290 iSerialPort.notifyOnBreakInterrupt(true);
291 iSerialPort.notifyOnCarrierDetect(true);
292 iSerialPort.notifyOnCTS(true);
293 iSerialPort.notifyOnDataAvailable(true);
294 iSerialPort.notifyOnDSR(true);
295 iSerialPort.notifyOnFramingError(true);
296 iSerialPort.notifyOnOutputEmpty(true);
297 iSerialPort.notifyOnOverrunError(true);
298 iSerialPort.notifyOnParityError(true);
299 iSerialPort.notifyOnRingIndicator(true);
300 iSerialPort.setInputBufferSize(BUFFER_SIZE);
306 * @param aValue String representation of the baud rate
308 private void setBaudRate(final String aValue)
312 iBaudRate=Integer.parseInt(aValue);
316 iLogger.severe("convertToBaudRate(" + aValue + "):exception" + e);
323 * @param aValue String representation of the data bits
325 private void setDataBits(final String aValue)
329 if ( aValue.compareTo(DATA_BITS_5)==0 )
331 iDataBits=SerialPort.DATABITS_5;
333 else if ( aValue.compareTo(DATA_BITS_6)==0 )
335 iDataBits=SerialPort.DATABITS_6;
337 else if ( aValue.compareTo(DATA_BITS_7)==0 )
339 iDataBits=SerialPort.DATABITS_7;
341 else if ( aValue.compareTo(DATA_BITS_8)==0 )
343 iDataBits=SerialPort.DATABITS_8;
347 iLogger.severe("setDataBits(" + aValue + ")");
352 iLogger.severe("setDataBits(" + aValue + "):excpetion" + e);
357 * Set the flow control
359 * @param aValue String representation of the flow control
361 private void setFlowControl(final String aValue)
365 if ( aValue.compareTo(FLOWCONTROL_NONE)==0 )
367 iFlowControl=SerialPort.FLOWCONTROL_NONE;
369 else if ( aValue.compareTo(FLOWCONTROL_RTSCTS)==0 )
371 iFlowControl=SerialPort.FLOWCONTROL_RTSCTS_IN | SerialPort.FLOWCONTROL_RTSCTS_OUT;
373 else if ( aValue.compareTo(FLOWCONTROL_XONXOFF)==0 )
375 iFlowControl=SerialPort.FLOWCONTROL_XONXOFF_IN | SerialPort.FLOWCONTROL_XONXOFF_OUT;
379 iLogger.severe("setFlowControl(" + aValue + ")");
384 iLogger.severe("setFlowControl(" + aValue + "):exception" + e);
391 * @param aValue String representation of the parity
393 private void setParity(final String aValue)
397 if ( aValue.compareTo(PARITY_NONE)==0 )
399 iParity=SerialPort.PARITY_NONE;
401 else if ( aValue.compareTo(PARITY_EVEN)==0 )
403 iParity=SerialPort.PARITY_EVEN;
405 else if ( aValue.compareTo(PARITY_ODD)==0 )
407 iParity=SerialPort.PARITY_ODD;
409 else if ( aValue.compareTo(PARITY_MARK)==0 )
411 iParity=SerialPort.PARITY_MARK;
413 else if ( aValue.compareTo(PARITY_SPACE)==0 )
415 iParity=SerialPort.PARITY_SPACE;
419 iLogger.severe("setParity(" + aValue + ")");
424 iLogger.severe("setParity(" + aValue + "):exception" + e);
431 * @param aValue String representation of the stop bits
433 private void setStopBits(final String aValue)
437 if ( aValue.compareTo(STOP_BITS_1)==0 )
439 iStopBits=SerialPort.STOPBITS_1;
441 else if ( aValue.compareTo(STOP_BITS_1_5)==0 )
443 iStopBits=SerialPort.STOPBITS_1_5;
445 else if ( aValue.compareTo(STOP_BITS_2)==0 )
447 iStopBits=SerialPort.STOPBITS_2;
451 iLogger.severe("setStopBits(" + aValue + ")");
456 iLogger.severe("setStopBits(" + aValue + "):exception" + e);
461 * Process a command from the input
463 private void processCommand() throws Exception
465 final String values[] = iCommand.split(BLOCK_SEPERATOR);
467 iSerialPort.getOutputStream().flush();
468 for ( int i=0; i<values.length; i++ )
471 * Commands should be of the type variable=value
473 final String parts[]=values[i].split(BLOCK_ASSIGN);
475 if ( parts.length==2 )
478 * Set baud rate command
480 if ( parts[0].compareTo(CMD_BAUD_RATE)==0 )
482 setBaudRate(parts[1]);
483 iSerialPort.setSerialPortParams(iBaudRate, iDataBits, iStopBits, iParity);
486 * Set data bits command
488 else if ( parts[0].compareTo(CMD_DATA_BITS)==0 )
490 setDataBits(parts[1]);
491 iSerialPort.setSerialPortParams(iBaudRate, iDataBits, iStopBits, iParity);
496 else if ( parts[0].compareTo(CMD_DELAY)==0 )
498 final int delay=Integer.parseInt(parts[1]);
504 else if ( parts[0].compareTo(CMD_DISCONNECT)==0 )
506 iRestartingDelay=Integer.parseInt(parts[1]);
512 else if ( parts[0].compareTo(CMD_ECHO)==0 )
514 final int length=parts[1].length();
515 for ( int index=0; index<length; ++index )
517 final byte out=(byte)(parts[1].charAt(index));
518 iLogger.finest("<< " + out);
519 iSerialPort.getOutputStream().write(out);
523 * Set flow control command
525 else if ( parts[0].compareTo(CMD_FLOW_CONTROL)==0 )
527 setFlowControl(parts[1]);
528 iSerialPort.setFlowControlMode(iFlowControl);
533 else if ( parts[0].compareTo(CMD_LOG)==0 )
535 iLogger.info(parts[1]);
540 else if ( parts[0].compareTo(CMD_PARITY)==0 )
543 iSerialPort.setSerialPortParams(iBaudRate, iDataBits, iStopBits, iParity);
546 * Set stop bits command
548 else if ( parts[0].compareTo(CMD_STOP_BITS)==0 )
550 setStopBits(parts[1]);
551 iSerialPort.setSerialPortParams(iBaudRate, iDataBits, iStopBits, iParity);
558 iLogger.severe("Bad command(" + parts[0] + ")");
563 iLogger.severe("Bad data");
569 * Process data read from input stream
571 * @param aLength Length of the data in the buffer
573 private void processInput(final int aLength) throws Exception
575 final String buffer=new String(iBuffer, 0, aLength);
576 iLogger.finest(">> " + buffer);
577 for ( int index=0; index<aLength; ++index )
579 switch ( iBuffer[index] )
587 * Clear the break interrupt count
593 * Query the break interrupt count
596 iLogger.finest("BI Count=" + iBI);
597 iLogger.finest("<< " + iBI);
598 iSerialPort.getOutputStream().write(iBI);
601 * Reset port setting to startup values
604 iBaudRate=iStartupBaudRate;
605 iDataBits=iStartupDataBits;
606 iStopBits=iStartupStopBits;
607 iParity=iStartupParity;
608 iFlowControl=iStartupFlowControl;
609 iSerialPort.setFlowControlMode(iFlowControl);
610 iSerialPort.setSerialPortParams(iBaudRate, iDataBits, iStopBits, iParity);
611 iStatus=EStatus.EStatusEcho;
615 * If in command mode add the byte to the command buffer
616 * unless we read the end of command block character
618 if ( iStatus==EStatus.EStatusCommandStart )
620 if ( iBuffer[index]==BYTE_BLOCK_END )
623 iStatus=EStatus.EStatusEcho;
627 iCommand += buffer.charAt(index);
631 * If in echo mode, echo the character unless we read the
632 * start of command block character
634 else if ( iStatus==EStatus.EStatusEcho )
636 if ( iBuffer[index]==BYTE_BLOCK_START )
639 iStatus=EStatus.EStatusCommandStart;
643 iLogger.finest("<< " + iBuffer[index]);
644 iSerialPort.getOutputStream().write(iBuffer[index]);
653 * Serial port event received
655 * @param aEvent Event received
657 public void serialEvent(SerialPortEvent aEvent)
659 switch ( aEvent.getEventType() )
661 case SerialPortEvent.DATA_AVAILABLE:
663 * Process data in input buffer
667 final int length = iSerialPort.getInputStream().read(iBuffer);
671 processInput(length);
680 iMainThread.interrupt();
683 case SerialPortEvent.BI:
685 * Increment break interrupt count
688 iLogger.finest("Break Interrupt");
690 case SerialPortEvent.CD:
694 iLogger.finest("Carrier Detect");
696 case SerialPortEvent.CTS:
700 iLogger.finest("Clear To Send");
702 case SerialPortEvent.DSR:
706 iLogger.finest("Data Set Ready");
708 case SerialPortEvent.FE:
712 iLogger.finest("Framing Error");
714 case SerialPortEvent.OE:
718 iLogger.finest("Overflow Error");
720 case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
724 iLogger.finest("Output Buffer Empty");
726 case SerialPortEvent.PE:
730 iLogger.finest("Parity Error");
732 case SerialPortEvent.RI:
736 iLogger.finest("Ring Interrupt");
739 iLogger.finest("Unknown event");
745 * Application entry point
747 * @param aArgs COmmand line arguments
749 public static void main(String[] aArgs)
751 final Options options = new Options();
753 options.addOption(new Option(OPTION_HELP, "print this message"));
755 OptionBuilder.withLongOpt(OPTION_PORT);
756 OptionBuilder.withDescription("set port COMx");
757 OptionBuilder.withValueSeparator( '=' );
758 OptionBuilder.hasArg();
759 options.addOption(OptionBuilder.create());
761 OptionBuilder.withLongOpt(OPTION_BAUD);
762 OptionBuilder.withDescription("set the baud rate");
763 OptionBuilder.withValueSeparator( '=' );
764 OptionBuilder.hasArg();
765 options.addOption(OptionBuilder.create());
767 OptionBuilder.withLongOpt(OPTION_DATA);
768 OptionBuilder.withDescription("set the data bits [" + DATA_BITS_5 +"|" + DATA_BITS_6 + "|" + DATA_BITS_7 + "|" + DATA_BITS_8 + "]");
769 OptionBuilder.withValueSeparator( '=' );
770 OptionBuilder.hasArg();
771 options.addOption(OptionBuilder.create());
773 OptionBuilder.withLongOpt(OPTION_STOP);
774 OptionBuilder.withDescription("set the stop bits [" + STOP_BITS_1 + "|" + STOP_BITS_1_5 + "|" + STOP_BITS_2 + "]");
775 OptionBuilder.withValueSeparator( '=' );
776 OptionBuilder.hasArg();
777 options.addOption(OptionBuilder.create());
779 OptionBuilder.withLongOpt(OPTION_PARITY);
780 OptionBuilder.withDescription("set the parity [" + PARITY_NONE + "|" + PARITY_EVEN + "|" + PARITY_ODD + "|" + PARITY_MARK + "|" + PARITY_SPACE + "]");
781 OptionBuilder.withValueSeparator( '=' );
782 OptionBuilder.hasArg();
783 options.addOption(OptionBuilder.create());
785 OptionBuilder.withLongOpt(OPTION_FLOW);
786 OptionBuilder.withDescription("set the flow control [" + FLOWCONTROL_NONE + "|" + FLOWCONTROL_RTSCTS + "|" + FLOWCONTROL_XONXOFF + "]");
787 OptionBuilder.withValueSeparator( '=' );
788 OptionBuilder.hasArg();
789 options.addOption(OptionBuilder.create());
791 final CommandLineParser parser = new PosixParser();
795 // parse the command line arguments
796 final CommandLine commandLine = parser.parse(options, aArgs);
798 if ( commandLine.hasOption(OPTION_HELP) )
800 final HelpFormatter formatter = new HelpFormatter();
801 formatter.printHelp("UartEchoServer", options);
805 final UartEchoServer echoServer=new UartEchoServer();
806 echoServer.Construct(commandLine);
809 catch ( Exception e )