All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gnu.io.RXTXCommDriver Maven / Gradle / Ivy

There is a newer version: 1.0.1
Show newest version
/*-------------------------------------------------------------------------
|   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); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy