diff --git a/example/pom.xml b/example/pom.xml
index 24c22d7e50..8416c11ad6 100644
--- a/example/pom.xml
+++ b/example/pom.xml
@@ -75,6 +75,11 @@
netty-transport-udt
${project.version}
+
+ ${project.groupId}
+ netty-transport-rxtx
+ ${project.version}
+
diff --git a/example/src/main/java/io/netty/example/rxtx/RxtxClient.java b/example/src/main/java/io/netty/example/rxtx/RxtxClient.java
new file mode 100644
index 0000000000..c18525ce2c
--- /dev/null
+++ b/example/src/main/java/io/netty/example/rxtx/RxtxClient.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2013 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package io.netty.example.rxtx;
+
+import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.socket.oio.OioEventLoopGroup;
+import io.netty.handler.codec.LineBasedFrameDecoder;
+import io.netty.handler.codec.string.StringDecoder;
+import io.netty.handler.codec.string.StringEncoder;
+import io.netty.transport.rxtx.RxtxChannel;
+import io.netty.transport.rxtx.RxtxDeviceAddress;
+
+/**
+ * Sends one message to a serial device
+ */
+public final class RxtxClient {
+
+ public static void main(String[] args) throws Exception {
+ Bootstrap b = new Bootstrap();
+ try {
+ b.group(new OioEventLoopGroup())
+ .channel(RxtxChannel.class)
+ .remoteAddress(new RxtxDeviceAddress("/dev/ttyUSB0"))
+ .handler(new ChannelInitializer() {
+ @Override
+ public void initChannel(RxtxChannel ch) throws Exception {
+ ch.pipeline().addLast(
+ new LineBasedFrameDecoder(32768),
+ new StringEncoder(),
+ new StringDecoder(),
+ new RxtxClientHandler()
+ );
+ }
+ });
+
+ ChannelFuture f = b.connect().sync();
+
+ f.channel().closeFuture().sync();
+ } finally {
+ b.shutdown();
+ }
+ }
+
+ private RxtxClient() {
+ }
+}
diff --git a/example/src/main/java/io/netty/example/rxtx/RxtxClientHandler.java b/example/src/main/java/io/netty/example/rxtx/RxtxClientHandler.java
new file mode 100644
index 0000000000..5b42bd8874
--- /dev/null
+++ b/example/src/main/java/io/netty/example/rxtx/RxtxClientHandler.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2013 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package io.netty.example.rxtx;
+
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundMessageHandlerAdapter;
+
+public class RxtxClientHandler extends ChannelInboundMessageHandlerAdapter {
+
+ @Override
+ public void channelActive(ChannelHandlerContext ctx) {
+ ctx.write("AT\n");
+ }
+
+ @Override
+ protected void messageReceived(ChannelHandlerContext ctx, String msg) throws Exception {
+ if ("OK".equals(msg)) {
+ System.out.println("Serial port responded to AT");
+ } else {
+ System.out.println("Serial port responded with not-OK: " + msg);
+ }
+ ctx.close();
+ }
+}
diff --git a/pom.xml b/pom.xml
index ea635cef21..4651ba63d2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -79,6 +79,7 @@
codec-http
codec-socks
transport
+ transport-rxtx
transport-sctp
transport-udt
handler
@@ -106,6 +107,12 @@
2.4.1
+
+ org.rxtx
+ rxtx
+ 2.1.7
+
+
javax.servlet
servlet-api
diff --git a/transport-rxtx/pom.xml b/transport-rxtx/pom.xml
new file mode 100644
index 0000000000..71e46bec3f
--- /dev/null
+++ b/transport-rxtx/pom.xml
@@ -0,0 +1,54 @@
+
+
+
+
+ 4.0.0
+
+ io.netty
+ netty-parent
+ 4.0.0.Beta1-SNAPSHOT
+
+
+ netty-transport-rxtx
+ jar
+
+ Netty/RXTX Transport
+
+
+
+ ${project.groupId}
+ netty-buffer
+ ${project.version}
+
+
+ ${project.groupId}
+ netty-codec
+ ${project.version}
+
+
+ ${project.groupId}
+ netty-transport
+ ${project.version}
+
+
+ org.rxtx
+ rxtx
+
+
+
+
+
diff --git a/transport-rxtx/src/main/java/io/netty/transport/rxtx/RxtxChannel.java b/transport-rxtx/src/main/java/io/netty/transport/rxtx/RxtxChannel.java
new file mode 100644
index 0000000000..3bde80ec2d
--- /dev/null
+++ b/transport-rxtx/src/main/java/io/netty/transport/rxtx/RxtxChannel.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2013 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package io.netty.transport.rxtx;
+
+import static io.netty.transport.rxtx.RxtxChannelOptions.*;
+
+import io.netty.buffer.BufType;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelConfig;
+import io.netty.channel.ChannelMetadata;
+import io.netty.channel.socket.oio.AbstractOioByteChannel;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.SocketAddress;
+import java.net.SocketTimeoutException;
+import java.nio.channels.NotYetConnectedException;
+
+import gnu.io.CommPort;
+import gnu.io.CommPortIdentifier;
+import gnu.io.SerialPort;
+
+/**
+ * A channel to a serial device using the RXTX library.
+ */
+public class RxtxChannel extends AbstractOioByteChannel {
+ private static final ChannelMetadata METADATA = new ChannelMetadata(BufType.BYTE, true);
+
+ private final ChannelConfig config;
+
+ private RxtxDeviceAddress deviceAddress;
+ private SerialPort serialPort;
+ private InputStream in;
+ private OutputStream out;
+
+ public RxtxChannel() {
+ super(null, null);
+
+ config = new RxtxChannelConfig(this);
+ }
+
+ @Override
+ public ChannelConfig config() {
+ return config;
+ }
+
+ @Override
+ public ChannelMetadata metadata() {
+ return METADATA;
+ }
+
+ @Override
+ public boolean isOpen() {
+ return true;
+ }
+
+ @Override
+ public boolean isActive() {
+ return in != null && out != null;
+ }
+
+ @Override
+ protected int available() {
+ try {
+ return in.available();
+ } catch (IOException e) {
+ return 0;
+ }
+ }
+
+ @Override
+ protected int doReadBytes(ByteBuf buf) throws Exception {
+ try {
+ return buf.writeBytes(in, buf.writableBytes());
+ } catch (SocketTimeoutException e) {
+ return 0;
+ }
+ }
+
+ @Override
+ protected void doWriteBytes(ByteBuf buf) throws Exception {
+ if (out == null) {
+ throw new NotYetConnectedException();
+ }
+ buf.readBytes(out, buf.readableBytes());
+ }
+
+ @Override
+ protected void doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception {
+ RxtxDeviceAddress remote = (RxtxDeviceAddress) remoteAddress;
+ final CommPortIdentifier cpi =
+ CommPortIdentifier.getPortIdentifier(remote.getDeviceAddress());
+ final CommPort commPort = cpi.open(getClass().getName(), 1000);
+
+ deviceAddress = remote;
+
+ serialPort = (SerialPort) commPort;
+ serialPort.setSerialPortParams(
+ config().getOption(BAUD_RATE),
+ config().getOption(DATA_BITS).getValue(),
+ config().getOption(STOP_BITS).getValue(),
+ config().getOption(PARITY_BIT).getValue()
+ );
+ serialPort.setDTR(config().getOption(DTR));
+ serialPort.setRTS(config().getOption(RTS));
+
+ out = serialPort.getOutputStream();
+ in = serialPort.getInputStream();
+ }
+
+ @Override
+ protected SocketAddress localAddress0() {
+ return null;
+ }
+
+ @Override
+ protected SocketAddress remoteAddress0() {
+ return deviceAddress;
+ }
+
+ @Override
+ protected void doBind(SocketAddress localAddress) throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected void doDisconnect() throws Exception {
+ doClose();
+ }
+
+ @Override
+ protected void doClose() throws Exception {
+ IOException ex = null;
+
+ try {
+ if (in != null) {
+ in.close();
+ }
+ } catch (IOException e) {
+ ex = e;
+ }
+
+ try {
+ if (out != null) {
+ out.close();
+ }
+ } catch (IOException e) {
+ ex = e;
+ }
+
+ if (serialPort != null) {
+ serialPort.removeEventListener();
+ serialPort.close();
+ }
+
+ in = null;
+ out = null;
+ serialPort = null;
+
+ if (ex != null) {
+ throw ex;
+ }
+ }
+}
diff --git a/transport-rxtx/src/main/java/io/netty/transport/rxtx/RxtxChannelConfig.java b/transport-rxtx/src/main/java/io/netty/transport/rxtx/RxtxChannelConfig.java
new file mode 100644
index 0000000000..6233011531
--- /dev/null
+++ b/transport-rxtx/src/main/java/io/netty/transport/rxtx/RxtxChannelConfig.java
@@ -0,0 +1,317 @@
+/*
+ * Copyright 2013 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package io.netty.transport.rxtx;
+
+import static io.netty.transport.rxtx.RxtxChannelOptions.*;
+
+import io.netty.channel.ChannelOption;
+import io.netty.channel.DefaultChannelConfig;
+
+import java.util.Map;
+
+import gnu.io.SerialPort;
+
+/**
+ * A configuration class for RXTX device connections.
+ */
+public class RxtxChannelConfig extends DefaultChannelConfig {
+
+ public enum Stopbits {
+ /**
+ * 1 stop bit will be sent at the end of every character
+ */
+ STOPBITS_1(SerialPort.STOPBITS_1),
+ /**
+ * 2 stop bits will be sent at the end of every character
+ */
+ STOPBITS_2(SerialPort.STOPBITS_2),
+ /**
+ * 1.5 stop bits will be sent at the end of every character
+ */
+ STOPBITS_1_5(SerialPort.STOPBITS_1_5);
+
+ private final int value;
+
+ Stopbits(int value) {
+ this.value = value;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public static Stopbits ofValue(int value) {
+ for (Stopbits stopbit : Stopbits.values()) {
+ if (stopbit.value == value) {
+ return stopbit;
+ }
+ }
+ throw new IllegalArgumentException("Unknown value for Stopbits: " + value + '.');
+ }
+ }
+
+ public enum Databits {
+ /**
+ * 5 data bits will be used for each character (ie. Baudot code)
+ */
+ DATABITS_5(SerialPort.DATABITS_5),
+ /**
+ * 6 data bits will be used for each character
+ */
+ DATABITS_6(SerialPort.DATABITS_6),
+ /**
+ * 7 data bits will be used for each character (ie. ASCII)
+ */
+ DATABITS_7(SerialPort.DATABITS_7),
+ /**
+ * 8 data bits will be used for each character (ie. binary data)
+ */
+ DATABITS_8(SerialPort.DATABITS_8);
+
+ private final int value;
+
+ Databits(int value) {
+ this.value = value;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public static Databits ofValue(int value) {
+ for (Databits databit : Databits.values()) {
+ if (databit.value == value) {
+ return databit;
+ }
+ }
+ throw new IllegalArgumentException("Unknown value for Databits: " + value + '.');
+ }
+ }
+
+ public enum Paritybit {
+ /**
+ * No parity bit will be sent with each data character at all
+ */
+ NONE(SerialPort.PARITY_NONE),
+ /**
+ * An odd parity bit will be sent with each data character, ie. will be set
+ * to 1 if the data character contains an even number of bits set to 1.
+ */
+ ODD(SerialPort.PARITY_ODD),
+ /**
+ * An even parity bit will be sent with each data character, ie. will be set
+ * to 1 if the data character contains an odd number of bits set to 1.
+ */
+ EVEN(SerialPort.PARITY_EVEN),
+ /**
+ * A mark parity bit (ie. always 1) will be sent with each data character
+ */
+ MARK(SerialPort.PARITY_MARK),
+ /**
+ * A space parity bit (ie. always 0) will be sent with each data character
+ */
+ SPACE(SerialPort.PARITY_SPACE);
+
+ private final int value;
+
+ Paritybit(int value) {
+ this.value = value;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public static Paritybit ofValue(int value) {
+ for (Paritybit paritybit : Paritybit.values()) {
+ if (paritybit.value == value) {
+ return paritybit;
+ }
+ }
+ throw new IllegalArgumentException("Unknown value for paritybit: " + value + '.');
+ }
+ }
+
+ private volatile int baudrate = 115200;
+
+ private volatile boolean dtr;
+
+ private volatile boolean rts;
+
+ private volatile Stopbits stopbits = Stopbits.STOPBITS_1;
+
+ private volatile Databits databits = Databits.DATABITS_8;
+
+ private volatile Paritybit paritybit = Paritybit.NONE;
+
+ public RxtxChannelConfig(RxtxChannel channel) {
+ super(channel);
+ }
+
+ @Override
+ public Map, Object> getOptions() {
+ return getOptions(super.getOptions(),
+ BAUD_RATE, DTR, RTS, STOP_BITS, DATA_BITS, PARITY_BIT);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public T getOption(ChannelOption option) {
+ if (option == BAUD_RATE) {
+ return (T) Integer.valueOf(getBaudrate());
+ }
+ if (option == DTR) {
+ return (T) Boolean.valueOf(isDtr());
+ }
+ if (option == RTS) {
+ return (T) Boolean.valueOf(isRts());
+ }
+ if (option == STOP_BITS) {
+ return (T) getStopbits();
+ }
+ if (option == DATA_BITS) {
+ return (T) getDatabits();
+ }
+ if (option == PARITY_BIT) {
+ return (T) getParitybit();
+ }
+ return super.getOption(option);
+ }
+
+ @Override
+ public boolean setOption(ChannelOption option, T value) {
+ validate(option, value);
+
+ if (option == BAUD_RATE) {
+ setBaudrate((Integer) value);
+ } else if (option == DTR) {
+ setDtr((Boolean) value);
+ } else if (option == RTS) {
+ setRts((Boolean) value);
+ } else if (option == STOP_BITS) {
+ setStopbits((Stopbits) value);
+ } else if (option == DATA_BITS) {
+ setDatabits((Databits) value);
+ } else if (option == PARITY_BIT) {
+ setParitybit((Paritybit) value);
+ } else {
+ return super.setOption(option, value);
+ }
+ return true;
+ }
+
+ /**
+ * Sets the baud rate (ie. bits per second) for communication with the serial device.
+ * The baud rate will include bits for framing (in the form of stop bits and parity),
+ * such that the effective data rate will be lower than this value.
+ *
+ * @param baudrate The baud rate (in bits per second)
+ */
+ public void setBaudrate(final int baudrate) {
+ this.baudrate = baudrate;
+ }
+
+ /**
+ * Sets the number of stop bits to include at the end of every character to aid the
+ * serial device in synchronising with the data.
+ *
+ * @param stopbits The number of stop bits to use
+ */
+ public void setStopbits(final Stopbits stopbits) {
+ this.stopbits = stopbits;
+ }
+
+ /**
+ * Sets the number of data bits to use to make up each character sent to the serial
+ * device.
+ *
+ * @param databits The number of data bits to use
+ */
+ public void setDatabits(final Databits databits) {
+ this.databits = databits;
+ }
+
+ /**
+ * Sets the type of parity bit to be used when communicating with the serial device.
+ *
+ * @param paritybit The type of parity bit to be used
+ */
+ public void setParitybit(final Paritybit paritybit) {
+ this.paritybit = paritybit;
+ }
+
+ /**
+ * @return The configured baud rate, defaulting to 115200 if unset
+ */
+ public int getBaudrate() {
+ return baudrate;
+ }
+
+ /**
+ * @return The configured stop bits, defaulting to {@link Stopbits#STOPBITS_1} if unset
+ */
+ public Stopbits getStopbits() {
+ return stopbits;
+ }
+
+ /**
+ * @return The configured data bits, defaulting to {@link Databits#DATABITS_8} if unset
+ */
+ public Databits getDatabits() {
+ return databits;
+ }
+
+ /**
+ * @return The configured parity bit, defaulting to {@link Paritybit#NONE} if unset
+ */
+ public Paritybit getParitybit() {
+ return paritybit;
+ }
+
+ /**
+ * @return true if the serial device should support the Data Terminal Ready signal
+ */
+ public boolean isDtr() {
+ return dtr;
+ }
+
+ /**
+ * Sets whether the serial device supports the Data Terminal Ready signal, used for
+ * flow control
+ *
+ * @param dtr true if DTR is supported, false otherwise
+ */
+ public void setDtr(final boolean dtr) {
+ this.dtr = dtr;
+ }
+
+ /**
+ * @return true if the serial device should support the Ready to Send signal
+ */
+ public boolean isRts() {
+ return rts;
+ }
+
+ /**
+ * Sets whether the serial device supports the Request To Send signal, used for flow
+ * control
+ *
+ * @param rts true if RTS is supported, false otherwise
+ */
+ public void setRts(final boolean rts) {
+ this.rts = rts;
+ }
+}
diff --git a/transport-rxtx/src/main/java/io/netty/transport/rxtx/RxtxChannelOptions.java b/transport-rxtx/src/main/java/io/netty/transport/rxtx/RxtxChannelOptions.java
new file mode 100644
index 0000000000..a50ab28b30
--- /dev/null
+++ b/transport-rxtx/src/main/java/io/netty/transport/rxtx/RxtxChannelOptions.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2013 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package io.netty.transport.rxtx;
+
+import io.netty.channel.ChannelOption;
+import io.netty.transport.rxtx.RxtxChannelConfig.Databits;
+import io.netty.transport.rxtx.RxtxChannelConfig.Paritybit;
+import io.netty.transport.rxtx.RxtxChannelConfig.Stopbits;
+
+/**
+ * Options for configuring a serial port connection
+ */
+public final class RxtxChannelOptions {
+ public static final ChannelOption BAUD_RATE =
+ new ChannelOption("BAUD_RATE");
+
+ public static final ChannelOption DTR =
+ new ChannelOption("DTR");
+
+ public static final ChannelOption RTS =
+ new ChannelOption("RTS");
+
+ public static final ChannelOption STOP_BITS =
+ new ChannelOption("STOP_BITS");
+
+ public static final ChannelOption DATA_BITS =
+ new ChannelOption("DATA_BITS");
+
+ public static final ChannelOption PARITY_BIT =
+ new ChannelOption("PARITY_BIT");
+
+ private RxtxChannelOptions() {
+ }
+}
diff --git a/transport-rxtx/src/main/java/io/netty/transport/rxtx/RxtxDeviceAddress.java b/transport-rxtx/src/main/java/io/netty/transport/rxtx/RxtxDeviceAddress.java
new file mode 100644
index 0000000000..d1db101436
--- /dev/null
+++ b/transport-rxtx/src/main/java/io/netty/transport/rxtx/RxtxDeviceAddress.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2013 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package io.netty.transport.rxtx;
+
+import java.net.SocketAddress;
+
+/**
+ * A {@link SocketAddress} subclass to wrap the serial port address of a RXTX
+ * device (e.g. COM1, /dev/ttyUSB0).
+ */
+public class RxtxDeviceAddress extends SocketAddress {
+
+ private static final long serialVersionUID = -2907820090993709523L;
+
+ private final String deviceAddress;
+
+ /**
+ * Creates a RxtxDeviceAddress representing the address of the serial port.
+ *
+ * @param deviceAddress the address of the device (e.g. COM1, /dev/ttyUSB0, ...)
+ */
+ public RxtxDeviceAddress(String deviceAddress) {
+ this.deviceAddress = deviceAddress;
+ }
+
+ /**
+ * @return The serial port address of the device (e.g. COM1, /dev/ttyUSB0, ...)
+ */
+ public String getDeviceAddress() {
+ return deviceAddress;
+ }
+}
diff --git a/transport-rxtx/src/main/java/io/netty/transport/rxtx/package-info.java b/transport-rxtx/src/main/java/io/netty/transport/rxtx/package-info.java
new file mode 100644
index 0000000000..98223e759e
--- /dev/null
+++ b/transport-rxtx/src/main/java/io/netty/transport/rxtx/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * A serial and parallel port communication transport based on RXTX.
+ */
+package io.netty.transport.rxtx;