View Javadoc
1   /*
2    * Copyright 2013 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.channel.rxtx;
17  
18  import gnu.io.CommPort;
19  import gnu.io.CommPortIdentifier;
20  import gnu.io.SerialPort;
21  import io.netty.channel.ChannelFuture;
22  import io.netty.channel.ChannelPromise;
23  import io.netty.channel.oio.OioByteStreamChannel;
24  
25  import java.net.SocketAddress;
26  import java.util.concurrent.TimeUnit;
27  
28  import static io.netty.channel.rxtx.RxtxChannelOption.BAUD_RATE;
29  import static io.netty.channel.rxtx.RxtxChannelOption.DATA_BITS;
30  import static io.netty.channel.rxtx.RxtxChannelOption.DTR;
31  import static io.netty.channel.rxtx.RxtxChannelOption.PARITY_BIT;
32  import static io.netty.channel.rxtx.RxtxChannelOption.READ_TIMEOUT;
33  import static io.netty.channel.rxtx.RxtxChannelOption.RTS;
34  import static io.netty.channel.rxtx.RxtxChannelOption.STOP_BITS;
35  import static io.netty.channel.rxtx.RxtxChannelOption.WAIT_TIME;
36  
37  /**
38   * A channel to a serial device using the RXTX library.
39   *
40   * @deprecated this transport will be removed in the next major version.
41   */
42  @Deprecated
43  public class RxtxChannel extends OioByteStreamChannel {
44  
45      private static final RxtxDeviceAddress LOCAL_ADDRESS = new RxtxDeviceAddress("localhost");
46  
47      private final RxtxChannelConfig config;
48  
49      private boolean open = true;
50      private RxtxDeviceAddress deviceAddress;
51      private SerialPort serialPort;
52  
53      public RxtxChannel() {
54          super(null);
55  
56          config = new DefaultRxtxChannelConfig(this);
57      }
58  
59      @Override
60      public RxtxChannelConfig config() {
61          return config;
62      }
63  
64      @Override
65      public boolean isOpen() {
66          return open;
67      }
68  
69      @Override
70      protected AbstractUnsafe newUnsafe() {
71          return new RxtxUnsafe();
72      }
73  
74      @Override
75      protected void doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception {
76          RxtxDeviceAddress remote = (RxtxDeviceAddress) remoteAddress;
77          final CommPortIdentifier cpi = CommPortIdentifier.getPortIdentifier(remote.value());
78          final CommPort commPort = cpi.open(getClass().getName(), 1000);
79          commPort.enableReceiveTimeout(config().getOption(READ_TIMEOUT));
80          deviceAddress = remote;
81  
82          serialPort = (SerialPort) commPort;
83      }
84  
85      protected void doInit() throws Exception {
86          serialPort.setSerialPortParams(
87              config().getOption(BAUD_RATE),
88              config().getOption(DATA_BITS).value(),
89              config().getOption(STOP_BITS).value(),
90              config().getOption(PARITY_BIT).value()
91          );
92          serialPort.setDTR(config().getOption(DTR));
93          serialPort.setRTS(config().getOption(RTS));
94  
95          activate(serialPort.getInputStream(), serialPort.getOutputStream());
96      }
97  
98      @Override
99      public RxtxDeviceAddress localAddress() {
100         return (RxtxDeviceAddress) super.localAddress();
101     }
102 
103     @Override
104     public RxtxDeviceAddress remoteAddress() {
105         return (RxtxDeviceAddress) super.remoteAddress();
106     }
107 
108     @Override
109     protected RxtxDeviceAddress localAddress0() {
110         return LOCAL_ADDRESS;
111     }
112 
113     @Override
114     protected RxtxDeviceAddress remoteAddress0() {
115         return deviceAddress;
116     }
117 
118     @Override
119     protected void doBind(SocketAddress localAddress) throws Exception {
120         throw new UnsupportedOperationException();
121     }
122 
123     @Override
124     protected void doDisconnect() throws Exception {
125         doClose();
126     }
127 
128     @Override
129     protected void doClose() throws Exception {
130         open = false;
131         try {
132            super.doClose();
133         } finally {
134             if (serialPort != null) {
135                 serialPort.removeEventListener();
136                 serialPort.close();
137                 serialPort = null;
138             }
139         }
140     }
141 
142     @Override
143     protected boolean isInputShutdown() {
144         return !open;
145     }
146 
147     @Override
148     protected ChannelFuture shutdownInput() {
149         return newFailedFuture(new UnsupportedOperationException("shutdownInput"));
150     }
151 
152     private final class RxtxUnsafe extends AbstractUnsafe {
153         @Override
154         public void connect(
155                 final SocketAddress remoteAddress,
156                 final SocketAddress localAddress, final ChannelPromise promise) {
157             if (!promise.setUncancellable() || !ensureOpen(promise)) {
158                 return;
159             }
160 
161             try {
162                 final boolean wasActive = isActive();
163                 doConnect(remoteAddress, localAddress);
164 
165                 int waitTime = config().getOption(WAIT_TIME);
166                 if (waitTime > 0) {
167                     eventLoop().schedule(new Runnable() {
168                         @Override
169                         public void run() {
170                             try {
171                                 doInit();
172                                 safeSetSuccess(promise);
173                                 if (!wasActive && isActive()) {
174                                     pipeline().fireChannelActive();
175                                 }
176                             } catch (Throwable t) {
177                                 safeSetFailure(promise, t);
178                                 closeIfClosed();
179                             }
180                         }
181                    }, waitTime, TimeUnit.MILLISECONDS);
182                 } else {
183                     doInit();
184                     safeSetSuccess(promise);
185                     if (!wasActive && isActive()) {
186                         pipeline().fireChannelActive();
187                     }
188                 }
189             } catch (Throwable t) {
190                 safeSetFailure(promise, t);
191                 closeIfClosed();
192             }
193         }
194     }
195 }