1
/*-------------------------------------------------------------------------
2
| rxtx is a native interface to serial ports in java.
3
| Copyright 1997-2004 by Trent Jarvi taj@www.linux.org.uk
5
| This library is free software; you can redistribute it and/or
6
| modify it under the terms of the GNU Library General Public
7
| License as published by the Free Software Foundation; either
8
| version 2 of the License, or (at your option) any later version.
10
| This library is distributed in the hope that it will be useful,
11
| but WITHOUT ANY WARRANTY; without even the implied warranty of
12
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
| Library General Public License for more details.
15
| You should have received a copy of the GNU Library General Public
16
| License along with this library; if not, write to the Free
17
| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
--------------------------------------------------------------------------*/
19
#include "gnu/io/RXTXPort.h" /* dima */
20
#include "gnu/io/RXTXCommDriver.h" /* dima */
21
#include "gnu/io/PortInUseException.h"
22
#if defined(__MWERKS__) /* dima */
28
#else /* windows lcc compiler for fd_set. probably wrong */
39
#include <sys/ioctl.h>
40
#include <sys/param.h>
41
#include <sys/utsname.h>
44
# include <win32termios.h>
45
/* FIXME returns 0 in all cases on win32
46
#define S_ISCHR(m) (((m)&S_IFMT) == S_IFCHR)
48
# if !defined(S_ISCHR)
49
# define S_ISCHR(m) (1)
50
# endif /* S_ISCHR(m) */
52
#ifdef HAVE_ASM_TERMBITS_H
53
//# include <asm/termbits.h>
54
#endif /* HAVE_ASM_TERMBITS_H */
57
#endif /* HAVE_TERMIOS_H */
60
#endif /* HAVE_SIGNAL_H */
61
#ifdef HAVE_SYS_SIGNAL_H
62
# include <sys/signal.h>
63
#endif /* HAVE_SYS_SIGNAL_H */
64
#include <sys/types.h>
65
#ifdef HAVE_SYS_TIME_H
66
# include <sys/time.h>
67
#endif /* HAVE_SYS_TIME_H */
69
#ifdef HAVE_SYS_FCNTL_H
70
# include <sys/fcntl.h>
71
#endif /* HAVE_SYS_FCNTL_H */
72
#ifdef HAVE_SYS_FILE_H
73
# include <sys/file.h>
74
#endif /* HAVE_SYS_FILE_H */
75
#ifdef LFS /* File Lock Server */
76
# include <sys/socket.h>
77
# include <netinet/in.h>
78
# include <arpa/inet.h>
80
#if defined(__linux__)
81
# include <linux/types.h> /* fix for linux-2.3.4? kernels */
82
# include <linux/serial.h>
83
# include <linux/version.h>
84
#endif /* __linux__ */
86
# include <sys/filio.h>
87
# include <sys/mkdev.h>
90
# include <sys/modem.h>
92
/* FIXME -- new file */
93
#if defined(__APPLE__)
94
# include <CoreFoundation/CoreFoundation.h>
95
# include <IOKit/IOKitLib.h>
96
# include <IOKit/serial/IOSerialKeys.h>
97
# include <IOKit/IOBSD.h>
98
#endif /* __APPLE__ */
100
# include <sys/filio.h>
101
#endif /* __unixware__ */
104
#endif /* HAVE_PWD_H */
107
#endif /* HAVE_GRP_H */
111
#include "SerialImp.h"
113
#include <java/lang/System.h>
114
#include <java/io/PrintStream.h>
115
#include <java/lang/String.h>
116
#include <java/io/IOException.h>
117
#include <gnu/io/UnsupportedCommOperationException.h>
118
#include <java/lang/ArrayIndexOutOfBoundsException.h>
119
//#define TRENT_IS_HERE_DEBUGGING_ENUMERATION
121
struct preopened *preopened_port = NULL;
123
#if defined(__sun__) || defined(__hpux__)
124
/*----------------------------------------------------------
127
accept: termios to be set to raw
128
perform: initializes the termios structure.
129
return: int 0 on success
131
comments: this is how linux cfmakeraw works.
133
----------------------------------------------------------*/
135
int cfmakeraw ( struct termios *term )
137
ENTER( "cfmakeraw" );
138
term->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
139
term->c_oflag &= ~OPOST;
140
term->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
141
term->c_cflag &= ~(CSIZE|PARENB);
142
term->c_cflag |= CS8;
143
LEAVE( "cfmakeraw" );
146
#endif /* __sun__ || __hpux__ */
149
struct timeval snow, enow, seloop, eeloop;
150
#define report_time_eventLoop( ) { \
151
if ( seloop.tv_sec == eeloop.tv_sec && seloop.tv_usec == eeloop.tv_usec ) \
153
gettimeofday(&eeloop, NULL); \
154
seloop.tv_sec = eeloop.tv_sec; \
155
seloop.tv_usec = eeloop.tv_usec; \
156
printf("%8i sec : %8i usec\n", eeloop.tv_sec - seloop.tv_sec, eeloop.tv_usec - seloop.tv_usec); \
159
#define report_time( ) \
161
struct timeval now; \
162
gettimeofday(&now, NULL); \
163
mexPrintf("%8s : %5i : %8i sec : %8i usec\n", __TIME__, __LINE__, now.tv_sec, now.tv_usec); \
165
#define report_time_start( ) \
167
gettimeofday(&snow, NULL); \
168
mexPrintf("%8s : %5i : %8i sec : %8i usec", __TIME__, __LINE__, snow.tv_sec, snow.tv_usec); \
170
#define report_time_end( ) \
172
gettimeofday(&enow, NULL); \
173
mexPrintf("%8i sec : %8i usec\n", enow.tv_sec - snow.tv_sec, enow.tv_sec - snow.tv_sec?snow.tv_usec-enow.tv_usec:enow.tv_usec - snow.tv_usec); \
176
#define report_time_eventLoop( ){};
177
#define report_time( ) {}
178
#define report_time_start( ) {}
179
#define report_time_end( ) {}
180
#endif /* DEBUG_TIMING */
183
struct event_info_struct *master_index = NULL;
185
/*----------------------------------------------------------
189
perform: Initialize the native library
192
comments: Basically this just causes rxtx to ignore signals. signal
193
handlers where tried but the VM (circa 1.1) did not like it.
195
It also allows for some sanity checks on linux boxes if DEBUG
197
----------------------------------------------------------*/
198
void gnu::io::RXTXPort::Initialize(
201
#if defined DEBUG && defined(__linux__)
204
#endif /* DEBUG && __linux__ */
205
/* This bit of code checks to see if there is a signal handler installed
206
for SIGIO, and installs SIG_IGN if there is not. This is necessary
207
for the native threads jdk, but we don't want to do it with green
208
threads, because it slows things down. Go figure. */
210
/* POSIX signal handling functions */
212
struct sigaction old_action;
213
sigaction(SIGIO, NULL, &old_action);
214
/* green threads already has handler, no touch */
215
if (old_action.sa_handler == NULL) {
216
/* no handler when using native threads, set to ignore */
217
struct sigaction new_action;
219
sigemptyset(&block_mask);
220
new_action.sa_handler = SIG_IGN;
222
new_action.sa_flags = SA_RESTART;
223
#endif /* SA_RESTART */
224
new_action.sa_mask = block_mask;
225
sigaction(SIGIO, &new_action, NULL);
228
ENTER( "RXTXPort:Initialize" );
230
/* this is just for avoiding confusion while testing new libraries */
232
mexPrintf("RXTX Prerelease for testing Tue Feb 19 18:00:27 EST 2002\n");
234
printf("RXTX Prerelease for testing Thu Feb 21 19:31:38\n");
235
#endif /* DEBUG_MW */
236
#endif /* PRERELEASE */
238
gettimeofday(&seloop, NULL);
239
#endif /* DEBUG_TIMING */
240
#if defined(DEBUG) && defined(__linux__)
241
/* Lets let people who upgraded kernels know they may have problems */
242
if (uname (&name) == -1)
244
report( "RXTX WARNING: cannot get system name\n" );
245
LEAVE( "RXTXPort:Initialize" );
248
if(strcmp(name.release,UTS_RELEASE)!=0)
250
sprintf( message, LINUX_KERNEL_VERSION_ERROR, UTS_RELEASE,
255
LEAVE( "RXTXPort:Initialize" );
256
#endif /* DEBUG && __linux__ */
259
/*----------------------------------------------------------
260
RXTXPort.find_preopened_ports
261
accept: The device to find if preopened. ie "/dev/ttyS0"
262
perform: find the filedescriptor if preopened
266
RXTXPort.nativeStaticSetDSR
267
RXTXPort.nativeStaticSetDTR
268
RXTXPort.nativeStaticSetRTS
269
RXTXPort.nativeStaticSetSerialPortParams
270
This is used so people can setDTR low before calling the
272
----------------------------------------------------------*/
273
int find_preopened_ports( const char *filename )
276
struct preopened *p = preopened_port;
284
if( !strcmp( p->filename, filename) )
287
if( p->prev && p->next )
289
p->prev->next = p->next;
290
p->next->prev = p->prev;
294
p->prev->next = NULL;
298
p->next->prev = NULL;
303
preopened_port = NULL;
320
/*----------------------------------------------------------
323
accept: env, file descriptor
324
perform: set the termios struct to sane settings and
326
exceptions: IOExcepiton
327
comments: Very often people complain about not being able to get past
328
this function and it turns out to be permissions on the
329
device file or bios has the device disabled.
330
----------------------------------------------------------*/
332
int configure_port( int fd )
334
struct termios ttyset;
336
if( fd < 0 ) goto fail;
338
if( tcgetattr( fd, &ttyset ) < 0 ) goto fail;
339
ttyset.c_iflag = INPCK;
342
ttyset.c_cflag = CREAD | CS8 | CLOCAL;
343
ttyset.c_cc[ VMIN ] = 0;
344
ttyset.c_cc[ VTIME ] = 0;
347
if( cfsetspeed( &ttyset, B9600 ) < 0 ) goto fail;
349
if( cfsetispeed( &ttyset, B9600 ) < 0 ) goto fail;
350
if( cfsetospeed( &ttyset, B9600 ) < 0 ) goto fail;
352
if( tcsetattr( fd, TCSANOW, &ttyset ) < 0 ) goto fail;
354
fcntl( fd, F_SETOWN, getpid() );
357
fcntl( fd, F_SETFL, FASYNC );
367
/*----------------------------------------------------------
370
accept: the native speed setting
371
perform: translate the native speed to a Java speed
372
return: the Java speed
374
comments: This is used by open() (indirectly) and
375
nativeStaticGetBaudRate()
376
----------------------------------------------------------*/
377
int get_java_baudrate( int native_speed )
379
switch( native_speed )
384
case B110: return 110;
385
case B134: return 134;
386
case B150: return 150;
387
case B200: return 200;
388
case B300: return 300;
389
case B600: return 600;
390
case B1200: return 1200;
391
case B1800: return 1800;
392
case B2400: return 2400;
393
case B4800: return 4800;
394
case B9600: return 9600;
395
case B19200: return 19200;
396
case B38400: return 38400;
397
case B57600: return 57600;
402
/*----------------------------------------------------------
405
accept: fd of the preopened device
406
perform: Now that the object is instatiated, set the Java variables
407
to the preopened states.
410
comments: preopened refers to the fact that the serial port has
411
been configured before the Java open() has been called.
412
----------------------------------------------------------*/
414
void set_java_vars( gnu::io::RXTXPort *p,
418
struct termios ttyset;
421
int stop_bits = STOPBITS_1_5;
424
if( tcgetattr( fd, &ttyset ) < 0 )
426
report( "Cannot Get Serial Port Settings\n" );
431
switch( ttyset.c_cflag&CSIZE ) {
432
case CS5: databits = JDATABITS_5; break;
433
case CS6: databits = JDATABITS_6; break;
434
case CS7: databits = JDATABITS_7; break;
435
case CS8: databits = JDATABITS_8; break;
438
switch( ttyset.c_cflag&(PARENB|PARODD|CMSPAR ) ) {
440
switch( ttyset.c_cflag&(PARENB|PARODD) ) {
442
case 0: jparity = JPARITY_NONE; break;
443
case PARENB: jparity = JPARITY_EVEN; break;
444
case PARENB | PARODD: jparity = JPARITY_ODD; break;
446
case PARENB | PARODD | CMSPAR: jparity = JPARITY_MARK; break;
447
case PARENB | CMSPAR: jparity = JPARITY_SPACE; break;
450
switch( ttyset.c_cflag&(CSTOPB) ) {
451
case 0: stop_bits = STOPBITS_1; break;
452
case CSTOPB: stop_bits = STOPBITS_2; break;
457
Trent, here is something I found with google:
458
(freebsd list freebsd-current@freebsd.org)
460
Andrzej Bialecki <abial@korin.warman.org.pl> asked:
461
I tried to compile a piece of software, probably for Linux, and I noticed
462
that we don't define CBAUD constant. I'm not sure, but I think POSIX
463
defines and uses it. Should(n't) we?
465
Bruce Evans <bde@zeta.org.au> answered:
466
CBAUD is for SYSV compatibility. It is considerably inferior to POSIX's
467
cf{get,set}{i,o}speed and shouldn't be provided or used.
470
#if defined(CBAUD)/* dima */
471
baudrate = ttyset.c_cflag&CBAUD;
473
baudrate = cfgetispeed(&ttyset);
475
p->speed = ( jint ) get_java_baudrate(baudrate) ;
476
p->dataBits = ( jint ) databits ;
477
p->stopBits = ( jint ) stop_bits ;
478
p->parity = ( jint ) jparity ;
480
/*----------------------------------------------------------
483
accept: The device to open. ie "/dev/ttyS0"
484
perform: open the device, set the termios struct to sane settings and
485
return the filedescriptor
487
exceptions: IOExcepiton
488
comments: Very often people complain about not being able to get past
489
this function and it turns out to be permissions on the
490
device file or bios has the device disabled.
491
----------------------------------------------------------*/
492
jint gnu::io::RXTXPort::open(
493
java::lang::String *jstr
499
report_time_start( );
502
for( i=0;i<jstr->length();i++)
503
filename[i] = jstr->charAt(i);
512
LOCK is one of three functions defined in SerialImp.h
516
system_does_not_lock Win32
519
ENTER( "RXTXPort:open" );
520
if ( LOCK( filename, pid ) )
522
sprintf( message, "open: locking has failed for %s\n",
529
sprintf( message, "open: locking worked for %s\n", filename );
532
/* This is used so DTR can remain low on 'open()' */
539
fd=::OPEN (filename, O_RDWR | O_NOCTTY | O_NONBLOCK );
540
} while (fd < 0 && errno==EINTR);
542
if( configure_port( fd ) ) goto fail;
543
sprintf( message, "open: fd returned is %i\n", fd );
545
LEAVE( "RXTXPort:open" );
550
LEAVE( "RXTXPort:open" );
551
snprintf(message, 79, "%s %s",strerror(errno)," in open");
552
throw new gnu::io::PortInUseException( JvNewStringUTF( message ) );
553
//throw new PortInUseException;
557
/*----------------------------------------------------------
561
perform: get the fd from the java end and close it
564
----------------------------------------------------------*/
565
void gnu::io::RXTXPort::nativeClose(
566
java::lang::String *jstr
572
for( i=0;i<jstr->length();i++)
573
filename[i] = jstr->charAt(i);
576
report_time_start( );
580
UNLOCK is one of three functions defined in SerialImp.h
584
system_does_not_unlock Win32
586
ENTER( "RXTXPort:nativeClose" );
590
result=::CLOSE (this->fd);
591
} while ( result < 0 && errno == EINTR );
592
UNLOCK( filename, this->pid );
594
LEAVE( "RXTXPort:nativeClose" );
599
/*----------------------------------------------------------
600
RXTXPort.set_port_params
602
accept: env, fd, speed, data bits, stop bits, parity
603
perform: set the serial port parameters
605
exceptions: UnsupportedCommOperationException
606
comments: There is a static method and an instance method that use this
607
function. The static method gets a fd first. The instance
608
method can get the fd from the object.
610
see: nativeSetSerialPortParams & nativeStaticSerialPortParams
611
----------------------------------------------------------*/
620
struct termios ttyset;
622
#if defined(TIOCGSERIAL)
623
struct serial_struct sstruct;
624
#endif /* TIOCGSERIAL */
626
if( tcgetattr( fd, &ttyset ) < 0 )
628
report( "set_port_params: Cannot Get Serial Port Settings\n" );
632
if( translate_data_bits( &(ttyset.c_cflag), dataBits ) )
634
report( "set_port_params: Invalid Data Bits Selected\n" );
638
if( translate_stop_bits( &(ttyset.c_cflag), stopBits ) )
640
report( "set_port_params: Invalid Stop Bits Selected\n" );
644
if( translate_parity( &(ttyset.c_cflag), parity ) )
646
report( "set_port_params: Invalid Parity Selected\n" );
651
if( cfsetspeed( &ttyset, cspeed ) < 0 )
653
report( "set_port_params: Cannot Set Speed\n" );
656
#endif /* __FreeBSD__ */
659
/* hang up the modem aka drop DTR */
660
/* Unix should handle this */
662
mexPrintf("dropping DTR\n");
663
printf("dropping DTR\n");
665
ioctl( fd, TIOCMGET, &result );
666
result &= ~TIOCM_DTR;
667
ioctl( fd, TIOCMSET, &result );
669
if( cfsetispeed( &ttyset, cspeed ) < 0 ||
670
cfsetospeed( &ttyset, cspeed ) < 0 )
673
Some people need to set the baud rate to ones not defined
676
This includes some baud rates which are supported by CommAPI
677
in Unix ( 14400, 28800, 128000, 256000 )
679
If the above fails, we assume this is not a defined
680
baud rate on Unix. With Win32, It is assumed the kernel
683
The baud_base and desired speed are used to
684
calculate a custom divisor.
686
On linux the setserial man page covers this.
689
#if defined(TIOCGSERIAL)
690
sstruct.custom_divisor = ( sstruct.baud_base/cspeed );
692
#endif /* TIOCGSERIAL */
693
if( cfsetispeed( &ttyset, cspeed ) < 0 ||
694
cfsetospeed( &ttyset, cspeed ) < 0 )
696
/* OK, we tried everything */
697
report( "nativeSetSerialPortParams: Cannot Set Speed\n" );
700
#if defined(TIOCSSERIAL)
701
/* It is assumed Win32 does this for us */
702
if ( sstruct.baud_base < 1 ||
703
ioctl( fd, TIOCSSERIAL, &sstruct ) < 0 )
707
#endif /* TIOCSSERIAL */
710
if( tcsetattr( fd, TCSANOW, &ttyset ) < 0 )
712
report("tcsetattr returns nonzero value!\n");
718
/*----------------------------------------------------------
719
RXTXPort.nativeSetSerialPortParams
721
accept: speed, data bits, stop bits, parity
722
perform: set the serial port parameters
723
return: jboolean 1 on error
724
exceptions: UnsupportedCommOperationException
725
----------------------------------------------------------*/
726
jboolean gnu::io::RXTXPort::nativeSetSerialPortParams(
733
int fd = (int) this->fd;
734
int cspeed = translate_speed( speed );
736
ENTER( "RXTXPort:nativeSetSerialPortParams" );
737
report_time_start( );
741
report(" invalid cspeed\n");
743
For some reason the native exceptions are not being caught. Moving this
744
to the Java side fixed the issue. taj.
745
throw_java_exception( env, UNSUPPORTED_COMM_OPERATION,
746
"", "BaudRate could not be set to the specified value" );
752
if( set_port_params( fd, cspeed, dataBits, stopBits, parity ) )
754
report("set_port_params failed\n");
755
LEAVE( "RXTXPort:nativeSetSerialPortParams" );
757
For some reason the native exceptions are not being caught. Moving this
758
to the Java side fixed the issue. taj.
759
throw_java_exception( env, UNSUPPORTED_COMM_OPERATION,
760
"nativeSetSerialPortParams", strerror( errno ) );
765
LEAVE( "RXTXPort:nativeSetSerialPortParams" );
770
/*----------------------------------------------------------
773
accept: speed in bits-per-second
774
perform: convert bits-per-second to a speed_t constant
775
return: speed_t constant
776
exceptions: returns -1 and the calling method throws the exception so
777
it may be caught in java.
778
comments: Only the lowest level code should know about
780
----------------------------------------------------------*/
785
LEAVE( "RXTXPort:translate_speed" );
790
case 110: return B110;
791
case 134: return B134;
792
case 150: return B150;
793
case 200: return B200;
794
case 300: return B300;
795
case 600: return B600;
796
case 1200: return B1200;
797
case 1800: return B1800;
798
case 2400: return B2400;
799
case 4800: return B4800;
800
case 9600: return B9600;
801
case 19200: return B19200;
802
case 38400: return B38400;
804
case 57600: return B57600;
807
case 115200: return B115200;
810
case 230400: return B230400;
813
case 460800: return B460800;
816
case 14400: return B14400;
819
case 28800: return B28800;
821
#ifdef B128000 /* dima */
822
case 128000: return B128000;
824
#ifdef B256000 /* dima */
825
case 256000: return B256000;
829
/* Handle custom speeds */
830
if( speed >= 0 ) return speed;
833
LEAVE( "RXTXPort:translate_speed: Error condition" );
838
/*----------------------------------------------------------
841
accept: gnu.io.SerialPort.DATABITS_* constant
842
perform: set proper termios c_cflag bits
844
exceptions: UnsupportedCommOperationException
845
----------------------------------------------------------*/
846
int translate_data_bits(
851
int temp = (*cflag) & ~CSIZE;
853
ENTER( "translate_date_bits" );
856
(*cflag) = temp | CS5;
859
(*cflag) = temp | CS6;
862
(*cflag) = temp | CS7;
865
(*cflag) = temp | CS8;
869
LEAVE( "RXTXPort:translate_date_bits" );
871
For some reason the native exceptions are not being caught. Moving this
872
to the Java side fixed the issue. taj.
873
throw_java_exception( env, UNSUPPORTED_COMM_OPERATION,
874
"", "databit value not supported" );
879
/*----------------------------------------------------------
882
accept: gnu.io.SerialPort.STOPBITS_* constant
883
perform: set proper termios c_cflag bits
885
exceptions: UnsupportedCommOperationException
886
comments: If you specify 5 data bits and 2 stop bits, the port will
887
allegedly use 1.5 stop bits. Does anyone care?
888
----------------------------------------------------------*/
889
int translate_stop_bits(
894
ENTER( "translate_stop_bits" );
898
LEAVE( "RXTXPort:translate_stop_bits" );
900
/* ok.. lets try putting it in and see if anyone notices */
902
if ( translate_data_bits( cflag, JDATABITS_5 ) )
907
LEAVE( "RXTXPort:translate_stop_bits" );
911
LEAVE( "RXTXPort:translate_stop_bits" );
913
For some reason the native exceptions are not being caught. Moving this
914
to the Java side fixed the issue. taj.
915
throw_java_exception( env, UNSUPPORTED_COMM_OPERATION,
916
"", "stopbit value not supported" );
920
jint gnu::io::RXTXPort::nativeGetFlowControlMode(
924
struct termios ttyset;
927
tcgetattr( fd, &ttyset );
929
if( ttyset.c_cflag & HARDWARE_FLOW_CONTROL )
931
ret |= ( FLOWCONTROL_RTSCTS_IN | FLOWCONTROL_RTSCTS_OUT );
933
if ( ttyset.c_iflag & IXOFF )
935
ret |= FLOWCONTROL_XONXOFF_IN;
937
if ( ttyset.c_iflag & IXON )
939
ret |= FLOWCONTROL_XONXOFF_OUT;
941
return( (jint) ret );
943
jint gnu::io::RXTXPort::nativeGetParity(
947
struct termios ttyset;
949
if( tcgetattr( fd, &ttyset ) < 0 )
951
report("nativeGetParity: tcgetattr failed\n");
955
if ( ( ttyset.c_cflag & PARENB ) &&
956
( ttyset.c_cflag & PARODD ) &&
957
( ttyset.c_cflag & CMSPAR ) )
959
return( JPARITY_MARK );
961
else if ( ttyset.c_cflag & ( PARENB &&
962
ttyset.c_cflag & CMSPAR ) )
964
return( JPARITY_SPACE );
967
if ( ttyset.c_cflag & PARENB &&
968
ttyset.c_cflag & PARODD )
970
return( JPARITY_ODD );
972
else if ( ttyset.c_cflag & PARENB )
974
return( JPARITY_EVEN );
978
return( JPARITY_NONE );
982
/*----------------------------------------------------------
985
accept: javax.comm.SerialPort.PARITY_* constant
986
perform: set proper termios c_cflag bits
988
exceptions: UnsupportedCommOperationException
989
comments: The CMSPAR bit should be used for 'mark' and 'space' parity,
990
but it's not in glibc's includes. Oh well, rarely used anyway.
991
----------------------------------------------------------*/
992
int translate_parity(
997
ENTER( "translate_parity" );
999
(*cflag) &= ~(PARENB | PARODD | CMSPAR );
1003
LEAVE( "translate_parity" );
1007
LEAVE( "translate_parity" );
1010
(*cflag) |= PARENB | PARODD;
1011
LEAVE( "translate_parity" );
1015
(*cflag) |= PARENB | PARODD | CMSPAR;
1016
LEAVE( "translate_parity" );
1019
(*cflag) |= PARENB | CMSPAR;
1020
LEAVE( "translate_parity" );
1024
printf("Parity missed %i\n", (int) parity );
1027
LEAVE( "translate_parity" );
1029
For some reason the native exceptions are not being caught. Moving this
1030
to the Java side fixed the issue. taj.
1031
throw_java_exception( env, UNSUPPORTED_COMM_OPERATION,
1032
"", "parity value not supported" );
1036
#if !defined(TIOCSERGETLSR) && !defined(WIN32)
1037
/*----------------------------------------------------------
1041
perform: call tcdrain() and report an event when it succeds
1045
----------------------------------------------------------*/
1046
void *drain_loop( void *arg )
1048
struct event_info_struct *eis = ( struct event_info_struct * ) arg;
1051
pthread_detach( pthread_self() );
1055
report_verbose("drain_loop: looping\n");
1056
#if defined(__sun__)
1057
/* FIXME: No time to test on all OS's for production */
1061
#endif /* __sun__ */
1065
if( eis->eventloop_interrupted )
1069
if( tcdrain( eis->fd ) == 0 )
1071
if( eis && eis->writing )
1074
sprintf(msg, "drain_loop: setting OUTPUT_BUFFER_EMPTY\n" );
1077
eis->output_buffer_empty_flag = 1;
1086
report_verbose("drain_loop: writing not set\n");
1091
report("drain_loop: tcdrain bad fd\n");
1096
report("------------------ drain_loop exiting ---------------------\n");
1098
pthread_exit( NULL );
1101
#endif /* !defined(TIOCSERGETLSR) && !defined(WIN32) */
1102
/*----------------------------------------------------------
1105
accept: event_info_struct used to access java and communicate with
1107
perform: see comments
1111
The is the pthread spawned on systems that can't access the
1112
LSR (Line Status Register). Without access to the LSR rxtx
1113
cannot detect when the output buffer is empty in the Monitor
1114
Thread. The solution is to return the value of write's return
1115
but hang around in this thread waiting for tcdrain to finish.
1117
once the drain has finished, we let the eventLoop know that the
1118
output buffer is empty and the Signal is sent.
1119
----------------------------------------------------------*/
1120
void finalize_threads( struct event_info_struct *eis )
1122
#if !defined(TIOCSERGETLSR) && !defined( WIN32 )
1123
/* used to shut down any remaining write threads */
1125
eis->output_buffer_empty_flag = 0;
1126
ENTER("finalize_threads\n");
1128
/* need to clean up again after working events */
1129
LEAVE("---------------- finalize_threads ---------------");
1130
#endif /* TIOCSERGETLSR & !WIN32 */
1133
#if !defined(TIOCSERGETLSR) && !defined( WIN32 )
1134
static void warn_sig_abort( int signo )
1137
sprintf( msg, "RXTX Recieved Signal %i\n", signo );
1139
report_error( msg );
1142
#endif /* TIOCSERGETLSR */
1144
/*----------------------------------------------------------
1152
----------------------------------------------------------*/
1153
int init_threads( gnu::io::RXTXPort *p, struct event_info_struct *eis )
1155
#if !defined(TIOCSERGETLSR) & !defined(WIN32)
1156
sigset_t newmask, oldmask;
1157
struct sigaction newaction, oldaction;
1160
report_time_start( );
1161
report("init_threads: start\n");
1162
sigemptyset(&newmask);
1163
sigaddset(&newmask, SIGCHLD);
1164
newaction.sa_handler = warn_sig_abort;
1165
sigemptyset( &newaction.sa_mask );
1167
newaction.sa_flags = SA_INTERRUPT;
1168
#endif /* SA_INTERRUPT */
1170
newaction.sa_flags = SA_RESTART;
1171
#endif /* SA_RESTART */
1173
sigaction(SIGABRT, &newaction, &oldaction);
1174
sigaction(SIGCHLD, &newaction, &oldaction);
1175
sigaction(SIGALRM, &newaction, &oldaction);
1176
sigaction(SIGCONT, &newaction, &oldaction);
1178
sigaction(SIGPOLL, &newaction, &oldaction);
1179
sigaction(SIGTRAP, &newaction, &oldaction);
1180
sigaction(SIGBUS, &newaction, &oldaction);
1181
sigaction(SIGSEGV, &newaction, &oldaction);
1182
sigaction(SIGFPE, &newaction, &oldaction);
1183
sigaction(SIGILL, &newaction, &oldaction);
1185
sigfillset(&newmask);
1186
sigprocmask( SIG_SETMASK, &newmask, &oldmask );
1187
pthread_sigmask( SIG_BLOCK, &newmask, &oldmask );
1189
sigprocmask( SIG_SETMASK, &newmask, &oldmask );
1191
report("init_threads: creating drain_loop\n");
1192
pthread_create( &tid, NULL, drain_loop, (void *) eis );
1193
pthread_detach( tid );
1194
#endif /* TIOCSERGETLSR */
1195
report("init_threads: set eis\n");
1196
p->eis = ( jint ) eis;
1197
report("init_threads: stop\n");
1202
/*----------------------------------------------------------
1205
accept: byte to write (passed as int)
1206
jboolean interrupted (no events if true)
1207
perform: write a single byte to the port
1209
exceptions: IOException
1210
----------------------------------------------------------*/
1211
void gnu::io::RXTXPort::writeByte(
1213
jboolean interrupted
1216
#ifndef TIOCSERGETLSR
1217
struct event_info_struct *index = master_index;
1219
unsigned char byte = (unsigned char)ji;
1220
int fd = ( int ) this->fd;
1223
#if defined ( __sun__ )
1225
#endif /* __sun__ */
1227
report_time_start();
1228
ENTER( "RXTXPort:writeByte" );
1230
sprintf( msg, "writeByte %c>>\n", byte );
1232
result=WRITE (fd, (void * ) &byte, sizeof(unsigned char));
1233
} while (result < 0 && errno==EINTR);
1234
if ( result < 0 && errno != EINTR )
1236
snprintf( msg, 79, "%s%s", strerror( errno ), " in writeByte" );
1237
throw new java::io::IOException( JvNewStringUTF( msg ) );
1238
/* On win32 I'm not sure how many bytes made it out */
1242
This makes write for win32, glinux and Sol behave the same
1243
#if defined ( __sun__ )
1245
report_verbose( "nativeDrain: trying tcdrain\n" );
1248
} while (result && errno==EINTR && count <3);
1249
#endif *//* __sun __ */
1250
#ifndef TIOCSERGETLSR
1253
index = master_index;
1256
while( index->fd != fd &&
1257
index->next ) index = index->next;
1260
report( "writeByte: index->writing = 1" );
1263
sprintf( msg, "RXTXPort:writeByte %i\n", result );
1265
LEAVE( "RXTXPort:writeByte" );
1271
snprintf( msg, 79, "%s%s", strerror( errno ), " in writeByte" );
1272
throw new java::io::IOException( JvNewStringUTF( msg ) );
1275
/*----------------------------------------------------------
1278
accept: jbarray: bytes used for writing
1279
offset: offset in array to start writing
1280
count: Number of bytes to write
1281
jboolean interrupted (no events if true)
1282
perform: write length bytes of jbarray
1284
exceptions: IOException
1285
----------------------------------------------------------*/
1286
void gnu::io::RXTXPort::writeArray(
1290
jboolean interrupted
1293
#ifndef TIOCSERGETLSR
1294
struct event_info_struct *index = master_index;
1295
#endif /* TIOCSERGETLSR */
1297
int result=0,total=0;
1298
jbyte *out = elements( jbarray );
1300
#if defined ( __sun__ )
1302
#endif /* __sun__ */
1303
#if defined ( __sun__ )
1304
struct timespec retspec;
1307
retspec.tv_nsec = 50000;
1308
#endif /* __sun__ */
1309
fd = ( int ) this->fd;
1311
report_time_start();
1312
ENTER( "writeArray" );
1313
/* warning Roy Rogers */
1315
sprintf( message, "::::RXTXPort:writeArray(%s);\n", (char *) body );
1316
report_verbose( message );
1320
result=WRITE (fd, (void * ) ((char *) out + total + offset), count - total); /* dima */
1324
report("writeArray()\n");
1325
} while ( ( total < count ) && ( (result < 0 && errno==EINTR ) || ( result >= 0 ) ) ) ;
1326
if ( result < 0 && errno != EINTR )
1328
snprintf( msg, 79, "%s%s", strerror( errno ), " in writeArray" );
1329
throw new java::io::IOException( JvNewStringUTF( msg ) );
1330
/* On win32 I'm not sure how many bytes made it out */
1334
This makes write for win32, glinux and Sol behave the same
1335
#if defined ( __sun__ )
1337
report_verbose( "nativeDrain: trying tcdrain\n" );
1340
} while (result && errno==EINTR && icount <3);
1341
#endif *//* __sun__ */
1342
#ifndef TIOCSERGETLSR
1347
while( index->fd != fd &&
1348
index->next ) index = index->next;
1351
report( "writeArray: index->writing = 1" );
1353
#endif /* TIOCSERGETLSR */
1355
50 ms sleep to make sure read can get in
1357
what I think is happening here is the data writen is causing
1358
signals, the event loop can't select with data available
1360
I think things like BlackBox with 2 ports open are getting
1361
signals for both the reciever and transmitter since they
1364
Things just start spinning out of control after that.
1366
LEAVE( "RXTXPort:writeArray" );
1370
snprintf( msg, 79, "%s%s", strerror( errno ), " in writeArray" );
1371
throw new java::io::IOException( JvNewStringUTF( msg ) );
1374
/*----------------------------------------------------------
1375
RXTXPort.nativeDrain
1377
accept: jboolean interrupted (no events if true)
1378
perform: wait until all data is transmitted
1380
exceptions: IOException
1381
comments: java.io.OutputStream.flush() is equivalent to tcdrain,
1382
not tcflush, which throws away unsent bytes
1384
count logic added to avoid infinite loops when EINTR is
1385
true... Thread.yeild() was suggested.
1386
----------------------------------------------------------*/
1387
jboolean gnu::io::RXTXPort::nativeDrain(
1388
jboolean interrupted
1391
int fd = ( int ) this->fd;
1392
struct event_info_struct *eis = ( struct event_info_struct * ) this->eis;
1393
int result, count=0;
1397
ENTER( "SerialImp.c:drain()" );
1398
report_time_start( );
1400
report_verbose( "nativeDrain: trying tcdrain\n" );
1403
} while (result && errno==EINTR && count <3);
1405
sprintf( message, "RXTXPort:drain() returns: %i\n", result );
1406
report_verbose( message );
1407
#if defined(__sun__)
1408
/* FIXME: No time to test on all OS's for production */
1410
#endif /* __sun__ */
1411
LEAVE( "RXTXPort:drain()" );
1414
snprintf( message, 79, "%s%s", strerror( errno ), " in nativeDrain" );
1415
throw new java::io::IOException( JvNewStringUTF( message ) );
1417
if( interrupted ) return( false );
1418
#if !defined(TIOCSERGETLSR) && !defined(WIN32)
1419
if( eis && eis->writing )
1422
eis->output_buffer_empty_flag = 0;
1424
#endif /* !TIOCSERGETLSR !WIN32 */
1425
if( eis && eis->eventflags[SPE_OUTPUT_BUFFER_EMPTY] )
1427
send_event( this, eis, SPE_OUTPUT_BUFFER_EMPTY, 1 );
1433
/*----------------------------------------------------------
1436
accept: duration in milliseconds.
1437
perform: send break for actual time. not less than 0.25 seconds.
1439
comments: not very precise
1440
----------------------------------------------------------*/
1441
void gnu::io::RXTXPort::sendBreak(
1445
int fd = ( int ) this->fd;
1446
report_time_start( );
1447
ENTER( "RXTXPort:sendBreak()" );
1448
tcsendbreak( fd, (int)( duration / 250 ) );
1450
LEAVE( "RXTXPort:sendBreak()" );
1453
/*----------------------------------------------------------
1454
RXTXPort.NativegetReceiveTimeout
1457
perform: get termios.c_cc[VTIME]
1459
comments: see NativeEnableReceiveTimeoutThreshold
1460
----------------------------------------------------------*/
1461
jint gnu::io::RXTXPort::NativegetReceiveTimeout(
1465
struct termios ttyset;
1468
ENTER( "RXTXPort:nativegetRecieveTimeout()" );
1469
if( tcgetattr( fd, &ttyset ) < 0 ) goto fail;
1470
LEAVE( "RXTXPort:nativegetRecieveTimeout()" );
1471
return(ttyset.c_cc[ VTIME ] * 100);
1473
LEAVE( "RXTXPort:nativegetRecieveTimeout()" );
1474
snprintf( msg, 79, "%s%s", strerror( errno ), " in nativeGetRecieveTimeout()" );
1475
throw new java::io::IOException( JvNewStringUTF( msg ) );
1479
/*----------------------------------------------------------
1480
RXTXPort.NativeisReceiveTimeoutEnabled
1483
perform: determine if VTIME is none 0
1484
return: true if VTIME > 0 else false
1485
comments: see NativeEnableReceiveTimeoutThreshold
1486
----------------------------------------------------------*/
1487
jboolean gnu::io::RXTXPort::NativeisReceiveTimeoutEnabled(
1491
struct termios ttyset;
1493
ENTER( "RXTXPort:NativeisRecieveTimeoutEnabled()" );
1494
if( tcgetattr( fd, &ttyset ) < 0 ) goto fail;
1495
LEAVE( "RXTXPort:NativeisRecieveTimeoutEnabled()" );
1496
return(ttyset.c_cc[ VTIME ] > 0 ? true:false);
1498
LEAVE( "RXTXPort:NativeisRecieveTimeoutEnabled()" );
1499
snprintf( msg, 79, "%s%s", strerror( errno ), " in isRecieveTimeoutEnabled()" );
1500
throw new java::io::IOException( JvNewStringUTF( msg ) );
1504
/*----------------------------------------------------------
1508
perform: check status of DSR
1509
return: true if TIOCM_DSR is set
1510
false if TIOCM_DSR is not set
1512
comments: DSR stands for Data Set Ready
1513
----------------------------------------------------------*/
1514
jboolean gnu::io::RXTXPort::isDSR(
1517
unsigned int result = 0;
1521
ENTER( "RXTXPort:isDSR" );
1522
ioctl( fd, TIOCMGET, &result );
1523
sprintf( message, "RXTXPort:isDSR returns %i\n", result & TIOCM_DSR );
1525
LEAVE( "RXTXPort:isDSR" );
1526
if( result & TIOCM_DSR ) return true;
1530
/*----------------------------------------------------------
1534
perform: check status of CD
1535
return: true if TIOCM_CD is set
1536
false if TIOCM_CD is not set
1538
comments: CD stands for Carrier Detect
1539
The following comment has been made...
1540
"well, it works, there might ofcourse be a bug, but making DCD
1541
permanently on fixed it for me so I don't care"
1543
----------------------------------------------------------*/
1544
jboolean gnu::io::RXTXPort::isCD(
1547
unsigned int result = 0;
1548
int fd = ( int ) this->fd;
1551
ENTER( "RXTXPort:isCD" );
1552
ioctl( fd, TIOCMGET, &result );
1553
sprintf( message, "RXTXPort:isCD returns %i\n", result & TIOCM_CD );
1554
LEAVE( "RXTXPort:isCD" );
1555
if( result & TIOCM_CD ) return true;
1559
/*----------------------------------------------------------
1563
perform: check status of CTS
1564
return: true if TIOCM_CTS is set
1565
false if TIOCM_CTS is not set
1567
comments: CTS stands for Clear To Send.
1568
----------------------------------------------------------*/
1569
jboolean gnu::io::RXTXPort::isCTS(
1572
unsigned int result = 0;
1573
int fd = ( int ) this->fd;
1576
ENTER( "RXTXPort:isCTS" );
1577
ioctl( fd, TIOCMGET, &result );
1578
sprintf( message, "RXTXPort:isCTS returns %i\n", result & TIOCM_CTS );
1580
LEAVE( "RXTXPort:isCTS" );
1581
if( result & TIOCM_CTS ) return true;
1585
/*----------------------------------------------------------
1589
perform: check status of RI
1590
return: true if TIOCM_RI is set
1591
false if TIOCM_RI is not set
1593
comments: RI stands for Ring Indicator
1594
----------------------------------------------------------*/
1595
jboolean gnu::io::RXTXPort::isRI(
1598
unsigned int result = 0;
1599
int fd = ( int ) this->fd;
1602
ENTER( "RXTXPort:isRI" );
1603
ioctl( fd, TIOCMGET, &result );
1604
sprintf( message, "RXTXPort:isRI returns %i\n", result & TIOCM_RI );
1606
LEAVE( "RXTXPort:isRI" );
1607
if( result & TIOCM_RI ) return true;
1611
/*----------------------------------------------------------
1615
perform: check status of RTS
1616
return: true if TIOCM_RTS is set
1617
false if TIOCM_RTS is not set
1619
comments: tcgetattr with c_cflag CRTS_IFLOW
1620
----------------------------------------------------------*/
1621
jboolean gnu::io::RXTXPort::isRTS(
1624
unsigned int result = 0;
1625
int fd = ( int ) this->fd;
1628
ENTER( "RXTXPort:isRTS" );
1629
ioctl( fd, TIOCMGET, &result );
1630
sprintf( message, "RXTXPort:isRTS returns %i\n", result & TIOCM_RTS );
1632
LEAVE( "RXTXPort:isRTS" );
1633
if( result & TIOCM_RTS ) return true;
1637
/*----------------------------------------------------------
1640
accept: state flag to set/unset.
1641
perform: depends on the state flag
1642
if true TIOCM_RTS is set
1643
if false TIOCM_RTS is unset
1646
comments: tcsetattr with c_cflag CRTS_IFLOW
1647
----------------------------------------------------------*/
1648
void gnu::io::RXTXPort::setRTS(
1652
unsigned int result = 0;
1653
int fd = ( int ) this->fd;
1656
ENTER( "RXTXPort:setRTS" );
1657
ioctl( fd, TIOCMGET, &result );
1658
if( state == true ) result |= TIOCM_RTS;
1659
else result &= ~TIOCM_RTS;
1660
ioctl( fd, TIOCMSET, &result );
1661
sprintf( message, "setRTS( %i )\n", state );
1663
LEAVE( "RXTXPort:setRTS" );
1667
/*----------------------------------------------------------
1670
accept: state flag to set/unset.
1671
perform: depends on the state flag
1672
if true TIOCM_DSR is set
1673
if false TIOCM_DSR is unset
1676
comments: tcsetattr with c_cflag CRTS_IFLOW
1677
----------------------------------------------------------*/
1678
void gnu::io::RXTXPort::setDSR(
1682
unsigned int result = 0;
1683
int fd = ( int ) this->fd;
1686
ENTER( "RXTXPort:setDSR()" );
1687
ioctl( fd, TIOCMGET, &result );
1689
sprintf( message, "setDSR( %i )\n", state );
1690
if( state == true ) result |= TIOCM_DSR;
1691
else result &= ~TIOCM_DSR;
1692
ioctl( fd, TIOCMSET, &result );
1693
sprintf( message, "setDSR( %i )\n", state );
1695
LEAVE( "RXTXPort:setDSR()" );
1699
/*----------------------------------------------------------
1703
perform: check status of DTR
1704
return: true if TIOCM_DTR is set
1705
false if TIOCM_DTR is not set
1707
comments: DTR stands for Data Terminal Ready
1708
----------------------------------------------------------*/
1709
jboolean gnu::io::RXTXPort::isDTR(
1712
unsigned int result = 0;
1713
int fd = ( int ) this->fd;
1716
ENTER( "RXTXPort:isDTR" );
1717
ioctl( fd, TIOCMGET, &result );
1718
sprintf( message, "isDTR( ) returns %i\n", result& TIOCM_DTR );
1720
LEAVE( "RXTXPort:isDTR" );
1721
if( result & TIOCM_DTR ) return true;
1725
/*----------------------------------------------------------
1728
accept: new DTR state
1729
perform: if state is true, TIOCM_DTR is set
1730
if state is false, TIOCM_DTR is unset
1733
comments: DTR stands for Data Terminal Ready
1734
----------------------------------------------------------*/
1735
void gnu::io::RXTXPort::setDTR(
1739
unsigned int result = 0;
1740
int fd = ( int ) this->fd;
1743
ENTER( "RXTXPort:setDTR" );
1744
ioctl( fd, TIOCMGET, &result );
1745
if( state == true ) result |= TIOCM_DTR;
1746
else result &= ~TIOCM_DTR;
1747
ioctl( fd, TIOCMSET, &result );
1748
sprintf( message, "setDTR( %i )\n", state );
1750
LEAVE( "RXTXPort:setDTR" );
1753
/*----------------------------------------------------------
1754
RXTXPort.static_add_filename
1756
accept: filename and fd to save
1757
perform: add a struct holding the info to a linked list
1760
comments: the info is checked on open() if its in the list no
1761
changes are performed on the file on open()
1764
RXTXPort.nativeStaticSetDSR
1765
RXTXPort.nativeStaticSetDTR
1766
RXTXPort.nativeStaticSetRTS
1767
RXTXPort.nativeStaticSetSerialPortParams
1768
This is used so people can setDTR low before calling the
1769
-----------------------------------------------------------*/
1771
void static_add_filename( const char *filename, int fd)
1773
struct preopened *newp, *p = preopened_port;
1775
newp = ( struct preopened *) malloc( sizeof( struct preopened ) );
1776
strcpy( newp->filename, filename );
1783
preopened_port = newp;
1788
if( !strcmp( p->filename, filename) )
1808
/*----------------------------------------------------------
1809
RXTXPort.nativeSetBaudBase
1811
accept: The Baud Base for custom speeds
1812
perform: set the Baud Base
1813
return: 0 on success
1814
exceptions: Unsupported Comm Operation on systems not supporting
1817
Set baud rate to 38400 before using this
1818
First introduced in rxtx-2.1-3
1819
----------------------------------------------------------*/
1820
jboolean gnu::io::RXTXPort::nativeSetBaudBase(
1825
#if defined(TIOCGSERIAL)
1827
int fd = ( int ) this->fd;
1828
struct serial_struct sstruct;
1830
if ( sstruct.baud_base < 1 ||
1831
ioctl( fd, TIOCSSERIAL, &sstruct ) < 0 )
1837
snprintf( msg, 79, "%s%s", strerror( errno ), " in nativeSetBaudBase" );
1838
throw new gnu::io::UnsupportedCommOperationException( JvNewStringUTF( msg ) );
1840
#endif /* TIOCGSERIAL */
1843
/*----------------------------------------------------------
1844
RXTXPort.nativeGetBaudBase
1846
accept: the Baud Base used for custom speeds
1849
exceptions: Unsupported Comm Operation on systems not supporting
1852
First introduced in rxtx-2.1-3
1853
----------------------------------------------------------*/
1854
jint gnu::io::RXTXPort::nativeGetBaudBase(
1858
#if defined(TIOCGSERIAL)
1860
int fd = ( int ) this->fd;
1861
struct serial_struct sstruct;
1863
if ( ioctl( fd, TIOCGSERIAL, &sstruct ) < 0 )
1865
return( ( jint ) -1 );
1867
return( ( jint ) ( sstruct.baud_base ) );
1869
snprintf( msg, 79, "%s%s", strerror( errno ), " in nativeGetBaudBase" );
1870
throw new gnu::io::UnsupportedCommOperationException( JvNewStringUTF( msg ) );
1871
return( ( jint ) -1 );
1872
#endif /* TIOCGSERIAL */
1875
/*----------------------------------------------------------
1876
RXTXPort.nativeSetDivisor
1878
accept: Divisor for custom speeds
1879
perform: set the Divisor for custom speeds
1880
return: 0 on success
1881
exceptions: Unsupported Comm Operation on systems not supporting
1884
Set baud rate to 38400 before using this
1885
First introduced in rxtx-2.1-3
1886
----------------------------------------------------------*/
1887
jboolean gnu::io::RXTXPort::nativeSetDivisor(
1892
#if defined(TIOCGSERIAL)
1894
int fd = ( int ) this->fd;
1895
struct serial_struct sstruct;
1897
if ( ioctl( fd, TIOCGSERIAL, &sstruct ) < 0 )
1902
if ( sstruct.custom_divisor < 1 ||
1903
ioctl( fd, TIOCSSERIAL, &sstruct ) < 0 )
1909
snprintf( msg, 79, "%s%s", strerror( errno ), " in nativeSetDivisor" );
1910
throw new gnu::io::UnsupportedCommOperationException( JvNewStringUTF( msg ) );
1912
#endif /* TIOCGSERIAL */
1915
/*----------------------------------------------------------
1916
RXTXPort.nativeGetDivisor
1919
perform: Find the Divisor used for custom speeds
1921
exceptions: Unsupported Comm Operation on systems not supporting
1924
First introduced in rxtx-2.1-3
1925
----------------------------------------------------------*/
1926
jint gnu::io::RXTXPort::nativeGetDivisor(
1930
#if defined(TIOCGSERIAL)
1932
int fd = ( int ) this->fd;
1933
struct serial_struct sstruct;
1935
if ( ioctl( fd, TIOCGSERIAL, &sstruct ) < 0 )
1937
return( ( jint ) -1 );
1940
return( ( jint ) sstruct.custom_divisor );
1942
snprintf( msg, 79, "%s%s", strerror( errno ), " in nativeGetDivisor" );
1943
throw new gnu::io::UnsupportedCommOperationException( JvNewStringUTF( msg ) );
1944
return( ( jint ) -1 );
1945
#endif /* TIOCGSERIAL */
1948
/*----------------------------------------------------------
1949
RXTXPort.nativeStaticSetDSR
1951
accept: new RTS state
1952
perform: if flag is true, TIOCM_DSR is set
1953
if flag is false, TIOCM_DSR is unset
1956
comments: Set the DSR so it does not raise on the next open
1957
needed for some funky test boards?
1959
This is static so we can not call the open() setDSR()
1960
we dont have the jobject.
1962
First introduced in rxtx-1.5-9
1963
----------------------------------------------------------*/
1964
jboolean gnu::io::RXTXPort::nativeStaticSetDSR (
1969
int fd, i, pid = -1, result;
1972
for( i=0;i<jstr->length();i++)
1973
filename[i] = jstr->charAt(i);
1976
ENTER( "RXTXPort:nativeStaticSetDSR" );
1981
/* Open and lock the port so nothing else changes the setting */
1983
if ( LOCK( filename, pid ) ) goto fail;;
1985
fd = find_preopened_ports( filename );
1989
fd = ::OPEN (filename, O_RDWR | O_NOCTTY | O_NONBLOCK );
1990
} while (fd < 0 && errno==EINTR);
1991
if ( configure_port( fd ) ) goto fail;
1993
if ( fd < 0 ) goto fail;
1997
ioctl( fd, TIOCMGET, &result );
1998
if( flag == true ) result |= TIOCM_DSR;
1999
else result &= ~TIOCM_DSR;
2000
ioctl( fd, TIOCMSET, &result );
2002
/* Unlock the port. Good luck! :) */
2004
UNLOCK( filename, pid );
2006
static_add_filename( filename, fd );
2008
/* dont close the port. Its not clear if the DSR would remain high */
2009
LEAVE( "RXTXPort:nativeStaticSetDSR" );
2012
LEAVE( "RXTXPort:nativeStaticSetDSR" );
2016
/*----------------------------------------------------------
2017
RXTXPort.nativeStaticSetRTS
2019
accept: new RTS state
2020
perform: if flag is true, TIOCM_RTS is set
2021
if flag is false, TIOCM_RTS is unset
2024
comments: Set the RTS so it does not raise on the next open
2025
needed for some funky test boards?
2027
This is static so we can not call the open() setDTR()
2028
we dont have the jobject.
2030
First introduced in rxtx-1.5-9
2031
----------------------------------------------------------*/
2032
jboolean gnu::io::RXTXPort::nativeStaticSetRTS (
2037
int fd, i, pid = -1, result;
2040
for( i=0;i<jstr->length();i++)
2041
filename[i] = jstr->charAt(i);
2044
ENTER( "RXTXPort:nativeStaticSetRTS" );
2049
/* Open and lock the port so nothing else changes the setting */
2051
if ( LOCK( filename, pid ) ) goto fail;;
2053
fd = find_preopened_ports( filename );
2057
fd = ::OPEN (filename, O_RDWR | O_NOCTTY | O_NONBLOCK );
2058
} while (fd < 0 && errno==EINTR);
2059
if ( configure_port( fd ) ) goto fail;
2061
if ( fd < 0 ) goto fail;
2065
ioctl( fd, TIOCMGET, &result );
2066
if( flag == true ) result |= TIOCM_RTS;
2067
else result &= ~TIOCM_RTS;
2068
ioctl( fd, TIOCMSET, &result );
2070
/* Unlock the port. Good luck! :) */
2072
UNLOCK( filename, pid );
2074
static_add_filename( filename, fd );
2076
/* dont close the port. Its not clear if the RTS would remain high */
2077
LEAVE( "RXTXPort:nativeStaticSetRTS" );
2080
LEAVE( "RXTXPort:nativeStaticSetRTS" );
2084
/*----------------------------------------------------------
2085
RXTXPort.nativeStaticSetSerialPortParams
2087
accept: string for the filename, int baudrate, int databits,
2088
int stopbits, int parity
2089
perform: set the serial port, set the params, save the fd in a linked
2093
comments: Not set the speed on the next 'open'
2095
This is static so we can not call the open() setDTR()
2096
we dont have the jobject.
2098
First introduced in rxtx-1.5-9
2099
----------------------------------------------------------*/
2100
void gnu::io::RXTXPort::nativeStaticSetSerialPortParams (
2108
int fd, i, pid = -1, cspeed = translate_speed( baudrate );
2112
for( i=0;i<jstr->length();i++)
2113
filename[i] = jstr->charAt(i);
2117
ENTER( "RXTXPort:nativeStaticSetSerialPortParams" );
2121
/* Open and lock the port so nothing else changes the setting */
2123
if ( LOCK( filename, pid ) ) goto fail;
2125
fd = find_preopened_ports( filename );
2129
fd = ::OPEN (filename, O_RDWR | O_NOCTTY | O_NONBLOCK );
2130
} while (fd < 0 && errno==EINTR);
2131
if ( configure_port( fd ) ) goto fail;
2136
LEAVE( "RXTXPort:nativeStaticSetSerialPortParams" );
2137
snprintf( msg, 79, "%s%s", strerror( errno ), " in nativeStaticSetSerialPortParams" );
2138
throw new gnu::io::UnsupportedCommOperationException( JvNewStringUTF( msg ) );
2144
LEAVE( "RXTXPort:nativeStaticSetSerialPortParams" );
2145
snprintf( msg, 79, "%s%s", "BaudRate could not be set to the specified value", " in nativeStaticSetSerialPortParams" );
2146
throw new gnu::io::UnsupportedCommOperationException( JvNewStringUTF( msg ) );
2150
if( set_port_params( fd, cspeed, dataBits, stopBits, parity ) )
2152
LEAVE( "RXTXPort:nativeStaticSetSerialPortParams" );
2153
snprintf( msg, 79, "%s%s", strerror( errno ), " in nativeStaticSetSerialPortParams" );
2157
/* Unlock the port. Good luck! :) */
2159
UNLOCK( filename, pid );
2161
static_add_filename( filename, fd );
2162
/* dont close the port. */
2164
LEAVE( "RXTXPort:nativeStaticSetSerialPortParams" );
2167
LEAVE( "RXTXPort:nativeStaticSetSerialPortParams" );
2171
/*----------------------------------------------------------
2172
RXTXPort.nativeStaticSetDTR
2174
accept: new DTR state
2175
perform: if flag is true, TIOCM_DTR is set
2176
if flag is false, TIOCM_DTR is unset
2179
comments: Set the DTR so it does not raise on the next open
2180
needed for some funky test boards?
2182
This is static so we can not call the open() setDTR()
2183
we dont have the jobject.
2185
First introduced in rxtx-1.5-9
2186
----------------------------------------------------------*/
2187
jboolean gnu::io::RXTXPort::nativeStaticSetDTR (
2192
int fd, i, pid = -1, result;
2195
for( i=0;i<jstr->length();i++)
2196
filename[i] = jstr->charAt(i);
2199
ENTER( "RXTXPort:nativeStaticSetDTR" );
2204
/* Open and lock the port so nothing else changes the setting */
2206
if ( LOCK( filename, pid ) ) goto fail;;
2208
fd = find_preopened_ports( filename );
2212
fd = ::OPEN (filename, O_RDWR | O_NOCTTY | O_NONBLOCK );
2213
} while (fd < 0 && errno==EINTR);
2214
if ( configure_port( fd ) ) goto fail;
2216
if ( fd < 0 ) goto fail;
2220
ioctl( fd, TIOCMGET, &result );
2221
if( flag == true ) result |= TIOCM_DTR;
2222
else result &= ~TIOCM_DTR;
2223
ioctl( fd, TIOCMSET, &result );
2225
/* Unlock the port. Good luck! :) */
2227
UNLOCK( filename, pid );
2229
static_add_filename( filename, fd );
2230
/* dont close the port. Its not clear if the DTR would remain high */
2232
LEAVE( "RXTXPort:nativeStaticSetDTR" );
2235
LEAVE( "RXTXPort:nativeStaticSetDTR" );
2239
/*----------------------------------------------------------
2240
RXTXPort.nativeStaticIsRTS
2243
perform: check status of RTS of preopened ports (setting lines/params
2244
before calling the Java open()
2245
return: true if TIOCM_RTS is set
2246
false if TIOCM_RTS is not set
2248
comments: RTS stands for Request to Send
2249
----------------------------------------------------------*/
2250
jboolean gnu::io::RXTXPort::nativeStaticIsRTS(
2254
unsigned int result = 0;
2259
for( i=0;i<jstr->length();i++)
2260
filename[i] = jstr->charAt(i);
2262
fd = find_preopened_ports( filename );
2264
ENTER( "RXTXPort:nativeStaticIsRTS" );
2267
/* Exception? FIXME */
2270
ioctl( fd, TIOCMGET, &result );
2271
sprintf( message, "nativeStaticIsRTS( ) returns %i\n", result& TIOCM_RTS );
2273
LEAVE( "RXTXPort:nativeStaticIsRTS" );
2274
if( result & TIOCM_RTS ) return true;
2277
/*----------------------------------------------------------
2278
RXTXPort.nativeStaticIsDSR
2281
perform: check status of DSR of preopened ports (setting lines/params
2282
before calling the Java open()
2283
return: true if TIOCM_DSR is set
2284
false if TIOCM_DSR is not set
2287
----------------------------------------------------------*/
2288
jboolean gnu::io::RXTXPort::nativeStaticIsDSR(
2292
unsigned int result = 0;
2297
for( i=0;i<jstr->length();i++)
2298
filename[i] = jstr->charAt(i);
2300
fd = find_preopened_ports( filename );
2302
ENTER( "RXTXPort:nativeStaticIsDSR" );
2305
/* Exception? FIXME */
2308
ioctl( fd, TIOCMGET, &result );
2309
sprintf( message, "nativeStaticIsDSR( ) returns %i\n", result& TIOCM_DSR );
2311
LEAVE( "RXTXPort:nativeStaticIsDSR" );
2312
if( result & TIOCM_DSR ) return true;
2315
/*----------------------------------------------------------
2316
RXTXPort.nativeStaticIsDTR
2319
perform: check status of DTR of preopened ports (setting lines/params
2320
before calling the Java open()
2321
return: true if TIOCM_DTR is set
2322
false if TIOCM_DTR is not set
2324
comments: DTR stands for Data Terminal Ready
2325
----------------------------------------------------------*/
2326
jboolean gnu::io::RXTXPort::nativeStaticIsDTR(
2330
unsigned int result = 0;
2335
for( i=0;i<jstr->length();i++)
2336
filename[i] = jstr->charAt(i);
2338
fd = find_preopened_ports( filename );
2340
ENTER( "RXTXPort:nativeStaticIsDTR" );
2343
/* Exception? FIXME */
2346
ioctl( fd, TIOCMGET, &result );
2347
sprintf( message, "nativeStaticIsDTR( ) returns %i\n", result& TIOCM_DTR );
2349
LEAVE( "RXTXPort:nativeStaticIsDTR" );
2350
if( result & TIOCM_DTR ) return true;
2353
/*----------------------------------------------------------
2354
RXTXPort.nativeStaticIsCD
2357
perform: check status of CD of preopened ports (setting lines/params
2358
before calling the Java open()
2359
return: true if TIOCM_CD is set
2360
false if TIOCM_CD is not set
2362
comments: CD stands for carrier detect
2363
----------------------------------------------------------*/
2364
jboolean gnu::io::RXTXPort::nativeStaticIsCD(
2368
unsigned int result = 0;
2373
for( i=0;i<jstr->length();i++)
2374
filename[i] = jstr->charAt(i);
2376
fd = find_preopened_ports( filename );
2378
ENTER( "RXTXPort:nativeStaticIsCD" );
2381
/* Exception? FIXME */
2384
ioctl( fd, TIOCMGET, &result );
2385
sprintf( message, "nativeStaticIsCD( ) returns %i\n", result& TIOCM_CD );
2387
LEAVE( "RXTXPort:nativeStaticIsCD" );
2388
if( result & TIOCM_CD ) return true;
2391
/*----------------------------------------------------------
2392
RXTXPort.nativeStaticIsCTS
2395
perform: check status of CTS of preopened ports (setting lines/params
2396
before calling the Java open()
2397
return: true if TIOCM_CTS is set
2398
false if TIOCM_CTS is not set
2400
comments: CTS stands for Clear To Send
2401
----------------------------------------------------------*/
2402
jboolean gnu::io::RXTXPort::nativeStaticIsCTS(
2406
unsigned int result = 0;
2411
for( i=0;i<jstr->length();i++)
2412
filename[i] = jstr->charAt(i);
2414
fd = find_preopened_ports( filename );
2416
ENTER( "RXTXPort:nativeStaticIsCTS" );
2419
/* Exception? FIXME */
2422
ioctl( fd, TIOCMGET, &result );
2423
sprintf( message, "nativeStaticIsCTS( ) returns %i\n", result& TIOCM_CTS );
2425
LEAVE( "RXTXPort:nativeStaticIsCTS" );
2426
if( result & TIOCM_CTS ) return true;
2429
/*----------------------------------------------------------
2430
RXTXPort.nativeStaticIsRI
2433
perform: check status of RI of preopened ports (setting lines/params
2434
before calling the Java open()
2435
return: true if TIOCM_RI is set
2436
false if TIOCM_RI is not set
2438
comments: RI stands for carrier detect
2439
----------------------------------------------------------*/
2440
jboolean gnu::io::RXTXPort::nativeStaticIsRI(
2444
unsigned int result = 0;
2449
for( i=0;i<jstr->length();i++)
2450
filename[i] = jstr->charAt(i);
2452
fd = find_preopened_ports( filename );
2454
ENTER( "RXTXPort:nativeStaticIsRI" );
2457
/* Exception? FIXME */
2460
ioctl( fd, TIOCMGET, &result );
2461
sprintf( message, "nativeStaticRI( ) returns %i\n", result& TIOCM_RI );
2463
LEAVE( "RXTXPort:nativeStaticIsRI" );
2464
if( result & TIOCM_RI ) return true;
2468
/*----------------------------------------------------------
2469
RXTXPort.nativeStaticGetBaudRate
2472
perform: find the baud rate (not all buads are handled yet)
2473
return: return the baud rate or -1 if not supported yet.
2475
comments: simple test for preopened ports
2476
----------------------------------------------------------*/
2477
jint gnu::io::RXTXPort::nativeStaticGetBaudRate(
2482
struct termios ttyset;
2486
for( i=0;i<jstr->length();i++)
2487
filename[i] = jstr->charAt(i);
2489
fd = find_preopened_ports( filename );
2491
ENTER( "RXTXPort:nativeStaticGetBaudRate" );
2494
/* Exception? FIXME */
2497
if( tcgetattr( fd, &ttyset ) < 0 )
2499
report( "nativeStaticGetBaudRate: Cannot Get Serial Port Settings\n" );
2505
Trent, here is something I found with google:
2506
(freebsd list freebsd-current@freebsd.org)
2508
Andrzej Bialecki <abial@korin.warman.org.pl> asked:
2509
I tried to compile a piece of software, probably for Linux, and I noticed
2510
that we don't define CBAUD constant. I'm not sure, but I think POSIX
2511
defines and uses it. Should(n't) we?
2513
Bruce Evans <bde@zeta.org.au> answered:
2514
CBAUD is for SYSV compatibility. It is considerably inferior to POSIX's
2515
cf{get,set}{i,o}speed and shouldn't be provided or used.
2518
#if defined(CBAUD)/* dima */
2519
baudrate = ttyset.c_cflag&CBAUD;
2521
if(cfgetispeed(&ttyset) != cfgetospeed(&ttyset)) return -1;
2522
baudrate = cfgetispeed(&ttyset);
2524
return( get_java_baudrate(baudrate) );
2526
/*----------------------------------------------------------
2527
RXTXPort.nativeStaticGetDataBits
2530
perform: find the data bits (not all buads are handled yet)
2531
return: return the data bits
2533
comments: simple test for preopened ports
2534
----------------------------------------------------------*/
2535
jint gnu::io::RXTXPort::nativeStaticGetDataBits(
2540
struct termios ttyset;
2543
for( i=0;i<jstr->length();i++)
2544
filename[i] = jstr->charAt(i);
2546
fd = find_preopened_ports( filename );
2548
ENTER( "RXTXPort:nativeStaticGetDataBits" );
2551
/* Exception? FIXME */
2554
if( tcgetattr( fd, &ttyset ) < 0 )
2556
report( "nativeStaticGetDataBits: Cannot Get Serial Port Settings\n" );
2559
switch( ttyset.c_cflag&CSIZE ) {
2560
case CS5: return JDATABITS_5;
2561
case CS6: return JDATABITS_6;
2562
case CS7: return JDATABITS_7;
2563
case CS8: return JDATABITS_8;
2564
default: return(-1);
2567
/*----------------------------------------------------------
2568
RXTXPort.nativeStaticGetParity
2571
perform: find the parity
2572
return: return the parity
2574
comments: simple test for preopened ports
2575
----------------------------------------------------------*/
2576
jint gnu::io::RXTXPort::nativeStaticGetParity(
2581
struct termios ttyset;
2584
for( i=0;i<jstr->length();i++)
2585
filename[i] = jstr->charAt(i);
2587
fd = find_preopened_ports( filename );
2589
ENTER( "RXTXPort:nativeStaticGetParity" );
2592
/* Exception? FIXME */
2595
if( tcgetattr( fd, &ttyset ) < 0 )
2597
report( "nativeStaticGetParity: Cannot Get Serial Port Settings\n" );
2601
switch( ttyset.c_cflag&(PARENB|PARODD|CMSPAR ) ) {
2603
switch( ttyset.c_cflag&(PARENB|PARODD) ) {
2605
case 0: return JPARITY_NONE;
2606
case PARENB: return JPARITY_EVEN;
2607
case PARENB | PARODD: return JPARITY_ODD;
2609
case PARENB | PARODD | CMSPAR: return JPARITY_MARK;
2610
case PARENB | CMSPAR: return JPARITY_SPACE;
2612
default: return(-1);
2615
/*----------------------------------------------------------
2616
RXTXPort.nativeStaticGetStopBits
2619
perform: find the stop bits
2620
return: return the stop bits
2622
comments: simple test for preopened ports
2623
----------------------------------------------------------*/
2624
jint gnu::io::RXTXPort::nativeStaticGetStopBits(
2629
struct termios ttyset;
2631
fd = find_preopened_ports( filename );
2633
for( i=0;i<jstr->length();i++)
2634
filename[i] = jstr->charAt(i);
2637
ENTER( "RXTXPort:nativeStaticGetStopBits" );
2640
/* Exception? FIXME */
2643
if( tcgetattr( fd, &ttyset ) < 0 )
2645
report( "nativeStaticGetStopBits: Cannot Get Serial Port Settings\n" );
2648
switch( ttyset.c_cflag&(CSTOPB) ) {
2649
case 0: return STOPBITS_1;
2650
case CSTOPB: return STOPBITS_2;
2651
default: return STOPBITS_1_5;
2655
/*----------------------------------------------------------
2656
RXTXPort.nativeGetParityErrorChar
2659
perform: check the ParityErrorChar
2660
return: The ParityErrorChar as an jbyte.
2661
exceptions: UnsupportedCommOperationException if not implemented
2662
comments: It appears the Parity char is usually \0. The windows
2663
API allows for this to be changed. I cant find may
2664
examples of this being done. Maybe for a reason.
2666
Use a direct call to the termios file until we find a
2668
----------------------------------------------------------*/
2669
jbyte gnu::io::RXTXPort::nativeGetParityErrorChar(
2672
unsigned int result = 0;
2674
ENTER( "nativeGetParityErrorChar" );
2676
result = ( jbyte ) termiosGetParityErrorChar(
2680
arg! I cant find a way to change it from \0 in Linux. I think
2681
the frame and parity error characters are hardcoded.
2683
result = ( jint ) '\0';
2686
LEAVE( "nativeGetParityErrorChar" );
2687
return( ( jbyte ) result );
2690
/*----------------------------------------------------------
2691
RXTXPort.nativeGetEndOfInputChar
2694
perform: check the EndOf InputChar
2695
return: the EndOfInputChar as an jbyte. -1 on error
2696
exceptions: UnsupportedCommOperationException if not implemented
2698
----------------------------------------------------------*/
2699
jbyte gnu::io::RXTXPort::nativeGetEndOfInputChar(
2702
int fd = ( int ) this->fd;
2703
struct termios ttyset;
2705
ENTER( "nativeGetEndOfInputChar" );
2706
if( tcgetattr( fd, &ttyset ) < 0 ) goto fail;
2707
LEAVE( "nativeGetEndOfInputChar" );
2708
return( (jbyte) ttyset.c_cc[VEOF] );
2710
LEAVE( "nativeGetEndOfInputChar" );
2711
report( "nativeGetEndOfInputChar failed\n" );
2712
return( ( jbyte ) -1 );
2715
/*----------------------------------------------------------
2716
RXTXPort.nativeSetParityErrorChar
2718
accept: the ParityArrorCharacter as an int.
2719
perform: Set the ParityErrorChar
2720
return: true on success
2721
exceptions: UnsupportedCommOperationException if not implemented
2722
comments: It appears the Parity char is usually \0. The windows
2723
API allows for this to be changed. I cant find may
2724
examples of this being done. Maybe for a reason.
2726
Use a direct call to the termios file until we find a
2728
----------------------------------------------------------*/
2729
jboolean gnu::io::RXTXPort::nativeSetParityErrorChar(
2736
int fd = ( int ) this->fd;
2737
ENTER( "nativeSetParityErrorChar" );
2738
termiosSetParityError( fd, ( char ) value );
2739
LEAVE( "nativeSetParityErrorChar" );
2742
ENTER( "nativeSetParityErrorChar" );
2744
arg! I cant find a way to change it from \0 in Linux. I think
2745
the frame and parity error characters are hardcoded.
2748
snprintf( msg, 79, "%s%s", strerror( errno ), " in setParityErrorChar()" );
2749
throw new gnu::io::UnsupportedCommOperationException( JvNewStringUTF( msg ) );
2750
LEAVE( "nativeSetParityErrorChar" );
2755
/*----------------------------------------------------------
2756
RXTXPort.nativeSetEndOfInputChar
2758
accept: The EndOfInputChar as an int
2759
perform: set the EndOfInputChar
2760
return: true on success
2761
exceptions: UnsupportedCommOperationException if not implemented
2762
comments: This may cause troubles on Windows.
2763
Lets give it a shot and see what happens.
2765
See termios.c for the windows bits.
2768
fBinary = false; winapi docs say always use true. ?
2769
----------------------------------------------------------*/
2770
jboolean gnu::io::RXTXPort::nativeSetEndOfInputChar(
2774
int fd = ( int ) this->fd;
2775
struct termios ttyset;
2778
ENTER( "nativeSetEndOfInputChar" );
2779
if( tcgetattr( fd, &ttyset ) < 0 ) goto fail;
2780
ttyset.c_cc[VEOF] = ( char ) value;
2781
if( tcsetattr( fd, TCSANOW, &ttyset ) < 0 ) goto fail;
2782
LEAVE( "nativeSetEndOfInputChar" );
2785
snprintf( msg, 79, "%s%s", strerror( errno ), " in nativeSetEndOfInputChar" );
2786
throw new gnu::io::UnsupportedCommOperationException( JvNewStringUTF( msg ) );
2787
report( "nativeSetEndOfInputChar failed\n" );
2788
LEAVE( "nativeSetEndOfInputChar" );
2796
/* return milliseconds */
2799
gettimeofday(&now, NULL);
2800
report_verbose("gettimeofday\n");
2803
return ( ( now.tv_sec * 1000 + now.tv_usec / 1000 ) );
2805
return ( ( now.tv_sec * 1000) + ( long ) ceil( ( double ) now.tv_usec / 1000 ) );
2806
#endif /* __QNX__ */
2811
/*----------------------------------------------------------
2814
accept: int fd file descriptor to read from
2815
unsigned char *buffer buffer to read data into
2816
int length number of bytes to read
2817
int timeout milliseconds to wait before returning
2818
perform: read bytes from the port into a buffer
2819
return: status of read
2820
-1 fail (IOException)
2822
>0 number of bytes read
2823
comments: According to the Communications API spec, a receive threshold
2824
of 1 is the same as having the threshold disabled.
2826
The nuts and bolts are documented in
2827
NativeEnableReceiveTimeoutThreshold()
2828
----------------------------------------------------------*/
2830
int read_byte_array(
2832
unsigned char *buffer,
2837
int ret, left, bytes = 0;
2838
long timeLeft, now = 0, start = 0;
2840
struct timeval tv, *tvP;
2844
sigset_t sigpwr_mask;
2846
// init the sigset for blocking SIGPWR + SIGXCPU
2847
sigemptyset(&sigpwr_mask);
2848
sigaddset(&sigpwr_mask, SIGPWR);
2849
sigaddset(&sigpwr_mask, SIGXCPU);
2851
report_time_start();
2852
ENTER( "read_byte_array" );
2853
sprintf(msg, "read_byte_array requests %i\n", length);
2857
start = GetTickCount();
2858
while( bytes < length && count++ < 20 );
2861
now = GetTickCount();
2862
if ( now-start >= timeout )
2870
timeLeft = timeout - (now - start);
2871
tv.tv_sec = timeLeft / 1000;
2872
tv.tv_usec = 1000 * ( timeLeft % 1000 );
2879
// ignore SIGPWR + SIGXCPU during SELECT as gcj GC uses these signals
2880
sigprocmask(SIG_BLOCK, &sigpwr_mask, NULL);
2882
ret = SELECT(fd + 1, &rset, NULL, NULL, tvP);
2883
} while ( ret < 0 && errno == EINTR );
2884
sigprocmask(SIG_UNBLOCK, &sigpwr_mask, NULL);
2886
report( "read_byte_array: select returned -1\n" );
2887
LEAVE( "read_byte_array" );
2891
if ((ret = READ( fd, buffer + bytes, left )) < 0 ){
2892
if (errno != EINTR && errno != EAGAIN){
2893
report( "read_byte_array: read returned -1\n" );
2894
LEAVE( "read_byte_array" );
2903
The only thing that is bugging me with the new
2904
version is the CPU usage when reading on the serial port. I
2905
looked at it today and find a quick fix. It doesn't seems to
2906
affect the performance for our apps (I mean in a negative way,
2907
cause the CPU is back to normal, near 0-5%). All I did is add
2908
a usleep in the reading function.
2910
Nicolas <ripley@8d.com>
2921
throw_java_exception( env, IO_EXCEPTION, "read_byte_array",
2922
"No data available" );
2926
//*(buffer+bytes) = 0;
2927
sprintf(msg, "read_byte_array returns %i\n", bytes);
2929
LEAVE( "read_byte_array" );
2934
/*----------------------------------------------------------
2935
NativeEnableReceiveTimeoutThreshold
2936
accept: int threshold, int vtime,int buffer
2937
perform: Set c_cc->VMIN to threshold and c_cc=>VTIME to vtime
2939
exceptions: IOException
2940
comments: This is actually all handled in read with select in
2941
canonical input mode.
2942
----------------------------------------------------------*/
2943
void gnu::io::RXTXPort::NativeEnableReceiveTimeoutThreshold(
2949
int fd = ( int ) this->fd;
2950
struct termios ttyset;
2957
else if (vtime == 0){
2964
ENTER( "RXTXPort:NativeEnableRecieveTimeoutThreshold" );
2965
if( tcgetattr( fd, &ttyset ) < 0 ) goto fail;
2966
/* TESTING ttyset.c_cc[ VMIN ] = threshold; */
2967
ttyset.c_cc[ VMIN ] = 0;
2968
ttyset.c_cc[ VTIME ] = timeout/100;
2969
if( tcsetattr( fd, TCSANOW, &ttyset ) < 0 ) goto fail;
2971
LEAVE( "RXTXPort:NativeEnableRecieveTimeoutThreshold" );
2974
LEAVE( "RXTXPort:NativeEnableRecieveTimeoutThreshold" );
2975
snprintf( msg, 79, "%s%s", strerror( errno ), " in TimeoutThreshold" );
2976
throw new java::io::IOException( JvNewStringUTF( msg ) );
2980
/*----------------------------------------------------------
2984
perform: Read a single byte from the port. Block unless an exeption
2985
is thrown, or end of stream.
2986
return: The byte read
2987
exceptions: IOException
2990
On Fri, 30 Aug 2002, Bill Smith wrote:
2992
I agree, the documentation isn't the best. No surprises there.
2994
I did do a test using the sun/win32 comm driver with read() and retrieve
2995
timeout enabled. It blocked until the timeout expired, then returned a -1.
2996
This seems to jive with the way I'm reading it which is the javax.comm
2997
comments regarding read (in the CommPort.getInputStream stuff)
2999
the documentation for java.io.InputStream.
3001
This is the same behavior that the Windriver driver for vxworks exhibits.
3003
On Fri, 30 Aug 2002, Bill Smith wrote:
3007
> I have a couple of questions/comments.
3009
> 1) I noticed in the thread last night and in the code changes this morning that you
3010
> now have readByte() (which is called from the input stream read(), to block
3011
> forever. I pulled the following info from the javax.comm doc for the CommPort class in
3014
> The way I interpret that is that read() just like read(byte[]), and read(byte[], int, int),
3015
> show only block indefinitely if timeout is disabled. The sun implementation for win32 (as
3016
> well as the one we have for vxworks) returns a -1 when it times out.
3019
Doing what Sun does is going to the least hassle. The documentation was a
3020
little unclear to me. I assume this is the CommPort.getInputStream
3021
comment that you mention
3023
The read behaviour of the input stream returned by getInputStream
3024
depends on combination of the threshold and timeout values. The
3025
possible behaviours are described in the table below: ...
3027
But InputStream is where read(byte) is documented
3028
http://java.sun.com/j2se/1.3/docs/api/java/io/InputStream.html#read()
3030
Reads the next byte of data from the input stream. The value byte
3031
is returned as an int in the range 0 to 255. If no byte is
3032
available because the end of the stream has been reached, the value
3033
-1 is returned. This method blocks until input data is
3034
available, the end of the stream is detected, or an exception is
3037
If you are sure commapi is doing a timeout and returning -1, I can change
3038
it back and document the issue.
3040
Because I often grep my own mailbox for details, I'm going to add
3041
these two comments also:
3043
public int read(byte[] b)
3045
http://java.sun.com/j2se/1.3/docs/api/java/io/InputStream.html#read(byte[])
3047
Reads some number of bytes from the input stream and stores them
3048
into the buffer array b. The number of bytes actually read is
3049
returned as an integer. This method blocks until input data is
3050
available, end of file is detected, or an exception is thrown.
3052
If b is null, a NullPointerException is thrown. If the length of b
3053
is zero, then no bytes are read and 0 is returned; otherwise,
3054
there is an attempt to read at least one byte. If no byte is
3055
available because the stream is at end of file, the value -1 is
3056
returned; otherwise, at least one byte is read and stored into b.
3058
So read(byte[] b) is documented as blocking for the first byte.
3060
public int read(byte[] b,int off,int len)
3061
http://java.sun.com/j2se/1.3/docs/api/java/io/InputStream.html#read(byte[],
3064
Reads up to len bytes of data from the input stream into an array of
3065
bytes. An attempt is made to read as many as len bytes, but a
3066
smaller number may be read, possibly zero. The number of bytes
3067
actually read is returned as an integer.
3069
Which makes sense with the timeout documentation.
3071
<snip>threshold comment I'll look at that next. I thought those changes
3072
where in the ifdefed code. I'll take a second look and reply.
3075
> Thoughts? Comments?
3079
> ----------------------
3081
> public abstract InputStream getInputStream() throws IOException
3084
> Returns an input stream. This is the only way to receive data from the
3086
> port. If the port is unidirectional and doesn't support receiving data, then
3087
> getInputStream returns null.
3089
> The read behaviour of the input stream returned by getInputStream depends on
3090
> combination of the threshold and timeout values. The possible behaviours are
3091
> described in the table below:
3094
> Threshold Timeout Read Buffer Read Behaviour
3095
> State Value State Value Size
3097
-----------------------------------------------------------------------------------
3098
> disabled - disabled - n bytes block until any data is available
3100
> enabled m bytes disabled - n bytes block until min(m,n) bytes are available
3102
> disabled - enabled x ms n bytes block for x ms or
3103
until any data is available
3105
> enabled m bytes enabled x ms n bytes block for x ms or
3106
until min(m,n) bytes are available
3108
> Returns: InputStream object that can be used to read from the port
3110
> Throws: IOException if an I/O error occurred
3113
----------------------------------------------------------*/
3114
jint gnu::io::RXTXPort::readByte(
3118
unsigned char buffer[ 1 ];
3119
int fd = ( int ) this->fd;
3120
int timeout = ( int ) this->timeout;
3123
ENTER( "RXTXPort:readByte" );
3124
report_time_start( );
3125
bytes = read_byte_array( fd, buffer, 1, timeout );
3127
LEAVE( "RXTXPort:readByte" );
3128
snprintf( msg, 79, "%s%s", strerror( errno ), " in readByte" );
3129
throw new java::io::IOException( JvNewStringUTF( msg ) );
3132
LEAVE( "RXTXPort:readByte" );
3133
sprintf( msg, "readByte return(%i)\n", bytes ? buffer[ 0 ] : -1 );
3136
return (bytes ? (jint)buffer[ 0 ] : -1);
3139
/*----------------------------------------------------------
3142
accept: offset (offset to start storing data in the jbarray) and
3143
Length (bytes to read)
3144
perform: read bytes from the port into a byte array
3145
return: bytes read on success
3147
exceptions: IOException
3148
comments: throws ArrayIndexOutOfBoundsException if asked to
3149
read more than SSIZE_MAX bytes
3150
----------------------------------------------------------*/
3151
jint gnu::io::RXTXPort::readArray(
3159
int fd = ( int ) this->fd;
3160
int timeout = ( int ) this->timeout;
3161
jbyte *in = elements( jbarray ) + offset;
3163
ENTER( "readArray" );
3164
report_time_start( );
3165
if( length > SSIZE_MAX || length < 0 ) {
3166
report( "RXTXPort:readArray length > SSIZE_MAX" );
3167
LEAVE( "RXTXPort:readArray" );
3168
snprintf( msg, 79, "%s%s", "Invalid length", " in readArray" );
3169
throw new java::lang::ArrayIndexOutOfBoundsException( JvNewStringUTF( msg ) );
3172
bytes = read_byte_array( fd, (unsigned char *) in, length, timeout );/* dima */
3174
report( "RXTXPort:readArray bytes < 0" );
3175
LEAVE( "RXTXPort:readArray" );
3176
snprintf( msg, 79, "%s%s", strerror( errno ), " in readArray" );
3177
throw new java::io::IOException( JvNewStringUTF( msg ) );
3180
sprintf( msg, "RXTXPort:readArray: %i %i\n", (int) length, bytes);
3184
LEAVE( "RXTXPort:readArray" );
3188
/*----------------------------------------------------------
3189
RXTXPort.nativeavailable
3192
perform: find out the number of bytes available for reading
3193
return: available bytes
3196
----------------------------------------------------------*/
3197
jint gnu::io::RXTXPort::nativeavailable(
3200
int fd = ( int ) this->fd;
3205
ENTER( "RXTXPort:nativeavailable" );
3207
On SCO OpenServer FIONREAD always fails for serial devices,
3208
so try ioctl FIORDCHK instead; will only tell us whether
3209
bytes are available, not how many, but better than nothing.
3211
This turns out to be true on Solaris also. taj.
3213
#ifdef FIORDCHK /* __unixware__ __sun__ probably others */
3214
result = ioctl(fd, FIORDCHK, 0);
3216
if( ioctl( fd, FIONREAD, &result ) < 0 )
3220
#endif /* FIORDCHK */
3221
sprintf(msg, " nativeavailable: FIORDCHK result %d, \
3222
errno %d\n", result , result == -1 ? errno : 0);
3223
report_verbose( msg );
3229
sprintf(msg, " nativeavailable: FIORDCHK result %d, \
3230
errno %d\n", result , result == -1 ? errno : 0);
3234
LEAVE( "RXTXPort:nativeavailable" );
3236
return (jint)result;
3238
report("RXTXPort:nativeavailable: ioctl() failed\n");
3240
LEAVE( "RXTXPort:nativeavailable" );
3242
snprintf( msg, 79, "%s%s", strerror( errno ), " in nativeavailable" );
3243
throw new java::io::IOException( JvNewStringUTF( msg ) );
3244
return (jint)result;
3247
/*----------------------------------------------------------
3248
RXTXPort.setflowcontrol
3251
FLOWCONTROL_NONE none
3252
FLOWCONTROL_RTSCTS_IN hardware flow control
3253
FLOWCONTROL_RTSCTS_OUT ""
3254
FLOWCONTROL_XONXOFF_IN input software flow control
3255
FLOWCONTROL_XONXOFF_OUT output software flow control
3256
perform: set flow control to flowmode
3258
exceptions: UnsupportedCommOperationException
3259
comments: there is no differentiation between input and output hardware
3261
----------------------------------------------------------*/
3262
void gnu::io::RXTXPort::setflowcontrol(
3266
struct termios ttyset;
3267
int fd = ( int ) this->fd;
3270
ENTER( "RXTXPort:setflowcontrol" );
3271
if( tcgetattr( fd, &ttyset ) ) goto fail;
3273
if ( flowmode & ( FLOWCONTROL_RTSCTS_IN | FLOWCONTROL_RTSCTS_OUT ) )
3275
ttyset.c_cflag |= HARDWARE_FLOW_CONTROL;
3277
else ttyset.c_cflag &= ~HARDWARE_FLOW_CONTROL;
3279
ttyset.c_iflag &= ~IXANY;
3281
if ( flowmode & FLOWCONTROL_XONXOFF_IN )
3283
ttyset.c_iflag |= IXOFF;
3285
else ttyset.c_iflag &= ~IXOFF;
3287
if ( flowmode & FLOWCONTROL_XONXOFF_OUT )
3290
ttyset.c_iflag |= IXON;
3292
else ttyset.c_iflag &= ~IXON;
3294
if( tcsetattr( fd, TCSANOW, &ttyset ) ) goto fail;
3295
LEAVE( "RXTXPort:setflowcontrol" );
3298
LEAVE( "RXTXPort:setflowcontrol" );
3299
snprintf( msg, 79, "%s%s", "flow control type not supported", " in setflowcontrol" );
3300
throw new java::io::IOException( JvNewStringUTF( msg ) );
3304
/*----------------------------------------------------------
3305
unlock_monitor_thread
3307
accept: event_info_struct
3308
perform: unlock the monitor thread so event notification can start.
3311
comments: Events can be missed otherwise.
3312
----------------------------------------------------------*/
3314
void unlock_monitor_thread( gnu::io::RXTXPort *p, struct event_info_struct *eis )
3316
p->MonitorThreadLock = false;
3319
/*----------------------------------------------------------
3320
check_line_status_register
3322
accept: event_info_struct
3323
perform: check for changes on the LSR
3324
return: 0 on success
3326
comments: not supported on all devices/drivers.
3327
----------------------------------------------------------*/
3328
int check_line_status_register( gnu::io::RXTXPort *p, struct event_info_struct *eis )
3330
#ifdef TIOCSERGETLSR
3331
struct stat fstatbuf;
3333
if( ! eis->eventflags[SPE_OUTPUT_BUFFER_EMPTY] )
3335
report( "check_line_status_registe OUPUT_BUFFER_EMPTY not set\n" );
3338
if ( fstat( eis->fd, &fstatbuf ) )
3340
report( "check_line_status_register: fstat\n" );
3343
if( ioctl( eis->fd, TIOCSERGETLSR, &eis->change ) )
3345
report( "check_line_status_register: TIOCSERGETLSR\n is nonnull\n" );
3348
else if( eis && eis->change )
3350
report_verbose( "check_line_status_register: sending OUTPUT_BUFFER_EMPTY\n" );
3351
send_event( p, eis, SPE_OUTPUT_BUFFER_EMPTY, 1 );
3355
printf("test %i\n", eis->output_buffer_empty_flag );
3357
if( eis && eis->output_buffer_empty_flag == 1 &&
3358
eis->eventflags[SPE_OUTPUT_BUFFER_EMPTY] )
3360
report_verbose("check_line_status_register: sending SPE_OUTPUT_BUFFER_EMPTY\n");
3361
send_event( p, eis, SPE_OUTPUT_BUFFER_EMPTY, 1 );
3363
send_event( this, eis, SPE_DATA_AVAILABLE, 1 );
3365
eis->output_buffer_empty_flag = 0;
3367
#endif /* TIOCSERGETLSR */
3371
/*----------------------------------------------------------
3372
has_line_status_register_access
3374
accept: fd of interest
3375
perform: check for access to the LSR
3376
return: 0 if not available
3378
comments: not supported on all devices/drivers.
3379
JK00: work around for multiport cards without TIOCSERGETLSR
3380
Cyclades is one of those :-(
3381
----------------------------------------------------------*/
3382
int has_line_status_register_access( int fd )
3384
#if defined(TIOCSERGETLSR)
3387
if( !ioctl( fd, TIOCSERGETLSR, &change ) ) {
3390
#endif /* TIOCSERGETLSR */
3391
report( "has_line_status_register_acess: Port does not support TIOCSERGETLSR\n" );
3395
/*----------------------------------------------------------
3398
accept: fd of interest
3399
perform: check for access to TIOCGICOUNT
3400
return: 0 if not available
3402
comments: not supported on all devices/drivers.
3403
* wait for RNG, DSR, CD or CTS but not DataAvailable
3404
* The drawback here is it never times out so if someone
3405
* reads there will be no chance to try again.
3406
* This may make sense if the program does not want to
3407
* be notified of data available or errors.
3408
* ret=ioctl(fd,TIOCMIWAIT);
3409
----------------------------------------------------------*/
3410
void check_cgi_count( gnu::io::RXTXPort *p, struct event_info_struct *eis )
3412
#if defined(TIOCGICOUNT)
3414
/* JK00: only use it if supported by this port */
3416
struct serial_icounter_struct sis;
3417
memcpy( &sis, &eis->osis, sizeof( struct serial_icounter_struct ) );
3419
if( ioctl( eis->fd, TIOCGICOUNT, &sis ) )
3421
report( "check_cgi_count: TIOCGICOUNT\n is not 0\n" );
3424
while( eis && sis.frame != eis->osis.frame ) {
3425
send_event( p, eis, SPE_FE, 1);
3428
while( eis && sis.overrun != eis->osis.overrun ) {
3429
send_event( p, eis, SPE_OE, 1);
3430
eis->osis.overrun++;
3432
while( eis && sis.parity != eis->osis.parity ) {
3433
send_event( p, eis, SPE_PE, 1);
3436
while( eis && sis.brk != eis->osis.brk ) {
3437
send_event( p, eis, SPE_BI, 1);
3441
memcpy( &eis->osis, &sis, sizeof( struct serial_icounter_struct ) );
3442
#endif /* TIOCGICOUNT */
3445
/*----------------------------------------------------------
3446
port_has_changed_fionread
3448
accept: fd of interest
3449
perform: check if FIONREAD has changed
3450
return: 0 if no data available
3453
----------------------------------------------------------*/
3454
int port_has_changed_fionread( struct event_info_struct *eis )
3459
rc = ioctl( eis->fd, FIONREAD, &change );
3460
sprintf( message, "port_has_changed_fionread: change is %i ret is %i\n", change, eis->ret );
3461
#if defined(__unixware__) || defined(__sun__)
3463
On SCO OpenServer FIONREAD always fails for serial devices,
3464
so rely upon select() result to know whether data available.
3466
This is true for Solaris, also. taj.
3468
if( (rc != -1 && change) || (rc == -1 && eis->ret > 0) )
3471
sprintf( message, "port_has_changed_fionread: change is %i\n", change );
3472
report_verbose( message );
3475
#endif /* __unixware__ || __sun__ */
3479
/*----------------------------------------------------------
3480
check_tiocmget_changes
3482
accept: event_info_struct
3483
perform: use TIOCMGET to report events
3486
comments: not supported on all devices/drivers.
3487
----------------------------------------------------------*/
3488
void check_tiocmget_changes( gnu::io::RXTXPort *p, struct event_info_struct * eis )
3490
unsigned int mflags = 0;
3495
change = eis->change;
3497
report_verbose("entering check_tiocmget_changes\n");
3498
if( ioctl( eis->fd, TIOCMGET, &mflags ) )
3500
report( "=======================================\n");
3501
report( "check_tiocmget_changes: ioctl(TIOCMGET)\n" );
3505
change = (mflags&TIOCM_CTS) - (eis->omflags&TIOCM_CTS);
3506
if( eis && change ) send_event( p, eis, SPE_CTS, change );
3508
change = (mflags&TIOCM_DSR) - (eis->omflags&TIOCM_DSR);
3511
report( "sending DSR ===========================\n");
3512
send_event( p, eis, SPE_DSR, change );
3515
change = (mflags&TIOCM_RNG) - (eis->omflags&TIOCM_RNG);
3516
if( eis && change ) send_event( p, eis, SPE_RI, change );
3518
change = (mflags&TIOCM_CD) - (eis->omflags&TIOCM_CD);
3519
if( eis && change ) send_event( p, eis, SPE_CD, change );
3522
eis->omflags = mflags;
3523
report_verbose("leaving check_tiocmget_changes\n");
3526
/*----------------------------------------------------------
3534
----------------------------------------------------------*/
3537
#if defined (__sun__ )
3538
struct timespec retspec, tspec;
3540
retspec.tv_nsec = 100000000;
3543
nanosleep( &tspec, &retspec );
3544
} while( tspec.tv_nsec != 0 );
3548
#ifdef TRENT_IS_HERE_DEBUGGING_THREADS
3549
/* On NT4 The following was observed in a intense test:
3552
1000000 95% 203 sec some callback failures sometimes.
3553
2000000 0-95% callback failures.
3555
#endif /* TRENT_IS_HERE_DEBUGGING_THREADS */
3556
#endif /* __sun__ */
3559
/*----------------------------------------------------------
3560
driver_has_tiocgicount
3562
accept: fd of interest
3563
perform: check for access to TIOCGICOUNT
3564
return: 0 if not available
3566
comments: not supported on all devices/drivers.
3567
Some multiport serial cards do not implement TIOCGICOUNT ...
3568
So use the 'dumb' mode to enable using them after all! JK00
3569
----------------------------------------------------------*/
3570
int driver_has_tiocgicount( struct event_info_struct * eis )
3572
#if defined(TIOCGICOUNT)
3574
/* Some multiport serial cards do not implement TIOCGICOUNT ... */
3575
/* So use the 'dumb' mode to enable using them after all! JK00 */
3577
if( ioctl( eis->fd, TIOCGICOUNT, &eis->osis ) < 0 ) {
3578
report_verbose( " driver_has_tiocgicount: Port does not support TIOCGICOUNT events\n" );
3583
#endif /* TIOCGICOUNT */
3588
/*----------------------------------------------------------
3589
report_serial_events
3591
accept: event_info_struct
3592
perform: send events if they occured
3593
return: 0 if not available
3595
comments: not supported on all devices/drivers.
3596
----------------------------------------------------------*/
3597
void report_serial_events( gnu::io::RXTXPort *p, struct event_info_struct *eis )
3599
/* JK00: work around for Multi IO cards without TIOCSERGETLSR */
3600
/* if( eis->has_tiocsergetlsr ) we have a fix for output empty */
3601
if( check_line_status_register( p, eis ) )
3604
#ifndef WIN32 /* something is wrong here */
3605
if ( eis && eis->has_tiocgicount )
3606
check_cgi_count( p, eis );
3609
check_tiocmget_changes( p, eis );
3611
if( eis && port_has_changed_fionread( eis ) )
3613
if(!eis->eventflags[SPE_DATA_AVAILABLE] )
3615
report_verbose("report_serial_events: ignoring DATA_AVAILABLE\n");
3619
#if !defined(__sun__)
3620
/* FIXME: No time to test on all OS's for production */
3622
#endif /* !__sun__ */
3625
report("report_serial_events: sending DATA_AVAILABLE\n");
3626
if(!send_event( p, eis, SPE_DATA_AVAILABLE, 1 ))
3628
/* select wont block */
3629
#if !defined(__sun__)
3630
/* FIXME: No time to test on all OS's for production */
3632
#endif /* !__sun__ */
3640
/*----------------------------------------------------------
3641
initialise_event_info_struct
3643
accept: event_info_struct for this thread.
3644
perform: initialise or reset the event_info_struct
3645
return: 1 on success
3648
----------------------------------------------------------*/
3649
int initialise_event_info_struct( gnu::io::RXTXPort *p, struct event_info_struct *eis )
3652
struct event_info_struct *index = master_index;
3654
if ( eis->initialised == 1 )
3658
memset(&eis->osis,0,sizeof(eis->osis));
3659
#endif /* TIOCGICOUNT */
3663
while( index->next )
3665
index = index->next;
3674
master_index->next = NULL;
3675
master_index->prev = NULL;
3678
for( i = 0; i < 11; i++ ) eis->eventflags[i] = 0;
3679
#if !defined(TIOCSERGETLSR) && !defined(WIN32)
3680
eis->output_buffer_empty_flag = 0;
3682
#endif /* TIOCSERGETLSR */
3683
eis->eventloop_interrupted = 0;
3686
eis->fd = ( int ) p->fd;
3687
eis->has_tiocsergetlsr = has_line_status_register_access( eis->fd );
3688
eis->has_tiocgicount = driver_has_tiocgicount( eis );
3690
if( ioctl( eis->fd, TIOCMGET, &eis->omflags) < 0 ) {
3691
report( "initialise_event_info_struct: Port does not support events\n" );
3695
FD_ZERO( &eis->rfds );
3696
FD_SET( eis->fd, &eis->rfds );
3697
eis->tv_sleep.tv_sec = 0;
3698
eis->tv_sleep.tv_usec = 1000;
3699
eis->initialised = 1;
3703
/*----------------------------------------------------------
3704
finalize_event_info_struct
3706
accept: event_info_struct for this thread.
3707
perform: free resources
3711
----------------------------------------------------------*/
3712
void finalize_event_info_struct( struct event_info_struct *eis )
3714
if( eis->next && eis->prev )
3716
eis->prev->next = eis->next;
3717
eis->next->prev = eis->prev;
3719
else if( eis->next )
3721
eis->next->prev = NULL;
3722
master_index = eis->next;
3724
else if( eis->prev )
3725
eis->prev->next = NULL;
3726
else master_index = NULL;
3729
/*----------------------------------------------------------
3733
perform: periodically check for SerialPortEvents
3736
comments: please keep this function clean.
3737
----------------------------------------------------------*/
3738
void gnu::io::RXTXPort::eventLoop(
3741
struct event_info_struct eis;
3742
eis.initialised = 0;
3744
ENTER( "eventLoop\n" );
3745
if ( !initialise_event_info_struct( this, &eis ) ) goto end;
3746
if ( !init_threads( this, &eis ) ) goto end;
3747
unlock_monitor_thread( this, &eis );
3749
report_time_eventLoop( );
3751
/* report( "." ); */
3752
eis.ret = SELECT( eis.fd + 1, &eis.rfds, NULL, NULL,
3754
/* nothing goes between this call and select */
3757
report("eventLoop: got interrupt\n");
3758
finalize_threads( &eis );
3759
finalize_event_info_struct( &eis );
3760
this->MonitorThreadCloseLock = false;
3766
Trent system_wait();
3768
} while ( eis.ret < 0 && errno == EINTR );
3771
report_serial_events( this, &eis );
3773
initialise_event_info_struct( this, &eis );
3776
LEAVE( "eventLoop: Bailing!\n" );
3779
/*----------------------------------------------------------
3780
RXTXCommDriver.nativeGetVersion
3783
perform: return the current version
3786
comments: This is used to avoid mixing versions of the .jar and
3788
First introduced in rxtx-1.5-9
3790
----------------------------------------------------------*/
3791
jstring gnu::io::RXTXCommDriver::nativeGetVersion (
3794
return JvNewStringUTF( "RXTX-2.1-7" );
3797
/*----------------------------------------------------------
3798
RXTXCommDriver.testRead
3800
accept: jstr The device to be tested
3801
perform: test if the device can be read from
3802
return: true if the device can be read from
3804
comments: From Wayne Roberts wroberts1@home.com
3805
check tcget/setattr returns.
3806
support for non serial ports Trent
3807
----------------------------------------------------------*/
3809
jboolean gnu::io::RXTXCommDriver::testRead(
3814
struct termios ttyset;
3816
int i, fd, ret = true, pid = -1;
3817
//char filename[80];
3819
#ifdef TRENT_IS_HERE_DEBUGGING_ENUMERATION
3821
#endif /* TRENT_IS_HERE_DEBUGGING_ENUMERATION */
3823
for( i=0;i<jstr->length();i++)
3824
filename[i] = jstr->charAt(i);
3826
//java::lang::System::out->println( filename );
3827
//const char *filename = (const char *) jstr->toCharArray();
3829
/* We opened the file in this thread, use this pid to unlock */
3830
//java::lang::System::out->println( jstr );
3834
char full_windows_name[80];
3837
ENTER( "RXTXPort:testRead" );
3838
//printf( "RXTXCommDriver::testRead( %s )\n", filename );
3839
#ifdef TRENT_IS_HERE_DEBUGGING_ENUMERATION
3840
/* vmware lies about which ports are there causing irq conflicts */
3841
/* this is for testing only */
3842
if( !strcmp( filename, "COM1" ) || !strcmp( filename, "COM2") )
3844
printf("%s is good\n",filename);
3845
sprintf( message, "testRead: %s is good!\n", filename );
3850
#endif /* TRENT_IS_HERE_DEBUGGING_ENUMERATION */
3852
strcpy( full_windows_name, DEVICEDIR );
3853
strcat( full_windows_name, filename );
3854
ret = serial_test((char *) full_windows_name );
3859
LOCK is one of three functions defined in SerialImp.h
3863
system_does_not_lock Win32
3865
//printf( "RXTXCommDriver::testRead( %s )\n", filename );
3867
if ( LOCK( filename, pid ) )
3869
LEAVE( "RXTXPort:testRead no lock" );
3874
CLOCAL eliminates open blocking on modem status lines
3875
-- changed to O_NONBLOCK
3878
fd=::OPEN ( filename, O_RDWR | O_NOCTTY | O_NONBLOCK );
3879
} while ( fd < 0 && errno==EINTR );
3883
report_verbose( "testRead() open failed\n" );
3888
if ( port_type == PORT_SERIAL )
3891
struct termios saved_termios;
3893
if (tcgetattr(fd, &ttyset) < 0) {
3898
/* save, restore later */
3899
if ( ( saved_flags = fcntl(fd, F_GETFL ) ) < 0 )
3901
report( "testRead() fcntl(F_GETFL) failed\n" );
3906
memcpy( &saved_termios, &ttyset, sizeof( struct termios ) );
3908
if ( fcntl( fd, F_SETFL, O_NONBLOCK ) < 0 )
3910
report( "testRead() fcntl(F_SETFL) failed\n" );
3916
ttyset.c_cc[VMIN] = ttyset.c_cc[VTIME] = 0;
3918
if ( tcsetattr( fd, TCSANOW, &ttyset) < 0 )
3920
report( "testRead() tcsetattr failed\n" );
3922
tcsetattr( fd, TCSANOW, &saved_termios );
3928
The following may mess up if both EAGAIN and EWOULDBLOCK
3929
are defined but only EWOULDBLOCK is used
3934
O_NONBLOCK or O_NDELAY
3935
When possible, the file is opened in non-blocking
3936
mode. Neither the open nor any subsequent opera�
3937
tions on the file descriptor which is returned will
3938
cause the calling process to wait. For the han�
3939
dling of FIFOs (named pipes), see also fifo(4).
3940
This mode need not have any effect on files other
3945
Non-blocking I/O has been selected using O_NONBLOCK
3946
and no data was immediately available for reading.
3949
/usr/include/asm/error.h:
3950
#define EAGAIN 11 / Try again /
3951
#define EWOULDBLOCK EAGAIN / Operation would block /
3953
looks like the kernel is using EAGAIN
3960
EAGAIN The path argument names the slave side of a
3961
pseudo-terminal device that is locked.
3964
If O_NONBLOCK is set, read() returns -1 and sets errno
3971
both are defined but EAGAIN is used.
3977
neither errno is currently set. Comment added to termios.c
3982
Steven's book. Advanced programming in the Unix Environment pg 364
3984
"A common use for nonblocking I/O is for dealing with a terminal device
3985
for a network connection and these devices are normally used by one process
3986
at a time. This means that the change in the BSD semantics normally does 't
3987
effect us. The different error return, EWOULDBLOCK, instead of POSIX.1
3988
EAGAIN, continues to be a portability difference that we must deal with."
3992
if ( READ( fd, &c, 1 ) < 0 )
3995
if ( errno != EAGAIN ) {
3996
report( "testRead() read failed\n" );
4001
if ( errno != EWOULDBLOCK )
4003
report( "testRead() read failed\n" );
4008
#endif /* EWOULDBLOCK */
4012
/* dont walk over unlocked open devices */
4013
tcsetattr( fd, TCSANOW, &saved_termios );
4014
fcntl( fd, F_SETFL, saved_flags );
4018
UNLOCK is one of three functions defined in SerialImp.h
4022
system_does_not_unlock Win32
4026
UNLOCK(filename, pid );
4028
LEAVE( "RXTXPort:testRead" );
4032
#if defined(__APPLE__)
4033
/*----------------------------------------------------------
4034
createSerialIterator()
4040
Code courtesy of Eric Welch at Keyspan, except for the bugs
4041
which are courtesy of Joseph Goldstone (joseph@lp.com)
4042
----------------------------------------------------------*/
4045
createSerialIterator(io_iterator_t *serialIterator)
4047
kern_return_t kernResult;
4048
mach_port_t masterPort;
4049
CFMutableDictionaryRef classesToMatch;
4050
if ((kernResult=IOMasterPort(NULL, &masterPort)) != KERN_SUCCESS)
4052
printf( "IOMasterPort returned %d\n", kernResult);
4055
if ((classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue)) == NULL)
4057
printf( "IOServiceMatching returned NULL\n" );
4060
CFDictionarySetValue(classesToMatch, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
4061
kernResult = IOServiceGetMatchingServices(masterPort, classesToMatch, serialIterator);
4062
if (kernResult != KERN_SUCCESS)
4064
printf( "IOServiceGetMatchingServices returned %d\n", kernResult);
4069
/*----------------------------------------------------------
4077
Code courtesy of Eric Welch at Keyspan, except for the bugs
4078
which are courtesy of Joseph Goldstone (joseph@lp.com)
4079
----------------------------------------------------------*/
4081
getRegistryString(io_object_t sObj, char *propName)
4083
static char resultStr[256];
4084
CFTypeRef nameCFstring;
4086
nameCFstring = IORegistryEntryCreateCFProperty(sObj,
4087
CFStringCreateWithCString(kCFAllocatorDefault, propName, kCFStringEncodingASCII),
4088
kCFAllocatorDefault, 0);
4091
CFStringGetCString(nameCFstring, resultStr, sizeof(resultStr), kCFStringEncodingASCII);
4092
CFRelease(nameCFstring);
4097
/*----------------------------------------------------------
4098
registerKnownSerialPorts()
4104
----------------------------------------------------------*/
4106
registerKnownSerialPorts(
4110
io_iterator_t theSerialIterator;
4111
io_object_t theObject;
4112
int numPorts = 0;/* dima it should initiated */
4113
if (createSerialIterator(&theSerialIterator) != KERN_SUCCESS)
4115
printf( "createSerialIterator failed\n" );
4117
while (theObject = IOIteratorNext(theSerialIterator))
4119
/* begin dima taj got this close for gcj */
4120
jstring tempJstring;
4121
tempJstring = JvNewStringUTF(getRegistryString(theObject, kIODialinDeviceKey));
4122
gnu::io::ComPortIdentifier->addPortName(tempJstring,portType,this);/* dima */
4125
tempJstring = JvNewStringUTF(getRegistryString(theObject, kIOCalloutDeviceKey));
4126
gnu::io::ComPortIdentifier->addPortName(tempJstring,portType,this);/* dima */
4128
/* end dima taj got this close for gcj */
4134
#endif /* __APPLE__ */
4137
/*----------------------------------------------------------
4140
accept: the type of port
4141
perform: register any ports of the desired type a priori known to this OS
4142
return: true if any such ports were registered otherwise false
4145
----------------------------------------------------------*/
4146
jboolean gnu::io::RXTXCommDriver::registerKnownPorts(
4150
enum {PORT_TYPE_SERIAL = 1,
4155
jboolean result = false;
4159
case PORT_TYPE_SERIAL:
4160
#if defined(__APPLE__)
4161
if (registerKnownSerialPorts( PORT_TYPE_SERIAL) > 0)
4167
case PORT_TYPE_PARALLEL: break;
4168
case PORT_TYPE_I2C: break;
4169
case PORT_TYPE_RS485: break;
4170
case PORT_TYPE_RAW: break;
4172
sprintf( message, "unknown portType %d handed to \
4173
native RXTXCommDriver.registerKnownPorts() \
4182
/*----------------------------------------------------------
4185
accept: a port prefix
4186
perform: see if the port prefix matches a port that is valid on this OS.
4187
return: true if it exists otherwise false
4190
----------------------------------------------------------*/
4191
jboolean gnu::io::RXTXCommDriver::isPortPrefixValid(
4196
static struct stat mystat;
4197
char teststring[256];
4201
for( i=0;i<jstr->length();i++)
4202
filename[i] = jstr->charAt(i);
4205
ENTER( "RXTXCommDriver:isPortPrefixValid" );
4207
#if defined(__sun__)
4208
/* Solaris uses /dev/cua/a instead of /dev/cua0 */
4210
sprintf(teststring,"%s%s%c",DEVICEDIR, name, i + 97 );
4211
fprintf(stderr, "testing: %s\n", teststring);
4213
#if defined(_GNU_SOURCE)
4214
snprintf(teststring, 256, "%s%s%i",DEVICEDIR,filename, i);
4216
sprintf(teststring,"%s%s%i",DEVICEDIR,filename, i);
4217
#endif /* _GNU_SOURCE */
4218
stat(teststring,&mystat);
4219
#endif /* __sun__ */
4220
/* XXX the following hoses freebsd when it tries to open the port later on */
4222
if(S_ISCHR(mystat.st_mode)){
4223
fd=::OPEN(teststring,O_RDONLY|O_NONBLOCK);
4236
#endif /* __FreeBSD __ */
4238
#if defined(_GNU_SOURCE)
4239
snprintf(teststring, 256, "%s%s",DEVICEDIR,filename);
4241
sprintf(teststring,"%s%s",DEVICEDIR,filename);
4242
#endif /* _GNU_SOURCE */
4243
stat(teststring,&mystat);
4244
if(S_ISCHR(mystat.st_mode)){
4245
fd=::OPEN(teststring,O_RDONLY|O_NONBLOCK);
4251
LEAVE( "RXTXCommDriver:isPortPrefixValid" );
4255
/*----------------------------------------------------------
4260
return: the directory containing the device files
4262
comments: use this to avoid hard coded "/dev/"
4263
values are in SerialImp.h
4264
----------------------------------------------------------*/
4266
jstring gnu::io::RXTXCommDriver::getDeviceDirectory(
4269
ENTER( "RXTXCommDriver:getDeviceDirectory" );
4270
return JvNewStringUTF(DEVICEDIR);
4271
LEAVE( "RXTXCommDriver:getDeviceDirectory" );
4274
#ifdef GOING_TO_MESS_WITH_BUFFERS
4275
/*----------------------------------------------------------
4282
comments: see fopen/fclose/fwrite/fread man pages.
4283
----------------------------------------------------------*/
4284
void gnu::io::RXTXPort::setInputBufferSize(
4288
report( "setInputBufferSize is not implemented\n" );
4291
/*----------------------------------------------------------
4298
comments: see fopen/fclose/fwrite/fread man pages.
4299
----------------------------------------------------------*/
4300
jint gnu::io::RXTXPort::getInputBufferSize(
4303
report( "getInputBufferSize is not implemented\n" );
4308
/*----------------------------------------------------------
4315
comments: see fopen/fclose/fwrite/fread man pages.
4316
----------------------------------------------------------*/
4317
void gnu::io::RXTXPort::setOutputBufferSize(
4321
report( "setOutputBufferSize is not implemented\n" );
4324
/*----------------------------------------------------------
4331
comments: see fopen/fclose/fwrite/fread man pages.
4332
----------------------------------------------------------*/
4333
jint gnu::io::RXTXPort::getOutputBufferSize()
4335
report( "getOutputBufferSize is not implemented\n" );
4339
#endif /* GOING_TO_MESS_WITH_BUFFERS */
4341
/*----------------------------------------------------------
4345
perform: increment eventloop_interrupted
4348
comments: all eventloops in this PID will check if their thread
4349
is interrupted. When all the interrupted threads exit
4350
they will decrement the var leaving it 0.
4351
the remaining threads will continue.
4352
----------------------------------------------------------*/
4353
void gnu::io::RXTXPort::interruptEventLoop(
4356
struct event_info_struct *index = master_index;
4357
int fd = ( int ) this->fd;
4363
index = master_index;
4366
while( index->fd != fd &&
4367
index->next ) index = index->next;
4368
if ( index->fd == fd ) searching = 0;
4378
index->eventloop_interrupted = 1;
4380
Many OS's need a thread running to determine if output buffer is
4381
empty. For Linux and Win32 it is not needed. So closing is used to
4382
shut down the thread in the write order on OS's that don't have
4383
kernel support for output buffer empty.
4385
In rxtx TIOCSERGETLSR is defined for win32 and Linux
4387
#ifdef TIOCSERGETLSR
4389
#endif /* TIOCSERGETLSR */
4391
termios_interrupt_event_loop( index->fd, 1 );
4393
report("interruptEventLoop: interrupted\n");
4396
/*----------------------------------------------------------
4399
accept: event_info_struct
4400
perform: see if the port is being closed.
4401
return: a positive value if the port is being closed.
4404
----------------------------------------------------------*/
4405
jboolean is_interrupted( gnu::io::RXTXPort *p, struct event_info_struct *eis )
4409
ENTER( "is_interrupted" );
4410
result = p->checkMonitorThread( );
4412
if((*env)->ExceptionOccurred(env)) {
4413
report ( "is_interrupted: an error occured calling sendEvent()\n" );
4414
(*env)->ExceptionDescribe(env);
4415
(*env)->ExceptionClear(env);
4418
LEAVE( "RXTXCommDriver:is_interrupted" );
4422
/*----------------------------------------------------------
4425
accept: fd for finding the struct, event to flag, flag.
4426
perform: toggle the flag
4429
comments: all the logic used to be done in Java but its too noisy
4430
----------------------------------------------------------*/
4431
void gnu::io::RXTXPort::nativeSetEventFlag(
4437
struct event_info_struct *index = master_index;
4441
report_error("nativeSetEventFlag !index\n");
4444
while( index->fd != fd && index->next )
4446
index = index->next;
4448
if( index->fd != fd )
4450
report_error("nativeSetEventFlag !fd\n");
4453
index->eventflags[event] = (int) flag;
4455
termios_setflags( fd, index->eventflags );
4460
/*----------------------------------------------------------
4463
accept: event_info_structure, event type and true/false
4464
perform: if state is > 0 send a true event otherwise send false
4465
return: a positive value if the port is being closed.
4468
----------------------------------------------------------*/
4469
int send_event( gnu::io::RXTXPort *p, struct event_info_struct *eis, jint type, int flag )
4473
ENTER( "send_event" );
4474
if( !eis || eis->eventloop_interrupted > 1 )
4476
report("event loop interrupted\n");
4479
report_verbose("send_event: !eventloop_interupted\n");
4481
#ifdef TODO /* FIXME jcj hack */
4482
(*env)->ExceptionClear(env);
4483
#endif /* FIXME jcj hack */
4485
report_verbose("send_event: calling\n");
4486
result = p->sendEvent( type, flag > 0 ? true : false );
4487
report_verbose("send_event: called\n");
4490
if(!eis || (*eis->env)->ExceptionOccurred(eis->env)) {
4491
report ( "send_event: an error occured calling sendEvent()\n" );
4492
(*eis->env)->ExceptionDescribe(eis->env);
4493
(*eis->env)->ExceptionClear(eis->env);
4497
LEAVE( "send_event" );
4501
/*----------------------------------------------------------
4504
accept: string to send to report as an message
4505
perform: send the string to stderr or however it needs to be reported.
4509
----------------------------------------------------------*/
4510
void report_warning(char *msg)
4513
fprintf(stderr, msg);
4515
mexWarnMsgTxt( (const char *) msg );
4516
#endif /* DEBUG_MW */
4519
/*----------------------------------------------------------
4522
accept: string to send to report as an verbose message
4523
perform: send the string to stderr or however it needs to be reported.
4527
----------------------------------------------------------*/
4528
void report_verbose(char *msg)
4530
#ifdef DEBUG_VERBOSE
4532
mexErrMsgTxt( msg );
4534
fprintf(stderr, msg);
4535
#endif /* DEBUG_MW */
4536
#endif /* DEBUG_VERBOSE */
4538
/*----------------------------------------------------------
4541
accept: string to send to report as an error
4542
perform: send the string to stderr or however it needs to be reported.
4546
----------------------------------------------------------*/
4547
void report_error(char *msg)
4550
fprintf(stderr, msg);
4552
mexWarnMsgTxt( msg );
4553
#endif /* DEBUG_MW */
4556
/*----------------------------------------------------------
4559
accept: string to send to stderr
4560
perform: if DEBUG is defined send the string to stderr.
4564
----------------------------------------------------------*/
4565
void report(char *msg)
4569
fprintf(stderr, msg);
4572
# endif /* DEBUG_MW */
4578
/*----------------------------------------------------------
4581
accept: The name of the device to try to lock
4582
perform: Create a lock file if there is not one already using a
4584
return: 1 on failure 0 on success
4588
----------------------------------------------------------*/
4589
int lfs_lock( const char *filename, int pid )
4594
char *buffer = malloc(size);
4595
struct sockaddr_in addr;
4597
if ( !( s = socket( AF_INET, SOCK_STREAM, 0 ) ) > 0 )
4599
addr.sin_family = AF_INET;
4600
addr.sin_port = htons( 50001 );
4601
addr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
4603
if ( !connect( s, ( struct sockaddr * ) &addr, sizeof( addr ) ) == 0 )
4605
ret=recv( s, buffer, size, 0 );
4606
sprintf( buffer, "lock %s %i\n", filename, pid );
4607
/* printf( "%s", buffer ); */
4608
send( s, buffer, strlen(buffer), 0 );
4609
ret=recv( s, buffer, size, 0 );
4613
/* printf( "Message recieved: %s", buffer ); */
4615
send( s, "quit\n", strlen( "quit\n" ), 0 );
4617
/* printf("%s\n", buffer); */
4618
if( buffer[0] == '2' ) return 0;
4622
/*----------------------------------------------------------
4625
accept: The name of the device to try to unlock
4626
perform: Remove a lock file if there is one using a
4628
return: 1 on failure 0 on success
4632
----------------------------------------------------------*/
4633
int lfs_unlock( const char *filename, int pid )
4638
char *buffer = malloc(size);
4639
struct sockaddr_in addr;
4641
if ( !( s = socket( AF_INET, SOCK_STREAM, 0 ) ) > 0 )
4643
addr.sin_family = AF_INET;
4644
addr.sin_port = htons( 50001 );
4645
addr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
4647
if ( !connect( s, ( struct sockaddr * ) &addr, sizeof( addr ) ) == 0 )
4649
sprintf( buffer, "unlock %s %i\n", filename, pid );
4650
/* printf( "%s", buffer ); */
4651
send( s, buffer, strlen(buffer), 0 );
4652
ret = recv( s, buffer, size, 0 );
4656
/* printf( "Message recieved: %s", buffer ); */
4658
send( s, "quit\n", strlen( "quit\n" ), 0 );
4660
if( buffer[0] == '2' ) return 0;
4665
/*----------------------------------------------------------
4668
accept: The name of the device to try to lock
4670
perform: Create a lock file if there is not one already.
4671
return: 1 on failure 0 on success
4673
comments: This is for linux and freebsd only currently. I see SVR4 does
4674
this differently and there are other proposed changes to the
4675
Filesystem Hierachy Standard
4679
----------------------------------------------------------*/
4680
int fhs_lock( const char *filename, int pid )
4683
* There is a zoo of lockdir possibilities
4684
* Its possible to check for stale processes with most of them.
4685
* for now we will just check for the lockfile on most
4686
* Problem lockfiles will be dealt with. Some may not even be in use.
4690
char lockinfo[12], message[80];
4693
j = strlen( filename );
4694
p = ( char * ) filename + j;
4695
/* FIXME need to handle subdirectories /dev/cua/...
4696
SCO Unix use lowercase all the time
4699
//printf("lock file is %s\n",filename);
4700
while( *( p - 1 ) != '/' && j-- != 1 )
4702
#if defined ( __unixware__ )
4704
#endif /* __unixware__ */
4707
sprintf( file, "%s/LCK..%s", LOCKDIR, p );
4708
if ( check_lock_status( filename ) )
4710
report( "fhs_lock() lockstatus fail\n" );
4713
fd = open( file, O_CREAT | O_WRONLY | O_EXCL, 0444 );
4717
"RXTX fhs_lock() Error: creating lock file: %s: %s\n",
4718
file, strerror(errno) );
4719
report_error( message );
4722
sprintf( lockinfo, "%10d\n",(int) getpid() );
4723
sprintf( message, "fhs_lock: creating lockfile: %s\n", lockinfo );
4725
write( fd, lockinfo, 11 );
4730
/*----------------------------------------------------------
4733
accept: char * filename. Device to be locked
4734
perform: Try to get a uucp_lock
4735
return: int 0 on success
4738
The File System Hierarchy Standard
4739
http://www.pathname.com/fhs/
4742
http://docs.freebsd.org/info/uucp/uucp.info.UUCP_Lock_Files.html
4745
ftp://tsx-11.mit.edu/pub/linux/docs/linux-standards/fsstnd/
4747
Proposed Changes to the File System Hierarchy Standard
4748
ftp://scicom.alphacdc.com/pub/linux/devlock-0.X.tgz
4750
"UNIX Network Programming", W. Richard Stevens,
4751
Prentice-Hall, 1990, pages 96-101.
4753
There is much to do here.
4755
1) UUCP style locks (done)
4759
3) FSSTND locks (done)
4761
4) handle stale locks (done except kermit locks)
4762
5) handle minicom lockfile contents (FSSTND?)
4763
" 16929 minicom root\n" (done)
4764
6) there are other Lock conventions that use Major and Minor
4766
7) Stevens recommends LCK..<pid>
4768
most are caught above. If they turn out to be problematic
4769
rather than an exercise, we will handle them.
4771
----------------------------------------------------------*/
4772
int uucp_lock( const char *filename, int pid )
4774
char lockfilename[80], lockinfo[12], message[80];
4779
sprintf( message, "uucp_lock( %s );\n", filename );
4782
if ( check_lock_status( filename ) )
4784
report( "RXTX uucp check_lock_status true\n" );
4787
if ( stat( LOCKDIR, &buf ) != 0 )
4789
report( "RXTX uucp_lock() could not find lock directory.\n" );
4792
if ( stat( filename, &buf ) != 0 )
4794
report( "RXTX uucp_lock() could not find device.\n" );
4795
sprintf( message, "uucp_lock: device was %s\n", name );
4799
sprintf( lockfilename, "%s/LK.%03d.%03d.%03d",
4801
(int) major( buf.st_dev ),
4802
(int) major( buf.st_rdev ),
4803
(int) minor( buf.st_rdev )
4805
sprintf( lockinfo, "%10d\n", (int) getpid() );
4806
if ( stat( lockfilename, &buf ) == 0 )
4808
sprintf( message, "RXTX uucp_lock() %s is there\n",
4811
report_error( message );
4814
fd = open( lockfilename, O_CREAT | O_WRONLY | O_EXCL, 0444 );
4818
"RXTX uucp_lock() Error: creating lock file: %s\n",
4820
report_error( message );
4823
write( fd, lockinfo,11 );
4828
/*----------------------------------------------------------
4831
accept: the lock name in question
4832
perform: Make sure everything is sane
4833
return: 0 on success
4836
----------------------------------------------------------*/
4837
int check_lock_status( const char *filename )
4840
/* First, can we find the directory? */
4842
if ( stat( LOCKDIR, &buf ) != 0 )
4844
report( "check_lock_status: could not find lock directory.\n" );
4848
/* OK. Are we able to write to it? If not lets bail */
4850
if ( check_group_uucp() )
4852
report_error( "check_lock_status: No permission to create lock file.\nplease see: How can I use Lock Files with rxtx? in INSTALL\n" );
4856
/* is the device alread locked */
4858
if ( is_device_locked( filename ) )
4860
report( "check_lock_status: device is locked by another application\n" );
4867
/*----------------------------------------------------------
4870
accept: The name of the device to unlock
4871
perform: delete the lock file
4874
comments: This is for linux only currently. I see SVR4 does this
4875
differently and there are other proposed changes to the
4876
Filesystem Hierachy Standard
4877
----------------------------------------------------------*/
4878
void fhs_unlock( const char *filename, int openpid )
4883
i = strlen( filename );
4884
p = ( char * ) filename + i;
4885
/* FIXME need to handle subdirectories /dev/cua/... */
4886
while( *( p - 1 ) != '/' && i-- != 1 ) p--;
4887
sprintf( file, "%s/LCK..%s", LOCKDIR, p );
4889
if( !check_lock_pid( file, openpid ) )
4892
report("fhs_unlock: Removing LockFile\n");
4896
report("fhs_unlock: Unable to remove LockFile\n");
4900
/*----------------------------------------------------------
4903
accept: char *filename the device that is locked
4904
perform: remove the uucp lockfile if it exists
4907
comments: http://docs.freebsd.org/info/uucp/uucp.info.UUCP_Lock_Files.html
4908
----------------------------------------------------------*/
4909
void uucp_unlock( const char *filename, int openpid )
4912
char file[80], message[80];
4915
sprintf( message, "uucp_unlock( %s );\n", filename );
4918
if ( stat( filename, &buf ) != 0 )
4920
/* hmm the file is not there? */
4921
report( "uucp_unlock() no such device\n" );
4924
sprintf( file, LOCKDIR"/LK.%03d.%03d.%03d",
4925
(int) major( buf.st_dev ),
4926
(int) major( buf.st_rdev ),
4927
(int) minor( buf.st_rdev )
4929
if ( stat( file, &buf ) != 0 )
4931
/* hmm the file is not there? */
4932
report( "uucp_unlock no such lockfile\n" );
4935
if( !check_lock_pid( file, openpid ) )
4937
sprintf( message, "uucp_unlock: unlinking %s\n", file );
4943
sprintf( message, "uucp_unlock: unlinking failed %s\n", file );
4948
/*----------------------------------------------------------
4951
accept: the name of the lockfile
4952
perform: make sure the lock file is ours.
4953
return: 0 on success
4956
----------------------------------------------------------*/
4957
int check_lock_pid( const char *file, int openpid )
4960
char pid_buffer[12];
4963
fd=open( file, O_RDONLY );
4968
if ( read( fd, pid_buffer, 11 ) < 0 )
4974
pid_buffer[11] = '\0';
4975
lockpid = atol( pid_buffer );
4976
/* Native threads JVM's have multiple pids */
4977
if ( lockpid != getpid() && lockpid != getppid() && lockpid != openpid )
4979
sprintf(message, "check_lock_pid: lock = %s pid = %i gpid=%i openpid=%i\n",
4980
pid_buffer, (int) getpid(), (int) getppid(), openpid );
4987
/*----------------------------------------------------------
4991
perform: check if the user is root or in group uucp
4992
return: 0 on success
4995
This checks if the effective user is in group uucp so we can
4996
create lock files. If not we give them a warning and bail.
4997
If its root we just skip the test.
4999
if someone really wants to override this they can use the USER_LOCK_DIRECTORY --not recommended.
5001
In a recent change RedHat 7.2 decided to use group lock.
5002
In order to get around this we just check the group id
5003
of the lock directory.
5005
* Modified to support Debian *
5007
The problem was that checking the ownership of the lock file
5008
dir is not enough, in the sense that even if the current user
5009
is not in the group of the lock directory if the lock
5010
directory has 777 permissions the lock file can be anyway
5011
created. My solution is simply to try to create a tmp file
5012
there and if it works then we can go on. Here is my code that
5013
I tried and seems to work.
5015
Villa Valerio <valerio.villa@siemens.com>
5016
----------------------------------------------------------*/
5017
int check_group_uucp()
5019
#ifndef USER_LOCK_DIRECTORY
5020
FILE *testLockFile ;
5021
char testLockFileDirName[] = LOCKDIR;
5022
char testLockFileName[] = "tmpXXXXXX";
5023
char *testLockAbsFileName;
5025
testLockAbsFileName = ( char * ) calloc(strlen(testLockFileDirName)
5026
+ strlen(testLockFileName) + 2, sizeof(char));
5027
if ( NULL == testLockAbsFileName )
5029
report_error("check_group_uucp(): Insufficient memory");
5032
strcat(testLockAbsFileName, testLockFileDirName);
5033
strcat(testLockAbsFileName, "/");
5034
strcat(testLockAbsFileName, testLockFileName);
5035
if ( NULL == mkstemp(testLockAbsFileName) )
5037
free(testLockAbsFileName);
5038
report_error("check_group_uucp(): mktemp malformed string - \
5039
should not happen");
5043
testLockFile = fopen (testLockAbsFileName, "w+");
5044
if (NULL == testLockFile)
5046
report_error("check_group_uucp(): error testing lock file \
5047
creation Error details: ");
5048
report_error(strerror(errno));
5050
free(testLockAbsFileName);
5054
fclose (testLockFile);
5055
unlink (testLockAbsFileName);
5056
free(testLockAbsFileName);
5058
#endif /* USER_LOCK_DIRECTORY */
5061
#ifdef USE_OLD_CHECK_GROUP_UUCP
5062
int check_group_uucp()
5064
#ifndef USER_LOCK_DIRECTORY
5066
struct passwd *user = getpwuid( geteuid() );
5069
gid_t list[ NGROUPS_MAX ];
5071
if( stat( LOCKDIR, &buf) )
5073
sprintf( msg, "check_group_uucp: Can not find Lock Directory: %s\n", LOCKDIR );
5074
report_error( msg );
5077
group_count = getgroups( NGROUPS_MAX, list );
5078
list[ group_count ] = geteuid();
5080
/* JJO changes start */
5083
report_error( "Not able to get user groups.\n" );
5086
/* JJO changes stop */
5091
while( group_count >= 0 && buf.st_gid != list[ group_count ] )
5095
if( buf.st_gid == list[ group_count ] )
5097
sprintf( msg, "%i %i\n", buf.st_gid, list[ group_count ] );
5098
report_error( msg );
5099
report_error( UUCP_ERROR );
5104
if( strcmp( user->pw_name, "root" ) )
5108
if( !strcmp( *g->gr_mem, user->pw_name ) )
5112
(void) *g->gr_mem++;
5116
report( UUCP_ERROR );
5121
#endif /* USER_LOCK_DIRECTORY */
5123
#endif /* USE_OLD_CHECK_GROUP_UUCP */
5126
/*----------------------------------------------------------
5127
The following should be able to follow symbolic links. I think the stat
5128
method used below will work on more systems. This was found while looking
5131
* realpath() doesn't exist on all of the systems my code has to run
5132
on (HP-UX 9.x, specifically)
5133
----------------------------------------------------------
5134
int different_from_LOCKDIR(const char* ld)
5136
char real_ld[MAXPATHLEN];
5137
char real_LOCKDIR[MAXPATHLEN];
5138
if (strncmp(ld, LOCKDIR, strlen(ld)) == 0)
5140
if (realpath(ld, real_ld) == NULL)
5142
if (realpath(LOCKDIR, real_LOCKDIR) == NULL)
5144
if (strncmp(real_ld, real_LOCKDIR, strlen(real_ld)) == 0)
5151
/*----------------------------------------------------------
5154
accept: char * filename. The device in question including the path.
5155
perform: see if one of the many possible lock files is aready there
5156
if there is a stale lock, remove it.
5157
return: 1 if the device is locked or somethings wrong.
5158
0 if its possible to create our own lock file.
5160
comments: check if the device is already locked
5161
----------------------------------------------------------*/
5162
int is_device_locked( const char *port_filename )
5164
const char *lockdirs[] = { "/etc/locks", "/usr/spool/kermit",
5165
"/usr/spool/locks", "/usr/spool/uucp", "/usr/spool/uucp/",
5166
"/usr/spool/uucp/LCK", "/var/lock", "/var/lock/modem",
5167
"/var/spool/lock", "/var/spool/locks", "/var/spool/uucp",
5170
const char *lockprefixes[] = { "LCK..", "lk..", "LK.", NULL };
5171
char *p, file[80], pid_buffer[20], message[80];
5172
int i = 0, j, k, fd , pid;
5176
j = strlen( port_filename );
5177
p = ( char * ) port_filename+j;
5178
while( *( p-1 ) != '/' && j-- !=1 ) p--;
5180
while( lockdirs[i] )
5183
Look for lockfiles in all known places other than the
5184
defined lock directory for this system
5185
report any unexpected lockfiles.
5187
Is the suspect lockdir there?
5188
if it is there is it not the expected lock dir?
5190
if( !stat( lockdirs[i], &buf2 ) &&
5191
strncmp( lockdirs[i], LOCKDIR, strlen( lockdirs[i] ) ) )
5193
j = strlen( port_filename );
5194
p = ( char * ) port_filename + j;
5196
SCO Unix use lowercase all the time
5199
while( *( p - 1 ) != '/' && j-- != 1 )
5201
#if defined ( __unixware__ )
5203
#endif /* __unixware__ */
5207
while ( lockprefixes[k] )
5210
sprintf( file, "%s/%s%s", lockdirs[i],
5211
lockprefixes[k], p );
5212
if( stat( file, &buf ) == 0 )
5214
sprintf( message, UNEXPECTED_LOCK_FILE,
5216
report_warning( message );
5221
stat(port_filename , &buf );
5222
sprintf( file, "%s/%s%03d.%03d.%03d",
5225
(int) major( buf.st_dev ),
5226
(int) major( buf.st_rdev ),
5227
(int) minor( buf.st_rdev )
5229
if( stat( file, &buf ) == 0 )
5231
sprintf( message, UNEXPECTED_LOCK_FILE,
5233
report_warning( message );
5243
OK. We think there are no unexpect lock files for this device
5244
Lets see if there any stale lock files that need to be
5249
/* FHS standard locks */
5250
i = strlen( port_filename );
5251
p = ( char * ) port_filename + i;
5252
while( *(p-1) != '/' && i-- != 1)
5254
#if defined ( __unixware__ )
5256
#endif /* __unixware__ */
5259
sprintf( file, "%s/%s%s", LOCKDIR, LOCKFILEPREFIX, p );
5261
/* UUCP standard locks */
5262
if ( stat( port_filename, &buf ) != 0 )
5264
report( "RXTX is_device_locked() could not find device.\n" );
5267
sprintf( file, "%s/LK.%03d.%03d.%03d",
5269
(int) major( buf.st_dev ),
5270
(int) major( buf.st_rdev ),
5271
(int) minor( buf.st_rdev )
5276
if( stat( file, &buf ) == 0 )
5279
/* check if its a stale lock */
5280
fd=open( file, O_RDONLY );
5281
read( fd, pid_buffer, 11 );
5282
/* FIXME null terminiate pid_buffer? need to check in Solaris */
5284
sscanf( pid_buffer, "%d", &pid );
5286
if( kill( (pid_t) pid, 0 ) && errno==ESRCH )
5289
"RXTX Warning: Removing stale lock file. %s\n",
5291
report_warning( message );
5292
if( unlink( file ) != 0 )
5294
snprintf( message, 80, "RXTX Error: Unable to \
5295
remove stale lock file: %s\n",
5298
report_warning( message );
5307
/*----------------------------------------------------------
5308
system_does_not_lock
5310
accept: the filename the system thinks should be locked.
5311
perform: avoid trying to create lock files on systems that dont use them
5312
return: 0 for success ;)
5314
comments: OS's like Win32 may not have lock files.
5315
----------------------------------------------------------*/
5316
int system_does_not_lock( const char * filename, int pid )
5321
/*----------------------------------------------------------
5322
system_does_not_unlock
5324
accept: the filename the system thinks should be locked.
5325
perform: avoid trying to create lock files on systems that dont use them
5328
comments: OS's like Win32 may not have lock files.
5329
----------------------------------------------------------*/
5330
void system_does_not_unlock( const char * filename, int openpid )
5335
/*----------------------------------------------------------
5338
accept: string to indicate where this was called.
5340
perform: print the termios struct to stderr.
5343
comments: used to debug the termios struct.
5344
----------------------------------------------------------*/
5345
void dump_termios(char *foo,struct termios *ttyset)
5350
fprintf(stderr, "%s c_iflag=%#x\n", foo, ttyset->c_iflag);
5351
fprintf(stderr, "%s c_lflag=%#x\n", foo, ttyset->c_lflag);
5352
fprintf(stderr, "%s c_oflag=%#x\n", foo, ttyset->c_oflag);
5353
fprintf(stderr, "%s c_cflag=%#x\n", foo, ttyset->c_cflag);
5354
fprintf(stderr, "%s c_cc[]: ", foo);
5355
for(i=0; i<NCCS; i++)
5357
fprintf(stderr,"%d=%x ", i, ttyset->c_cc[i]);
5359
fprintf(stderr,"\n" );
5362
/*----------------------------------------------------------
5365
accept: like vwprintf()
5366
return: number of jchars written or -1
5368
comments: prints data using System.out.print()
5371
Just use java::lang::System::out->println(s);
5372
----------------------------------------------------------*/
5380
/* for gcj compiles */
5382
jboolean gnu::io::RXTXPort::nativeSetCallOutHangup( jboolean NoHup )
5386
jboolean gnu::io::RXTXPort::nativeGetCallOutHangup( )
5390
jboolean gnu::io::RXTXPort::nativeSetLowLatency( )
5394
jboolean gnu::io::RXTXPort::nativeGetLowLatency( )
5398
jboolean gnu::io::RXTXPort::nativeSetUartType( jstring ty, jboolean te )
5402
jstring gnu::io::RXTXPort::nativeGetUartType( )
5404
return JvNewStringUTF( "RXTX-2.1-7pre13 SAM I AM" );