gnu.io.RXTXCommDriver Maven / Gradle / Ivy
Show all versions of jrxtx Show documentation
/*-------------------------------------------------------------------------
| RXTX License v 2.1 - LGPL v 2.1 + Linking Over Controlled Interface.
| RXTX is a native interface to serial ports in java.
| Copyright 1998 Kevin Hester, [email protected]
| Copyright 2000-2008 Trent Jarvi [email protected] and others who
| actually wrote it. See individual source files for more information.
|
| A copy of the LGPL v 2.1 may be found at
| http://www.gnu.org/licenses/lgpl.txt on March 4th 2007. A copy is
| here for your convenience.
|
| This library is free software; you can redistribute it and/or
| modify it under the terms of the GNU Lesser General Public
| License as published by the Free Software Foundation; either
| version 2.1 of the License, or (at your option) any later version.
|
| This library is distributed in the hope that it will be useful,
| but WITHOUT ANY WARRANTY; without even the implied warranty of
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
| Lesser General Public License for more details.
|
| An executable that contains no derivative of any portion of RXTX, but
| is designed to work with RXTX by being dynamically linked with it,
| is considered a "work that uses the Library" subject to the terms and
| conditions of the GNU Lesser General Public License.
|
| The following has been added to the RXTX License to remove
| any confusion about linking to RXTX. We want to allow in part what
| section 5, paragraph 2 of the LGPL does not permit in the special
| case of linking over a controlled interface. The intent is to add a
| Java Specification Request or standards body defined interface in the
| future as another exception but one is not currently available.
|
| http://www.fsf.org/licenses/gpl-faq.html#LinkingOverControlledInterface
|
| As a special exception, the copyright holders of RXTX give you
| permission to link RXTX with independent modules that communicate with
| RXTX solely through the Sun Microsytems CommAPI interface version 2,
| regardless of the license terms of these independent modules, and to copy
| and distribute the resulting combined work under terms of your choice,
| provided that every copy of the combined work is accompanied by a complete
| copy of the source code of RXTX (the version of RXTX used to produce the
| combined work), being distributed under the terms of the GNU Lesser General
| Public License plus this exception. An independent module is a
| module which is not derived from or based on RXTX.
|
| Note that people who make modified versions of RXTX are not obligated
| to grant this special exception for their modified versions; it is
| their choice whether to do so. The GNU Lesser General Public License
| gives permission to release a modified version without this exception; this
| exception also makes it possible to release a modified version which
| carries forward this exception.
|
| You should have received a copy of the GNU Lesser General Public
| License along with this library; if not, write to the Free
| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
| All trademarks belong to their respective owners.
--------------------------------------------------------------------------*/
/* Martin Pool added support for explicitly-specified
* lists of ports, October 2000. */
/* Joseph Goldstone reorganized to support registered ports,
* known ports, and scanned ports, July 2001 */
package gnu.io;
import java.io.File;
import java.io.FileInputStream;
import java.util.Iterator;
import java.util.Properties;
import java.util.StringTokenizer;
/**
* This is the JavaComm for Linux driver.
*/
public class RXTXCommDriver implements CommDriver {
private final static boolean debug = false;
private final static boolean devel = false;
private final static boolean noVersionOutput = "true".equals(System.getProperty("gnu.io.rxtx.NoVersionOutput"));
static {
if (debug)
System.out.println("RXTXCommDriver {}");
LibraryLoader.loadRxtxNative();
/*
* Perform a crude check to make sure people don't mix versions of the Jar and native lib
*
* Mixing the libs can create a nightmare.
*
* It could be possible to move this over to RXTXVersion but All we want to do is warn people when first loading
* the Library.
*/
String JarVersion = RXTXVersion.getVersion();
String LibVersion;
try {
LibVersion = RXTXVersion.nativeGetVersion();
} catch (Error UnsatisfiedLinkError) {
// for rxtx prior to 2.1.7
LibVersion = nativeGetVersion();
}
if (devel) {
if (!noVersionOutput) {
System.out.println("Stable Library");
System.out.println("=========================================");
System.out.println("Native lib Version = " + LibVersion);
System.out.println("Java lib Version = " + JarVersion);
}
}
if (!JarVersion.equals(LibVersion)) {
System.out.println("WARNING: RXTX Version mismatch\n\tJar version = " + JarVersion
+ "\n\tnative lib Version = " + LibVersion);
}
else if (debug) {
System.out.println(
"RXTXCommDriver:\n\tJar version = " + JarVersion + "\n\tnative lib Version = " + LibVersion);
}
}
/** Get the Serial port prefixes for the running OS */
private String deviceDirectory;
private String osName;
private native boolean registerKnownPorts(int PortType);
private native boolean isPortPrefixValid(String dev);
private native boolean testRead(String dev, int type);
private native String getDeviceDirectory();
// for rxtx prior to 2.1.7
public static native String nativeGetVersion();
private final String[] getValidPortPrefixes(String CandidatePortPrefixes[]) {
/*
* 256 is the number of prefixes ( COM, cua, ttyS, ...) not the number of devices (ttyS0, ttyS1, ttyS2, ...)
*
* On a Linux system there are about 400 prefixes in deviceDirectory. registerScannedPorts() assigns
* CandidatePortPrefixes to something less than 50 prefixes.
*
* Trent
*/
String ValidPortPrefixes[] = new String[256];
if (debug)
System.out.println("\nRXTXCommDriver:getValidPortPrefixes()");
if (CandidatePortPrefixes == null) {
if (debug)
System.out.println(
"\nRXTXCommDriver:getValidPortPrefixes() No ports prefixes known for this System.\nPlease check the port prefixes listed for "
+ osName + " in RXTXCommDriver:registerScannedPorts()\n");
}
int i = 0;
for (int j = 0; j < CandidatePortPrefixes.length; j++) {
if (isPortPrefixValid(CandidatePortPrefixes[j])) {
ValidPortPrefixes[i++] = CandidatePortPrefixes[j];
}
}
String[] returnArray = new String[i];
System.arraycopy(ValidPortPrefixes, 0, returnArray, 0, i);
if (ValidPortPrefixes[0] == null) {
if (debug) {
System.out.println(
"\nRXTXCommDriver:getValidPortPrefixes() No ports matched the list assumed for this\nSystem in the directory "
+ deviceDirectory + ". Please check the ports listed for \"" + osName
+ "\" in\nRXTXCommDriver:registerScannedPorts()\nTried:");
for (int j = 0; j < CandidatePortPrefixes.length; j++) {
System.out.println("\t" + CandidatePortPrefixes[i]);
}
}
}
else {
if (debug)
System.out.println(
"\nRXTXCommDriver:getValidPortPrefixes()\nThe following port prefixes have been identified as valid on "
+ osName + ":\n");
/*
* for(int j=0;jFrom the NullDriver.java CommAPI sample.
*
* added printerport stuff Holger Lehmann July 12, 1999 IBM
*
* Added ttyM for Moxa boards Removed obsolete device cuaa Peter Bennett January 02, 2000 Bencom
*
*/
/**
* Determine the OS and where the OS has the devices located
*/
public void initialize() {
if (debug)
System.out.println("RXTXCommDriver:initialize()");
osName = System.getProperty("os.name");
deviceDirectory = getDeviceDirectory();
/*
* First try to register ports specified in the properties file. If that doesn't exist, then scan for ports.
*/
for (int PortType = CommPortIdentifier.PORT_SERIAL; PortType <= CommPortIdentifier.PORT_PARALLEL; PortType++) {
if (!registerSpecifiedPorts(PortType)) {
if (!registerKnownPorts(PortType)) {
registerScannedPorts(PortType);
}
}
}
}
private void addSpecifiedPorts(String names, int PortType) {
final String pathSep = System.getProperty("path.separator", ":");
final StringTokenizer tok = new StringTokenizer(names, pathSep);
if (debug)
System.out.println("\nRXTXCommDriver:addSpecifiedPorts()");
while (tok.hasMoreElements()) {
String PortName = tok.nextToken();
if (debug)
System.out.println("Trying " + PortName + ".");
if (testRead(PortName, PortType)) {
CommPortIdentifier.addPortName(PortName, PortType, this);
if (debug)
System.out.println("Success: Read from " + PortName + ".");
}
else {
if (debug)
System.out.println("Fail: Cannot read from " + PortName + ".");
}
}
}
/*
* Register ports specified in the file "gnu.io.rxtx.properties" Key system properties: gnu.io.rxtx.SerialPorts
* gnu.io.rxtx.ParallelPorts
*
* Tested only with sun jdk1.3 The file gnu.io.rxtx.properties must reside in the java extension dir
*
* Example: /usr/local/java/jre/lib/ext/gnu.io.rxtx.properties
*
* The file contains the following key properties:
*
* gnu.io.rxtx.SerialPorts=/dev/ttyS0:/dev/ttyS1: gnu.io.rxtx.ParallelPorts=/dev/lp0:
*
*/
private boolean registerSpecifiedPorts(int PortType) {
String val = null;
Properties origp = System.getProperties(); // save system properties
String[] ext_dirs = System.getProperty("java.ext.dirs").split(":");
String fs = System.getProperty("file.separator");
for (int n = 0; n < ext_dirs.length; ++n) {
String ext_file = "?";
try {
ext_file = ext_dirs[n] + fs + "gnu.io.rxtx.properties";
FileInputStream rxtx_prop = new FileInputStream(ext_file);
Properties p = new Properties();
p.load(rxtx_prop);
System.setProperties(p);
for (Iterator> it = p.keySet().iterator(); it.hasNext();) {
String key = (String) it.next();
String value = p.getProperty(key);
if (debug) {
System.out.println(key + " -> " + value);
}
System.setProperty(key, value);
}
} catch (Exception e) {
if (debug) {
System.out.println("The file \"" + ext_file + "\" doesn't exist.");
System.out.println(e.toString());
} // end if
continue;
} // end catch
if (debug) {
System.out.println("Read properties from \"" + ext_file + "\".");
} // end if
} // end for
if (debug)
System.out.println("checking for system-known ports of type " + PortType);
if (debug)
System.out.println("checking registry for ports of type " + PortType);
switch (PortType) {
case CommPortIdentifier.PORT_SERIAL:
if ((val = System.getProperty("gnu.io.rxtx.SerialPorts")) == null)
val = System.getProperty("gnu.io.SerialPorts");
break;
case CommPortIdentifier.PORT_PARALLEL:
if ((val = System.getProperty("gnu.io.rxtx.ParallelPorts")) == null)
val = System.getProperty("gnu.io.ParallelPorts");
break;
default:
if (debug)
System.out.println(
"unknown port type " + PortType + " passed to RXTXCommDriver.registerSpecifiedPorts()");
}
System.setProperties(origp); // recall saved properties
if (val != null) {
addSpecifiedPorts(val, PortType);
return true;
}
else {
return false;
}
}
/*
* Look for all entries in deviceDirectory, and if they look like they should be serial ports on this OS and they
* can be opened then register them.
*
*/
private void registerScannedPorts(int PortType) {
String[] CandidateDeviceNames;
if (debug)
System.out.println("scanning device directory " + deviceDirectory + " for ports of type " + PortType);
if (osName.equals("Windows CE")) {
String[] temp = { "COM1:", "COM2:", "COM3:", "COM4:", "COM5:", "COM6:", "COM7:", "COM8:" };
CandidateDeviceNames = temp;
}
else if (osName.toLowerCase().indexOf("windows") != -1) {
String[] temp = new String[259];
for (int i = 1; i <= 256; i++) {
temp[i - 1] = "COM" + i;
}
for (int i = 1; i <= 3; i++) {
temp[i + 255] = "LPT" + i;
}
CandidateDeviceNames = temp;
}
else if (osName.equals("Solaris") || osName.equals("SunOS")) {
/*
* Solaris uses a few different ways to identify ports. They could be /dev/term/a /dev/term0 /dev/cua/a
* /dev/cuaa the /dev/???/a appears to be on more systems.
*
* The uucp lock files should not cause problems.
*/
/*
* File dev = new File( "/dev/term" ); String deva[] = dev.list(); dev = new File( "/dev/cua" ); String
* devb[] = dev.list(); String[] temp = new String[ deva.length + devb.length ]; for(int j
* =0;j 0)
term[l++] = "term/";
/*
* dev = new File( "/dev/cua0" ); if( dev.list().length > 0 ) term[l++] = "cua/";
*/
String[] temp = new String[l];
for (l--; l >= 0; l--)
temp[l] = term[l];
CandidateDeviceNames = temp;
}
else {
File dev = new File(deviceDirectory);
String[] temp = dev.list();
CandidateDeviceNames = temp;
}
if (CandidateDeviceNames == null) {
if (debug)
System.out.println("RXTXCommDriver:registerScannedPorts() no Device files to check ");
return;
}
String CandidatePortPrefixes[] = {};
switch (PortType) {
case CommPortIdentifier.PORT_SERIAL:
if (debug)
System.out.println("scanning for serial ports for os " + osName);
/*
* There are _many_ possible ports that can be used on Linux. See below in the fake Linux-all-ports case for
* a list. You may add additional ports here but be warned that too many will significantly slow down port
* enumeration. Linux 2.6 has udev support which should be faster as only ports the kernel finds should be
* exposed in /dev
*
* See also how to override port enumeration and specifying port in INSTALL.
*
* taj
*/
if (osName.equals("Linux")) {
String[] Temp = { "ttySA", // for the IPAQs
"comx", // linux COMMX synchronous serial card
"holter", // custom card for heart monitoring
"modem", // linux symbolic link to modem.
"rfcomm", // bluetooth serial device
"ttyircomm", // linux IrCommdevices (IrDA serial emu)
"ttycosa0c", // linux COSA/SRP synchronous serial card
"ttycosa1c", // linux COSA/SRP synchronous serial card
"ttyACM", // linux CDC ACM devices
"ttyC", // linux cyclades cards
"ttyCH", // linux Chase Research AT/PCI-Fast serial card
"ttyD", // linux Digiboard serial card
"ttyE", // linux Stallion serial card
"ttyF", // linux Computone IntelliPort serial card
"ttyH", // linux Chase serial card
"ttyI", // linux virtual modems
"ttyL", // linux SDL RISCom serial card
"ttyM", // linux PAM Software's multimodem boards
// linux ISI serial card
"ttyMX", // linux Moxa Smart IO cards
"ttyP", // linux Hayes ESP serial card
"ttyR", // linux comtrol cards
// linux Specialix RIO serial card
"ttyS", // linux Serial Ports
"ttySI", // linux SmartIO serial card
"ttySR", // linux Specialix RIO serial card 257+
"ttyT", // linux Technology Concepts serial card
"ttyUSB", // linux USB serial converters
"ttyV", // linux Comtrol VS-1000 serial controller
"ttyW", // linux specialix cards
"ttyX" // linux SpecialX serial card
};
CandidatePortPrefixes = Temp;
}
else if (osName.toLowerCase().indexOf("qnx") != -1) {
String[] Temp = { "ser" };
CandidatePortPrefixes = Temp;
}
else if (osName.equals("Irix")) {
String[] Temp = { "ttyc", // irix raw character devices
"ttyd", // irix basic serial ports
"ttyf", // irix serial ports with hardware flow
"ttym", // irix modems
"ttyq", // irix pseudo ttys
"tty4d", // irix RS422
"tty4f", // irix RS422 with HSKo/HSki
"midi", // irix serial midi
"us" // irix mapped interface
};
CandidatePortPrefixes = Temp;
}
else if (osName.equals("FreeBSD")) // FIXME this is probably wrong
{
String[] Temp = { "ttyd", // general purpose serial ports
"cuaa", // dialout serial ports
"ttyA", // Specialix SI/XIO dialin ports
"cuaA", // Specialix SI/XIO dialout ports
"ttyD", // Digiboard - 16 dialin ports
"cuaD", // Digiboard - 16 dialout ports
"ttyE", // Stallion EasyIO (stl) dialin ports
"cuaE", // Stallion EasyIO (stl) dialout ports
"ttyF", // Stallion Brumby (stli) dialin ports
"cuaF", // Stallion Brumby (stli) dialout ports
"ttyR", // Rocketport dialin ports
"cuaR", // Rocketport dialout ports
"stl" // Stallion EasyIO board or Brumby N
};
CandidatePortPrefixes = Temp;
}
else if (osName.equals("NetBSD")) // FIXME this is probably wrong
{
String[] Temp = { "tty0" // netbsd serial ports
};
CandidatePortPrefixes = Temp;
}
else if (osName.equals("Solaris") || osName.equals("SunOS")) {
String[] Temp = { "term/", "cua/" };
CandidatePortPrefixes = Temp;
}
else if (osName.equals("HP-UX")) {
String[] Temp = { "tty0p", // HP-UX serial ports
"tty1p" // HP-UX serial ports
};
CandidatePortPrefixes = Temp;
}
else if (osName.equals("UnixWare") || osName.equals("OpenUNIX")) {
String[] Temp = { "tty00s", // UW7/OU8 serial ports
"tty01s", "tty02s", "tty03s" };
CandidatePortPrefixes = Temp;
}
else if (osName.equals("OpenServer")) {
String[] Temp = { "tty1A", // OSR5 serial ports
"tty2A", "tty3A", "tty4A", "tty5A", "tty6A", "tty7A", "tty8A", "tty9A", "tty10A", "tty11A",
"tty12A", "tty13A", "tty14A", "tty15A", "tty16A", "ttyu1A", // OSR5 USB-serial ports
"ttyu2A", "ttyu3A", "ttyu4A", "ttyu5A", "ttyu6A", "ttyu7A", "ttyu8A", "ttyu9A", "ttyu10A",
"ttyu11A", "ttyu12A", "ttyu13A", "ttyu14A", "ttyu15A", "ttyu16A" };
CandidatePortPrefixes = Temp;
}
else if (osName.equals("Compaq's Digital UNIX") || osName.equals("OSF1")) {
String[] Temp = { "tty0" // Digital Unix serial ports
};
CandidatePortPrefixes = Temp;
}
else if (osName.equals("BeOS")) {
String[] Temp = { "serial" // BeOS serial ports
};
CandidatePortPrefixes = Temp;
}
else if (osName.equals("Mac OS X")) {
String[] Temp = {
// Keyspan USA-28X adapter, USB port 1
"cu.KeyUSA28X191.",
// Keyspan USA-28X adapter, USB port 1
"tty.KeyUSA28X191.",
// Keyspan USA-28X adapter, USB port 2
"cu.KeyUSA28X181.",
// Keyspan USA-28X adapter, USB port 2
"tty.KeyUSA28X181.",
// Keyspan USA-19 adapter
"cu.KeyUSA19181.",
// Keyspan USA-19 adapter
"tty.KeyUSA19181." };
CandidatePortPrefixes = Temp;
}
else if (osName.toLowerCase().indexOf("windows") != -1) {
String[] Temp = { "COM" // win32 serial ports
// "//./COM" // win32 serial ports
};
CandidatePortPrefixes = Temp;
}
else {
if (debug)
System.out.println("No valid prefixes for serial ports have been entered for " + osName
+ " in RXTXCommDriver.java. This may just be a typo in the method registerScanPorts().");
}
break;
case CommPortIdentifier.PORT_PARALLEL:
if (debug)
System.out.println("scanning for parallel ports for os " + osName);
/**
* Get the Parallel port prefixes for the running os Holger Lehmann July 12, 1999 IBM
*/
if (osName.equals("Linux")
/*
* || osName.equals("NetBSD") FIXME || osName.equals("HP-UX") FIXME || osName.equals("Irix") FIXME ||
* osName.equals("BeOS") FIXME || osName.equals("Compaq's Digital UNIX") FIXME
*/
) {
String[] temp = { "lp" // linux printer port
};
CandidatePortPrefixes = temp;
}
else if (osName.equals("FreeBSD")) {
String[] temp = { "lpt" };
CandidatePortPrefixes = temp;
}
else if (osName.toLowerCase().indexOf("windows") != -1) {
String[] temp = { "LPT" };
CandidatePortPrefixes = temp;
}
else /* printer support is green */
{
String[] temp = {};
CandidatePortPrefixes = temp;
}
break;
default:
if (debug)
System.out.println("Unknown PortType " + PortType + " passed to RXTXCommDriver.registerScannedPorts()");
}
registerValidPorts(CandidateDeviceNames, CandidatePortPrefixes, PortType);
}
/*
* From the NullDriver.java CommAPI sample.
*/
/**
* @param PortName
* The name of the port the OS recognizes
* @param PortType
* CommPortIdentifier.PORT_SERIAL or PORT_PARALLEL
* @return CommPort getCommPort() will be called by CommPortIdentifier from its openPort() method. PortName is a
* string that was registered earlier using the CommPortIdentifier.addPortName() method. getCommPort()
* returns an object that extends either SerialPort or ParallelPort.
*/
public CommPort getCommPort(String PortName, int PortType) {
if (debug)
System.out.println("RXTXCommDriver:getCommPort(" + PortName + "," + PortType + ")");
try {
switch (PortType) {
case CommPortIdentifier.PORT_SERIAL:
if (osName.toLowerCase().indexOf("windows") == -1) {
return new RXTXPort(PortName);
}
else {
return new RXTXPort(deviceDirectory + PortName);
}
case CommPortIdentifier.PORT_PARALLEL:
return new LPRPort(PortName);
default:
if (debug)
System.out.println("unknown PortType " + PortType + " passed to RXTXCommDriver.getCommPort()");
}
} catch (PortInUseException e) {
if (debug)
System.out.println("Port " + PortName + " in use by another application");
}
return null;
}
/* Yikes. Trying to call println from C for odd reasons */
public void Report(String arg) {
System.out.println(arg);
}
}