001package jmri.jmrix.xpa.serialdriver;
002
003import java.io.IOException;
004
005import jmri.InstanceManager;
006import jmri.jmrix.xpa.XpaPortController;
007import jmri.jmrix.xpa.XpaSystemConnectionMemo;
008import jmri.jmrix.xpa.XpaTrafficController;
009
010import org.slf4j.Logger;
011import org.slf4j.LoggerFactory;
012
013import purejavacomm.CommPortIdentifier;
014import purejavacomm.NoSuchPortException;
015import purejavacomm.PortInUseException;
016import purejavacomm.UnsupportedCommOperationException;
017
018/**
019 * Implements SerialPortAdapter for a modem connected to an XPA.
020 * <p>
021 * This connects an XPA+Modem connected to an XpressNet based command station
022 * via a serial com port. Normally controlled by the SerialDriverFrame class.
023 * <p>
024 * The current implementation only handles the 9,600 baud rate. It uses the
025 * first configuraiont variable for the modem initialization string.
026 *
027 * @author Paul Bender Copyright (C) 2004
028 */
029public class SerialDriverAdapter extends XpaPortController {
030
031    public SerialDriverAdapter() {
032
033        super(new XpaSystemConnectionMemo());
034        ((XpaSystemConnectionMemo)getSystemConnectionMemo()).setXpaTrafficController(new XpaTrafficController());
035
036
037        option1Name = "ModemInitString"; // NOI18N
038        options.put(option1Name, new Option(Bundle.getMessage("ModemInitStringLabel"), new String[]{"ATX0E0"}));
039        this.manufacturerName = jmri.jmrix.lenz.LenzConnectionTypeList.LENZ;
040    }
041
042    purejavacomm.SerialPort activeSerialPort = null;
043
044    @Override
045    public String openPort(String portName, String appName) {
046        // open the port, check ability to set moderators
047        try {
048            // get and open the primary port
049            CommPortIdentifier portID = CommPortIdentifier.getPortIdentifier(portName);
050            try {
051                activeSerialPort = (purejavacomm.SerialPort) portID.open(appName, 2000);  // name of program, msec to wait
052            } catch (PortInUseException p) {
053                return handlePortBusy(p, portName, log);
054            }
055
056            // try to set it for communication via SerialDriver
057            try {
058                activeSerialPort.setSerialPortParams(9600,
059                        purejavacomm.SerialPort.DATABITS_8,
060                        purejavacomm.SerialPort.STOPBITS_1,
061                        purejavacomm.SerialPort.PARITY_NONE);
062            } catch (UnsupportedCommOperationException e) {
063                log.error("Cannot set serial parameters on port {}: {}", portName, e.getMessage());
064                return "Cannot set serial parameters on port " + portName + ": " + e.getMessage();
065            }
066
067            // disable flow control; hardware lines used for signaling, XON/XOFF might appear in data
068            configureLeadsAndFlowControl(activeSerialPort, 0);
069
070            // set timeout
071            // activeSerialPort.enableReceiveTimeout(1000);
072            log.debug("Serial timeout was observed as: {} {}", activeSerialPort.getReceiveTimeout(), activeSerialPort.isReceiveTimeoutEnabled());
073
074            // purge contents, if any
075            purgeStream(activeSerialPort.getInputStream());
076
077            // report status?
078            if (log.isInfoEnabled()) {
079                log.info("{} port opened at {} baud, sees  DTR: {} RTS: {} DSR: {} CTS: {}  CD: {}", portName, activeSerialPort.getBaudRate(), activeSerialPort.isDTR(), activeSerialPort.isRTS(), activeSerialPort.isDSR(), activeSerialPort.isCTS(), activeSerialPort.isCD());
080            }
081
082            opened = true;
083
084        } catch (NoSuchPortException p) {
085            return handlePortNotFound(p, portName, log);
086        } catch (IOException ex) {
087            log.error("Unexpected exception while opening port {}", portName, ex);
088            return "IO Exception while opening port " + portName + ": " + ex;
089        }
090
091        return null; // indicates OK return
092
093    }
094
095    /**
096     * set up all of the other objects to operate with an XPA+Modem Connected to
097     * an XpressNet based command station connected to this port
098     */
099    @Override
100    public void configure() {
101
102        // connect to the traffic controller
103        XpaSystemConnectionMemo memo = ((XpaSystemConnectionMemo)getSystemConnectionMemo());
104        XpaTrafficController tc = memo.getXpaTrafficController();
105        tc.connectPort(this);
106
107        InstanceManager.store(memo.getPowerManager(), jmri.PowerManager.class);
108        InstanceManager.store(memo.getTurnoutManager(),jmri.TurnoutManager.class);
109        InstanceManager.store(memo.getThrottleManager(),jmri.ThrottleManager.class);
110        memo.register();
111
112        // start operation
113        tc.startTransmitThread();
114        sinkThread = new Thread(tc);
115        sinkThread.start();
116    }
117
118    private Thread sinkThread;
119
120    @Override
121    public boolean status() {
122        return opened;
123    }
124
125    /**
126     * {@inheritDoc}
127     * Currently only 9,600 bps
128     */
129    @Override
130    public String[] validBaudRates() {
131        return new String[]{"9,600 bps"};
132    }
133
134    /**
135     * {@inheritDoc}
136     */
137    @Override
138    public int[] validBaudNumbers() {
139        return new int[]{9600};
140    }
141
142    @Override
143    public int defaultBaudIndex() {
144        return 0;
145    }
146
147    private final static Logger log = LoggerFactory.getLogger(SerialDriverAdapter.class);
148
149}