001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.mina.transport.serial; 021 022import gnu.io.CommPortIdentifier; 023import gnu.io.PortInUseException; 024import gnu.io.SerialPort; 025import gnu.io.UnsupportedCommOperationException; 026 027import java.io.IOException; 028import java.net.SocketAddress; 029import java.util.Enumeration; 030import java.util.TooManyListenersException; 031import java.util.concurrent.Executor; 032 033import org.apache.mina.core.future.ConnectFuture; 034import org.apache.mina.core.future.DefaultConnectFuture; 035import org.apache.mina.core.service.AbstractIoConnector; 036import org.apache.mina.core.service.IoConnector; 037import org.apache.mina.core.service.TransportMetadata; 038import org.apache.mina.core.session.IdleStatusChecker; 039import org.apache.mina.core.session.IoSessionConfig; 040import org.apache.mina.core.session.IoSessionInitializer; 041import org.slf4j.Logger; 042import org.slf4j.LoggerFactory; 043 044/** 045 * {@link IoConnector} for serial communication transport. 046 * 047 * @author <a href="http://mina.apache.org">Apache MINA Project</a> 048 */ 049public final class SerialConnector extends AbstractIoConnector { 050 private final Logger log; 051 052 private IdleStatusChecker idleChecker; 053 054 public SerialConnector() { 055 this(null); 056 } 057 058 public SerialConnector(Executor executor) { 059 super(new DefaultSerialSessionConfig(), executor); 060 log = LoggerFactory.getLogger(SerialConnector.class); 061 062 idleChecker = new IdleStatusChecker(); 063 // we schedule the idle status checking task in this service exceutor 064 // it will be woke up every seconds 065 executeWorker(idleChecker.getNotifyingTask(), "idleStatusChecker"); 066 067 } 068 069 @Override 070 protected synchronized ConnectFuture connect0(SocketAddress remoteAddress, SocketAddress localAddress, 071 IoSessionInitializer<? extends ConnectFuture> sessionInitializer) { 072 073 CommPortIdentifier portId; 074 Enumeration<?> portList = CommPortIdentifier.getPortIdentifiers(); 075 076 SerialAddress portAddress = (SerialAddress) remoteAddress; 077 078 // looping around found ports 079 while (portList.hasMoreElements()) { 080 portId = (CommPortIdentifier) portList.nextElement(); 081 if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { 082 if (log.isDebugEnabled()) { 083 log.debug("Serial port discovered : " + portId.getName()); 084 } 085 if (portId.getName().equals(portAddress.getName())) { 086 try { 087 if (log.isDebugEnabled()) { 088 log.debug("Serial port found : " + portId.getName()); 089 } 090 091 SerialPort serialPort = initializePort("Apache MINA", portId, portAddress); 092 093 ConnectFuture future = new DefaultConnectFuture(); 094 SerialSessionImpl session = new SerialSessionImpl(this, getListeners(), portAddress, serialPort); 095 initSession(session, future, sessionInitializer); 096 session.start(); 097 return future; 098 } catch (PortInUseException e) { 099 if (log.isDebugEnabled()) { 100 log.debug("Port In Use Exception : ", e); 101 } 102 return DefaultConnectFuture.newFailedFuture(e); 103 } catch (UnsupportedCommOperationException e) { 104 if (log.isDebugEnabled()) { 105 log.debug("Comm Exception : ", e); 106 } 107 return DefaultConnectFuture.newFailedFuture(e); 108 } catch (IOException e) { 109 if (log.isDebugEnabled()) { 110 log.debug("IOException : ", e); 111 } 112 return DefaultConnectFuture.newFailedFuture(e); 113 } catch (TooManyListenersException e) { 114 if (log.isDebugEnabled()) { 115 log.debug("TooManyListenersException : ", e); 116 } 117 return DefaultConnectFuture.newFailedFuture(e); 118 } 119 } 120 } 121 } 122 123 return DefaultConnectFuture.newFailedFuture(new SerialPortUnavailableException("Serial port not found")); 124 } 125 126 @Override 127 protected void dispose0() throws Exception { 128 // stop the idle checking task 129 idleChecker.getNotifyingTask().cancel(); 130 } 131 132 public TransportMetadata getTransportMetadata() { 133 return SerialSessionImpl.METADATA; 134 } 135 136 private SerialPort initializePort(String user, CommPortIdentifier portId, SerialAddress portAddress) 137 throws UnsupportedCommOperationException, PortInUseException { 138 139 SerialSessionConfig config = (SerialSessionConfig) getSessionConfig(); 140 141 long connectTimeout = getConnectTimeoutMillis(); 142 if (connectTimeout > Integer.MAX_VALUE) { 143 connectTimeout = Integer.MAX_VALUE; 144 } 145 146 SerialPort serialPort = (SerialPort) portId.open(user, (int) connectTimeout); 147 148 serialPort.setSerialPortParams(portAddress.getBauds(), portAddress.getDataBitsForRXTX(), 149 portAddress.getStopBitsForRXTX(), portAddress.getParityForRXTX()); 150 151 serialPort.setFlowControlMode(portAddress.getFLowControlForRXTX()); 152 153 serialPort.notifyOnDataAvailable(true); 154 155 if (config.isLowLatency()) { 156 serialPort.setLowLatency(); 157 } 158 159 serialPort.setInputBufferSize(config.getInputBufferSize()); 160 serialPort.setOutputBufferSize(config.getOutputBufferSize()); 161 162 if (config.getReceiveThreshold() >= 0) { 163 serialPort.enableReceiveThreshold(config.getReceiveThreshold()); 164 } else { 165 serialPort.disableReceiveThreshold(); 166 } 167 168 return serialPort; 169 } 170 171 IdleStatusChecker getIdleStatusChecker0() { 172 return idleChecker; 173 } 174 175 public IoSessionConfig getSessionConfig() { 176 return sessionConfig; 177 } 178}