001package jmri.jmrix.purejavacomm; 002 003import java.io.InputStream; 004import java.io.IOException; 005import java.io.OutputStream; 006import java.util.TooManyListenersException; 007 008import jmri.jmrix.AbstractSerialPortController; 009 010/** 011 * Serial port. 012 */ 013public class SerialPort { 014 015 public static final int DATABITS_8 = 8; 016 public static final int PARITY_NONE = 0; 017 public static final int PARITY_ODD = 1; 018 public static final int PARITY_EVEN = 2; 019 public static final int STOPBITS_1 = 1; 020 public static final int STOPBITS_2 = 2; 021 public static final int FLOWCONTROL_NONE = 0; 022 public static final int FLOWCONTROL_RTSCTS_IN = 1; 023 public static final int FLOWCONTROL_RTSCTS_OUT = 2; 024 025 private jmri.jmrix.SerialPort _serialPort; 026 private SerialPortEventListener _eventListener; 027 private boolean _threadStarted = false; 028 private Thread _inputThread; 029 private volatile boolean _notifyOnDataAvailable; 030 031 public SerialPort(jmri.jmrix.SerialPort serialPort) { 032 this._serialPort = serialPort; 033 034 Runnable runnable = () -> { 035 final int TIMEOUT = Integer.getInteger("purejavacomm.pollperiod", 10); 036 InputStream inputStream = _serialPort.getInputStream(); 037 038 while (true) { 039 try { 040 while (_notifyOnDataAvailable && (_eventListener != null) 041 && (inputStream.available() > 0)) { 042 _eventListener.serialEvent(new SerialPortEvent( 043 this, SerialPortEvent.DATA_AVAILABLE, false, true)); 044 } 045 Thread.sleep(TIMEOUT); 046 } catch (InterruptedException e) { 047 log.error("Thread interrupted"); 048 break; 049 } catch (IOException e) { 050 log.error("An IO error occurred", e); 051 break; 052 } 053 } 054 }; 055 _inputThread = jmri.util.ThreadingUtil.newThread( 056 runnable, "jmri.jmrix.purejavacomm.SerialPort"); 057 _inputThread.setDaemon(true); 058 } 059 060 private void setParity(int parity) { 061 switch (parity) { 062 case PARITY_NONE: 063 _serialPort.setParity(jmri.jmrix.SerialPort.Parity.NONE); 064 break; 065 066 case PARITY_EVEN: 067 _serialPort.setParity(jmri.jmrix.SerialPort.Parity.EVEN); 068 break; 069 070 case PARITY_ODD: 071 _serialPort.setParity(jmri.jmrix.SerialPort.Parity.ODD); 072 break; 073 074 default: 075 throw new IllegalArgumentException("Unknown parity: "+Integer.toString(parity)); 076 } 077 } 078 079 public void setSerialPortParams(int baudRate, int dataBits, int stopBits, int parity) throws UnsupportedCommOperationException { 080 _serialPort.setBaudRate(baudRate); 081 _serialPort.setNumDataBits(dataBits); 082 _serialPort.setNumStopBits(stopBits); 083 setParity(parity); 084 } 085 086 public void addEventListener(SerialPortEventListener listener) throws TooManyListenersException { 087 if (listener == null) { 088 throw new IllegalArgumentException("listener cannot be null"); 089 } 090 if (this._eventListener != null) { 091 throw new TooManyListenersException(); 092 } 093 this._eventListener = listener; 094 if (!_threadStarted) { 095 _threadStarted = true; 096 _inputThread.start(); 097 } 098 } 099 100 public void notifyOnDataAvailable(boolean value) { 101 _notifyOnDataAvailable = value; 102 } 103 104 public void setFlowControlMode(int mode) throws UnsupportedCommOperationException { 105 switch (mode) { 106 case FLOWCONTROL_NONE: 107 _serialPort.setFlowControl(AbstractSerialPortController.FlowControl.NONE); 108 break; 109 110 case (FLOWCONTROL_RTSCTS_IN | FLOWCONTROL_RTSCTS_OUT): 111 _serialPort.setFlowControl(AbstractSerialPortController.FlowControl.RTSCTS); 112 break; 113 114 default: 115 throw new IllegalArgumentException("Unknown flow control mode: "+Integer.toString(mode)); 116 } 117 } 118 119 public InputStream getInputStream() throws IOException { 120 return _serialPort.getInputStream(); 121 } 122 123 public OutputStream getOutputStream() throws IOException { 124 return _serialPort.getOutputStream(); 125 } 126 127 public int getBaudRate() { 128 return _serialPort.getBaudRate(); 129 } 130 131 public void setDTR(boolean value) { 132 if (value) { 133 _serialPort.setDTR(); 134 } else { 135 _serialPort.clearDTR(); 136 } 137 } 138 139 public void setRTS(boolean value) { 140 if (value) { 141 _serialPort.setRTS(); 142 } else { 143 _serialPort.clearRTS(); 144 } 145 } 146 147 public boolean isDTR() { 148 return _serialPort.getDTR(); 149 } 150 151 public boolean isRTS() { 152 return _serialPort.getRTS(); 153 } 154 155 public boolean isDSR() { 156 return _serialPort.getDSR(); 157 } 158 159 public boolean isCTS() { 160 return _serialPort.getCTS(); 161 } 162 163 public boolean isCD() { 164 return _serialPort.getDCD(); 165 } 166 167 public boolean isRI() { 168 return _serialPort.getRI(); 169 } 170 171 public boolean isReceiveTimeoutEnabled() { 172 return false; // Not implemented 173 } 174 175 public int getReceiveTimeout() { 176 return 0; // Not implemented 177 } 178 179 public void close() { 180 _serialPort.closePort(); 181 } 182 183 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(SerialPort.class); 184}