001package jmri.jmrix.dccpp; 002 003import java.io.DataInputStream; 004import java.io.DataOutputStream; 005import org.slf4j.Logger; 006import org.slf4j.LoggerFactory; 007import purejavacomm.SerialPort; 008 009/** 010 * Abstract base for classes representing a DCC++ communications port. 011 * Based on XNetSerialPortController by Bob Jacobsen and Paul Bender. 012 * 013 * @author Bob Jacobsen Copyright (C) 2001, 2008 014 * @author Paul Bender Copyright (C) 2004,2010 015 * @author Mark Underwood Copyright (C) 2015 016 */ 017public abstract class DCCppSerialPortController extends jmri.jmrix.AbstractSerialPortController implements DCCppPortController { 018 019 protected SerialPort activeSerialPort = null; 020 021 private boolean outputBufferEmpty = true; 022 023 public DCCppSerialPortController() { 024 super(new DCCppSystemConnectionMemo()); 025 //option2Name = "Buffer"; 026 //options.put(option2Name, new Option("Check Buffer : ", validOption2)); 027 } 028 029 // base class. Implementations will provide InputStream and OutputStream 030 // objects to XNetTrafficController classes, who in turn will deal in messages. 031 // returns the InputStream from the port 032 @Override 033 public abstract DataInputStream getInputStream(); 034 035 // returns the outputStream to the port 036 @Override 037 public abstract DataOutputStream getOutputStream(); 038 039 /** 040 * Check that this object is ready to operate. This is a question of 041 * configuration, not transient hardware status. 042 */ 043 @Override 044 public abstract boolean status(); 045 046 /** 047 * Can the port accept additional characters? The state of CTS determines 048 * this, as there seems to be no way to check the number of queued bytes and 049 * buffer length. This might go false for short intervals, but it might also 050 * stick off if something goes wrong. 051 */ 052 @Override 053 public boolean okToSend() { 054 if ((activeSerialPort.getFlowControlMode() & SerialPort.FLOWCONTROL_RTSCTS_OUT) == SerialPort.FLOWCONTROL_RTSCTS_OUT) { 055 if (checkBuffer) { 056 log.debug("CTS: {} Buffer Empty: {}", activeSerialPort.isCTS(), outputBufferEmpty); 057 return (activeSerialPort.isCTS() && outputBufferEmpty); 058 } else { 059 log.debug("CTS: {}", activeSerialPort.isCTS()); 060 return (activeSerialPort.isCTS()); 061 } 062 } else { 063 if (checkBuffer) { 064 log.debug("Buffer Empty: {}", outputBufferEmpty); 065 return (outputBufferEmpty); 066 } else { 067 log.debug("No Flow Control or Buffer Check"); 068 return (true); 069 } 070 } 071 } 072 073 /** 074 * Say if the output buffer is empty or full. 075 * This should only be set to false by external processes. 076 */ 077 @Override 078 synchronized public void setOutputBufferEmpty(boolean s) { 079 outputBufferEmpty = s; 080 } 081 082 083 /* Option 2 is not currently used with RxTx 2.0. In the past, it 084 was used for the "check buffer status when sending" If this is still set 085 in a configuration file, we need to handle it, but we are not writing it 086 to new configuration files. */ 087 /*public String getCurrentOption2Setting() { 088 if(getOptionState(option2Name)==null) return("no"); 089 else return getOptionState(option2Name); 090 }*/ 091 092 protected String[] validOption2 = new String[]{"yes", "no"}; 093 private boolean checkBuffer = false; 094 095 /** 096 * Allow derived classes to set the private checkBuffer value. 097 * @param b Buffer to be held and used from now on. 098 */ 099 protected void setCheckBuffer(boolean b) { 100 checkBuffer = b; 101 } 102 103 @Override 104 public DCCppSystemConnectionMemo getSystemConnectionMemo() { 105 return (DCCppSystemConnectionMemo) super.getSystemConnectionMemo(); 106 } 107 108 private final static Logger log = LoggerFactory.getLogger(DCCppSerialPortController.class); 109 110}