1
/*-------------------------------------------------------------------------
2
| A wrapper to convert RXTX into Linux Java Comm
3
| Copyright 1998 Kevin Hester, kevinh@acm.org
4
| Copyright 2000-2004 Trent Jarvi, taj@www.linux.org.uk
6
| This library is free software; you can redistribute it and/or
7
| modify it under the terms of the GNU Library General Public
8
| License as published by the Free Software Foundation; either
9
| version 2 of the License, or (at your option) any later version.
11
| This library is distributed in the hope that it will be useful,
12
| but WITHOUT ANY WARRANTY; without even the implied warranty of
13
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
| Library General Public License for more details.
16
| You should have received a copy of the GNU Library General Public
17
| License along with this library; if not, write to the Free
18
| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
--------------------------------------------------------------------------*/
21
/* Martin Pool <mbp@linuxcare.com> added support for explicitly-specified
22
* lists of ports, October 2000. */
23
/* Joseph Goldstone <joseph@lp.com> reorganized to support registered ports,
24
* known ports, and scanned ports, July 2001 */
30
import java.util.StringTokenizer;
33
This is the JavaComm for Linux driver.
35
public class RXTXCommDriver implements CommDriver
38
private final static boolean debug = false;
39
private final static boolean devel = true;
44
if(debug ) System.out.println("RXTXCommDriver {}");
46
System.loadLibrary( "rxtxSerial" );
50
Perform a crude check to make sure people don't mix
51
versions of the Jar and native lib
53
Mixing the libs can create a nightmare.
55
It could be possible to move this over to RXTXVersion
56
but All we want to do is warn people when first loading
59
String JarVersion = RXTXVersion.getVersion();
60
String LibVersion = nativeGetVersion();
64
System.out.println("Devel Library");
65
System.out.println("=========================================");
66
System.out.println("Native lib Version = " + JarVersion );
67
System.out.println("Java lib Version = " + LibVersion );
70
/* FIXME static not working
71
if ( ! JarVersion.equals( LibVersion ) )
73
System.out.println( "WARNING: RXTX Version mismatch\n\tJar version = " + JarVersion + "\n\tnative lib Version = " + LibVersion );
77
System.out.println( "RXTXCommDriver:\n\tJar version = " + JarVersion + "\n\tnative lib Version = " + LibVersion );
82
/** Get the Serial port prefixes for the running OS */
83
private String deviceDirectory;
84
private String osName;
85
private static native String nativeGetVersion();
86
private native boolean registerKnownPorts(int PortType);
87
private native boolean isPortPrefixValid(String dev);
88
private native boolean testRead(String dev, int type);
89
private native String getDeviceDirectory();
91
private final String[] getValidPortPrefixes(String CandidatePortPrefixes[])
94
256 is the number of prefixes ( COM, cua, ttyS, ...) not
95
the number of devices (ttyS0, ttyS1, ttyS2, ...)
97
On a Linux system there are about 400 prefixes in
99
registerScannedPorts() assigns CandidatePortPrefixes to
100
something less than 50 prefixes.
105
String ValidPortPrefixes[]=new String [256];
107
System.out.println("\nRXTXCommDriver:getValidPortPrefixes()");
108
if(CandidatePortPrefixes==null)
111
System.out.println("\nRXTXCommDriver:getValidPortPrefixes() No ports prefixes known for this System.\nPlease check the port prefixes listed for " + osName + " in RXTXCommDriver:registerScannedPorts()\n");
114
for(int j=0;j<CandidatePortPrefixes.length;j++){
115
if(isPortPrefixValid(CandidatePortPrefixes[j])) {
116
ValidPortPrefixes[i++]=
117
new String(CandidatePortPrefixes[j]);
120
String[] returnArray=new String[i];
121
System.arraycopy(ValidPortPrefixes, 0, returnArray, 0, i);
122
if(ValidPortPrefixes[0]==null)
126
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:");
127
for(int j=0;j<CandidatePortPrefixes.length;j++){
128
System.out.println("\t" +
129
CandidatePortPrefixes[i]);
136
System.out.println("\nRXTXCommDriver:getValidPortPrefixes()\nThe following port prefixes have been identified as valid on " + osName + ":\n");
138
for(int j=0;j<returnArray.length;j++)
141
System.out.println("\t" + j + " " +
149
/** handle solaris/sunos /dev/cua/a convention */
150
private void checkSolaris(String PortName, int PortType)
153
for( p[0] =97 ;p[0] < 123; p[0]++ )
155
if (testRead(PortName.concat(new String(p)),PortType))
157
CommPortIdentifier.addPortName(
158
PortName.concat(new String(p)),
165
private void registerValidPorts(
166
String CandidateDeviceNames[],
167
String ValidPortPrefixes[],
172
/* FIXME quick fix to get COM1-8 on windows working. The
173
Read test is not working properly and its crunch time...
174
if(osName.toLowerCase().indexOf("windows") != -1 )
176
for( i=0;i < CandidateDeviceNames.length;i++ )
178
CommPortIdentifier.addPortName( CandidateDeviceNames[i],
187
System.out.println("Entering registerValidPorts()");
189
System.out.println(" Candidate devices:");
190
for (int dn=0;dn<CandidateDeviceNames.length;dn++)
191
System.out.println(" " +
192
CandidateDeviceNames[dn]);
193
System.out.println(" valid port prefixes:");
194
for (int pp=0;pp<ValidPortPrefixes.length;pp++)
195
System.out.println(" "+ValidPortPrefixes[pp]);
198
if ( CandidateDeviceNames!=null && ValidPortPrefixes!=null)
200
for( i = 0;i<CandidateDeviceNames.length; i++ ) {
201
for( p = 0;p<ValidPortPrefixes.length; p++ ) {
203
* device file Valid ports
204
* /dev/ttyR[0-9]* != /dev/ttyS[0-9]*
205
* /dev/ttySI[0-9]* != /dev/ttyS[0-9]*
206
* /dev/ttyS[0-9]* == /dev/ttyS[0-9]*
208
* Otherwise we check some ports
209
* multiple times. Perl would rock
212
* If the above passes, we try to read
213
* from the port. If there is no err
217
String V = ValidPortPrefixes[ p ];
219
String C = CandidateDeviceNames[ i ];
220
if( C.length() < VL ) continue;
222
C.substring(VL).toUpperCase();
224
C.substring(VL).toLowerCase();
225
if( !( C.regionMatches(0, V, 0, VL ) &&
231
if(osName.toLowerCase().indexOf("windows") == -1 )
234
new String(deviceDirectory +
244
System.out.println( C +
246
System.out.println( CU +
249
if( osName.equals("Solaris") ||
250
osName.equals("SunOS"))
251
checkSolaris(PortName,PortType);
252
else if (testRead(PortName, PortType))
254
CommPortIdentifier.addPortName(
264
System.out.println("Leaving registerValidPorts()");
269
* initialize() will be called by the CommPortIdentifier's static
270
* initializer. The responsibility of this method is:
271
* 1) Ensure that that the hardware is present.
272
* 2) Load any required native libraries.
273
* 3) Register the port names with the CommPortIdentifier.
275
* <p>From the NullDriver.java CommAPI sample.
277
* added printerport stuff
282
* Added ttyM for Moxa boards
283
* Removed obsolete device cuaa
291
* Determine the OS and where the OS has the devices located
293
public void initialize()
296
if (debug) System.out.println("RXTXCommDriver:initialize()");
298
osName=System.getProperty("os.name");
299
deviceDirectory=getDeviceDirectory();
302
First try to register ports specified in the properties
303
file. If that doesn't exist, then scan for ports.
305
for (int PortType=CommPortIdentifier.PORT_SERIAL;PortType<=CommPortIdentifier.PORT_PARALLEL;PortType++) {
306
if (!registerSpecifiedPorts(PortType)) {
307
if (!registerKnownPorts(PortType)) {
308
registerScannedPorts(PortType);
314
private void addSpecifiedPorts(String names, int PortType)
316
final String pathSep = System.getProperty("path.separator", ":");
317
final StringTokenizer tok = new StringTokenizer(names, pathSep);
320
System.out.println("\nRXTXCommDriver:addSpecifiedPorts()");
321
while (tok.hasMoreElements())
323
String PortName = tok.nextToken();
325
if (testRead(PortName, PortType))
326
CommPortIdentifier.addPortName(PortName,
332
* Register ports specified in the file "gnu.io.rxtx.properties"
333
* Key system properties:
334
* gnu.io.rxtx.SerialPorts
335
* gnu.io.rxtx.ParallelPorts
337
* Tested only with sun jdk1.3
338
* The file gnu.io.rxtx.properties must reside in the java extension dir
340
* Example: /usr/local/java/jre/lib/ext/gnu.io.rxtx.properties
342
* The file contains the following key properties:
344
* gnu.io.rxtx.SerialPorts=/dev/ttyS0:/dev/ttyS1:
345
* gnu.io.rxtx.ParallelPorts=/dev/lp0:
348
private boolean registerSpecifiedPorts(int PortType)
355
String ext_dir=System.getProperty("java.ext.dirs")+System.getProperty("file.separator");
356
FileInputStream rxtx_prop=new FileInputStream(ext_dir+"gnu.io.rxtx.properties");
357
Properties p=new Properties(System.getProperties());
359
System.setProperties(p);
362
System.out.println("The file: gnu.io.rxtx.properties doesn't exists.");
363
System.out.println(e.toString());
368
System.out.println("checking for system-known ports of type "+PortType);
370
System.out.println("checking registry for ports of type "+PortType);
373
case CommPortIdentifier.PORT_SERIAL:
374
if ((val = System.getProperty("gnu.io.rxtx.SerialPorts")) == null)
375
val = System.getProperty("gnu.io.SerialPorts");
378
case CommPortIdentifier.PORT_PARALLEL:
379
if ((val = System.getProperty("gnu.io.rxtx.ParallelPorts")) == null)
380
val = System.getProperty("gnu.io.ParallelPorts");
384
System.out.println("unknown port type "+PortType+" passed to RXTXCommDriver.registerSpecifiedPorts()");
388
addSpecifiedPorts(val, PortType);
394
* Look for all entries in deviceDirectory, and if they look like they should
395
* be serial ports on this OS and they can be opened then register
399
private void registerScannedPorts(int PortType)
401
String[] CandidateDeviceNames;
403
System.out.println("scanning device directory "+deviceDirectory+" for ports of type "+PortType);
404
if(osName.equals("Windows CE"))
407
{ "COM1:", "COM2:","COM3:","COM4:",
408
"COM5:", "COM6:", "COM7:", "COM8:" };
409
CandidateDeviceNames=temp;
411
else if(osName.toLowerCase().indexOf("windows") != -1 )
414
{ "COM1:", "COM2:","COM3:","COM4:",
415
"COM5:", "COM6:", "COM7:", "COM8:" };
417
/* //./name is supposed to work for port numbers > 8 */
419
{ "//./COM1", "//./COM2", "//./COM3",
420
"//./COM4", "//./COM5", "//./COM6",
421
"//./COM7", "//./COM8" };
425
"COM1", "COM2", "COM3",
426
"COM4", "COM5", "COM6",
429
OK, you asked for it The thread gods will
432
"COM9", "COM10", "COM11",
433
"COM12", "COM13", "COM14",
436
Lets toss in LPT too!
438
"LPT1", "LPT2", "LPT3"
441
{ "COM1", "COM2","COM3","COM4",
442
"COM5", "COM6", "COM7", "COM8" };
444
CandidateDeviceNames=temp;
446
else if ( osName.equals("Solaris") || osName.equals("SunOS"))
448
/* Solaris uses a few different ways to identify ports.
449
They could be /dev/term/a /dev/term0 /dev/cua/a /dev/cuaa
450
the /dev/???/a appears to be on more systems.
452
The uucp lock files should not cause problems.
455
File dev = new File( "/dev/term" );
456
String deva[] = dev.list();
457
dev = new File( "/dev/cua" );
458
String devb[] = dev.list();
459
String[] temp = new String[ deva.length + devb.length ];
460
for(int j =0;j<deva.length;j++)
461
deva[j] = "term/" + deva[j];
462
for(int j =0;j<devb.length;j++)
463
devb[j] = "cua/" + devb[j];
464
System.arraycopy( deva, 0, temp, 0, deva.length );
465
System.arraycopy( devb, 0, temp,
466
deva.length, devb.length );
468
for( int j = 0; j< temp.length;j++)
469
System.out.println( temp[j] );
471
CandidateDeviceNames=temp;
476
ok.. Look the the dirctories representing the port
477
kernel driver interface.
479
If there are entries there are possibly ports we can
480
use and need to enumerate.
483
String term[] = new String[2];
487
dev = new File( "/dev/term" );
488
if( dev.list().length > 0 );
489
term[l++] = new String( "term/" );
491
dev = new File( "/dev/cua0" );
492
if( dev.list().length > 0 );
493
term[l++] = new String( "cua/" );
495
String[] temp = new String[l];
498
CandidateDeviceNames=temp;
502
File dev = new File( deviceDirectory );
503
String[] temp = dev.list();
504
CandidateDeviceNames=temp;
506
if (CandidateDeviceNames==null)
509
System.out.println("RXTXCommDriver:registerScannedPorts() no Device files to check ");
513
String CandidatePortPrefixes[] = {};
515
case CommPortIdentifier.PORT_SERIAL:
517
System.out.println("scanning for serial ports for os "+osName);
518
if(osName.equals("Linux"))
521
"ttyS", // linux Serial Ports
522
"ttySA" // for the IPAQs
524
CandidatePortPrefixes=Temp;
526
else if(osName.equals("Linux-all-ports"))
528
/* if you want to enumerate all ports ~5000
529
possible, then replace the above with this
532
"comx", // linux COMMX synchronous serial card
533
"holter", // custom card for heart monitoring
534
"modem", // linux symbolic link to modem.
535
"ttyircomm", // linux IrCommdevices (IrDA serial emu)
536
"ttycosa0c", // linux COSA/SRP synchronous serial card
537
"ttycosa1c", // linux COSA/SRP synchronous serial card
538
"ttyC", // linux cyclades cards
539
"ttyCH",// linux Chase Research AT/PCI-Fast serial card
540
"ttyD", // linux Digiboard serial card
541
"ttyE", // linux Stallion serial card
542
"ttyF", // linux Computone IntelliPort serial card
543
"ttyH", // linux Chase serial card
544
"ttyI", // linux virtual modems
545
"ttyL", // linux SDL RISCom serial card
546
"ttyM", // linux PAM Software's multimodem boards
547
// linux ISI serial card
548
"ttyMX",// linux Moxa Smart IO cards
549
"ttyP", // linux Hayes ESP serial card
550
"ttyR", // linux comtrol cards
551
// linux Specialix RIO serial card
552
"ttyS", // linux Serial Ports
553
"ttySI",// linux SmartIO serial card
554
"ttySR",// linux Specialix RIO serial card 257+
555
"ttyT", // linux Technology Concepts serial card
556
"ttyUSB",//linux USB serial converters
557
"ttyV", // linux Comtrol VS-1000 serial controller
558
"ttyW", // linux specialix cards
559
"ttyX" // linux SpecialX serial card
561
CandidatePortPrefixes=Temp;
563
else if(osName.toLowerCase().indexOf("qnx") != -1 )
568
CandidatePortPrefixes=Temp;
570
else if(osName.equals("Irix"))
573
"ttyc", // irix raw character devices
574
"ttyd", // irix basic serial ports
575
"ttyf", // irix serial ports with hardware flow
576
"ttym", // irix modems
577
"ttyq", // irix pseudo ttys
578
"tty4d",// irix RS422
579
"tty4f",// irix RS422 with HSKo/HSki
580
"midi", // irix serial midi
581
"us" // irix mapped interface
583
CandidatePortPrefixes=Temp;
585
else if(osName.equals("FreeBSD")) //FIXME this is probably wrong
588
"ttyd", //general purpose serial ports
589
"cuaa", //dialout serial ports
590
"ttyA", //Specialix SI/XIO dialin ports
591
"cuaA", //Specialix SI/XIO dialout ports
592
"ttyD", //Digiboard - 16 dialin ports
593
"cuaD", //Digiboard - 16 dialout ports
594
"ttyE", //Stallion EasyIO (stl) dialin ports
595
"cuaE", //Stallion EasyIO (stl) dialout ports
596
"ttyF", //Stallion Brumby (stli) dialin ports
597
"cuaF", //Stallion Brumby (stli) dialout ports
598
"ttyR", //Rocketport dialin ports
599
"cuaR", //Rocketport dialout ports
600
"stl" //Stallion EasyIO board or Brumby N
602
CandidatePortPrefixes=Temp;
604
else if(osName.equals("NetBSD")) // FIXME this is probably wrong
607
"tty0" // netbsd serial ports
609
CandidatePortPrefixes=Temp;
611
else if ( osName.equals("Solaris")
612
|| osName.equals("SunOS"))
618
CandidatePortPrefixes=Temp;
620
else if(osName.equals("HP-UX"))
623
"tty0p",// HP-UX serial ports
624
"tty1p" // HP-UX serial ports
626
CandidatePortPrefixes=Temp;
629
else if(osName.equals("UnixWare") ||
630
osName.equals("OpenUNIX"))
633
"tty00s", // UW7/OU8 serial ports
638
CandidatePortPrefixes=Temp;
641
else if (osName.equals("OpenServer"))
644
"tty1A", // OSR5 serial ports
660
"ttyu1A", // OSR5 USB-serial ports
677
CandidatePortPrefixes=Temp;
679
else if (osName.equals("Compaq's Digital UNIX") || osName.equals("OSF1"))
682
"tty0" // Digital Unix serial ports
684
CandidatePortPrefixes=Temp;
687
else if(osName.equals("BeOS"))
690
"serial" // BeOS serial ports
692
CandidatePortPrefixes=Temp;
694
else if(osName.equals("Mac OS X"))
697
// Keyspan USA-28X adapter, USB port 1
699
// Keyspan USA-28X adapter, USB port 1
701
// Keyspan USA-28X adapter, USB port 2
703
// Keyspan USA-28X adapter, USB port 2
705
// Keyspan USA-19 adapter
707
// Keyspan USA-19 adapter
710
CandidatePortPrefixes=Temp;
712
else if(osName.toLowerCase().indexOf("windows") != -1 )
715
"COM" // win32 serial ports
716
//"//./COM" // win32 serial ports
718
CandidatePortPrefixes=Temp;
723
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().");
727
case CommPortIdentifier.PORT_PARALLEL:
729
System.out.println("scanning for parallel ports for os "+osName);
730
/** Get the Parallel port prefixes for the running os
735
if(osName.equals("Linux")
737
|| osName.equals("NetBSD") FIXME
738
|| osName.equals("HP-UX") FIXME
739
|| osName.equals("Irix") FIXME
740
|| osName.equals("BeOS") FIXME
741
|| osName.equals("Compaq's Digital UNIX") FIXME
746
"lp" // linux printer port
748
CandidatePortPrefixes=temp;
750
else if(osName.equals("FreeBSD"))
755
CandidatePortPrefixes=temp;
757
else if(osName.toLowerCase().indexOf("windows") != -1 )
762
CandidatePortPrefixes=temp;
764
else /* printer support is green */
767
CandidatePortPrefixes=temp;
772
System.out.println("Unknown PortType "+PortType+" passed to RXTXCommDriver.registerScannedPorts()");
774
registerValidPorts(CandidateDeviceNames, CandidatePortPrefixes, PortType);
779
* <p>From the NullDriver.java CommAPI sample.
782
* @param PortName The name of the port the OS recognizes
783
* @param PortType CommPortIdentifier.PORT_SERIAL or PORT_PARALLEL
785
* getCommPort() will be called by CommPortIdentifier from its
786
* openPort() method. PortName is a string that was registered earlier
787
* using the CommPortIdentifier.addPortName() method. getCommPort()
788
* returns an object that extends either SerialPort or ParallelPort.
790
public CommPort getCommPort( String PortName, int PortType )
792
if (debug) System.out.println("RXTXCommDriver:getCommPort("
793
+PortName+","+PortType+")");
796
case CommPortIdentifier.PORT_SERIAL:
797
if(osName.toLowerCase().indexOf("windows") == -1 )
800
return new RXTXPort( PortName );
804
return new RXTXPort( deviceDirectory + PortName );
806
case CommPortIdentifier.PORT_PARALLEL:
807
//return new LPRPort( PortName );
810
System.out.println("unknown PortType "+PortType+" passed to RXTXCommDriver.getCommPort()");
812
} catch( PortInUseException e ) {
815
"Port "+PortName+" in use by another application");
820
/* Yikes. Trying to call println from C for odd reasons */
821
public void Report( String arg )
823
System.out.println(arg);