~ubuntu-branches/ubuntu/edgy/rxtx/edgy-201105201527

« back to all changes in this revision

Viewing changes to CNI/SerialImp.c

  • Committer: Bazaar Package Importer
  • Author(s): Mario Joussen
  • Date: 2006-03-01 18:56:52 UTC
  • mfrom: (1.1.2 upstream) (2.1.1 etch)
  • Revision ID: james.westby@ubuntu.com-20060301185652-ri9941gi01goklvz
Tags: 2.1.7-2
Fixed stupid bug in clean target.
(closes: Bug#354859)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
|   rxtx is a native interface to serial ports in java.
 
3
|   Copyright 1997-2004 by Trent Jarvi taj@www.linux.org.uk
 
4
|
 
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.
 
9
|
 
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.
 
14
|
 
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 */
 
23
#else  /* dima */
 
24
#include "config.h"
 
25
#endif /* dima */
 
26
#ifndef __LCC__
 
27
#   include <unistd.h>
 
28
#else /* windows lcc compiler for fd_set. probably wrong */
 
29
#   include<winsock.h>
 
30
#endif /* __LCC__ */
 
31
#include <time.h>
 
32
#include <stdio.h>
 
33
#include <string.h>
 
34
#include <stdlib.h>
 
35
#include <errno.h>
 
36
#include <limits.h>
 
37
#include <sys/stat.h>
 
38
#ifndef WIN32
 
39
#include <sys/ioctl.h>
 
40
#include <sys/param.h>
 
41
#include <sys/utsname.h>
 
42
#include <pthread.h>
 
43
#else
 
44
#       include <win32termios.h>
 
45
/*  FIXME  returns 0 in all cases on win32
 
46
#define S_ISCHR(m)      (((m)&S_IFMT) == S_IFCHR)
 
47
*/
 
48
#       if !defined(S_ISCHR)
 
49
#               define S_ISCHR(m) (1)
 
50
#       endif /* S_ISCHR(m) */
 
51
#endif /* WIN32 */
 
52
#ifdef HAVE_ASM_TERMBITS_H
 
53
//#     include <asm/termbits.h>
 
54
#endif /* HAVE_ASM_TERMBITS_H */
 
55
#ifdef HAVE_TERMIOS_H
 
56
#       include <termios.h>
 
57
#endif /* HAVE_TERMIOS_H */
 
58
#ifdef HAVE_SIGNAL_H
 
59
#   include <signal.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 */
 
68
#   include <fcntl.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>
 
79
#endif /* FLS */
 
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__ */
 
85
#if defined(__sun__)
 
86
#       include <sys/filio.h>
 
87
#       include <sys/mkdev.h>
 
88
#endif /* __sun__ */
 
89
#if defined(__hpux__)
 
90
#       include <sys/modem.h>
 
91
#endif /* __hpux__ */
 
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__ */
 
99
#ifdef __unixware__
 
100
#       include  <sys/filio.h>
 
101
#endif /* __unixware__ */
 
102
#ifdef HAVE_PWD_H
 
103
#include        <pwd.h>
 
104
#endif /* HAVE_PWD_H */
 
105
#ifdef HAVE_GRP_H
 
106
#include        <grp.h>
 
107
#endif /* HAVE_GRP_H */
 
108
#include <math.h>
 
109
 
 
110
extern int errno;
 
111
#include "SerialImp.h"
 
112
#include <gcj/cni.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
 
120
 
 
121
struct preopened *preopened_port = NULL;
 
122
 
 
123
#if defined(__sun__) || defined(__hpux__)
 
124
/*----------------------------------------------------------
 
125
cfmakeraw
 
126
 
 
127
   accept:      termios to be set to raw
 
128
   perform:     initializes the termios structure.
 
129
   return:      int 0 on success
 
130
   exceptions:  none
 
131
   comments:    this is how linux cfmakeraw works.
 
132
                termios(3) manpage
 
133
----------------------------------------------------------*/
 
134
 
 
135
int cfmakeraw ( struct termios *term )
 
136
{
 
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" );
 
144
        return( 0 );
 
145
}
 
146
#endif /* __sun__  || __hpux__ */
 
147
 
 
148
#ifdef DEBUG_TIMING
 
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 ) \
 
152
        { \
 
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); \
 
157
        } \
 
158
}
 
159
#define report_time( ) \
 
160
{ \
 
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); \
 
164
}
 
165
#define report_time_start( ) \
 
166
{ \
 
167
        gettimeofday(&snow, NULL); \
 
168
        mexPrintf("%8s : %5i : %8i sec : %8i usec", __TIME__, __LINE__, snow.tv_sec, snow.tv_usec); \
 
169
}
 
170
#define report_time_end( ) \
 
171
{ \
 
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); \
 
174
}
 
175
#else
 
176
#define report_time_eventLoop( ){};
 
177
#define report_time( ) {}
 
178
#define report_time_start( ) {}
 
179
#define report_time_end( ) {}
 
180
#endif /* DEBUG_TIMING */
 
181
 
 
182
 
 
183
struct event_info_struct *master_index = NULL;
 
184
 
 
185
/*----------------------------------------------------------
 
186
RXTXPort.Initialize
 
187
 
 
188
   accept:      none
 
189
   perform:     Initialize the native library
 
190
   return:      none
 
191
   exceptions:  none
 
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.
 
194
 
 
195
                It also allows for some sanity checks on linux boxes if DEBUG
 
196
                is enabled.
 
197
----------------------------------------------------------*/
 
198
void gnu::io::RXTXPort::Initialize(
 
199
)
 
200
{
 
201
#if defined DEBUG && defined(__linux__)
 
202
        struct utsname name;
 
203
        char message[80];
 
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. */
 
209
 
 
210
        /* POSIX signal handling functions */
 
211
#if !defined(WIN32)
 
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;
 
218
                sigset_t block_mask;
 
219
                sigemptyset(&block_mask);
 
220
                new_action.sa_handler = SIG_IGN;
 
221
#ifdef SA_RESTART
 
222
                new_action.sa_flags = SA_RESTART;
 
223
#endif /* SA_RESTART */
 
224
                new_action.sa_mask = block_mask;
 
225
                sigaction(SIGIO, &new_action, NULL);
 
226
        } 
 
227
#endif /* !WIN32 */
 
228
        ENTER( "RXTXPort:Initialize" );
 
229
#ifdef PRERELEASE
 
230
        /*  this is just for avoiding confusion while testing new libraries */
 
231
#ifdef DEBUG_MW
 
232
        mexPrintf("RXTX Prerelease for testing  Tue Feb 19 18:00:27 EST 2002\n");
 
233
#else
 
234
        printf("RXTX Prerelease for testing  Thu Feb 21 19:31:38\n");
 
235
#endif /* DEBUG_MW */
 
236
#endif /* PRERELEASE */
 
237
#if DEBUG_TIMING
 
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)
 
243
        {
 
244
                report( "RXTX WARNING:  cannot get system name\n" );
 
245
                LEAVE( "RXTXPort:Initialize" );
 
246
                return;
 
247
        }
 
248
        if(strcmp(name.release,UTS_RELEASE)!=0)
 
249
        {
 
250
                sprintf( message, LINUX_KERNEL_VERSION_ERROR, UTS_RELEASE,
 
251
                        name.release );
 
252
                report( message );
 
253
                getchar();
 
254
        }
 
255
        LEAVE( "RXTXPort:Initialize" );
 
256
#endif /* DEBUG && __linux__ */
 
257
}
 
258
 
 
259
/*----------------------------------------------------------
 
260
RXTXPort.find_preopened_ports
 
261
   accept:      The device to find if preopened.  ie "/dev/ttyS0"
 
262
   perform:     find the filedescriptor if preopened
 
263
   return:      fd
 
264
   exceptions:  none
 
265
   comments:    see
 
266
                        RXTXPort.nativeStaticSetDSR
 
267
                        RXTXPort.nativeStaticSetDTR
 
268
                        RXTXPort.nativeStaticSetRTS
 
269
                        RXTXPort.nativeStaticSetSerialPortParams
 
270
                This is used so people can setDTR low before calling the
 
271
                Java open().
 
272
----------------------------------------------------------*/
 
273
int find_preopened_ports( const char *filename )
 
274
{
 
275
        int fd;
 
276
        struct preopened *p = preopened_port;
 
277
 
 
278
        if( !p )
 
279
        {
 
280
                return(0);
 
281
        }
 
282
        for(;;)
 
283
        {
 
284
                if( !strcmp( p->filename, filename) )
 
285
                {
 
286
                        fd = p->fd;
 
287
                        if( p->prev && p->next )
 
288
                        {
 
289
                                p->prev->next = p->next;
 
290
                                p->next->prev = p->prev;
 
291
                        }
 
292
                        else if ( p->prev )
 
293
                        {
 
294
                                p->prev->next = NULL;
 
295
                        }
 
296
                        else if ( p->next )
 
297
                        {
 
298
                                p->next->prev = NULL;
 
299
                        }
 
300
                        else
 
301
                        {
 
302
                                free( p );
 
303
                                preopened_port = NULL;
 
304
                                return( fd );
 
305
                        }
 
306
                        free( p );
 
307
                        return( fd );
 
308
                }
 
309
                if( p->next )
 
310
                {
 
311
                        p = p->next;
 
312
                }
 
313
                else
 
314
                {
 
315
                        return(0);
 
316
                }
 
317
        }
 
318
}
 
319
 
 
320
/*----------------------------------------------------------
 
321
configure_port
 
322
 
 
323
   accept:      env, file descriptor
 
324
   perform:     set the termios struct to sane settings and
 
325
   return:      0 on success
 
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
----------------------------------------------------------*/
 
331
 
 
332
int configure_port( int fd )
 
333
{
 
334
        struct termios ttyset;
 
335
 
 
336
        if( fd < 0 ) goto fail;
 
337
 
 
338
        if( tcgetattr( fd, &ttyset ) < 0 ) goto fail;
 
339
        ttyset.c_iflag = INPCK;
 
340
        ttyset.c_lflag = 0;
 
341
        ttyset.c_oflag = 0;
 
342
        ttyset.c_cflag = CREAD | CS8 | CLOCAL;
 
343
        ttyset.c_cc[ VMIN ] = 0;
 
344
        ttyset.c_cc[ VTIME ] = 0;
 
345
 
 
346
#ifdef __FreeBSD__
 
347
        if( cfsetspeed( &ttyset, B9600 ) < 0 ) goto fail;
 
348
#else
 
349
        if( cfsetispeed( &ttyset, B9600 ) < 0 ) goto fail;
 
350
        if( cfsetospeed( &ttyset, B9600 ) < 0 ) goto fail;
 
351
#endif
 
352
        if( tcsetattr( fd, TCSANOW, &ttyset ) < 0 ) goto fail;
 
353
#ifndef WIN32
 
354
        fcntl( fd, F_SETOWN, getpid() );
 
355
#endif /* WIN32 */
 
356
#ifdef FASYNC
 
357
        fcntl( fd, F_SETFL, FASYNC );
 
358
#endif /* FASYNC */
 
359
 
 
360
        return 0;
 
361
 
 
362
fail:
 
363
        return 1;
 
364
}
 
365
 
 
366
 
 
367
/*----------------------------------------------------------
 
368
get_java_baudrate
 
369
 
 
370
   accept:      the native speed setting
 
371
   perform:     translate the native speed to a Java speed
 
372
   return:      the Java speed
 
373
   exceptions:  none
 
374
   comments:    This is used by open() (indirectly) and
 
375
                nativeStaticGetBaudRate()
 
376
----------------------------------------------------------*/
 
377
int get_java_baudrate( int native_speed )
 
378
{
 
379
        switch( native_speed )
 
380
        {
 
381
                case B0:     return 0;
 
382
                case B50:    return 50;
 
383
                case B75:    return 75;
 
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;
 
398
                default: return -1;
 
399
        }
 
400
}
 
401
 
 
402
/*----------------------------------------------------------
 
403
set_java_vars
 
404
 
 
405
   accept:      fd of the preopened device
 
406
   perform:     Now that the object is instatiated, set the Java variables
 
407
                to the preopened states.
 
408
   return:      none
 
409
   exceptions:  none
 
410
   comments:    preopened refers to the fact that the serial port has
 
411
                been configured before the Java open() has been called.
 
412
----------------------------------------------------------*/
 
413
                
 
414
void set_java_vars( gnu::io::RXTXPort *p,
 
415
        int fd
 
416
)
 
417
{
 
418
        struct termios ttyset;
 
419
        int databits = -1;
 
420
        int jparity = -1;
 
421
        int stop_bits = STOPBITS_1_5;
 
422
        int baudrate;
 
423
 
 
424
        if( tcgetattr( fd, &ttyset ) < 0 )
 
425
        {
 
426
                report( "Cannot Get Serial Port Settings\n" );
 
427
                return;
 
428
        }
 
429
 
 
430
        
 
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;
 
436
        }
 
437
#ifdef CMSPAR
 
438
        switch( ttyset.c_cflag&(PARENB|PARODD|CMSPAR ) ) {
 
439
#else
 
440
        switch( ttyset.c_cflag&(PARENB|PARODD) ) {
 
441
#endif /* CMSPAR */
 
442
                case 0: jparity = JPARITY_NONE; break;
 
443
                case PARENB: jparity = JPARITY_EVEN; break;
 
444
                case PARENB | PARODD: jparity = JPARITY_ODD; break;
 
445
#ifdef CMSPAR
 
446
                case PARENB | PARODD | CMSPAR: jparity = JPARITY_MARK; break;
 
447
                case PARENB | CMSPAR: jparity = JPARITY_SPACE; break;
 
448
#endif /* CMSPAR */
 
449
        }
 
450
        switch( ttyset.c_cflag&(CSTOPB) ) {
 
451
                case 0: stop_bits = STOPBITS_1; break;
 
452
                case CSTOPB:  stop_bits = STOPBITS_2; break;
 
453
        }
 
454
/*
 
455
dima writes:
 
456
 
 
457
Trent, here is something I found with google:
 
458
(freebsd list freebsd-current@freebsd.org)
 
459
 
 
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?
 
464
 
 
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.
 
468
 
 
469
*/
 
470
#if defined(CBAUD)/* dima */
 
471
        baudrate = ttyset.c_cflag&CBAUD;
 
472
#else
 
473
        baudrate = cfgetispeed(&ttyset);
 
474
#endif
 
475
        p->speed = ( jint ) get_java_baudrate(baudrate) ;
 
476
        p->dataBits = ( jint ) databits ;
 
477
        p->stopBits = ( jint ) stop_bits ;
 
478
        p->parity = ( jint ) jparity ;
 
479
}
 
480
/*----------------------------------------------------------
 
481
RXTXPort.open
 
482
 
 
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
 
486
   return:      fd
 
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
 
494
)
 
495
{
 
496
        int fd =0, i;
 
497
        int  pid = -1;
 
498
        char message[80];
 
499
        report_time_start( );
 
500
        char filename[80];
 
501
 
 
502
        for( i=0;i<jstr->length();i++)
 
503
                filename[i] = jstr->charAt(i);
 
504
        filename[i] = '\0';
 
505
 
 
506
#ifndef WIN32
 
507
        pid = getpid();
 
508
#endif /* WIN32 */
 
509
 
 
510
        this->pid = pid;
 
511
        /* 
 
512
                LOCK is one of three functions defined in SerialImp.h
 
513
 
 
514
                        uucp_lock               Solaris
 
515
                        fhs_lock                Linux
 
516
                        system_does_not_lock    Win32
 
517
        */
 
518
                        
 
519
        ENTER( "RXTXPort:open" );
 
520
        if ( LOCK( filename, pid ) )
 
521
        {
 
522
                sprintf( message, "open: locking has failed for %s\n",
 
523
                        filename );
 
524
                report( message );
 
525
                goto fail;
 
526
        }
 
527
        else
 
528
        {
 
529
                sprintf( message, "open: locking worked for %s\n", filename );
 
530
                report( message );
 
531
        }
 
532
        /* This is used so DTR can remain low on 'open()' */
 
533
        if( fd )
 
534
        {
 
535
                return (jint)fd;
 
536
        }
 
537
 
 
538
        do {
 
539
                fd=::OPEN (filename, O_RDWR | O_NOCTTY | O_NONBLOCK );
 
540
        }  while (fd < 0 && errno==EINTR);
 
541
 
 
542
        if( configure_port( fd ) ) goto fail;
 
543
        sprintf( message, "open: fd returned is %i\n", fd );
 
544
        report( message );
 
545
        LEAVE( "RXTXPort:open" );
 
546
        report_time_end( );
 
547
        return (jint)fd;
 
548
 
 
549
fail:
 
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;
 
554
        return -1;
 
555
}
 
556
 
 
557
/*----------------------------------------------------------
 
558
RXTXPort.nativeClose
 
559
 
 
560
   accept:      none
 
561
   perform:     get the fd from the java end and close it
 
562
   return:      none
 
563
   exceptions:  none
 
564
----------------------------------------------------------*/
 
565
void gnu::io::RXTXPort::nativeClose(
 
566
        java::lang::String *jstr
 
567
)
 
568
{
 
569
        int result = -1, i;
 
570
        char filename[80];
 
571
 
 
572
        for( i=0;i<jstr->length();i++)
 
573
                filename[i] = jstr->charAt(i);
 
574
        filename[i] = '\0';
 
575
 
 
576
        report_time_start( );
 
577
#ifndef WIN32
 
578
#endif /* WIN32 */
 
579
        /* 
 
580
                UNLOCK is one of three functions defined in SerialImp.h
 
581
 
 
582
                        uucp_unlock             Solaris
 
583
                        fhs_unlock              Linux
 
584
                        system_does_not_unlock  Win32
 
585
        */
 
586
        ENTER( "RXTXPort:nativeClose" );
 
587
        if (this->fd > 0)
 
588
        {
 
589
                do {
 
590
                        result=::CLOSE (this->fd);
 
591
                }  while ( result < 0 && errno == EINTR );
 
592
                UNLOCK( filename, this->pid );
 
593
        }
 
594
        LEAVE( "RXTXPort:nativeClose" );
 
595
        report_time_end( );
 
596
        return;
 
597
}
 
598
 
 
599
/*----------------------------------------------------------
 
600
 RXTXPort.set_port_params
 
601
 
 
602
   accept:     env, fd, speed, data bits, stop bits, parity
 
603
   perform:    set the serial port parameters
 
604
   return:     1 on error
 
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.
 
609
 
 
610
                see:  nativeSetSerialPortParams & nativeStaticSerialPortParams
 
611
----------------------------------------------------------*/
 
612
int set_port_params(
 
613
        int fd,
 
614
        int cspeed,
 
615
        int dataBits,
 
616
        int stopBits,
 
617
        int parity
 
618
)
 
619
{
 
620
        struct termios ttyset;
 
621
        int result = 0;
 
622
#if defined(TIOCGSERIAL)
 
623
        struct serial_struct sstruct;
 
624
#endif /* TIOCGSERIAL */
 
625
 
 
626
        if( tcgetattr( fd, &ttyset ) < 0 )
 
627
        {
 
628
                report( "set_port_params: Cannot Get Serial Port Settings\n" );
 
629
                return(1);
 
630
        }
 
631
 
 
632
        if( translate_data_bits( &(ttyset.c_cflag), dataBits ) )
 
633
        {
 
634
                report( "set_port_params: Invalid Data Bits Selected\n" );
 
635
                return(1);
 
636
        }
 
637
 
 
638
        if( translate_stop_bits( &(ttyset.c_cflag), stopBits ) )
 
639
        {
 
640
                report( "set_port_params: Invalid Stop Bits Selected\n" );
 
641
                return(1);
 
642
        }
 
643
 
 
644
        if( translate_parity( &(ttyset.c_cflag), parity ) )
 
645
        {
 
646
                report( "set_port_params: Invalid Parity Selected\n" );
 
647
                return(1);
 
648
        }
 
649
 
 
650
#ifdef __FreeBSD__
 
651
        if( cfsetspeed( &ttyset, cspeed ) < 0 )
 
652
        {
 
653
                report( "set_port_params: Cannot Set Speed\n" );
 
654
                return( 1 );
 
655
        }
 
656
#endif  /* __FreeBSD__ */
 
657
        if( !cspeed )
 
658
        {
 
659
                /* hang up the modem aka drop DTR  */
 
660
                /* Unix should handle this */
 
661
                /*
 
662
                mexPrintf("dropping DTR\n");
 
663
                printf("dropping DTR\n");
 
664
                */
 
665
                ioctl( fd, TIOCMGET, &result );
 
666
                result &= ~TIOCM_DTR;
 
667
                ioctl( fd, TIOCMSET, &result );
 
668
        }
 
669
        if(     cfsetispeed( &ttyset, cspeed ) < 0 ||
 
670
                cfsetospeed( &ttyset, cspeed ) < 0 )
 
671
        {
 
672
                /*
 
673
                    Some people need to set the baud rate to ones not defined
 
674
                    in termios.h
 
675
 
 
676
                    This includes some baud rates which are supported by CommAPI
 
677
                    in Unix ( 14400, 28800, 128000, 256000 )
 
678
 
 
679
                    If the above fails, we assume this is not a defined
 
680
                    baud rate on Unix.  With Win32, It is assumed the kernel
 
681
                    will do this for us.
 
682
 
 
683
                    The baud_base and desired speed are used to
 
684
                    calculate a custom divisor.
 
685
 
 
686
                    On linux the setserial man page covers this.
 
687
                */
 
688
 
 
689
#if defined(TIOCGSERIAL)
 
690
                sstruct.custom_divisor = ( sstruct.baud_base/cspeed );
 
691
                cspeed = B38400;
 
692
#endif /* TIOCGSERIAL */
 
693
                if(     cfsetispeed( &ttyset, cspeed ) < 0 ||
 
694
                        cfsetospeed( &ttyset, cspeed ) < 0 )
 
695
                {
 
696
                        /* OK, we tried everything */
 
697
                        report( "nativeSetSerialPortParams: Cannot Set Speed\n" );
 
698
                        return( 1 );
 
699
                }
 
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 )
 
704
                {
 
705
                        return( 1 );
 
706
                }
 
707
#endif /* TIOCSSERIAL */
 
708
        }
 
709
 
 
710
        if( tcsetattr( fd, TCSANOW, &ttyset ) < 0 )
 
711
        {
 
712
                report("tcsetattr returns nonzero value!\n");
 
713
                return( 1 );
 
714
        }
 
715
        return(0);
 
716
}
 
717
 
 
718
/*----------------------------------------------------------
 
719
 RXTXPort.nativeSetSerialPortParams
 
720
 
 
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(
 
727
        jint speed,
 
728
        jint dataBits,
 
729
        jint stopBits,
 
730
        jint parity
 
731
)
 
732
{
 
733
        int fd = (int) this->fd;
 
734
        int cspeed = translate_speed( speed );
 
735
 
 
736
        ENTER( "RXTXPort:nativeSetSerialPortParams" );
 
737
        report_time_start( );
 
738
 
 
739
        if (cspeed < 0 )
 
740
        {
 
741
                report(" invalid cspeed\n");
 
742
/*
 
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" );
 
747
*/
 
748
                return(1);
 
749
        }
 
750
 
 
751
 
 
752
        if( set_port_params( fd, cspeed, dataBits, stopBits, parity ) )
 
753
        {
 
754
                report("set_port_params failed\n");
 
755
                LEAVE( "RXTXPort:nativeSetSerialPortParams" );
 
756
/*
 
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 ) );
 
761
*/
 
762
                return(1);
 
763
        }
 
764
 
 
765
        LEAVE( "RXTXPort:nativeSetSerialPortParams" );
 
766
        report_time_end( );
 
767
        return(0);
 
768
}
 
769
 
 
770
/*----------------------------------------------------------
 
771
 translate_speed
 
772
 
 
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
 
779
               the magic constants.
 
780
----------------------------------------------------------*/
 
781
int translate_speed(
 
782
        jint speed
 
783
)
 
784
{
 
785
        LEAVE( "RXTXPort:translate_speed" );
 
786
        switch( speed ) {
 
787
                case 0:         return B0;
 
788
                case 50:        return B50;
 
789
                case 75:        return B75;
 
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;
 
803
#ifdef B57600
 
804
                case 57600:     return B57600;
 
805
#endif /* B57600 */
 
806
#ifdef B115200
 
807
                case 115200:    return B115200;
 
808
#endif /* B115200 */
 
809
#ifdef B230400
 
810
                case 230400:    return B230400;
 
811
#endif /* B230400 */
 
812
#ifdef B460800
 
813
                case 460800:    return B460800;
 
814
#endif /* B460800 */
 
815
#ifdef B14400
 
816
                case 14400:     return B14400;
 
817
#endif /* B14400 */
 
818
#ifdef B28800
 
819
                case 28800:     return B28800;
 
820
#endif /* B28800 */
 
821
#ifdef B128000  /* dima */
 
822
                case 128000:    return B128000;
 
823
#endif  /* dima */
 
824
#ifdef B256000  /* dima */
 
825
                case 256000:    return B256000;
 
826
#endif  /* dima */
 
827
        }
 
828
 
 
829
        /* Handle custom speeds */
 
830
        if( speed >= 0 ) return speed;
 
831
        else
 
832
        {
 
833
                LEAVE( "RXTXPort:translate_speed: Error condition" );
 
834
                return -1;
 
835
        }
 
836
}
 
837
 
 
838
/*----------------------------------------------------------
 
839
 translate_data_bits
 
840
 
 
841
   accept:     gnu.io.SerialPort.DATABITS_* constant
 
842
   perform:    set proper termios c_cflag bits
 
843
   return:     1 on error
 
844
   exceptions: UnsupportedCommOperationException
 
845
----------------------------------------------------------*/
 
846
int translate_data_bits(
 
847
        tcflag_t *cflag,
 
848
        jint dataBits
 
849
)
 
850
{
 
851
        int temp = (*cflag) & ~CSIZE;
 
852
 
 
853
        ENTER( "translate_date_bits" );
 
854
        switch( dataBits ) {
 
855
                case JDATABITS_5:
 
856
                        (*cflag) = temp | CS5;
 
857
                        return 0;
 
858
                case JDATABITS_6:
 
859
                        (*cflag) = temp | CS6;
 
860
                        return 0;
 
861
                case JDATABITS_7:
 
862
                        (*cflag) = temp | CS7;
 
863
                        return 0;
 
864
                case JDATABITS_8:
 
865
                        (*cflag) = temp | CS8;
 
866
                        return 0;
 
867
        }
 
868
 
 
869
        LEAVE( "RXTXPort:translate_date_bits" );
 
870
/*
 
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" );
 
875
*/
 
876
        return 1;
 
877
}
 
878
 
 
879
/*----------------------------------------------------------
 
880
 translate_stop_bits
 
881
 
 
882
   accept:     gnu.io.SerialPort.STOPBITS_* constant
 
883
   perform:    set proper termios c_cflag bits
 
884
   return:     1 on error
 
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(
 
890
        tcflag_t *cflag,
 
891
        jint stopBits
 
892
)
 
893
{
 
894
        ENTER( "translate_stop_bits" );
 
895
        switch( stopBits ) {
 
896
                case STOPBITS_1:
 
897
                        (*cflag) &= ~CSTOPB;
 
898
                        LEAVE( "RXTXPort:translate_stop_bits" );
 
899
                        return 0;
 
900
                /*  ok.. lets try putting it in and see if anyone notices */
 
901
                case STOPBITS_1_5:
 
902
                        if ( translate_data_bits( cflag, JDATABITS_5 ) )
 
903
                                return( 1 );
 
904
                        return 0;
 
905
                case STOPBITS_2:
 
906
                        (*cflag) |= CSTOPB;
 
907
                        LEAVE( "RXTXPort:translate_stop_bits" );
 
908
                        return 0;
 
909
        }
 
910
 
 
911
        LEAVE( "RXTXPort:translate_stop_bits" );
 
912
/*
 
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" );
 
917
*/
 
918
        return 1;
 
919
}
 
920
jint gnu::io::RXTXPort::nativeGetFlowControlMode(
 
921
        jint fd
 
922
)
 
923
{
 
924
        struct termios ttyset;
 
925
        int ret = 0;
 
926
 
 
927
        tcgetattr( fd, &ttyset );
 
928
        
 
929
        if( ttyset.c_cflag & HARDWARE_FLOW_CONTROL )
 
930
        {
 
931
                ret |= ( FLOWCONTROL_RTSCTS_IN | FLOWCONTROL_RTSCTS_OUT );
 
932
        }
 
933
        if ( ttyset.c_iflag & IXOFF )
 
934
        {
 
935
                ret |= FLOWCONTROL_XONXOFF_IN;
 
936
        }
 
937
        if ( ttyset.c_iflag & IXON )
 
938
        {
 
939
                ret |= FLOWCONTROL_XONXOFF_OUT;
 
940
        }
 
941
        return( (jint) ret );
 
942
}
 
943
jint gnu::io::RXTXPort::nativeGetParity(
 
944
        jint fd
 
945
)
 
946
{
 
947
        struct termios ttyset;
 
948
 
 
949
        if( tcgetattr( fd, &ttyset ) < 0 )
 
950
        {
 
951
                report("nativeGetParity:  tcgetattr failed\n");
 
952
                return( -1 );
 
953
        }
 
954
#ifdef  CMSPAR 
 
955
        if ( ( ttyset.c_cflag & PARENB ) &&
 
956
                ( ttyset.c_cflag & PARODD ) &&
 
957
                ( ttyset.c_cflag & CMSPAR ) )
 
958
        {
 
959
                return( JPARITY_MARK );
 
960
        }
 
961
        else if ( ttyset.c_cflag & ( PARENB &&
 
962
                ttyset.c_cflag & CMSPAR ) )
 
963
        {
 
964
                return( JPARITY_SPACE );
 
965
        }
 
966
#endif /* CMSPAR */
 
967
        if ( ttyset.c_cflag & PARENB &&
 
968
                ttyset.c_cflag & PARODD )
 
969
        {
 
970
                return( JPARITY_ODD );
 
971
        }
 
972
        else if ( ttyset.c_cflag & PARENB )
 
973
        {
 
974
                return( JPARITY_EVEN );
 
975
        }
 
976
        else
 
977
        {
 
978
                return( JPARITY_NONE );
 
979
        }
 
980
}
 
981
 
 
982
/*----------------------------------------------------------
 
983
 translate_parity
 
984
 
 
985
   accept:     javax.comm.SerialPort.PARITY_* constant
 
986
   perform:    set proper termios c_cflag bits
 
987
   return:     1 on error
 
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(
 
993
        tcflag_t *cflag,
 
994
        jint parity
 
995
)
 
996
{
 
997
        ENTER( "translate_parity" );
 
998
#ifdef CMSPAR
 
999
        (*cflag) &= ~(PARENB | PARODD | CMSPAR );
 
1000
#endif /* CMSPAR */
 
1001
        switch( parity ) {
 
1002
                case JPARITY_NONE:
 
1003
                        LEAVE( "translate_parity" );
 
1004
                        return 0;
 
1005
                case JPARITY_EVEN:
 
1006
                        (*cflag) |= PARENB;
 
1007
                        LEAVE( "translate_parity" );
 
1008
                        return 0;
 
1009
                case JPARITY_ODD:
 
1010
                        (*cflag) |= PARENB | PARODD;
 
1011
                        LEAVE( "translate_parity" );
 
1012
                        return 0;
 
1013
#ifdef CMSPAR
 
1014
                case JPARITY_MARK:
 
1015
                        (*cflag) |= PARENB | PARODD | CMSPAR;
 
1016
                        LEAVE( "translate_parity" );
 
1017
                        return 0;
 
1018
                case JPARITY_SPACE:
 
1019
                        (*cflag) |= PARENB | CMSPAR;
 
1020
                        LEAVE( "translate_parity" );
 
1021
                        return 0;
 
1022
#endif /* CMSPAR */
 
1023
                default:
 
1024
                        printf("Parity missed %i\n", (int) parity );
 
1025
        }
 
1026
 
 
1027
        LEAVE( "translate_parity" );
 
1028
/*
 
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" );
 
1033
*/
 
1034
        return 1;
 
1035
}
 
1036
#if !defined(TIOCSERGETLSR) && !defined(WIN32)
 
1037
/*----------------------------------------------------------
 
1038
drain_loop()
 
1039
 
 
1040
   accept:      
 
1041
   perform:     call tcdrain() and report an event when it succeds  
 
1042
   return:      none
 
1043
   exceptions:  
 
1044
   comments:    
 
1045
----------------------------------------------------------*/
 
1046
void *drain_loop( void *arg )
 
1047
{
 
1048
        struct event_info_struct *eis = ( struct event_info_struct * ) arg;
 
1049
        /* char msg[80]; */
 
1050
        int i;
 
1051
        pthread_detach( pthread_self() );
 
1052
 
 
1053
        for(i=0;;i++)
 
1054
        {
 
1055
                report_verbose("drain_loop:  looping\n");
 
1056
#if defined(__sun__)
 
1057
        /* FIXME: No time to test on all OS's for production */
 
1058
                usleep(5000);
 
1059
#else
 
1060
                usleep(1000000);
 
1061
#endif /* __sun__ */
 
1062
                /*
 
1063
                system_wait();
 
1064
                */
 
1065
                if( eis->eventloop_interrupted )
 
1066
                {
 
1067
                        goto end;
 
1068
                }
 
1069
                if( tcdrain( eis->fd ) == 0 )
 
1070
                {
 
1071
                        if( eis && eis->writing )
 
1072
                        {
 
1073
                                /*
 
1074
                                sprintf(msg, "drain_loop: setting OUTPUT_BUFFER_EMPTY\n" );
 
1075
                                report( msg );
 
1076
                                */
 
1077
                                eis->output_buffer_empty_flag = 1;
 
1078
                                eis->writing=false;
 
1079
                        }
 
1080
                        else
 
1081
                        {
 
1082
                                if( !eis )
 
1083
                                {
 
1084
                                        goto end;
 
1085
                                }
 
1086
                                report_verbose("drain_loop:  writing not set\n");
 
1087
                        }
 
1088
                }
 
1089
                else
 
1090
                {
 
1091
                        report("drain_loop:  tcdrain bad fd\n");
 
1092
                        goto end;
 
1093
                }
 
1094
        }
 
1095
end:
 
1096
        report("------------------ drain_loop exiting ---------------------\n");
 
1097
        eis->closing = 1;
 
1098
        pthread_exit( NULL );
 
1099
        return( NULL );
 
1100
}
 
1101
#endif /* !defined(TIOCSERGETLSR) && !defined(WIN32) */
 
1102
/*----------------------------------------------------------
 
1103
finalize_threads( )
 
1104
 
 
1105
   accept:      event_info_struct used to access java and communicate with
 
1106
                eventLoop().
 
1107
   perform:     see comments
 
1108
   return:      none
 
1109
   exceptions:  none
 
1110
   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.
 
1116
        
 
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 )
 
1121
{
 
1122
#if     !defined(TIOCSERGETLSR) && !defined( WIN32 )
 
1123
        /* used to shut down any remaining write threads */
 
1124
 
 
1125
        eis->output_buffer_empty_flag = 0;
 
1126
        ENTER("finalize_threads\n");
 
1127
 
 
1128
        /* need to clean up again after working events */
 
1129
        LEAVE("---------------- finalize_threads ---------------");
 
1130
#endif /* TIOCSERGETLSR & !WIN32 */
 
1131
}
 
1132
 
 
1133
#if !defined(TIOCSERGETLSR) && !defined( WIN32 )
 
1134
static void warn_sig_abort( int signo )
 
1135
{
 
1136
        char msg[80];
 
1137
        sprintf( msg, "RXTX Recieved Signal %i\n", signo );
 
1138
        /*
 
1139
        report_error( msg );
 
1140
        */
 
1141
}
 
1142
#endif /* TIOCSERGETLSR */
 
1143
 
 
1144
/*----------------------------------------------------------
 
1145
init_threads( )
 
1146
 
 
1147
   accept:      none
 
1148
   perform:     
 
1149
   return:      none
 
1150
   exceptions:  none
 
1151
   comments:    
 
1152
----------------------------------------------------------*/
 
1153
int init_threads( gnu::io::RXTXPort *p, struct event_info_struct *eis )
 
1154
{
 
1155
#if !defined(TIOCSERGETLSR) & !defined(WIN32)
 
1156
        sigset_t newmask, oldmask;
 
1157
        struct sigaction newaction, oldaction;
 
1158
        pthread_t tid;
 
1159
 
 
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 );
 
1166
#ifdef SA_INTERRUPT
 
1167
        newaction.sa_flags = SA_INTERRUPT;
 
1168
#endif /* SA_INTERRUPT */
 
1169
#ifdef SA_RESTART
 
1170
        newaction.sa_flags = SA_RESTART;
 
1171
#endif /* SA_RESTART */
 
1172
 
 
1173
        sigaction(SIGABRT, &newaction, &oldaction);
 
1174
        sigaction(SIGCHLD, &newaction, &oldaction);
 
1175
        sigaction(SIGALRM, &newaction, &oldaction);
 
1176
        sigaction(SIGCONT, &newaction, &oldaction);
 
1177
/*
 
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);
 
1184
 
 
1185
        sigfillset(&newmask);
 
1186
        sigprocmask( SIG_SETMASK, &newmask, &oldmask );
 
1187
        pthread_sigmask( SIG_BLOCK, &newmask, &oldmask );
 
1188
*/
 
1189
        sigprocmask( SIG_SETMASK, &newmask, &oldmask );
 
1190
 
 
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");
 
1198
        report_time_end( );
 
1199
        return( 1 );
 
1200
}
 
1201
 
 
1202
/*----------------------------------------------------------
 
1203
RXTXPort.writeByte
 
1204
 
 
1205
   accept:      byte to write (passed as int)
 
1206
                jboolean interrupted (no events if true)
 
1207
   perform:     write a single byte to the port
 
1208
   return:      none
 
1209
   exceptions:  IOException
 
1210
----------------------------------------------------------*/
 
1211
void gnu::io::RXTXPort::writeByte(
 
1212
        jint ji,
 
1213
        jboolean interrupted
 
1214
)
 
1215
{
 
1216
#ifndef TIOCSERGETLSR
 
1217
        struct event_info_struct *index = master_index;
 
1218
#endif
 
1219
        unsigned char byte = (unsigned char)ji;
 
1220
        int fd = ( int ) this->fd;
 
1221
        int result;
 
1222
        char msg[80];
 
1223
#if defined ( __sun__ )
 
1224
        int count;
 
1225
#endif /* __sun__ */
 
1226
 
 
1227
        report_time_start();
 
1228
        ENTER( "RXTXPort:writeByte" );
 
1229
        do {
 
1230
                sprintf( msg, "writeByte %c>>\n", byte );
 
1231
                report( msg );
 
1232
                result=WRITE (fd, (void * ) &byte, sizeof(unsigned char));
 
1233
        }  while (result < 0 && errno==EINTR);
 
1234
        if ( result < 0 && errno != EINTR )
 
1235
        {
 
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 */
 
1239
                return;
 
1240
        }
 
1241
/*
 
1242
        This makes write for win32, glinux and Sol behave the same
 
1243
#if defined ( __sun__ )
 
1244
        do {
 
1245
                report_verbose( "nativeDrain: trying tcdrain\n" );
 
1246
                result=tcdrain(fd);
 
1247
                count++;
 
1248
        }  while (result && errno==EINTR && count <3);
 
1249
#endif *//* __sun __ */
 
1250
#ifndef TIOCSERGETLSR
 
1251
        if( ! interrupted )
 
1252
        {
 
1253
                index = master_index;
 
1254
                if( index )
 
1255
                {
 
1256
                        while( index->fd != fd &&
 
1257
                                index->next ) index = index->next;
 
1258
                }
 
1259
                index->writing = 1;
 
1260
                report( "writeByte:  index->writing = 1" );
 
1261
        }
 
1262
#endif
 
1263
        sprintf( msg, "RXTXPort:writeByte %i\n", result );
 
1264
        report( msg );
 
1265
        LEAVE( "RXTXPort:writeByte" );
 
1266
        if(result >= 0)
 
1267
        {
 
1268
                report_time_end();
 
1269
                return;
 
1270
        }
 
1271
        snprintf( msg, 79, "%s%s", strerror( errno ), " in writeByte" );
 
1272
        throw new java::io::IOException( JvNewStringUTF( msg ) );
 
1273
}
 
1274
 
 
1275
/*----------------------------------------------------------
 
1276
RXTXPort.writeArray
 
1277
 
 
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
 
1283
   return:      none
 
1284
   exceptions:  IOException
 
1285
----------------------------------------------------------*/
 
1286
void gnu::io::RXTXPort::writeArray(
 
1287
        jbyteArray jbarray,
 
1288
        jint offset,
 
1289
        jint count,
 
1290
        jboolean interrupted
 
1291
)
 
1292
{
 
1293
#ifndef TIOCSERGETLSR
 
1294
        struct event_info_struct *index = master_index;
 
1295
#endif /* TIOCSERGETLSR */
 
1296
        int fd;
 
1297
        int result=0,total=0;
 
1298
        jbyte *out = elements( jbarray );
 
1299
        char msg[80];
 
1300
#if defined ( __sun__ )
 
1301
        int icount;
 
1302
#endif /* __sun__ */
 
1303
#if defined ( __sun__ )
 
1304
        struct timespec retspec;
 
1305
 
 
1306
        retspec.tv_sec = 0;
 
1307
        retspec.tv_nsec = 50000;
 
1308
#endif /* __sun__ */
 
1309
        fd = ( int ) this->fd;
 
1310
 
 
1311
        report_time_start();
 
1312
        ENTER( "writeArray" );
 
1313
        /* warning Roy Rogers */
 
1314
        /*
 
1315
        sprintf( message, "::::RXTXPort:writeArray(%s);\n", (char *) body );
 
1316
        report_verbose( message );
 
1317
        */
 
1318
 
 
1319
        do {
 
1320
                result=WRITE (fd, (void * ) ((char *) out + total + offset), count - total); /* dima */
 
1321
                if(result >0){
 
1322
                        total += result;
 
1323
                }
 
1324
                report("writeArray()\n");
 
1325
        }  while ( ( total < count ) && ( (result < 0 && errno==EINTR ) || ( result >= 0 ) ) ) ;
 
1326
        if ( result < 0 && errno != EINTR )
 
1327
        {
 
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 */
 
1331
                return;
 
1332
        }
 
1333
/*
 
1334
        This makes write for win32, glinux and Sol behave the same
 
1335
#if defined ( __sun__ )
 
1336
        do {
 
1337
                report_verbose( "nativeDrain: trying tcdrain\n" );
 
1338
                result=tcdrain(fd);
 
1339
                icount++;
 
1340
        }  while (result && errno==EINTR && icount <3);
 
1341
#endif *//* __sun__ */
 
1342
#ifndef TIOCSERGETLSR
 
1343
        if( !interrupted )
 
1344
        {
 
1345
                if( index )
 
1346
                {
 
1347
                        while( index->fd != fd &&
 
1348
                                index->next ) index = index->next;
 
1349
                }
 
1350
                index->writing = 1;
 
1351
                report( "writeArray:  index->writing = 1" );
 
1352
        }
 
1353
#endif /* TIOCSERGETLSR */
 
1354
        /*
 
1355
                50 ms sleep to make sure read can get in
 
1356
 
 
1357
                what I think is happening here is the data writen is causing
 
1358
                signals, the event loop can't select with data available
 
1359
 
 
1360
                I think things like BlackBox with 2 ports open are getting
 
1361
                signals for both the reciever and transmitter since they
 
1362
                are the same PID.
 
1363
 
 
1364
                Things just start spinning out of control after that.
 
1365
        */
 
1366
        LEAVE( "RXTXPort:writeArray" );
 
1367
        report_time_end();
 
1368
        return;
 
1369
fail:
 
1370
        snprintf( msg, 79, "%s%s", strerror( errno ), " in writeArray" );
 
1371
        throw new java::io::IOException( JvNewStringUTF( msg ) );
 
1372
}
 
1373
 
 
1374
/*----------------------------------------------------------
 
1375
RXTXPort.nativeDrain
 
1376
 
 
1377
   accept:      jboolean interrupted (no events if true)
 
1378
   perform:     wait until all data is transmitted
 
1379
   return:      none
 
1380
   exceptions:  IOException
 
1381
   comments:    java.io.OutputStream.flush() is equivalent to tcdrain,
 
1382
                not tcflush, which throws away unsent bytes
 
1383
 
 
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
 
1389
)
 
1390
{
 
1391
        int fd = ( int ) this->fd;
 
1392
        struct event_info_struct *eis = ( struct event_info_struct * ) this->eis;
 
1393
        int result, count=0;
 
1394
 
 
1395
        char message[80];
 
1396
 
 
1397
        ENTER( "SerialImp.c:drain()" );
 
1398
        report_time_start( );
 
1399
        do {
 
1400
                report_verbose( "nativeDrain: trying tcdrain\n" );
 
1401
                result=tcdrain(fd);
 
1402
                count++;
 
1403
        }  while (result && errno==EINTR && count <3);
 
1404
 
 
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 */
 
1409
        return( true );
 
1410
#endif /* __sun__ */
 
1411
        LEAVE( "RXTXPort:drain()" );
 
1412
        if( result )
 
1413
        {
 
1414
                snprintf( message, 79, "%s%s", strerror( errno ), " in nativeDrain" );
 
1415
                throw new java::io::IOException( JvNewStringUTF( message ) );
 
1416
        }
 
1417
        if( interrupted ) return( false );
 
1418
#if !defined(TIOCSERGETLSR) && !defined(WIN32)
 
1419
        if( eis && eis->writing )
 
1420
        {
 
1421
                eis->writing=false;
 
1422
                eis->output_buffer_empty_flag = 0;
 
1423
        }
 
1424
#endif /* !TIOCSERGETLSR !WIN32 */
 
1425
        if( eis && eis->eventflags[SPE_OUTPUT_BUFFER_EMPTY] )
 
1426
        {
 
1427
                send_event( this, eis, SPE_OUTPUT_BUFFER_EMPTY, 1 );
 
1428
        }
 
1429
        report_time_end( );
 
1430
        return( false );
 
1431
}
 
1432
 
 
1433
/*----------------------------------------------------------
 
1434
RXTXPort.sendBreak
 
1435
 
 
1436
   accept:     duration in milliseconds.
 
1437
   perform:    send break for actual time.  not less than 0.25 seconds.
 
1438
   exceptions: none
 
1439
   comments:   not very precise
 
1440
----------------------------------------------------------*/
 
1441
void gnu::io::RXTXPort::sendBreak(
 
1442
        jint duration
 
1443
)
 
1444
{
 
1445
        int fd = ( int ) this->fd;
 
1446
        report_time_start( );
 
1447
        ENTER( "RXTXPort:sendBreak()" );
 
1448
        tcsendbreak( fd, (int)( duration / 250 ) );
 
1449
        report_time_end( );
 
1450
        LEAVE( "RXTXPort:sendBreak()" );
 
1451
}
 
1452
 
 
1453
/*----------------------------------------------------------
 
1454
RXTXPort.NativegetReceiveTimeout
 
1455
 
 
1456
   accept:     none
 
1457
   perform:    get termios.c_cc[VTIME]
 
1458
   return:     VTIME
 
1459
   comments:   see  NativeEnableReceiveTimeoutThreshold
 
1460
----------------------------------------------------------*/
 
1461
jint gnu::io::RXTXPort::NativegetReceiveTimeout(
 
1462
)
 
1463
{
 
1464
        int fd = this->fd;
 
1465
        struct termios ttyset;
 
1466
        char msg[80];
 
1467
 
 
1468
        ENTER( "RXTXPort:nativegetRecieveTimeout()" );
 
1469
        if( tcgetattr( fd, &ttyset ) < 0 ) goto fail;
 
1470
        LEAVE( "RXTXPort:nativegetRecieveTimeout()" );
 
1471
        return(ttyset.c_cc[ VTIME ] * 100);
 
1472
fail:
 
1473
        LEAVE( "RXTXPort:nativegetRecieveTimeout()" );
 
1474
        snprintf( msg, 79, "%s%s", strerror( errno ), " in nativeGetRecieveTimeout()" );
 
1475
        throw new java::io::IOException( JvNewStringUTF( msg ) );
 
1476
        return -1;
 
1477
}
 
1478
 
 
1479
/*----------------------------------------------------------
 
1480
RXTXPort.NativeisReceiveTimeoutEnabled
 
1481
 
 
1482
   accept:     none
 
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(
 
1488
)
 
1489
{
 
1490
        int fd = this->fd;
 
1491
        struct termios ttyset;
 
1492
        char msg[80];
 
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);
 
1497
fail:
 
1498
        LEAVE( "RXTXPort:NativeisRecieveTimeoutEnabled()" );
 
1499
        snprintf( msg, 79, "%s%s", strerror( errno ), " in isRecieveTimeoutEnabled()" );
 
1500
        throw new java::io::IOException( JvNewStringUTF( msg ) );
 
1501
        return false;
 
1502
}
 
1503
 
 
1504
/*----------------------------------------------------------
 
1505
RXTXPort.isDSR
 
1506
 
 
1507
   accept:      none
 
1508
   perform:     check status of DSR
 
1509
   return:      true if TIOCM_DSR is set
 
1510
                false if TIOCM_DSR is not set
 
1511
   exceptions:  none
 
1512
   comments:    DSR stands for Data Set Ready
 
1513
----------------------------------------------------------*/
 
1514
jboolean gnu::io::RXTXPort::isDSR(
 
1515
)
 
1516
{
 
1517
        unsigned int result = 0;
 
1518
        int fd = this->fd;
 
1519
        char message[80];
 
1520
 
 
1521
        ENTER( "RXTXPort:isDSR" );
 
1522
        ioctl( fd, TIOCMGET, &result );
 
1523
        sprintf( message, "RXTXPort:isDSR returns %i\n", result & TIOCM_DSR );
 
1524
        report( message );
 
1525
        LEAVE( "RXTXPort:isDSR" );
 
1526
        if( result & TIOCM_DSR ) return true;
 
1527
        else return false;
 
1528
}
 
1529
 
 
1530
/*----------------------------------------------------------
 
1531
RXTXPort.isCD
 
1532
 
 
1533
   accept:      none
 
1534
   perform:     check status of CD
 
1535
   return:      true if TIOCM_CD is set
 
1536
                false if TIOCM_CD is not set
 
1537
   exceptions:  none
 
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"
 
1542
 
 
1543
----------------------------------------------------------*/
 
1544
jboolean gnu::io::RXTXPort::isCD(
 
1545
)
 
1546
{
 
1547
        unsigned int result = 0;
 
1548
        int fd =  ( int ) this->fd;
 
1549
        char message[80];
 
1550
 
 
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;
 
1556
        else return false;
 
1557
}
 
1558
 
 
1559
/*----------------------------------------------------------
 
1560
RXTXPort.isCTS
 
1561
 
 
1562
   accept:      none
 
1563
   perform:     check status of CTS
 
1564
   return:      true if TIOCM_CTS is set
 
1565
                false if TIOCM_CTS is not set
 
1566
   exceptions:  none
 
1567
   comments:    CTS stands for Clear To Send.
 
1568
----------------------------------------------------------*/
 
1569
jboolean gnu::io::RXTXPort::isCTS(
 
1570
)
 
1571
{
 
1572
        unsigned int result = 0;
 
1573
        int fd = ( int ) this->fd;
 
1574
        char message[80];
 
1575
 
 
1576
        ENTER( "RXTXPort:isCTS" );
 
1577
        ioctl( fd, TIOCMGET, &result );
 
1578
        sprintf( message, "RXTXPort:isCTS returns %i\n", result & TIOCM_CTS );
 
1579
        report( message );
 
1580
        LEAVE( "RXTXPort:isCTS" );
 
1581
        if( result & TIOCM_CTS ) return true;
 
1582
        else return false;
 
1583
}
 
1584
 
 
1585
/*----------------------------------------------------------
 
1586
RXTXPort.isRI
 
1587
 
 
1588
   accept:      none
 
1589
   perform:     check status of RI
 
1590
   return:      true if TIOCM_RI is set
 
1591
                false if TIOCM_RI is not set
 
1592
   exceptions:  none
 
1593
   comments:    RI stands for Ring Indicator
 
1594
----------------------------------------------------------*/
 
1595
jboolean gnu::io::RXTXPort::isRI(
 
1596
)
 
1597
{
 
1598
        unsigned int result = 0;
 
1599
        int fd = ( int ) this->fd;
 
1600
        char message[80];
 
1601
 
 
1602
        ENTER( "RXTXPort:isRI" );
 
1603
        ioctl( fd, TIOCMGET, &result );
 
1604
        sprintf( message, "RXTXPort:isRI returns %i\n", result & TIOCM_RI );
 
1605
        report( message );
 
1606
        LEAVE( "RXTXPort:isRI" );
 
1607
        if( result & TIOCM_RI ) return true;
 
1608
        else return false;
 
1609
}
 
1610
 
 
1611
/*----------------------------------------------------------
 
1612
RXTXPort.isRTS
 
1613
 
 
1614
   accept:      none
 
1615
   perform:     check status of RTS
 
1616
   return:      true if TIOCM_RTS is set
 
1617
                false if TIOCM_RTS is not set
 
1618
   exceptions:  none
 
1619
   comments:    tcgetattr with c_cflag CRTS_IFLOW
 
1620
----------------------------------------------------------*/
 
1621
jboolean gnu::io::RXTXPort::isRTS(
 
1622
)
 
1623
{
 
1624
        unsigned int result = 0;
 
1625
        int fd = ( int ) this->fd;
 
1626
        char message[80];
 
1627
 
 
1628
        ENTER( "RXTXPort:isRTS" );
 
1629
        ioctl( fd, TIOCMGET, &result );
 
1630
        sprintf( message, "RXTXPort:isRTS returns %i\n", result & TIOCM_RTS );
 
1631
        report( message );
 
1632
        LEAVE( "RXTXPort:isRTS" );
 
1633
        if( result & TIOCM_RTS ) return true;
 
1634
        else return false;
 
1635
}
 
1636
 
 
1637
/*----------------------------------------------------------
 
1638
RXTXPort.setRTS
 
1639
 
 
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
 
1644
   return:      none
 
1645
   exceptions:  none
 
1646
   comments:    tcsetattr with c_cflag CRTS_IFLOW
 
1647
----------------------------------------------------------*/
 
1648
void gnu::io::RXTXPort::setRTS(
 
1649
        jboolean state
 
1650
)
 
1651
{
 
1652
        unsigned int result = 0;
 
1653
        int fd = ( int ) this->fd;
 
1654
        char message[80];
 
1655
 
 
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 );
 
1662
        report( message );
 
1663
        LEAVE( "RXTXPort:setRTS" );
 
1664
        return;
 
1665
}
 
1666
 
 
1667
/*----------------------------------------------------------
 
1668
RXTXPort.setDSR
 
1669
 
 
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
 
1674
   return:      none
 
1675
   exceptions:  none
 
1676
   comments:    tcsetattr with c_cflag CRTS_IFLOW
 
1677
----------------------------------------------------------*/
 
1678
void gnu::io::RXTXPort::setDSR(
 
1679
        jboolean state
 
1680
)
 
1681
{
 
1682
        unsigned int result = 0;
 
1683
        int fd = ( int ) this->fd;
 
1684
        char message[80];
 
1685
 
 
1686
        ENTER( "RXTXPort:setDSR()" );
 
1687
        ioctl( fd, TIOCMGET, &result );
 
1688
        
 
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 );
 
1694
        report( message );
 
1695
        LEAVE( "RXTXPort:setDSR()" );
 
1696
        return;
 
1697
}
 
1698
 
 
1699
/*----------------------------------------------------------
 
1700
RXTXPort.isDTR
 
1701
 
 
1702
   accept:      none
 
1703
   perform:     check status of DTR
 
1704
   return:      true if TIOCM_DTR is set
 
1705
                false if TIOCM_DTR is not set
 
1706
   exceptions:  none
 
1707
   comments:    DTR stands for Data Terminal Ready
 
1708
----------------------------------------------------------*/
 
1709
jboolean gnu::io::RXTXPort::isDTR(
 
1710
)
 
1711
{
 
1712
        unsigned int result = 0;
 
1713
        int fd = ( int ) this->fd;
 
1714
        char message[80];
 
1715
 
 
1716
        ENTER( "RXTXPort:isDTR" );
 
1717
        ioctl( fd, TIOCMGET, &result );
 
1718
        sprintf( message, "isDTR( ) returns %i\n", result& TIOCM_DTR );
 
1719
        report( message );
 
1720
        LEAVE( "RXTXPort:isDTR" );
 
1721
        if( result & TIOCM_DTR ) return true;
 
1722
        else return false;
 
1723
}
 
1724
 
 
1725
/*----------------------------------------------------------
 
1726
RXTXPort.setDTR
 
1727
 
 
1728
   accept:      new DTR state
 
1729
   perform:     if state is true, TIOCM_DTR is set
 
1730
                if state is false, TIOCM_DTR is unset
 
1731
   return:      none
 
1732
   exceptions:  none
 
1733
   comments:    DTR stands for Data Terminal Ready
 
1734
----------------------------------------------------------*/
 
1735
void gnu::io::RXTXPort::setDTR(
 
1736
        jboolean state
 
1737
)
 
1738
{
 
1739
        unsigned int result = 0;
 
1740
        int fd = ( int ) this->fd;
 
1741
        char message[80];
 
1742
 
 
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 );
 
1749
        report( message );
 
1750
        LEAVE( "RXTXPort:setDTR" );
 
1751
        return;
 
1752
}
 
1753
/*----------------------------------------------------------
 
1754
RXTXPort.static_add_filename
 
1755
 
 
1756
   accept:      filename and fd to save
 
1757
   perform:     add a struct holding the info to a linked list
 
1758
   return:      none
 
1759
   exceptions:  none
 
1760
   comments:    the info is checked on open() if its in the list no
 
1761
                changes are performed on the file on open()
 
1762
 
 
1763
   comments:    see
 
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
-----------------------------------------------------------*/
 
1770
 
 
1771
void static_add_filename( const char *filename, int fd)
 
1772
{
 
1773
        struct preopened *newp, *p = preopened_port;
 
1774
 
 
1775
        newp = ( struct preopened *) malloc( sizeof( struct preopened ) );
 
1776
        strcpy( newp->filename, filename );
 
1777
        newp->fd = fd;
 
1778
 
 
1779
        if( !p )
 
1780
        {
 
1781
                newp->next = NULL;
 
1782
                newp->prev = NULL;
 
1783
                preopened_port = newp;
 
1784
                return;
 
1785
        }
 
1786
        for(;;)
 
1787
        {
 
1788
                if( !strcmp( p->filename, filename) )
 
1789
                {
 
1790
                        /* already open */
 
1791
                        return;
 
1792
                }
 
1793
                if( p->next )
 
1794
                {
 
1795
                        p = p->next;
 
1796
                }
 
1797
                else
 
1798
                {
 
1799
                        /* end of list */
 
1800
                        newp->next = NULL;
 
1801
                        newp->prev = p;
 
1802
                        p->next = newp;
 
1803
                        preopened_port = p;
 
1804
                        return;
 
1805
                }
 
1806
        }
 
1807
}
 
1808
/*----------------------------------------------------------
 
1809
RXTXPort.nativeSetBaudBase
 
1810
 
 
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 
 
1815
                TIOCGSERIAL
 
1816
   comments:    
 
1817
                Set baud rate to 38400 before using this
 
1818
                First introduced in rxtx-2.1-3
 
1819
----------------------------------------------------------*/
 
1820
jboolean gnu::io::RXTXPort::nativeSetBaudBase(
 
1821
        jint BaudBase
 
1822
)
 
1823
{
 
1824
 
 
1825
#if defined(TIOCGSERIAL)
 
1826
 
 
1827
        int fd = ( int ) this->fd;
 
1828
        struct serial_struct sstruct;
 
1829
 
 
1830
        if (    sstruct.baud_base < 1 ||
 
1831
                ioctl( fd, TIOCSSERIAL, &sstruct ) < 0 )
 
1832
        {
 
1833
                return( true );
 
1834
        }
 
1835
        return( false );
 
1836
#else
 
1837
        snprintf( msg, 79, "%s%s", strerror( errno ), " in nativeSetBaudBase" );
 
1838
        throw new gnu::io::UnsupportedCommOperationException( JvNewStringUTF( msg ) );
 
1839
        return( true );
 
1840
#endif /* TIOCGSERIAL */
 
1841
}
 
1842
 
 
1843
/*----------------------------------------------------------
 
1844
RXTXPort.nativeGetBaudBase
 
1845
 
 
1846
   accept:      the Baud Base used for custom speeds
 
1847
   perform:     
 
1848
   return:      Baud Base
 
1849
   exceptions:  Unsupported Comm Operation on systems not supporting 
 
1850
                TIOCGSERIAL
 
1851
   comments:    
 
1852
                First introduced in rxtx-2.1-3
 
1853
----------------------------------------------------------*/
 
1854
jint gnu::io::RXTXPort::nativeGetBaudBase(
 
1855
)
 
1856
{
 
1857
 
 
1858
#if defined(TIOCGSERIAL)
 
1859
 
 
1860
        int fd = ( int ) this->fd;
 
1861
        struct serial_struct sstruct;
 
1862
 
 
1863
        if ( ioctl( fd, TIOCGSERIAL, &sstruct ) < 0 )
 
1864
        {
 
1865
                return( ( jint ) -1 );
 
1866
        }
 
1867
        return( ( jint ) ( sstruct.baud_base ) );
 
1868
#else
 
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 */
 
1873
}
 
1874
 
 
1875
/*----------------------------------------------------------
 
1876
RXTXPort.nativeSetDivisor
 
1877
 
 
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 
 
1882
                TIOCGSERIAL
 
1883
   comments:    
 
1884
                Set baud rate to 38400 before using this
 
1885
                First introduced in rxtx-2.1-3
 
1886
----------------------------------------------------------*/
 
1887
jboolean gnu::io::RXTXPort::nativeSetDivisor(
 
1888
        jint Divisor
 
1889
)
 
1890
{
 
1891
 
 
1892
#if defined(TIOCGSERIAL)
 
1893
 
 
1894
        int fd = ( int ) this->fd;
 
1895
        struct serial_struct sstruct;
 
1896
 
 
1897
        if ( ioctl( fd, TIOCGSERIAL, &sstruct ) < 0 )
 
1898
        {
 
1899
                return( true );
 
1900
        }
 
1901
 
 
1902
        if (    sstruct.custom_divisor < 1 ||
 
1903
                ioctl( fd, TIOCSSERIAL, &sstruct ) < 0 )
 
1904
        {
 
1905
                return( true );
 
1906
        }
 
1907
        return( false );
 
1908
#else
 
1909
        snprintf( msg, 79, "%s%s", strerror( errno ), " in nativeSetDivisor" );
 
1910
        throw new gnu::io::UnsupportedCommOperationException( JvNewStringUTF( msg ) );
 
1911
        return( true );
 
1912
#endif /* TIOCGSERIAL */
 
1913
}
 
1914
 
 
1915
/*----------------------------------------------------------
 
1916
RXTXPort.nativeGetDivisor
 
1917
 
 
1918
   accept:      none
 
1919
   perform:     Find the Divisor used for custom speeds
 
1920
   return:      Divisor
 
1921
   exceptions:  Unsupported Comm Operation on systems not supporting
 
1922
                TIOCGSERIAL
 
1923
   comments:    
 
1924
                First introduced in rxtx-2.1-3
 
1925
----------------------------------------------------------*/
 
1926
jint gnu::io::RXTXPort::nativeGetDivisor(
 
1927
)
 
1928
{
 
1929
 
 
1930
#if defined(TIOCGSERIAL)
 
1931
 
 
1932
        int fd = ( int ) this->fd;
 
1933
        struct serial_struct sstruct;
 
1934
 
 
1935
        if ( ioctl( fd, TIOCGSERIAL, &sstruct ) < 0 )
 
1936
        {
 
1937
                return( ( jint ) -1 );
 
1938
        }
 
1939
 
 
1940
        return( ( jint ) sstruct.custom_divisor );
 
1941
#else
 
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 */
 
1946
}
 
1947
 
 
1948
/*----------------------------------------------------------
 
1949
RXTXPort.nativeStaticSetDSR
 
1950
 
 
1951
   accept:      new RTS state
 
1952
   perform:     if flag is true, TIOCM_DSR is set
 
1953
                if flag is false, TIOCM_DSR is unset
 
1954
   return:      none
 
1955
   exceptions:  none
 
1956
   comments:    Set the DSR so it does not raise on the next open
 
1957
                needed for some funky test boards?
 
1958
 
 
1959
                This is static so we can not call the open() setDSR()
 
1960
                we dont have the jobject.
 
1961
 
 
1962
                First introduced in rxtx-1.5-9
 
1963
----------------------------------------------------------*/
 
1964
jboolean gnu::io::RXTXPort::nativeStaticSetDSR (
 
1965
        jstring jstr,
 
1966
        jboolean flag
 
1967
)
 
1968
{
 
1969
        int fd, i, pid = -1, result;
 
1970
        char filename[80];
 
1971
 
 
1972
        for( i=0;i<jstr->length();i++)
 
1973
                filename[i] = jstr->charAt(i);
 
1974
        filename[i] = '\0';
 
1975
 
 
1976
        ENTER( "RXTXPort:nativeStaticSetDSR" );
 
1977
#ifndef WIN32
 
1978
        pid = getpid();
 
1979
#endif /* WIN32 */
 
1980
 
 
1981
        /* Open and lock the port so nothing else changes the setting */
 
1982
 
 
1983
        if ( LOCK( filename, pid ) ) goto fail;;
 
1984
        
 
1985
        fd = find_preopened_ports( filename );
 
1986
        if( !fd )
 
1987
        {
 
1988
                do {
 
1989
                        fd = ::OPEN (filename, O_RDWR | O_NOCTTY | O_NONBLOCK );
 
1990
                }  while (fd < 0 && errno==EINTR);
 
1991
                if ( configure_port( fd ) ) goto fail;
 
1992
        }
 
1993
        if ( fd < 0 ) goto fail;
 
1994
 
 
1995
        /* raise the DSR */
 
1996
 
 
1997
        ioctl( fd, TIOCMGET, &result );
 
1998
        if( flag == true ) result |= TIOCM_DSR;
 
1999
        else result &= ~TIOCM_DSR;
 
2000
        ioctl( fd, TIOCMSET, &result );
 
2001
 
 
2002
        /* Unlock the port.  Good luck! :) */
 
2003
 
 
2004
        UNLOCK( filename,  pid );
 
2005
 
 
2006
        static_add_filename( filename, fd );
 
2007
        
 
2008
        /* dont close the port.  Its not clear if the DSR would remain high */
 
2009
        LEAVE( "RXTXPort:nativeStaticSetDSR" );
 
2010
        return( true );
 
2011
fail:
 
2012
        LEAVE( "RXTXPort:nativeStaticSetDSR" );
 
2013
        return( false );
 
2014
}
 
2015
 
 
2016
/*----------------------------------------------------------
 
2017
RXTXPort.nativeStaticSetRTS
 
2018
 
 
2019
   accept:      new RTS state
 
2020
   perform:     if flag is true, TIOCM_RTS is set
 
2021
                if flag is false, TIOCM_RTS is unset
 
2022
   return:      none
 
2023
   exceptions:  none
 
2024
   comments:    Set the RTS so it does not raise on the next open
 
2025
                needed for some funky test boards?
 
2026
 
 
2027
                This is static so we can not call the open() setDTR()
 
2028
                we dont have the jobject.
 
2029
 
 
2030
                First introduced in rxtx-1.5-9
 
2031
----------------------------------------------------------*/
 
2032
jboolean gnu::io::RXTXPort::nativeStaticSetRTS (
 
2033
        jstring jstr,
 
2034
        jboolean flag
 
2035
)
 
2036
{
 
2037
        int fd, i, pid = -1, result;
 
2038
        char filename[80];
 
2039
 
 
2040
        for( i=0;i<jstr->length();i++)
 
2041
                filename[i] = jstr->charAt(i);
 
2042
        filename[i] = '\0';
 
2043
 
 
2044
        ENTER( "RXTXPort:nativeStaticSetRTS" );
 
2045
#ifndef WIN32
 
2046
        pid = getpid();
 
2047
#endif /* WIN32 */
 
2048
 
 
2049
        /* Open and lock the port so nothing else changes the setting */
 
2050
 
 
2051
        if ( LOCK( filename, pid ) ) goto fail;;
 
2052
        
 
2053
        fd = find_preopened_ports( filename );
 
2054
        if( !fd )
 
2055
        {
 
2056
                do {
 
2057
                        fd = ::OPEN (filename, O_RDWR | O_NOCTTY | O_NONBLOCK );
 
2058
                }  while (fd < 0 && errno==EINTR);
 
2059
                if ( configure_port( fd ) ) goto fail;
 
2060
        }
 
2061
        if ( fd < 0 ) goto fail;
 
2062
 
 
2063
        /* raise the RTS */
 
2064
 
 
2065
        ioctl( fd, TIOCMGET, &result );
 
2066
        if( flag == true ) result |= TIOCM_RTS;
 
2067
        else result &= ~TIOCM_RTS;
 
2068
        ioctl( fd, TIOCMSET, &result );
 
2069
 
 
2070
        /* Unlock the port.  Good luck! :) */
 
2071
 
 
2072
        UNLOCK( filename,  pid );
 
2073
 
 
2074
        static_add_filename( filename, fd );
 
2075
        
 
2076
        /* dont close the port.  Its not clear if the RTS would remain high */
 
2077
        LEAVE( "RXTXPort:nativeStaticSetRTS" );
 
2078
        return( true );
 
2079
fail:
 
2080
        LEAVE( "RXTXPort:nativeStaticSetRTS" );
 
2081
        return( false );
 
2082
}
 
2083
 
 
2084
/*----------------------------------------------------------
 
2085
RXTXPort.nativeStaticSetSerialPortParams
 
2086
 
 
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
 
2090
                list.
 
2091
   return:      none
 
2092
   exceptions:  none
 
2093
   comments:    Not set the speed on the next 'open'
 
2094
 
 
2095
                This is static so we can not call the open() setDTR()
 
2096
                we dont have the jobject.
 
2097
 
 
2098
                First introduced in rxtx-1.5-9
 
2099
----------------------------------------------------------*/
 
2100
void gnu::io::RXTXPort::nativeStaticSetSerialPortParams (
 
2101
        jstring jstr,
 
2102
        jint baudrate,
 
2103
        jint dataBits,
 
2104
        jint stopBits,
 
2105
        jint parity
 
2106
)
 
2107
{
 
2108
        int fd, i, pid = -1, cspeed = translate_speed( baudrate );
 
2109
        char msg[80];
 
2110
        char filename[80];
 
2111
 
 
2112
        for( i=0;i<jstr->length();i++)
 
2113
                filename[i] = jstr->charAt(i);
 
2114
        filename[i] = '\0';
 
2115
 
 
2116
 
 
2117
        ENTER( "RXTXPort:nativeStaticSetSerialPortParams" );
 
2118
#ifndef WIN32
 
2119
        pid = getpid();
 
2120
#endif /* WIN32 */
 
2121
        /* Open and lock the port so nothing else changes the setting */
 
2122
 
 
2123
        if ( LOCK( filename, pid ) ) goto fail;
 
2124
        
 
2125
        fd = find_preopened_ports( filename );
 
2126
        if( !fd )
 
2127
        {
 
2128
                do {
 
2129
                        fd = ::OPEN (filename, O_RDWR | O_NOCTTY | O_NONBLOCK );
 
2130
                }  while (fd < 0 && errno==EINTR);
 
2131
                if ( configure_port( fd ) ) goto fail;
 
2132
        }
 
2133
 
 
2134
        if ( fd < 0 )
 
2135
        {
 
2136
                LEAVE( "RXTXPort:nativeStaticSetSerialPortParams" );
 
2137
                snprintf( msg, 79, "%s%s", strerror( errno ), " in nativeStaticSetSerialPortParams" );
 
2138
                throw new gnu::io::UnsupportedCommOperationException( JvNewStringUTF( msg ) );
 
2139
                return;
 
2140
        }
 
2141
 
 
2142
        if (cspeed == -1)
 
2143
        {
 
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 ) );
 
2147
                return;
 
2148
        }
 
2149
 
 
2150
        if( set_port_params( fd, cspeed, dataBits, stopBits, parity ) )
 
2151
        {
 
2152
                LEAVE( "RXTXPort:nativeStaticSetSerialPortParams" );
 
2153
                snprintf( msg, 79, "%s%s", strerror( errno ), " in nativeStaticSetSerialPortParams" );
 
2154
                return;
 
2155
        }
 
2156
 
 
2157
        /* Unlock the port.  Good luck! :) */
 
2158
 
 
2159
        UNLOCK( filename,  pid );
 
2160
 
 
2161
        static_add_filename( filename, fd );
 
2162
        /* dont close the port. */
 
2163
 
 
2164
        LEAVE( "RXTXPort:nativeStaticSetSerialPortParams" );
 
2165
        return;
 
2166
fail:
 
2167
        LEAVE( "RXTXPort:nativeStaticSetSerialPortParams" );
 
2168
        return;
 
2169
}
 
2170
 
 
2171
/*----------------------------------------------------------
 
2172
RXTXPort.nativeStaticSetDTR
 
2173
 
 
2174
   accept:      new DTR state
 
2175
   perform:     if flag is true, TIOCM_DTR is set
 
2176
                if flag is false, TIOCM_DTR is unset
 
2177
   return:      none
 
2178
   exceptions:  none
 
2179
   comments:    Set the DTR so it does not raise on the next open
 
2180
                needed for some funky test boards?
 
2181
 
 
2182
                This is static so we can not call the open() setDTR()
 
2183
                we dont have the jobject.
 
2184
 
 
2185
                First introduced in rxtx-1.5-9
 
2186
----------------------------------------------------------*/
 
2187
jboolean gnu::io::RXTXPort::nativeStaticSetDTR (
 
2188
        jstring jstr,
 
2189
        jboolean flag
 
2190
)
 
2191
{
 
2192
        int fd, i, pid = -1, result;
 
2193
        char filename[80];
 
2194
 
 
2195
        for( i=0;i<jstr->length();i++)
 
2196
                filename[i] = jstr->charAt(i);
 
2197
        filename[i] = '\0';
 
2198
 
 
2199
        ENTER( "RXTXPort:nativeStaticSetDTR" );
 
2200
#ifndef WIN32
 
2201
        pid = getpid();
 
2202
#endif /* WIN32 */
 
2203
 
 
2204
        /* Open and lock the port so nothing else changes the setting */
 
2205
 
 
2206
        if ( LOCK( filename, pid ) ) goto fail;;
 
2207
        
 
2208
        fd = find_preopened_ports( filename );
 
2209
        if( !fd )
 
2210
        {
 
2211
                do {
 
2212
                        fd = ::OPEN (filename, O_RDWR | O_NOCTTY | O_NONBLOCK );
 
2213
                }  while (fd < 0 && errno==EINTR);
 
2214
                if ( configure_port( fd ) ) goto fail;
 
2215
        }
 
2216
        if ( fd < 0 ) goto fail;
 
2217
 
 
2218
        /* raise the DTR */
 
2219
 
 
2220
        ioctl( fd, TIOCMGET, &result );
 
2221
        if( flag == true ) result |= TIOCM_DTR;
 
2222
        else result &= ~TIOCM_DTR;
 
2223
        ioctl( fd, TIOCMSET, &result );
 
2224
 
 
2225
        /* Unlock the port.  Good luck! :) */
 
2226
 
 
2227
        UNLOCK( filename,  pid );
 
2228
 
 
2229
        static_add_filename( filename, fd );
 
2230
        /* dont close the port.  Its not clear if the DTR would remain high */
 
2231
 
 
2232
        LEAVE( "RXTXPort:nativeStaticSetDTR" );
 
2233
        return( true );
 
2234
fail:
 
2235
        LEAVE( "RXTXPort:nativeStaticSetDTR" );
 
2236
        return( false );
 
2237
}
 
2238
 
 
2239
/*----------------------------------------------------------
 
2240
RXTXPort.nativeStaticIsRTS
 
2241
 
 
2242
   accept:      filename
 
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
 
2247
   exceptions:  none
 
2248
   comments:    RTS stands for Request to Send
 
2249
----------------------------------------------------------*/
 
2250
jboolean gnu::io::RXTXPort::nativeStaticIsRTS(
 
2251
        jstring jstr
 
2252
)
 
2253
{
 
2254
        unsigned int result = 0;
 
2255
        int i, fd;
 
2256
        char message[80];
 
2257
        char filename[80];
 
2258
 
 
2259
        for( i=0;i<jstr->length();i++)
 
2260
                filename[i] = jstr->charAt(i);
 
2261
        filename[i] = '\0';
 
2262
        fd = find_preopened_ports( filename );
 
2263
 
 
2264
        ENTER( "RXTXPort:nativeStaticIsRTS" );
 
2265
        if( !fd )
 
2266
        {
 
2267
                /* Exception? FIXME */
 
2268
                return false;
 
2269
        }
 
2270
        ioctl( fd, TIOCMGET, &result );
 
2271
        sprintf( message, "nativeStaticIsRTS( ) returns %i\n", result& TIOCM_RTS );
 
2272
        report( message );
 
2273
        LEAVE( "RXTXPort:nativeStaticIsRTS" );
 
2274
        if( result & TIOCM_RTS ) return true;
 
2275
        else return false;
 
2276
}
 
2277
/*----------------------------------------------------------
 
2278
RXTXPort.nativeStaticIsDSR
 
2279
 
 
2280
   accept:      filename
 
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
 
2285
   exceptions:  none
 
2286
   comments:    
 
2287
----------------------------------------------------------*/
 
2288
jboolean gnu::io::RXTXPort::nativeStaticIsDSR(
 
2289
        jstring jstr
 
2290
)
 
2291
{
 
2292
        unsigned int result = 0;
 
2293
        int i, fd;
 
2294
        char message[80];
 
2295
        char filename[80];
 
2296
 
 
2297
        for( i=0;i<jstr->length();i++)
 
2298
                filename[i] = jstr->charAt(i);
 
2299
        filename[i] = '\0';
 
2300
        fd = find_preopened_ports( filename );
 
2301
 
 
2302
        ENTER( "RXTXPort:nativeStaticIsDSR" );
 
2303
        if( !fd )
 
2304
        {
 
2305
                /* Exception? FIXME */
 
2306
                return false;
 
2307
        }
 
2308
        ioctl( fd, TIOCMGET, &result );
 
2309
        sprintf( message, "nativeStaticIsDSR( ) returns %i\n", result& TIOCM_DSR );
 
2310
        report( message );
 
2311
        LEAVE( "RXTXPort:nativeStaticIsDSR" );
 
2312
        if( result & TIOCM_DSR ) return true;
 
2313
        else return false;
 
2314
}
 
2315
/*----------------------------------------------------------
 
2316
RXTXPort.nativeStaticIsDTR
 
2317
 
 
2318
   accept:      filename
 
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
 
2323
   exceptions:  none
 
2324
   comments:    DTR stands for Data Terminal Ready
 
2325
----------------------------------------------------------*/
 
2326
jboolean gnu::io::RXTXPort::nativeStaticIsDTR(
 
2327
        jstring jstr
 
2328
)
 
2329
{
 
2330
        unsigned int result = 0;
 
2331
        int i, fd;
 
2332
        char message[80];
 
2333
        char filename[80];
 
2334
 
 
2335
        for( i=0;i<jstr->length();i++)
 
2336
                filename[i] = jstr->charAt(i);
 
2337
        filename[i] = '\0';
 
2338
        fd = find_preopened_ports( filename );
 
2339
 
 
2340
        ENTER( "RXTXPort:nativeStaticIsDTR" );
 
2341
        if( !fd )
 
2342
        {
 
2343
                /* Exception? FIXME */
 
2344
                return false;
 
2345
        }
 
2346
        ioctl( fd, TIOCMGET, &result );
 
2347
        sprintf( message, "nativeStaticIsDTR( ) returns %i\n", result& TIOCM_DTR );
 
2348
        report( message );
 
2349
        LEAVE( "RXTXPort:nativeStaticIsDTR" );
 
2350
        if( result & TIOCM_DTR ) return true;
 
2351
        else return false;
 
2352
}
 
2353
/*----------------------------------------------------------
 
2354
RXTXPort.nativeStaticIsCD
 
2355
 
 
2356
   accept:      filename
 
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
 
2361
   exceptions:  none
 
2362
   comments:    CD stands for carrier detect
 
2363
----------------------------------------------------------*/
 
2364
jboolean gnu::io::RXTXPort::nativeStaticIsCD(
 
2365
        jstring jstr
 
2366
)
 
2367
{
 
2368
        unsigned int result = 0;
 
2369
        int i, fd;
 
2370
        char message[80];
 
2371
        char filename[80];
 
2372
 
 
2373
        for( i=0;i<jstr->length();i++)
 
2374
                filename[i] = jstr->charAt(i);
 
2375
        filename[i] = '\0';
 
2376
        fd = find_preopened_ports( filename );
 
2377
 
 
2378
        ENTER( "RXTXPort:nativeStaticIsCD" );
 
2379
        if( !fd )
 
2380
        {
 
2381
                /* Exception? FIXME */
 
2382
                return false;
 
2383
        }
 
2384
        ioctl( fd, TIOCMGET, &result );
 
2385
        sprintf( message, "nativeStaticIsCD( ) returns %i\n", result& TIOCM_CD );
 
2386
        report( message );
 
2387
        LEAVE( "RXTXPort:nativeStaticIsCD" );
 
2388
        if( result & TIOCM_CD ) return true;
 
2389
        else return false;
 
2390
}
 
2391
/*----------------------------------------------------------
 
2392
RXTXPort.nativeStaticIsCTS
 
2393
 
 
2394
   accept:      filename
 
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
 
2399
   exceptions:  none
 
2400
   comments:    CTS stands for Clear To Send
 
2401
----------------------------------------------------------*/
 
2402
jboolean gnu::io::RXTXPort::nativeStaticIsCTS(
 
2403
        jstring jstr
 
2404
)
 
2405
{
 
2406
        unsigned int result = 0;
 
2407
        int i, fd;
 
2408
        char message[80];
 
2409
        char filename[80];
 
2410
 
 
2411
        for( i=0;i<jstr->length();i++)
 
2412
                filename[i] = jstr->charAt(i);
 
2413
        filename[i] = '\0';
 
2414
        fd = find_preopened_ports( filename );
 
2415
 
 
2416
        ENTER( "RXTXPort:nativeStaticIsCTS" );
 
2417
        if( !fd )
 
2418
        {
 
2419
                /* Exception? FIXME */
 
2420
                return false;
 
2421
        }
 
2422
        ioctl( fd, TIOCMGET, &result );
 
2423
        sprintf( message, "nativeStaticIsCTS( ) returns %i\n", result& TIOCM_CTS );
 
2424
        report( message );
 
2425
        LEAVE( "RXTXPort:nativeStaticIsCTS" );
 
2426
        if( result & TIOCM_CTS ) return true;
 
2427
        else return false;
 
2428
}
 
2429
/*----------------------------------------------------------
 
2430
RXTXPort.nativeStaticIsRI
 
2431
 
 
2432
   accept:      filename
 
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
 
2437
   exceptions:  none
 
2438
   comments:    RI stands for carrier detect
 
2439
----------------------------------------------------------*/
 
2440
jboolean gnu::io::RXTXPort::nativeStaticIsRI(
 
2441
        jstring jstr
 
2442
)
 
2443
{
 
2444
        unsigned int result = 0;
 
2445
        int i, fd;
 
2446
        char message[80];
 
2447
        char filename[80];
 
2448
 
 
2449
        for( i=0;i<jstr->length();i++)
 
2450
                filename[i] = jstr->charAt(i);
 
2451
        filename[i] = '\0';
 
2452
        fd = find_preopened_ports( filename );
 
2453
 
 
2454
        ENTER( "RXTXPort:nativeStaticIsRI" );
 
2455
        if( !fd )
 
2456
        {
 
2457
                /* Exception? FIXME */
 
2458
                return false;
 
2459
        }
 
2460
        ioctl( fd, TIOCMGET, &result );
 
2461
        sprintf( message, "nativeStaticRI( ) returns %i\n", result& TIOCM_RI );
 
2462
        report( message );
 
2463
        LEAVE( "RXTXPort:nativeStaticIsRI" );
 
2464
        if( result & TIOCM_RI ) return true;
 
2465
        else return false;
 
2466
}
 
2467
 
 
2468
/*----------------------------------------------------------
 
2469
RXTXPort.nativeStaticGetBaudRate
 
2470
 
 
2471
   accept:      filename
 
2472
   perform:     find the baud rate (not all buads are handled yet)
 
2473
   return:      return the baud rate or -1 if not supported yet.
 
2474
   exceptions:  
 
2475
   comments:    simple test for preopened ports
 
2476
----------------------------------------------------------*/
 
2477
jint gnu::io::RXTXPort::nativeStaticGetBaudRate(
 
2478
        jstring jstr
 
2479
)
 
2480
{
 
2481
        int i, fd;
 
2482
        struct termios ttyset;
 
2483
        int baudrate;
 
2484
        char filename[80];
 
2485
 
 
2486
        for( i=0;i<jstr->length();i++)
 
2487
                filename[i] = jstr->charAt(i);
 
2488
        filename[i] = '\0';
 
2489
        fd = find_preopened_ports( filename );
 
2490
 
 
2491
        ENTER( "RXTXPort:nativeStaticGetBaudRate" );
 
2492
        if( !fd )
 
2493
        {
 
2494
                /* Exception? FIXME */
 
2495
                return -1;
 
2496
        }
 
2497
        if( tcgetattr( fd, &ttyset ) < 0 )
 
2498
        {
 
2499
                report( "nativeStaticGetBaudRate: Cannot Get Serial Port Settings\n" );
 
2500
                return(-1);
 
2501
        }
 
2502
/*
 
2503
dima writes:
 
2504
 
 
2505
Trent, here is something I found with google:
 
2506
(freebsd list freebsd-current@freebsd.org)
 
2507
 
 
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?
 
2512
 
 
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.
 
2516
 
 
2517
*/
 
2518
#if defined(CBAUD)/* dima */
 
2519
        baudrate = ttyset.c_cflag&CBAUD;
 
2520
#else
 
2521
        if(cfgetispeed(&ttyset) != cfgetospeed(&ttyset)) return -1;
 
2522
        baudrate = cfgetispeed(&ttyset);
 
2523
#endif
 
2524
        return( get_java_baudrate(baudrate) );
 
2525
}
 
2526
/*----------------------------------------------------------
 
2527
RXTXPort.nativeStaticGetDataBits
 
2528
 
 
2529
   accept:      filename
 
2530
   perform:     find the data bits (not all buads are handled yet)
 
2531
   return:      return the data bits
 
2532
   exceptions:  
 
2533
   comments:    simple test for preopened ports
 
2534
----------------------------------------------------------*/
 
2535
jint gnu::io::RXTXPort::nativeStaticGetDataBits(
 
2536
        jstring jstr
 
2537
)
 
2538
{
 
2539
        int i, fd;
 
2540
        struct termios ttyset;
 
2541
        char filename[80];
 
2542
 
 
2543
        for( i=0;i<jstr->length();i++)
 
2544
                filename[i] = jstr->charAt(i);
 
2545
        filename[i] = '\0';
 
2546
        fd = find_preopened_ports( filename );
 
2547
 
 
2548
        ENTER( "RXTXPort:nativeStaticGetDataBits" );
 
2549
        if( !fd )
 
2550
        {
 
2551
                /* Exception? FIXME */
 
2552
                return -1;
 
2553
        }
 
2554
        if( tcgetattr( fd, &ttyset ) < 0 )
 
2555
        {
 
2556
                report( "nativeStaticGetDataBits: Cannot Get Serial Port Settings\n" );
 
2557
                return(-1);
 
2558
        }
 
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);
 
2565
        }
 
2566
}
 
2567
/*----------------------------------------------------------
 
2568
RXTXPort.nativeStaticGetParity
 
2569
 
 
2570
   accept:      filename
 
2571
   perform:     find the parity
 
2572
   return:      return the parity
 
2573
   exceptions:  
 
2574
   comments:    simple test for preopened ports
 
2575
----------------------------------------------------------*/
 
2576
jint gnu::io::RXTXPort::nativeStaticGetParity(
 
2577
        jstring jstr
 
2578
)
 
2579
{
 
2580
        int i, fd;
 
2581
        struct termios ttyset;
 
2582
        char filename[80];
 
2583
 
 
2584
        for( i=0;i<jstr->length();i++)
 
2585
                filename[i] = jstr->charAt(i);
 
2586
        filename[i] = '\0';
 
2587
        fd = find_preopened_ports( filename );
 
2588
 
 
2589
        ENTER( "RXTXPort:nativeStaticGetParity" );
 
2590
        if( !fd )
 
2591
        {
 
2592
                /* Exception? FIXME */
 
2593
                return -1;
 
2594
        }
 
2595
        if( tcgetattr( fd, &ttyset ) < 0 )
 
2596
        {
 
2597
                report( "nativeStaticGetParity: Cannot Get Serial Port Settings\n" );
 
2598
                return(-1);
 
2599
        }
 
2600
#ifdef CMSPAR
 
2601
        switch( ttyset.c_cflag&(PARENB|PARODD|CMSPAR ) ) {
 
2602
#else
 
2603
        switch( ttyset.c_cflag&(PARENB|PARODD) ) {
 
2604
#endif /* CMSPAR */
 
2605
                case 0: return JPARITY_NONE;
 
2606
                case PARENB: return JPARITY_EVEN;
 
2607
                case PARENB | PARODD: return JPARITY_ODD;
 
2608
#ifdef CMSPAR
 
2609
                case PARENB | PARODD | CMSPAR: return JPARITY_MARK;
 
2610
                case PARENB | CMSPAR: return JPARITY_SPACE;
 
2611
#endif /* CMSPAR */
 
2612
                default:  return(-1);
 
2613
        }
 
2614
}
 
2615
/*----------------------------------------------------------
 
2616
RXTXPort.nativeStaticGetStopBits
 
2617
 
 
2618
   accept:      filename
 
2619
   perform:     find the stop bits 
 
2620
   return:      return the stop bits
 
2621
   exceptions:  
 
2622
   comments:    simple test for preopened ports
 
2623
----------------------------------------------------------*/
 
2624
jint gnu::io::RXTXPort::nativeStaticGetStopBits(
 
2625
        jstring jstr
 
2626
)
 
2627
{
 
2628
        int i, fd;
 
2629
        struct termios ttyset;
 
2630
        char filename[80];
 
2631
        fd = find_preopened_ports( filename );
 
2632
 
 
2633
        for( i=0;i<jstr->length();i++)
 
2634
                filename[i] = jstr->charAt(i);
 
2635
        filename[i] = '\0';
 
2636
 
 
2637
        ENTER( "RXTXPort:nativeStaticGetStopBits" );
 
2638
        if( !fd )
 
2639
        {
 
2640
                /* Exception? FIXME */
 
2641
                return -1;
 
2642
        }
 
2643
        if( tcgetattr( fd, &ttyset ) < 0 )
 
2644
        {
 
2645
                report( "nativeStaticGetStopBits: Cannot Get Serial Port Settings\n" );
 
2646
                return(-1);
 
2647
        }
 
2648
        switch( ttyset.c_cflag&(CSTOPB) ) {
 
2649
                case 0: return STOPBITS_1;
 
2650
                case CSTOPB:  return STOPBITS_2;
 
2651
                default:  return  STOPBITS_1_5;
 
2652
        }
 
2653
}
 
2654
 
 
2655
/*----------------------------------------------------------
 
2656
RXTXPort.nativeGetParityErrorChar
 
2657
 
 
2658
   accept:      -
 
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.
 
2665
 
 
2666
                Use a direct call to the termios file until we find a
 
2667
                solution.
 
2668
----------------------------------------------------------*/
 
2669
jbyte gnu::io::RXTXPort::nativeGetParityErrorChar(
 
2670
)
 
2671
{
 
2672
        unsigned int result = 0;
 
2673
 
 
2674
        ENTER( "nativeGetParityErrorChar" );
 
2675
#ifdef WIN32
 
2676
        result = ( jbyte ) termiosGetParityErrorChar(
 
2677
                        this->fd );
 
2678
#else
 
2679
        /*
 
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.
 
2682
        */
 
2683
                result = ( jint ) '\0';
 
2684
 
 
2685
#endif /* WIN32 */
 
2686
        LEAVE( "nativeGetParityErrorChar" );
 
2687
        return( ( jbyte ) result );
 
2688
}
 
2689
 
 
2690
/*----------------------------------------------------------
 
2691
RXTXPort.nativeGetEndOfInputChar
 
2692
 
 
2693
   accept:      -
 
2694
   perform:     check the EndOf InputChar
 
2695
   return:      the EndOfInputChar as an jbyte.  -1 on error
 
2696
   exceptions:  UnsupportedCommOperationException if not implemented
 
2697
   comments:    
 
2698
----------------------------------------------------------*/
 
2699
jbyte gnu::io::RXTXPort::nativeGetEndOfInputChar(
 
2700
)
 
2701
{
 
2702
        int fd = ( int ) this->fd;
 
2703
        struct termios ttyset;
 
2704
 
 
2705
        ENTER( "nativeGetEndOfInputChar" );
 
2706
        if( tcgetattr( fd, &ttyset ) < 0 ) goto fail;
 
2707
        LEAVE( "nativeGetEndOfInputChar" );
 
2708
        return( (jbyte) ttyset.c_cc[VEOF] );
 
2709
fail:
 
2710
        LEAVE( "nativeGetEndOfInputChar" );
 
2711
        report( "nativeGetEndOfInputChar failed\n" );
 
2712
        return( ( jbyte ) -1 );
 
2713
}
 
2714
 
 
2715
/*----------------------------------------------------------
 
2716
RXTXPort.nativeSetParityErrorChar
 
2717
 
 
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.
 
2725
 
 
2726
                Use a direct call to the termios file until we find a
 
2727
                solution.
 
2728
----------------------------------------------------------*/
 
2729
jboolean gnu::io::RXTXPort::nativeSetParityErrorChar(
 
2730
        jbyte value
 
2731
)
 
2732
{
 
2733
 
 
2734
        char msg[80];
 
2735
#ifdef WIN32
 
2736
        int fd = ( int ) this->fd;
 
2737
        ENTER( "nativeSetParityErrorChar" );
 
2738
        termiosSetParityError( fd, ( char ) value );
 
2739
        LEAVE( "nativeSetParityErrorChar" );
 
2740
        return( true );
 
2741
#else
 
2742
        ENTER( "nativeSetParityErrorChar" );
 
2743
        /*
 
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.
 
2746
        */
 
2747
 
 
2748
        snprintf( msg, 79, "%s%s", strerror( errno ), " in setParityErrorChar()" );
 
2749
        throw new gnu::io::UnsupportedCommOperationException( JvNewStringUTF( msg ) );
 
2750
        LEAVE( "nativeSetParityErrorChar" );
 
2751
        return( false );
 
2752
#endif /* WIN32 */
 
2753
}
 
2754
 
 
2755
/*----------------------------------------------------------
 
2756
RXTXPort.nativeSetEndOfInputChar
 
2757
 
 
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.
 
2764
 
 
2765
                See termios.c for the windows bits.
 
2766
 
 
2767
                EofChar = val;
 
2768
                fBinary = false;  winapi docs say always use true. ?
 
2769
----------------------------------------------------------*/
 
2770
jboolean gnu::io::RXTXPort::nativeSetEndOfInputChar(
 
2771
        jbyte value
 
2772
)
 
2773
{
 
2774
        int fd = ( int ) this->fd;
 
2775
        struct termios ttyset;
 
2776
        char msg[80];
 
2777
 
 
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" );
 
2783
        return( true );
 
2784
fail:
 
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" );
 
2789
        return( false );
 
2790
}
 
2791
 
 
2792
#ifndef WIN32
 
2793
long
 
2794
GetTickCount()
 
2795
{
 
2796
        /* return milliseconds */
 
2797
        struct timeval now;
 
2798
 
 
2799
        gettimeofday(&now, NULL);
 
2800
        report_verbose("gettimeofday\n");
 
2801
 
 
2802
#ifdef __QNX__
 
2803
        return ( ( now.tv_sec * 1000 + now.tv_usec / 1000 ) );
 
2804
#else
 
2805
        return ( ( now.tv_sec * 1000) + ( long ) ceil( ( double ) now.tv_usec / 1000 ) );
 
2806
#endif /* __QNX__ */
 
2807
}
 
2808
 
 
2809
#endif /* !WIN32 */
 
2810
 
 
2811
/*----------------------------------------------------------
 
2812
read_byte_array
 
2813
 
 
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)
 
2821
                 0 timeout
 
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.
 
2825
                
 
2826
                The nuts and bolts are documented in
 
2827
                NativeEnableReceiveTimeoutThreshold()
 
2828
----------------------------------------------------------*/
 
2829
 
 
2830
int read_byte_array(
 
2831
        int fd,
 
2832
        unsigned char *buffer,
 
2833
        int length,
 
2834
        int timeout
 
2835
)
 
2836
{
 
2837
        int ret, left, bytes = 0;
 
2838
        long timeLeft, now = 0, start = 0;
 
2839
        char msg[80];
 
2840
        struct timeval tv, *tvP;
 
2841
        fd_set rset;
 
2842
        /* TRENT */
 
2843
        int count = 0;
 
2844
        sigset_t sigpwr_mask;
 
2845
 
 
2846
        // init the sigset for blocking SIGPWR + SIGXCPU
 
2847
        sigemptyset(&sigpwr_mask);
 
2848
        sigaddset(&sigpwr_mask, SIGPWR);
 
2849
        sigaddset(&sigpwr_mask, SIGXCPU);
 
2850
        
 
2851
        report_time_start();
 
2852
        ENTER( "read_byte_array" );
 
2853
        sprintf(msg, "read_byte_array requests %i\n", length);
 
2854
        report( msg );
 
2855
        left = length;
 
2856
        if (timeout >= 0)
 
2857
                start = GetTickCount();
 
2858
        while( bytes < length &&  count++ < 20 );
 
2859
        {
 
2860
                if (timeout >= 0) {
 
2861
                        now = GetTickCount();
 
2862
                        if ( now-start >= timeout )
 
2863
                                return bytes;
 
2864
                }
 
2865
 
 
2866
                FD_ZERO(&rset);
 
2867
                FD_SET(fd, &rset);
 
2868
 
 
2869
                if (timeout >= 0){
 
2870
                        timeLeft = timeout - (now - start);
 
2871
                        tv.tv_sec = timeLeft / 1000;
 
2872
                        tv.tv_usec = 1000 * ( timeLeft % 1000 );
 
2873
                        tvP = &tv;
 
2874
                }
 
2875
                else{
 
2876
                        tvP = NULL;
 
2877
                }
 
2878
                
 
2879
                // ignore SIGPWR + SIGXCPU during SELECT as gcj GC uses these signals
 
2880
                sigprocmask(SIG_BLOCK, &sigpwr_mask, NULL);
 
2881
                do {
 
2882
                        ret = SELECT(fd + 1, &rset, NULL, NULL, tvP);
 
2883
                } while ( ret < 0 && errno == EINTR );
 
2884
                sigprocmask(SIG_UNBLOCK, &sigpwr_mask, NULL);
 
2885
                if (ret == -1){
 
2886
                        report( "read_byte_array: select returned -1\n" );
 
2887
                        LEAVE( "read_byte_array" );
 
2888
                        return -1;
 
2889
                }
 
2890
                else if (ret > 0){
 
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" );
 
2895
                                        return -1;
 
2896
                                }
 
2897
                        }
 
2898
                        else if ( ret ) {
 
2899
                                bytes += ret;
 
2900
                                left -= ret;
 
2901
                        }
 
2902
                /*
 
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.
 
2909
 
 
2910
                Nicolas <ripley@8d.com>
 
2911
                */
 
2912
                        else {
 
2913
                                //usleep(10);
 
2914
                                usleep(1000);
 
2915
                        }
 
2916
                }
 
2917
        }
 
2918
/*
 
2919
        if( count > 19 )
 
2920
        {
 
2921
                throw_java_exception( env, IO_EXCEPTION, "read_byte_array",
 
2922
                        "No data available" );
 
2923
        }
 
2924
*/
 
2925
 
 
2926
        //*(buffer+bytes) = 0;
 
2927
        sprintf(msg, "read_byte_array returns %i\n", bytes);
 
2928
        report( msg );
 
2929
        LEAVE( "read_byte_array" );
 
2930
        report_time_end();
 
2931
        return bytes;
 
2932
}
 
2933
 
 
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
 
2938
   return:      void
 
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(
 
2944
        jint vtime,
 
2945
        jint threshold,
 
2946
        jint buffer
 
2947
)
 
2948
{
 
2949
        int fd = ( int ) this->fd;
 
2950
        struct termios ttyset;
 
2951
        int timeout;
 
2952
        char msg[80];
 
2953
 
 
2954
        if (vtime < 0){
 
2955
                timeout = 0; 
 
2956
        }
 
2957
        else if (vtime == 0){
 
2958
                timeout = 1;
 
2959
        }
 
2960
        else{
 
2961
                timeout = vtime;
 
2962
        }
 
2963
 
 
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;
 
2970
 
 
2971
        LEAVE( "RXTXPort:NativeEnableRecieveTimeoutThreshold" );
 
2972
        return;
 
2973
fail:
 
2974
        LEAVE( "RXTXPort:NativeEnableRecieveTimeoutThreshold" );
 
2975
        snprintf( msg, 79, "%s%s", strerror( errno ), " in TimeoutThreshold" );
 
2976
        throw new java::io::IOException( JvNewStringUTF( msg ) );
 
2977
        return;
 
2978
}
 
2979
 
 
2980
/*----------------------------------------------------------
 
2981
RXTXPort.readByte
 
2982
 
 
2983
   accept:      none
 
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
 
2988
   comments:
 
2989
 
 
2990
On Fri, 30 Aug 2002, Bill Smith wrote:
 
2991
 
 
2992
I agree, the documentation isn't the best. No surprises there. 
 
2993
 
 
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)
 
2998
extends/overrides 
 
2999
the documentation for java.io.InputStream.
 
3000
 
 
3001
This is the same behavior that the Windriver driver for vxworks exhibits.
 
3002
 
 
3003
On Fri, 30 Aug 2002, Bill Smith wrote:
 
3004
 
 
3005
> Hi Trent,
 
3006
 
3007
> I have a couple of questions/comments.
 
3008
 
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
 
3012
>    getInputStream().
 
3013
 
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.
 
3017
 
3018
 
 
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 
 
3022
 
 
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: ... 
 
3026
 
 
3027
But InputStream is where read(byte) is documented
 
3028
http://java.sun.com/j2se/1.3/docs/api/java/io/InputStream.html#read()
 
3029
 
 
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 
 
3035
        thrown
 
3036
 
 
3037
If you are sure commapi is doing a timeout and returning -1, I can change 
 
3038
it back and document the issue.
 
3039
 
 
3040
Because I often grep my own mailbox for details, I'm going to add
 
3041
these two comments also:
 
3042
 
 
3043
        public int read(byte[] b)
 
3044
)
 
3045
http://java.sun.com/j2se/1.3/docs/api/java/io/InputStream.html#read(byte[])
 
3046
 
 
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. 
 
3051
 
 
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. 
 
3057
 
 
3058
So read(byte[] b) is documented as blocking for the first byte.
 
3059
 
 
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[],
 
3062
int, int)
 
3063
 
 
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. 
 
3068
 
 
3069
Which makes sense with the timeout documentation.
 
3070
 
 
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.
 
3073
 
 
3074
 
3075
> Thoughts? Comments?
 
3076
 
3077
> Bill
 
3078
 
3079
> ----------------------
 
3080
 
3081
> public abstract InputStream getInputStream() throws IOException
 
3082
 
3083
 
3084
> Returns an input stream. This is the only way to receive data from the
 
3085
communications
 
3086
> port. If the port is unidirectional and doesn't support receiving data, then 
 
3087
> getInputStream returns null.
 
3088
 
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: 
 
3092
 
3093
 
3094
>    Threshold             Timeout        Read Buffer    Read Behaviour
 
3095
> State     Value       State     Value       Size   
 
3096
>
 
3097
-----------------------------------------------------------------------------------
 
3098
> disabled    -         disabled    -       n bytes      block until any data is available
 
3099
 
3100
> enabled   m bytes     disabled    -       n bytes      block until min(m,n) bytes are available
 
3101
 
3102
> disabled    -         enabled   x ms      n bytes      block for x ms or
 
3103
until any data is available
 
3104
 
3105
> enabled   m bytes     enabled   x ms      n bytes      block for x ms or
 
3106
until min(m,n) bytes are available
 
3107
 
3108
> Returns: InputStream object that can be used to read from the port 
 
3109
 
3110
> Throws: IOException if an I/O error occurred
 
3111
 
 
3112
 
 
3113
----------------------------------------------------------*/
 
3114
jint gnu::io::RXTXPort::readByte(
 
3115
)
 
3116
{
 
3117
        int bytes;
 
3118
        unsigned char buffer[ 1 ];
 
3119
        int fd = ( int ) this->fd;
 
3120
        int timeout = ( int ) this->timeout;
 
3121
        char msg[80];
 
3122
 
 
3123
        ENTER( "RXTXPort:readByte" );
 
3124
        report_time_start( );
 
3125
        bytes = read_byte_array( fd, buffer, 1, timeout );
 
3126
        if( bytes < 0 ) {
 
3127
                LEAVE( "RXTXPort:readByte" );
 
3128
                snprintf( msg, 79, "%s%s", strerror( errno ), " in readByte" );
 
3129
                throw new java::io::IOException( JvNewStringUTF( msg ) );
 
3130
                return -1;
 
3131
        }
 
3132
        LEAVE( "RXTXPort:readByte" );
 
3133
        sprintf( msg, "readByte return(%i)\n", bytes ? buffer[ 0 ] : -1 );
 
3134
        report( msg );
 
3135
        report_time_end( );
 
3136
        return (bytes ? (jint)buffer[ 0 ] : -1);
 
3137
}
 
3138
 
 
3139
/*----------------------------------------------------------
 
3140
RXTXPort.readArray
 
3141
 
 
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
 
3146
                 0 on read timeout
 
3147
   exceptions:   IOException
 
3148
   comments:     throws ArrayIndexOutOfBoundsException if asked to
 
3149
                 read more than SSIZE_MAX bytes
 
3150
----------------------------------------------------------*/
 
3151
jint gnu::io::RXTXPort::readArray(
 
3152
        jbyteArray jbarray,
 
3153
        jint offset,
 
3154
        jint length
 
3155
)
 
3156
{
 
3157
        int bytes;
 
3158
        char msg[80];
 
3159
        int fd = ( int ) this->fd;
 
3160
        int timeout = ( int ) this->timeout;
 
3161
        jbyte *in = elements( jbarray ) + offset;
 
3162
 
 
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 ) );
 
3170
                return -1;
 
3171
        }
 
3172
        bytes = read_byte_array( fd, (unsigned char *) in, length, timeout );/* dima */
 
3173
        if( bytes < 0 ) {
 
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 ) );
 
3178
                return -1;
 
3179
        }
 
3180
        sprintf( msg, "RXTXPort:readArray: %i %i\n", (int) length, bytes);
 
3181
        report( msg );
 
3182
        report_time_end( );
 
3183
 
 
3184
        LEAVE( "RXTXPort:readArray" );
 
3185
        return (bytes);
 
3186
}
 
3187
 
 
3188
/*----------------------------------------------------------
 
3189
RXTXPort.nativeavailable
 
3190
 
 
3191
   accept:      none
 
3192
   perform:     find out the number of bytes available for reading
 
3193
   return:      available bytes
 
3194
                -1 on error
 
3195
   exceptions:  none
 
3196
----------------------------------------------------------*/
 
3197
jint gnu::io::RXTXPort::nativeavailable(
 
3198
)
 
3199
{
 
3200
        int fd = ( int ) this->fd;
 
3201
        int result;
 
3202
        char msg[80];
 
3203
 
 
3204
/*
 
3205
        ENTER( "RXTXPort:nativeavailable" );
 
3206
 
 
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.
 
3210
 
 
3211
    This turns out to be true on Solaris also.  taj.
 
3212
*/
 
3213
#ifdef FIORDCHK  /* __unixware__ __sun__ probably others */
 
3214
        result = ioctl(fd, FIORDCHK, 0);
 
3215
#else
 
3216
        if( ioctl( fd, FIONREAD, &result ) < 0 )
 
3217
        {
 
3218
                goto fail;
 
3219
        }
 
3220
#endif /* FIORDCHK */
 
3221
        sprintf(msg, "    nativeavailable: FIORDCHK result %d, \
 
3222
                errno %d\n", result , result == -1 ? errno : 0);
 
3223
        report_verbose( msg );
 
3224
        if (result == -1) {
 
3225
                goto fail;
 
3226
        }
 
3227
        if( result )
 
3228
        {
 
3229
                sprintf(msg, "    nativeavailable: FIORDCHK result %d, \
 
3230
                                errno %d\n", result , result == -1 ? errno : 0);
 
3231
                report( msg );
 
3232
        }
 
3233
/*
 
3234
        LEAVE( "RXTXPort:nativeavailable" );
 
3235
*/
 
3236
        return (jint)result;
 
3237
fail:
 
3238
        report("RXTXPort:nativeavailable:  ioctl() failed\n");
 
3239
/*
 
3240
        LEAVE( "RXTXPort:nativeavailable" );
 
3241
*/
 
3242
        snprintf( msg, 79, "%s%s", strerror( errno ), " in nativeavailable" );
 
3243
        throw new java::io::IOException( JvNewStringUTF( msg ) );
 
3244
        return (jint)result;
 
3245
}
 
3246
 
 
3247
/*----------------------------------------------------------
 
3248
RXTXPort.setflowcontrol
 
3249
 
 
3250
   accept:      flowmode
 
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
 
3257
   return:      none
 
3258
   exceptions:  UnsupportedCommOperationException
 
3259
   comments:  there is no differentiation between input and output hardware
 
3260
              flow control
 
3261
----------------------------------------------------------*/
 
3262
void gnu::io::RXTXPort::setflowcontrol(
 
3263
        jint flowmode
 
3264
)
 
3265
{
 
3266
        struct termios ttyset;
 
3267
        int fd = ( int ) this->fd;
 
3268
        char msg[80];
 
3269
 
 
3270
        ENTER( "RXTXPort:setflowcontrol" );
 
3271
        if( tcgetattr( fd, &ttyset ) ) goto fail;
 
3272
        
 
3273
        if ( flowmode & ( FLOWCONTROL_RTSCTS_IN | FLOWCONTROL_RTSCTS_OUT ) )
 
3274
        {
 
3275
                ttyset.c_cflag |= HARDWARE_FLOW_CONTROL;
 
3276
        }
 
3277
        else ttyset.c_cflag &= ~HARDWARE_FLOW_CONTROL;
 
3278
 
 
3279
        ttyset.c_iflag &= ~IXANY;
 
3280
 
 
3281
        if ( flowmode & FLOWCONTROL_XONXOFF_IN )
 
3282
        {
 
3283
                ttyset.c_iflag |= IXOFF;
 
3284
        }
 
3285
        else ttyset.c_iflag &= ~IXOFF;
 
3286
 
 
3287
        if ( flowmode & FLOWCONTROL_XONXOFF_OUT )
 
3288
        {
 
3289
                
 
3290
                ttyset.c_iflag |= IXON;
 
3291
        }
 
3292
        else ttyset.c_iflag &= ~IXON;
 
3293
/* TRENT */
 
3294
        if( tcsetattr( fd, TCSANOW, &ttyset ) ) goto fail;
 
3295
        LEAVE( "RXTXPort:setflowcontrol" );
 
3296
        return;
 
3297
fail:
 
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 ) );
 
3301
        return;
 
3302
}
 
3303
 
 
3304
/*----------------------------------------------------------
 
3305
unlock_monitor_thread
 
3306
 
 
3307
   accept:      event_info_struct
 
3308
   perform:     unlock the monitor thread so event notification can start.
 
3309
   return:      none
 
3310
   exceptions:  none
 
3311
   comments:    Events can be missed otherwise.
 
3312
----------------------------------------------------------*/
 
3313
 
 
3314
void unlock_monitor_thread(  gnu::io::RXTXPort *p, struct event_info_struct *eis )
 
3315
{
 
3316
        p->MonitorThreadLock = false;
 
3317
}
 
3318
 
 
3319
/*----------------------------------------------------------
 
3320
check_line_status_register
 
3321
 
 
3322
   accept:      event_info_struct
 
3323
   perform:     check for changes on the LSR
 
3324
   return:      0 on success
 
3325
   exceptions:  none
 
3326
   comments:    not supported on all devices/drivers.
 
3327
----------------------------------------------------------*/
 
3328
int check_line_status_register( gnu::io::RXTXPort *p, struct event_info_struct *eis )
 
3329
{
 
3330
#ifdef TIOCSERGETLSR
 
3331
        struct stat fstatbuf;
 
3332
 
 
3333
        if( ! eis->eventflags[SPE_OUTPUT_BUFFER_EMPTY] )
 
3334
        {
 
3335
                report( "check_line_status_registe OUPUT_BUFFER_EMPTY not set\n" );
 
3336
                return 0;
 
3337
        }
 
3338
        if ( fstat( eis->fd, &fstatbuf ) )
 
3339
        {
 
3340
                report( "check_line_status_register: fstat\n" );
 
3341
                return( 1 );
 
3342
        }
 
3343
        if( ioctl( eis->fd, TIOCSERGETLSR, &eis->change ) )
 
3344
        {
 
3345
                report( "check_line_status_register: TIOCSERGETLSR\n is nonnull\n" );
 
3346
                return( 1 );
 
3347
        }
 
3348
        else if( eis && eis->change )
 
3349
        {
 
3350
                report_verbose( "check_line_status_register: sending OUTPUT_BUFFER_EMPTY\n" );
 
3351
                send_event( p, eis, SPE_OUTPUT_BUFFER_EMPTY, 1 );
 
3352
        }
 
3353
#else
 
3354
/*
 
3355
        printf("test %i\n",  eis->output_buffer_empty_flag );
 
3356
*/
 
3357
        if( eis && eis->output_buffer_empty_flag == 1 && 
 
3358
                eis->eventflags[SPE_OUTPUT_BUFFER_EMPTY] )
 
3359
        {
 
3360
                report_verbose("check_line_status_register: sending SPE_OUTPUT_BUFFER_EMPTY\n");
 
3361
                send_event( p, eis, SPE_OUTPUT_BUFFER_EMPTY, 1 );
 
3362
/*
 
3363
                send_event( this, eis, SPE_DATA_AVAILABLE, 1 );
 
3364
*/
 
3365
                eis->output_buffer_empty_flag = 0;
 
3366
        }
 
3367
#endif /* TIOCSERGETLSR */
 
3368
        return( 0 );
 
3369
}
 
3370
 
 
3371
/*----------------------------------------------------------
 
3372
has_line_status_register_access
 
3373
 
 
3374
   accept:      fd of interest
 
3375
   perform:     check for access to the LSR
 
3376
   return:      0 if not available
 
3377
   exceptions:  none
 
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 )
 
3383
{
 
3384
#if defined(TIOCSERGETLSR)
 
3385
        int change;
 
3386
 
 
3387
        if( !ioctl( fd, TIOCSERGETLSR, &change ) ) {
 
3388
                return(1);
 
3389
        }
 
3390
#endif /* TIOCSERGETLSR */
 
3391
        report( "has_line_status_register_acess: Port does not support TIOCSERGETLSR\n" );
 
3392
        return( 0 );
 
3393
}
 
3394
 
 
3395
/*----------------------------------------------------------
 
3396
check_cgi_count
 
3397
 
 
3398
   accept:      fd of interest
 
3399
   perform:     check for access to TIOCGICOUNT
 
3400
   return:      0 if not available
 
3401
   exceptions:  none
 
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 )
 
3411
{
 
3412
#if defined(TIOCGICOUNT)
 
3413
 
 
3414
        /* JK00: only use it if supported by this port */
 
3415
 
 
3416
        struct serial_icounter_struct sis;
 
3417
        memcpy( &sis, &eis->osis, sizeof( struct serial_icounter_struct ) );
 
3418
 
 
3419
        if( ioctl( eis->fd, TIOCGICOUNT, &sis ) )
 
3420
        {
 
3421
                report( "check_cgi_count: TIOCGICOUNT\n is not 0\n" );
 
3422
                return;
 
3423
        }
 
3424
        while( eis && sis.frame != eis->osis.frame ) {
 
3425
                send_event( p, eis, SPE_FE, 1);
 
3426
                eis->osis.frame++;
 
3427
        }
 
3428
        while( eis && sis.overrun != eis->osis.overrun ) {
 
3429
                send_event( p, eis, SPE_OE, 1);
 
3430
                eis->osis.overrun++;
 
3431
        }
 
3432
        while( eis && sis.parity != eis->osis.parity ) {
 
3433
                send_event( p, eis, SPE_PE, 1);
 
3434
                eis->osis.parity++;
 
3435
        }
 
3436
        while( eis && sis.brk != eis->osis.brk ) {
 
3437
                send_event( p, eis, SPE_BI, 1);
 
3438
                eis->osis.brk++;
 
3439
        }
 
3440
        if( eis )
 
3441
                memcpy( &eis->osis, &sis, sizeof( struct serial_icounter_struct ) );
 
3442
#endif /*  TIOCGICOUNT */
 
3443
}
 
3444
 
 
3445
/*----------------------------------------------------------
 
3446
port_has_changed_fionread
 
3447
 
 
3448
   accept:      fd of interest
 
3449
   perform:     check if FIONREAD has changed
 
3450
   return:      0 if no data available
 
3451
   exceptions:  none
 
3452
   comments:    
 
3453
----------------------------------------------------------*/
 
3454
int port_has_changed_fionread( struct event_info_struct *eis )
 
3455
{
 
3456
        int change, rc;
 
3457
        char message[80];
 
3458
 
 
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__)
 
3462
        /*
 
3463
           On SCO OpenServer FIONREAD always fails for serial devices,
 
3464
           so rely upon select() result to know whether data available.
 
3465
 
 
3466
           This is true for Solaris, also.  taj.
 
3467
        */
 
3468
        if( (rc != -1 && change) || (rc == -1 && eis->ret > 0) ) 
 
3469
                return( 1 );
 
3470
#else
 
3471
        sprintf( message, "port_has_changed_fionread: change is %i\n", change );
 
3472
        report_verbose( message );
 
3473
        if( change )
 
3474
                return( 1 );
 
3475
#endif /* __unixware__  || __sun__ */
 
3476
        return( 0 );
 
3477
}
 
3478
                
 
3479
/*----------------------------------------------------------
 
3480
check_tiocmget_changes
 
3481
 
 
3482
   accept:      event_info_struct
 
3483
   perform:     use TIOCMGET to report events
 
3484
   return:      none
 
3485
   exceptions:  none
 
3486
   comments:    not supported on all devices/drivers.
 
3487
----------------------------------------------------------*/
 
3488
void check_tiocmget_changes( gnu::io::RXTXPort *p, struct event_info_struct * eis )
 
3489
{
 
3490
        unsigned int mflags = 0;
 
3491
        int change;
 
3492
 
 
3493
        /* DORITO */
 
3494
        if( !eis ) return;
 
3495
        change  = eis->change;
 
3496
 
 
3497
        report_verbose("entering check_tiocmget_changes\n");
 
3498
        if( ioctl( eis->fd, TIOCMGET, &mflags ) )
 
3499
        {
 
3500
                report( "=======================================\n");
 
3501
                report( "check_tiocmget_changes: ioctl(TIOCMGET)\n" );
 
3502
                return;
 
3503
        }
 
3504
 
 
3505
        change = (mflags&TIOCM_CTS) - (eis->omflags&TIOCM_CTS);
 
3506
        if( eis && change ) send_event( p, eis, SPE_CTS, change );
 
3507
 
 
3508
        change = (mflags&TIOCM_DSR) - (eis->omflags&TIOCM_DSR);
 
3509
        if( eis && change )
 
3510
        {
 
3511
                report( "sending DSR ===========================\n");
 
3512
                send_event( p, eis, SPE_DSR, change );
 
3513
        }
 
3514
 
 
3515
        change = (mflags&TIOCM_RNG) - (eis->omflags&TIOCM_RNG);
 
3516
        if( eis && change ) send_event( p, eis, SPE_RI, change );
 
3517
 
 
3518
        change = (mflags&TIOCM_CD) - (eis->omflags&TIOCM_CD);
 
3519
        if( eis && change ) send_event( p, eis, SPE_CD, change );
 
3520
 
 
3521
        if( eis )
 
3522
                eis->omflags = mflags;
 
3523
        report_verbose("leaving check_tiocmget_changes\n");
 
3524
}
 
3525
 
 
3526
/*----------------------------------------------------------
 
3527
system_wait
 
3528
 
 
3529
   accept:      
 
3530
   perform:     
 
3531
   return:      
 
3532
   exceptions:  none
 
3533
   comments:    
 
3534
----------------------------------------------------------*/
 
3535
void system_wait()
 
3536
{
 
3537
#if defined (__sun__ )
 
3538
        struct timespec retspec, tspec;
 
3539
        retspec.tv_sec = 0;
 
3540
        retspec.tv_nsec = 100000000;
 
3541
        do {
 
3542
                tspec = retspec;
 
3543
                nanosleep( &tspec, &retspec );
 
3544
        } while( tspec.tv_nsec != 0 );
 
3545
/* Trent
 
3546
*/
 
3547
#else
 
3548
#ifdef TRENT_IS_HERE_DEBUGGING_THREADS
 
3549
        /* On NT4 The following was observed in a intense test:
 
3550
                50000   95%   179 sec
 
3551
                200000  95%   193 sec
 
3552
                1000000 95%   203 sec   some callback failures sometimes.
 
3553
                2000000 0-95%           callback failures.
 
3554
        */
 
3555
#endif /* TRENT_IS_HERE_DEBUGGING_THREADS */
 
3556
#endif /* __sun__ */
 
3557
}
 
3558
 
 
3559
/*----------------------------------------------------------
 
3560
driver_has_tiocgicount
 
3561
 
 
3562
   accept:      fd of interest
 
3563
   perform:     check for access to TIOCGICOUNT
 
3564
   return:      0 if not available
 
3565
   exceptions:  none
 
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 )
 
3571
{
 
3572
#if defined(TIOCGICOUNT)
 
3573
 
 
3574
        /* Some multiport serial cards do not implement TIOCGICOUNT ... */
 
3575
        /* So use the 'dumb' mode to enable using them after all! JK00 */
 
3576
 
 
3577
        if( ioctl( eis->fd, TIOCGICOUNT, &eis->osis ) < 0 ) {
 
3578
                report_verbose( " driver_has_tiocgicount:  Port does not support TIOCGICOUNT events\n" );
 
3579
                return(0);
 
3580
        }
 
3581
        else
 
3582
                return(1);
 
3583
#endif /*  TIOCGICOUNT */
 
3584
        return(0);
 
3585
        
 
3586
}
 
3587
 
 
3588
/*----------------------------------------------------------
 
3589
report_serial_events
 
3590
 
 
3591
   accept:      event_info_struct
 
3592
   perform:     send events if they occured
 
3593
   return:      0 if not available
 
3594
   exceptions:  none
 
3595
   comments:    not supported on all devices/drivers.
 
3596
----------------------------------------------------------*/
 
3597
void report_serial_events( gnu::io::RXTXPort *p, struct event_info_struct *eis )
 
3598
{
 
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 ) )
 
3602
                        return;
 
3603
 
 
3604
#ifndef WIN32 /* something is wrong here */
 
3605
        if ( eis && eis->has_tiocgicount )
 
3606
                check_cgi_count( p, eis );
 
3607
#endif /* WIN32 */
 
3608
 
 
3609
        check_tiocmget_changes( p, eis );
 
3610
 
 
3611
        if( eis && port_has_changed_fionread( eis ) )
 
3612
        {
 
3613
                if(!eis->eventflags[SPE_DATA_AVAILABLE] )
 
3614
                {
 
3615
                        report_verbose("report_serial_events: ignoring DATA_AVAILABLE\n");
 
3616
/*
 
3617
                        report(".");
 
3618
*/
 
3619
#if !defined(__sun__)
 
3620
        /* FIXME: No time to test on all OS's for production */
 
3621
                        usleep(20000);
 
3622
#endif /* !__sun__ */
 
3623
                        return;
 
3624
                }
 
3625
                report("report_serial_events: sending DATA_AVAILABLE\n");
 
3626
                if(!send_event( p, eis, SPE_DATA_AVAILABLE, 1 ))
 
3627
                {
 
3628
                        /* select wont block */
 
3629
#if !defined(__sun__)
 
3630
        /* FIXME: No time to test on all OS's for production */
 
3631
                        usleep(20000);
 
3632
#endif /* !__sun__ */
 
3633
/*
 
3634
                        system_wait();
 
3635
*/
 
3636
                }
 
3637
        }
 
3638
}
 
3639
 
 
3640
/*----------------------------------------------------------
 
3641
initialise_event_info_struct
 
3642
 
 
3643
   accept:      event_info_struct for this thread.
 
3644
   perform:     initialise or reset the event_info_struct
 
3645
   return:      1 on success
 
3646
   exceptions:  none
 
3647
   comments:    
 
3648
----------------------------------------------------------*/
 
3649
int initialise_event_info_struct(  gnu::io::RXTXPort *p, struct event_info_struct *eis )
 
3650
{
 
3651
        int i;
 
3652
        struct event_info_struct *index = master_index;
 
3653
 
 
3654
        if ( eis->initialised == 1 )
 
3655
                goto end;
 
3656
 
 
3657
#ifdef TIOCGICOUNT
 
3658
        memset(&eis->osis,0,sizeof(eis->osis));
 
3659
#endif /* TIOCGICOUNT */
 
3660
 
 
3661
        if( index )
 
3662
        {
 
3663
                while( index->next )
 
3664
                {
 
3665
                        index = index->next;
 
3666
                }
 
3667
                index->next = eis;
 
3668
                eis->prev = index;
 
3669
                eis->next = NULL;
 
3670
        }
 
3671
        else
 
3672
        {
 
3673
                master_index = eis;
 
3674
                master_index->next = NULL;
 
3675
                master_index->prev = NULL;
 
3676
        }
 
3677
 
 
3678
        for( i = 0; i < 11; i++ ) eis->eventflags[i] = 0;
 
3679
#if !defined(TIOCSERGETLSR) && !defined(WIN32)
 
3680
        eis->output_buffer_empty_flag = 0;
 
3681
        eis->writing = 0;
 
3682
#endif /* TIOCSERGETLSR */
 
3683
        eis->eventloop_interrupted = 0;
 
3684
        eis->closing = 0;
 
3685
 
 
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 );
 
3689
 
 
3690
        if( ioctl( eis->fd, TIOCMGET, &eis->omflags) < 0 ) {
 
3691
                report( "initialise_event_info_struct: Port does not support events\n" );
 
3692
        }
 
3693
 
 
3694
end:
 
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;
 
3700
        return( 1 );
 
3701
}
 
3702
 
 
3703
/*----------------------------------------------------------
 
3704
finalize_event_info_struct
 
3705
 
 
3706
   accept:      event_info_struct for this thread.
 
3707
   perform:     free resources
 
3708
   return:      none
 
3709
   exceptions:  none
 
3710
   comments:    
 
3711
----------------------------------------------------------*/
 
3712
void finalize_event_info_struct( struct event_info_struct *eis )
 
3713
{
 
3714
        if( eis->next && eis->prev ) 
 
3715
        {
 
3716
                eis->prev->next = eis->next;
 
3717
                eis->next->prev = eis->prev;
 
3718
        }
 
3719
        else if( eis->next )
 
3720
        {
 
3721
                eis->next->prev = NULL;
 
3722
                master_index = eis->next;
 
3723
        }
 
3724
        else if( eis->prev )
 
3725
                eis->prev->next = NULL;
 
3726
        else master_index = NULL;
 
3727
}
 
3728
 
 
3729
/*----------------------------------------------------------
 
3730
RXTXPort.eventLoop
 
3731
 
 
3732
   accept:      none
 
3733
   perform:     periodically check for SerialPortEvents
 
3734
   return:      none
 
3735
   exceptions:  none
 
3736
   comments:    please keep this function clean.
 
3737
----------------------------------------------------------*/
 
3738
void gnu::io::RXTXPort::eventLoop(
 
3739
)
 
3740
{
 
3741
        struct event_info_struct eis;
 
3742
        eis.initialised = 0;
 
3743
 
 
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 );
 
3748
        do{
 
3749
                report_time_eventLoop( );
 
3750
                do {
 
3751
                        /* report( "." ); */
 
3752
                        eis.ret = SELECT( eis.fd + 1, &eis.rfds, NULL, NULL,
 
3753
                                        &eis.tv_sleep );
 
3754
                        /* nothing goes between this call and select */
 
3755
                        if( eis.closing )
 
3756
                        {
 
3757
                                report("eventLoop: got interrupt\n");
 
3758
                                finalize_threads( &eis );
 
3759
                                finalize_event_info_struct( &eis );
 
3760
                                this->MonitorThreadCloseLock = false;
 
3761
                                LEAVE("eventLoop");
 
3762
                                return;
 
3763
                        }
 
3764
                        usleep(20000);
 
3765
/*
 
3766
                         Trent system_wait();
 
3767
*/
 
3768
                }  while ( eis.ret < 0 && errno == EINTR );
 
3769
                if( eis.ret >= 0 )
 
3770
                {
 
3771
                        report_serial_events( this, &eis );
 
3772
                }
 
3773
                initialise_event_info_struct( this, &eis );
 
3774
        } while( 1 );
 
3775
end:
 
3776
        LEAVE( "eventLoop:  Bailing!\n" );
 
3777
}
 
3778
 
 
3779
/*----------------------------------------------------------
 
3780
RXTXCommDriver.nativeGetVersion
 
3781
 
 
3782
   accept:      none
 
3783
   perform:     return the current version 
 
3784
   return:      version
 
3785
   exceptions:  none
 
3786
   comments:    This is used to avoid mixing versions of the .jar and
 
3787
                native library.
 
3788
                First introduced in rxtx-1.5-9
 
3789
                
 
3790
----------------------------------------------------------*/
 
3791
jstring gnu::io::RXTXCommDriver::nativeGetVersion (
 
3792
)
 
3793
{
 
3794
        return JvNewStringUTF( "RXTX-2.1-7" );
 
3795
}
 
3796
 
 
3797
/*----------------------------------------------------------
 
3798
RXTXCommDriver.testRead
 
3799
 
 
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
 
3803
   exceptions:  none
 
3804
   comments:    From Wayne Roberts wroberts1@home.com
 
3805
                check tcget/setattr returns.
 
3806
                support for non serial ports Trent
 
3807
----------------------------------------------------------*/
 
3808
 
 
3809
jboolean  gnu::io::RXTXCommDriver::testRead(
 
3810
        jstring jstr,
 
3811
        jint port_type
 
3812
)
 
3813
{
 
3814
        struct termios ttyset;
 
3815
        char c;
 
3816
        int i, fd, ret = true, pid = -1;
 
3817
        //char filename[80];
 
3818
        char filename[80];
 
3819
#ifdef TRENT_IS_HERE_DEBUGGING_ENUMERATION
 
3820
        char message[80];
 
3821
#endif /* TRENT_IS_HERE_DEBUGGING_ENUMERATION */
 
3822
 
 
3823
        for( i=0;i<jstr->length();i++)
 
3824
                filename[i] = jstr->charAt(i);
 
3825
        filename[i] = '\0';
 
3826
        //java::lang::System::out->println( filename );
 
3827
        //const char *filename = (const char *) jstr->toCharArray();
 
3828
 
 
3829
        /* We opened the file in this thread, use this pid to unlock */
 
3830
        //java::lang::System::out->println( jstr );
 
3831
#ifndef WIN32
 
3832
        pid = getpid();
 
3833
#else
 
3834
        char full_windows_name[80];
 
3835
#endif /* WIN32 */
 
3836
 
 
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") )
 
3843
        {
 
3844
                printf("%s is good\n",filename);
 
3845
                sprintf( message, "testRead: %s is good!\n", filename );
 
3846
                report( message );
 
3847
                return( true );
 
3848
        }
 
3849
        return( false );
 
3850
#endif /* TRENT_IS_HERE_DEBUGGING_ENUMERATION */
 
3851
#ifdef WIN32
 
3852
        strcpy( full_windows_name, DEVICEDIR );
 
3853
        strcat( full_windows_name, filename );
 
3854
        ret = serial_test((char *) full_windows_name );
 
3855
        return(ret);
 
3856
#endif /* WIN32 */
 
3857
 
 
3858
        /* 
 
3859
                LOCK is one of three functions defined in SerialImp.h
 
3860
 
 
3861
                        uucp_lock               Solaris
 
3862
                        fhs_lock                Linux
 
3863
                        system_does_not_lock    Win32
 
3864
        */
 
3865
        //printf( "RXTXCommDriver::testRead( %s )\n", filename );
 
3866
 
 
3867
        if ( LOCK( filename, pid ) )
 
3868
        {
 
3869
                LEAVE( "RXTXPort:testRead no lock" );
 
3870
                return false;
 
3871
        }
 
3872
 
 
3873
        /*
 
3874
           CLOCAL eliminates open blocking on modem status lines
 
3875
           -- changed to O_NONBLOCK
 
3876
        */
 
3877
        do {
 
3878
                fd=::OPEN ( filename, O_RDWR | O_NOCTTY | O_NONBLOCK );
 
3879
        }  while ( fd < 0 && errno==EINTR );
 
3880
 
 
3881
        if( fd < 0 )
 
3882
        {
 
3883
                report_verbose( "testRead() open failed\n" );
 
3884
                ret = false;
 
3885
                goto END;
 
3886
        }
 
3887
 
 
3888
        if ( port_type == PORT_SERIAL )
 
3889
        {
 
3890
                int saved_flags;
 
3891
                struct termios saved_termios;
 
3892
 
 
3893
                if (tcgetattr(fd, &ttyset) < 0) {
 
3894
                        ret = false;
 
3895
                        goto END;
 
3896
                }
 
3897
 
 
3898
                /* save, restore later */
 
3899
                if ( ( saved_flags = fcntl(fd, F_GETFL ) ) < 0 )
 
3900
                {
 
3901
                        report( "testRead() fcntl(F_GETFL) failed\n" );
 
3902
                        ret = false;
 
3903
                        goto END;
 
3904
                }
 
3905
 
 
3906
                memcpy( &saved_termios, &ttyset, sizeof( struct termios ) );
 
3907
 
 
3908
                if ( fcntl( fd, F_SETFL, O_NONBLOCK ) < 0 )
 
3909
                {
 
3910
                        report( "testRead() fcntl(F_SETFL) failed\n" );
 
3911
                        ret = false;
 
3912
                        goto END;
 
3913
                }
 
3914
 
 
3915
                cfmakeraw(&ttyset);
 
3916
                ttyset.c_cc[VMIN] = ttyset.c_cc[VTIME] = 0;
 
3917
 
 
3918
                if ( tcsetattr( fd, TCSANOW, &ttyset) < 0 )
 
3919
                {
 
3920
                        report( "testRead() tcsetattr failed\n" );
 
3921
                        ret = false;
 
3922
                        tcsetattr( fd, TCSANOW, &saved_termios );
 
3923
                        goto END;
 
3924
                }
 
3925
 
 
3926
/*
 
3927
 
 
3928
              The following may mess up if both EAGAIN and EWOULDBLOCK
 
3929
              are defined but only EWOULDBLOCK is used
 
3930
 
 
3931
              Linux:
 
3932
 
 
3933
              man 2 open
 
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
 
3941
              than FIFOs.
 
3942
 
 
3943
              man 2 read
 
3944
              EAGAIN
 
3945
              Non-blocking I/O has been selected using O_NONBLOCK
 
3946
              and no data was immediately available for  reading.
 
3947
 
 
3948
 
 
3949
              /usr/include/asm/error.h:
 
3950
              #define EAGAIN          11      / Try again /
 
3951
              #define EWOULDBLOCK     EAGAIN  / Operation would block /
 
3952
 
 
3953
              looks like the kernel is using EAGAIN
 
3954
 
 
3955
              -- should be OK
 
3956
 
 
3957
              Solaris:
 
3958
 
 
3959
              man 2 open
 
3960
              EAGAIN    The path  argument  names  the  slave  side  of  a
 
3961
              pseudo-terminal device that is locked.
 
3962
 
 
3963
              man 2 read
 
3964
              If O_NONBLOCK is set, read() returns -1 and sets errno
 
3965
              to EAGAIN.
 
3966
 
 
3967
              -- should be OK.
 
3968
 
 
3969
              HP-UX
 
3970
 
 
3971
              both are defined but EAGAIN is used.
 
3972
 
 
3973
              -- should be OK.
 
3974
 
 
3975
              Win32
 
3976
 
 
3977
              neither errno is currently set.  Comment added to termios.c
 
3978
              serial_open().
 
3979
 
 
3980
              -- should be OK
 
3981
 
 
3982
Steven's book.  Advanced programming in the Unix Environment pg 364
 
3983
 
 
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."
 
3989
 
 
3990
*/
 
3991
 
 
3992
                if ( READ( fd, &c, 1 ) < 0 )
 
3993
                {
 
3994
#ifdef EAGAIN
 
3995
                        if ( errno != EAGAIN ) {
 
3996
                                report( "testRead() read failed\n" );
 
3997
                                ret = false;
 
3998
                        }
 
3999
#else                      
 
4000
#ifdef EWOULDBLOCK
 
4001
                        if ( errno != EWOULDBLOCK )
 
4002
                        {
 
4003
                                report( "testRead() read failed\n" );
 
4004
                                ret = false;
 
4005
                        }
 
4006
#else
 
4007
                        ret = false;
 
4008
#endif /* EWOULDBLOCK */
 
4009
#endif /* EAGAIN */
 
4010
                }
 
4011
 
 
4012
                /* dont walk over unlocked open devices */
 
4013
                tcsetattr( fd, TCSANOW, &saved_termios );
 
4014
                fcntl( fd, F_SETFL, saved_flags );
 
4015
        }
 
4016
 
 
4017
        /* 
 
4018
                UNLOCK is one of three functions defined in SerialImp.h
 
4019
 
 
4020
                        uucp_unlock             Solaris
 
4021
                        fhs_unlock              Linux
 
4022
                        system_does_not_unlock  Win32
 
4023
        */
 
4024
 
 
4025
END:
 
4026
        UNLOCK(filename, pid );
 
4027
        ::CLOSE( fd );
 
4028
        LEAVE( "RXTXPort:testRead" );
 
4029
        return ret;
 
4030
}
 
4031
 
 
4032
#if defined(__APPLE__)
 
4033
/*----------------------------------------------------------
 
4034
 createSerialIterator()
 
4035
   accept:      
 
4036
   perform:     
 
4037
   return:      
 
4038
   exceptions:  
 
4039
   comments:
 
4040
                Code courtesy of Eric Welch at Keyspan, except for the bugs
 
4041
                which are courtesy of Joseph Goldstone (joseph@lp.com)
 
4042
----------------------------------------------------------*/
 
4043
 
 
4044
kern_return_t
 
4045
createSerialIterator(io_iterator_t *serialIterator)
 
4046
{
 
4047
    kern_return_t    kernResult;
 
4048
    mach_port_t        masterPort;
 
4049
    CFMutableDictionaryRef    classesToMatch;
 
4050
    if ((kernResult=IOMasterPort(NULL, &masterPort)) != KERN_SUCCESS)
 
4051
    {
 
4052
        printf( "IOMasterPort returned %d\n", kernResult);
 
4053
        return kernResult;
 
4054
    }
 
4055
    if ((classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue)) == NULL)
 
4056
    {
 
4057
        printf( "IOServiceMatching returned NULL\n" );
 
4058
        return kernResult;
 
4059
    }
 
4060
    CFDictionarySetValue(classesToMatch, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
 
4061
    kernResult = IOServiceGetMatchingServices(masterPort, classesToMatch, serialIterator);
 
4062
    if (kernResult != KERN_SUCCESS)
 
4063
    {
 
4064
        printf( "IOServiceGetMatchingServices returned %d\n", kernResult);
 
4065
    }
 
4066
    return kernResult;
 
4067
}
 
4068
 
 
4069
/*----------------------------------------------------------
 
4070
 getRegistryString()
 
4071
 
 
4072
   accept:      
 
4073
   perform:     
 
4074
   return:      
 
4075
   exceptions:  
 
4076
   comments:
 
4077
                Code courtesy of Eric Welch at Keyspan, except for the bugs
 
4078
                which are courtesy of Joseph Goldstone (joseph@lp.com)
 
4079
----------------------------------------------------------*/
 
4080
char *
 
4081
getRegistryString(io_object_t sObj, char *propName)
 
4082
{
 
4083
    static char resultStr[256];
 
4084
    CFTypeRef   nameCFstring;
 
4085
    resultStr[0] = 0;
 
4086
    nameCFstring = IORegistryEntryCreateCFProperty(sObj,
 
4087
            CFStringCreateWithCString(kCFAllocatorDefault, propName, kCFStringEncodingASCII),
 
4088
                                                   kCFAllocatorDefault, 0);
 
4089
    if (nameCFstring)
 
4090
    {
 
4091
        CFStringGetCString(nameCFstring, resultStr, sizeof(resultStr), kCFStringEncodingASCII);
 
4092
        CFRelease(nameCFstring);
 
4093
    }
 
4094
    return resultStr;
 
4095
}
 
4096
 
 
4097
/*----------------------------------------------------------
 
4098
 registerKnownSerialPorts()
 
4099
   accept:      
 
4100
   perform:     
 
4101
   return:      
 
4102
   exceptions:  
 
4103
   comments:
 
4104
----------------------------------------------------------*/
 
4105
int
 
4106
registerKnownSerialPorts(
 
4107
        jint portType
 
4108
) /* dima */
 
4109
{
 
4110
    io_iterator_t    theSerialIterator;
 
4111
    io_object_t      theObject;
 
4112
    int              numPorts = 0;/* dima it should initiated */
 
4113
    if (createSerialIterator(&theSerialIterator) != KERN_SUCCESS)
 
4114
    {
 
4115
        printf( "createSerialIterator failed\n" );
 
4116
    } else {
 
4117
            while (theObject = IOIteratorNext(theSerialIterator))
 
4118
            {
 
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 */
 
4123
                numPorts++;
 
4124
 
 
4125
                tempJstring = JvNewStringUTF(getRegistryString(theObject, kIOCalloutDeviceKey));
 
4126
                gnu::io::ComPortIdentifier->addPortName(tempJstring,portType,this);/* dima */
 
4127
                numPorts++;
 
4128
/* end dima  taj got this close for gcj */
 
4129
            }
 
4130
        }
 
4131
    }
 
4132
    return numPorts;
 
4133
}
 
4134
#endif /* __APPLE__ */
 
4135
 
 
4136
 
 
4137
/*----------------------------------------------------------
 
4138
 registerKnownPorts
 
4139
 
 
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
 
4143
   exceptions:  none
 
4144
   comments:
 
4145
----------------------------------------------------------*/
 
4146
jboolean gnu::io::RXTXCommDriver::registerKnownPorts(
 
4147
        jint portType
 
4148
)
 
4149
{
 
4150
        enum {PORT_TYPE_SERIAL = 1,
 
4151
                PORT_TYPE_PARALLEL,
 
4152
                PORT_TYPE_I2C,
 
4153
                PORT_TYPE_RS485,
 
4154
                PORT_TYPE_RAW};
 
4155
        jboolean result = false;
 
4156
        char message[80];
 
4157
 
 
4158
        switch(portType) {
 
4159
                case PORT_TYPE_SERIAL:
 
4160
#if defined(__APPLE__)
 
4161
                        if (registerKnownSerialPorts( PORT_TYPE_SERIAL) > 0)
 
4162
                        {/* dima */
 
4163
                                result = true;
 
4164
                        }
 
4165
#endif
 
4166
                         break;
 
4167
                case PORT_TYPE_PARALLEL: break;
 
4168
                case PORT_TYPE_I2C:      break;
 
4169
                case PORT_TYPE_RS485:    break;
 
4170
                case PORT_TYPE_RAW:      break;
 
4171
                default:
 
4172
                        sprintf( message, "unknown portType %d handed to \
 
4173
                                native RXTXCommDriver.registerKnownPorts() \
 
4174
                                 method.\n",
 
4175
                                (int) portType
 
4176
                        );
 
4177
                        report( message );
 
4178
        }
 
4179
        return result;
 
4180
}
 
4181
    
 
4182
/*----------------------------------------------------------
 
4183
 isPortPrefixValid
 
4184
 
 
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
 
4188
   exceptions:  none
 
4189
   comments:
 
4190
----------------------------------------------------------*/
 
4191
jboolean  gnu::io::RXTXCommDriver::isPortPrefixValid(
 
4192
        jstring jstr
 
4193
)
 
4194
{
 
4195
        jboolean result;
 
4196
        static struct stat mystat;
 
4197
        char teststring[256];
 
4198
        int fd,i;
 
4199
        char filename[80];
 
4200
 
 
4201
        for( i=0;i<jstr->length();i++)
 
4202
                filename[i] = jstr->charAt(i);
 
4203
        filename[i] = '\0';
 
4204
 
 
4205
        ENTER( "RXTXCommDriver:isPortPrefixValid" );
 
4206
        for(i=0;i<64;i++){
 
4207
#if defined(__sun__)
 
4208
                /* Solaris uses /dev/cua/a instead of /dev/cua0 */
 
4209
                if( i > 25 ) break;
 
4210
                sprintf(teststring,"%s%s%c",DEVICEDIR, name, i + 97 );
 
4211
                fprintf(stderr, "testing: %s\n", teststring);
 
4212
#else 
 
4213
#if defined(_GNU_SOURCE)
 
4214
                snprintf(teststring, 256, "%s%s%i",DEVICEDIR,filename, i);
 
4215
#else
 
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 */
 
4221
#ifndef __FreeBSD__
 
4222
                if(S_ISCHR(mystat.st_mode)){
 
4223
                        fd=::OPEN(teststring,O_RDONLY|O_NONBLOCK);
 
4224
                        if (fd>0){
 
4225
                                ::CLOSE(fd);
 
4226
                                result=true;
 
4227
                                break;
 
4228
                        }
 
4229
                        else
 
4230
                                result=false;
 
4231
                }
 
4232
                else
 
4233
                        result=false;
 
4234
#else
 
4235
                result=true;
 
4236
#endif  /* __FreeBSD __ */
 
4237
        }
 
4238
#if defined(_GNU_SOURCE)
 
4239
        snprintf(teststring, 256, "%s%s",DEVICEDIR,filename);
 
4240
#else
 
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);
 
4246
                if (fd>0){
 
4247
                        ::CLOSE(fd);
 
4248
                        result=true;
 
4249
                }
 
4250
        }
 
4251
        LEAVE( "RXTXCommDriver:isPortPrefixValid" );
 
4252
        return(result);
 
4253
}
 
4254
 
 
4255
/*----------------------------------------------------------
 
4256
 getDeviceDirectory
 
4257
 
 
4258
   accept:      
 
4259
   perform:     
 
4260
   return:      the directory containing the device files
 
4261
   exceptions:  
 
4262
   comments:    use this to avoid hard coded "/dev/"
 
4263
                values are in SerialImp.h
 
4264
----------------------------------------------------------*/
 
4265
 
 
4266
jstring gnu::io::RXTXCommDriver::getDeviceDirectory(
 
4267
)
 
4268
{
 
4269
        ENTER( "RXTXCommDriver:getDeviceDirectory" );
 
4270
        return JvNewStringUTF(DEVICEDIR);
 
4271
        LEAVE( "RXTXCommDriver:getDeviceDirectory" );
 
4272
}
 
4273
 
 
4274
#ifdef GOING_TO_MESS_WITH_BUFFERS
 
4275
/*----------------------------------------------------------
 
4276
 setInputBufferSize
 
4277
 
 
4278
   accept:      
 
4279
   perform:     
 
4280
   return:      none
 
4281
   exceptions:  none
 
4282
   comments:    see fopen/fclose/fwrite/fread man pages.
 
4283
----------------------------------------------------------*/
 
4284
void gnu::io::RXTXPort::setInputBufferSize(
 
4285
        jint size
 
4286
)
 
4287
{
 
4288
        report( "setInputBufferSize is not implemented\n" );
 
4289
}
 
4290
 
 
4291
/*----------------------------------------------------------
 
4292
 getIputBufferSize
 
4293
 
 
4294
   accept:      
 
4295
   perform:     
 
4296
   return:      none
 
4297
   exceptions:  none
 
4298
   comments:    see fopen/fclose/fwrite/fread man pages.
 
4299
----------------------------------------------------------*/
 
4300
jint gnu::io::RXTXPort::getInputBufferSize(
 
4301
)
 
4302
{
 
4303
        report( "getInputBufferSize is not implemented\n" );
 
4304
        return(1);
 
4305
}
 
4306
 
 
4307
 
 
4308
/*----------------------------------------------------------
 
4309
 setOutputBufferSize
 
4310
 
 
4311
   accept:      
 
4312
   perform:     
 
4313
   return:      none
 
4314
   exceptions:  none
 
4315
   comments:    see fopen/fclose/fwrite/fread man pages.
 
4316
----------------------------------------------------------*/
 
4317
void gnu::io::RXTXPort::setOutputBufferSize(
 
4318
        jint size
 
4319
)
 
4320
{
 
4321
        report( "setOutputBufferSize is not implemented\n" );
 
4322
}
 
4323
 
 
4324
/*----------------------------------------------------------
 
4325
 getOutputBufferSize
 
4326
 
 
4327
   accept:      
 
4328
   perform:     
 
4329
   return:      none
 
4330
   exceptions:  none
 
4331
   comments:    see fopen/fclose/fwrite/fread man pages.
 
4332
----------------------------------------------------------*/
 
4333
jint gnu::io::RXTXPort::getOutputBufferSize()
 
4334
{
 
4335
        report( "getOutputBufferSize is not implemented\n" );
 
4336
        return(1);
 
4337
}
 
4338
 
 
4339
#endif /* GOING_TO_MESS_WITH_BUFFERS */
 
4340
 
 
4341
/*----------------------------------------------------------
 
4342
 interruptEventLoop
 
4343
 
 
4344
   accept:      nothing
 
4345
   perform:     increment eventloop_interrupted 
 
4346
   return:      nothing
 
4347
   exceptions:  none
 
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(
 
4354
)
 
4355
{
 
4356
        struct event_info_struct *index = master_index;
 
4357
        int fd = ( int ) this->fd;
 
4358
        int searching = 1;
 
4359
 
 
4360
 
 
4361
        while( searching )
 
4362
        {
 
4363
                index = master_index;
 
4364
                if( index )
 
4365
                {
 
4366
                        while( index->fd != fd &&
 
4367
                                index->next ) index = index->next;
 
4368
                        if ( index->fd == fd ) searching = 0;
 
4369
                }
 
4370
                else
 
4371
                        report("x");
 
4372
                if( searching )
 
4373
                {
 
4374
                        report("@");
 
4375
                        usleep(1000);
 
4376
                }
 
4377
        }
 
4378
        index->eventloop_interrupted = 1;
 
4379
        /*
 
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.
 
4384
 
 
4385
        In rxtx TIOCSERGETLSR is defined for win32 and Linux
 
4386
        */
 
4387
#ifdef TIOCSERGETLSR
 
4388
        index->closing=1;
 
4389
#endif /* TIOCSERGETLSR */
 
4390
#ifdef WIN32
 
4391
        termios_interrupt_event_loop( index->fd, 1 );
 
4392
#endif /* WIN32 */
 
4393
        report("interruptEventLoop: interrupted\n");
 
4394
}
 
4395
 
 
4396
/*----------------------------------------------------------
 
4397
 is_interrupted
 
4398
 
 
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.
 
4402
   exceptions:  none
 
4403
   comments:
 
4404
----------------------------------------------------------*/
 
4405
jboolean is_interrupted( gnu::io::RXTXPort *p, struct event_info_struct *eis )
 
4406
{
 
4407
        int result;
 
4408
 
 
4409
        ENTER( "is_interrupted" );
 
4410
        result = p->checkMonitorThread( );
 
4411
#ifdef DEBUG
 
4412
        if((*env)->ExceptionOccurred(env)) {
 
4413
                report ( "is_interrupted: an error occured calling sendEvent()\n" );
 
4414
                (*env)->ExceptionDescribe(env);
 
4415
                (*env)->ExceptionClear(env);
 
4416
        }
 
4417
#endif /* DEBUG */
 
4418
        LEAVE( "RXTXCommDriver:is_interrupted" );
 
4419
        return(result);
 
4420
}
 
4421
 
 
4422
/*----------------------------------------------------------
 
4423
 nativeSetEventFlag
 
4424
 
 
4425
   accept:      fd for finding the struct, event to flag, flag.
 
4426
   perform:     toggle the flag
 
4427
   return:      none
 
4428
   exceptions:  none
 
4429
   comments:    all the logic used to be done in Java but its too noisy
 
4430
----------------------------------------------------------*/
 
4431
void gnu::io::RXTXPort::nativeSetEventFlag(
 
4432
        jint fd,
 
4433
        jint event,
 
4434
        jboolean flag
 
4435
)
 
4436
{
 
4437
        struct event_info_struct *index = master_index;
 
4438
 
 
4439
        if( !index )
 
4440
        {
 
4441
                report_error("nativeSetEventFlag !index\n");
 
4442
                return;
 
4443
        }
 
4444
        while( index->fd != fd && index->next )
 
4445
        {
 
4446
                index = index->next;
 
4447
        }
 
4448
        if( index->fd != fd )
 
4449
        {
 
4450
                report_error("nativeSetEventFlag !fd\n");
 
4451
                return;
 
4452
        }
 
4453
        index->eventflags[event] = (int) flag;
 
4454
#ifdef WIN32
 
4455
        termios_setflags( fd, index->eventflags );
 
4456
#endif /* win32 */
 
4457
        
 
4458
}
 
4459
 
 
4460
/*----------------------------------------------------------
 
4461
 send_event
 
4462
 
 
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.
 
4466
   exceptions:  none
 
4467
   comments:
 
4468
----------------------------------------------------------*/
 
4469
int send_event( gnu::io::RXTXPort *p, struct event_info_struct *eis, jint type, int flag )
 
4470
{
 
4471
        int result;
 
4472
 
 
4473
        ENTER( "send_event" );
 
4474
        if( !eis || eis->eventloop_interrupted > 1 )
 
4475
        {
 
4476
                report("event loop interrupted\n");
 
4477
                return true;
 
4478
        }
 
4479
        report_verbose("send_event: !eventloop_interupted\n");
 
4480
 
 
4481
#ifdef TODO /* FIXME jcj hack */
 
4482
        (*env)->ExceptionClear(env);
 
4483
#endif /* FIXME jcj hack */
 
4484
 
 
4485
        report_verbose("send_event: calling\n");
 
4486
        result = p->sendEvent( type, flag > 0 ? true : false );
 
4487
        report_verbose("send_event: called\n");
 
4488
 
 
4489
#ifdef asdf
 
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);
 
4494
        }
 
4495
#endif /* asdf */
 
4496
        /* report("e"); */
 
4497
        LEAVE( "send_event" );
 
4498
        return(result);
 
4499
}
 
4500
 
 
4501
/*----------------------------------------------------------
 
4502
 report_warning
 
4503
 
 
4504
   accept:      string to send to report as an message
 
4505
   perform:     send the string to stderr or however it needs to be reported.
 
4506
   return:      none
 
4507
   exceptions:  none
 
4508
   comments:
 
4509
----------------------------------------------------------*/
 
4510
void report_warning(char *msg)
 
4511
{
 
4512
#ifndef DEBUG_MW
 
4513
        fprintf(stderr, msg);
 
4514
#else
 
4515
        mexWarnMsgTxt( (const char *) msg );
 
4516
#endif /* DEBUG_MW */
 
4517
}
 
4518
 
 
4519
/*----------------------------------------------------------
 
4520
 report_verbose
 
4521
 
 
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.
 
4524
   return:      none
 
4525
   exceptions:  none
 
4526
   comments:
 
4527
----------------------------------------------------------*/
 
4528
void report_verbose(char *msg)
 
4529
{
 
4530
#ifdef DEBUG_VERBOSE
 
4531
#ifdef DEBUG_MW
 
4532
        mexErrMsgTxt( msg );
 
4533
#else
 
4534
        fprintf(stderr, msg);
 
4535
#endif /* DEBUG_MW */
 
4536
#endif /* DEBUG_VERBOSE */
 
4537
}
 
4538
/*----------------------------------------------------------
 
4539
 report_error
 
4540
 
 
4541
   accept:      string to send to report as an error
 
4542
   perform:     send the string to stderr or however it needs to be reported.
 
4543
   return:      none
 
4544
   exceptions:  none
 
4545
   comments:
 
4546
----------------------------------------------------------*/
 
4547
void report_error(char *msg)
 
4548
{
 
4549
#ifndef DEBUG_MW
 
4550
        fprintf(stderr, msg);
 
4551
#else
 
4552
        mexWarnMsgTxt( msg );
 
4553
#endif /* DEBUG_MW */
 
4554
}
 
4555
 
 
4556
/*----------------------------------------------------------
 
4557
 report
 
4558
 
 
4559
   accept:      string to send to stderr
 
4560
   perform:     if DEBUG is defined send the string to stderr.
 
4561
   return:      none
 
4562
   exceptions:  none
 
4563
   comments:
 
4564
----------------------------------------------------------*/
 
4565
void report(char *msg)
 
4566
{
 
4567
#ifdef DEBUG
 
4568
#       ifndef DEBUG_MW
 
4569
                fprintf(stderr, msg);
 
4570
#       else
 
4571
                mexPrintf( msg );
 
4572
#       endif /* DEBUG_MW */
 
4573
#endif /* DEBUG */
 
4574
}
 
4575
 
 
4576
#ifndef WIN32
 
4577
#ifdef LFS
 
4578
/*----------------------------------------------------------
 
4579
 lfs_lock
 
4580
 
 
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
 
4583
                lock file server.
 
4584
   return:      1 on failure 0 on success
 
4585
   exceptions:  none
 
4586
   comments:    
 
4587
 
 
4588
----------------------------------------------------------*/
 
4589
int lfs_lock( const char *filename, int pid )
 
4590
{
 
4591
        int s;
 
4592
        int ret;
 
4593
        int size = 1024;
 
4594
        char *buffer = malloc(size);
 
4595
        struct sockaddr_in addr;
 
4596
 
 
4597
        if ( !( s = socket( AF_INET, SOCK_STREAM, 0 ) ) > 0 )
 
4598
                return 1;
 
4599
        addr.sin_family = AF_INET;
 
4600
        addr.sin_port = htons( 50001 );
 
4601
        addr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
 
4602
   
 
4603
        if ( !connect( s, ( struct sockaddr * ) &addr, sizeof( addr ) ) == 0 )
 
4604
                return 1;
 
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 );
 
4610
        if ( ret > 0 )
 
4611
        {
 
4612
                buffer[ret] = '\0';
 
4613
                /* printf( "Message recieved: %s", buffer ); */
 
4614
        }
 
4615
        send( s, "quit\n", strlen( "quit\n" ), 0 );
 
4616
        close(s);
 
4617
        /* printf("%s\n", buffer); */
 
4618
        if( buffer[0] == '2' ) return 0;
 
4619
        return 1;
 
4620
}
 
4621
 
 
4622
/*----------------------------------------------------------
 
4623
 lfs_unlock
 
4624
 
 
4625
   accept:      The name of the device to try to unlock
 
4626
   perform:     Remove a lock file if there is one using a
 
4627
                lock file server.
 
4628
   return:      1 on failure 0 on success
 
4629
   exceptions:  none
 
4630
   comments:    
 
4631
 
 
4632
----------------------------------------------------------*/
 
4633
int lfs_unlock( const char *filename, int pid )
 
4634
{
 
4635
        int s;
 
4636
        int ret;
 
4637
        int size = 1024;
 
4638
        char *buffer = malloc(size);
 
4639
        struct sockaddr_in addr;
 
4640
 
 
4641
        if ( !( s = socket( AF_INET, SOCK_STREAM, 0 ) ) > 0 )
 
4642
                return 1;
 
4643
        addr.sin_family = AF_INET;
 
4644
        addr.sin_port = htons( 50001 );
 
4645
        addr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
 
4646
   
 
4647
        if ( !connect( s, ( struct sockaddr * ) &addr, sizeof( addr ) ) == 0 )
 
4648
                return 1;
 
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 );
 
4653
        if ( ret > 0 )
 
4654
        {
 
4655
                buffer[ret] = '\0';
 
4656
                /* printf( "Message recieved: %s", buffer ); */
 
4657
        }
 
4658
        send( s, "quit\n", strlen( "quit\n" ), 0 );
 
4659
        close(s);
 
4660
        if( buffer[0] == '2' ) return 0;
 
4661
        return 1;
 
4662
}
 
4663
#endif /* LFS */
 
4664
 
 
4665
/*----------------------------------------------------------
 
4666
 fhs_lock
 
4667
 
 
4668
   accept:      The name of the device to try to lock
 
4669
                termios struct
 
4670
   perform:     Create a lock file if there is not one already.
 
4671
   return:      1 on failure 0 on success
 
4672
   exceptions:  none
 
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
 
4676
 
 
4677
                more reading:
 
4678
 
 
4679
----------------------------------------------------------*/
 
4680
int fhs_lock( const char *filename, int pid )
 
4681
{
 
4682
        /*
 
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.
 
4687
         *
 
4688
         */
 
4689
        int fd,j;
 
4690
        char lockinfo[12], message[80];
 
4691
        char file[80], *p;
 
4692
 
 
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
 
4697
                        taj
 
4698
        */
 
4699
        //printf("lock file is %s\n",filename);
 
4700
        while( *( p - 1 ) != '/' && j-- != 1 )
 
4701
        {
 
4702
#if defined ( __unixware__ )
 
4703
                *p = tolower( *p );
 
4704
#endif /* __unixware__ */
 
4705
                p--;
 
4706
        }
 
4707
        sprintf( file, "%s/LCK..%s", LOCKDIR, p );
 
4708
        if ( check_lock_status( filename ) )
 
4709
        {
 
4710
                report( "fhs_lock() lockstatus fail\n" );
 
4711
                return 1;
 
4712
        }
 
4713
        fd = open( file, O_CREAT | O_WRONLY | O_EXCL, 0444 );
 
4714
        if( fd < 0 )
 
4715
        {
 
4716
                sprintf( message,
 
4717
                        "RXTX fhs_lock() Error: creating lock file: %s: %s\n",
 
4718
                        file, strerror(errno) );
 
4719
                report_error( message );
 
4720
                return 1;
 
4721
        }
 
4722
        sprintf( lockinfo, "%10d\n",(int) getpid() );
 
4723
        sprintf( message, "fhs_lock: creating lockfile: %s\n", lockinfo );
 
4724
        report( message );
 
4725
        write( fd, lockinfo, 11 );
 
4726
        close( fd );
 
4727
        return 0;
 
4728
}
 
4729
 
 
4730
/*----------------------------------------------------------
 
4731
 uucp_lock
 
4732
 
 
4733
   accept:     char * filename.  Device to be locked 
 
4734
   perform:    Try to get a uucp_lock
 
4735
   return:     int 0 on success
 
4736
   exceptions: none 
 
4737
   comments: 
 
4738
                The File System Hierarchy Standard
 
4739
                http://www.pathname.com/fhs/
 
4740
 
 
4741
                UUCP Lock Files
 
4742
                http://docs.freebsd.org/info/uucp/uucp.info.UUCP_Lock_Files.html
 
4743
 
 
4744
                FSSTND
 
4745
                ftp://tsx-11.mit.edu/pub/linux/docs/linux-standards/fsstnd/
 
4746
 
 
4747
                Proposed Changes to the File System Hierarchy Standard
 
4748
                ftp://scicom.alphacdc.com/pub/linux/devlock-0.X.tgz
 
4749
 
 
4750
                "UNIX Network Programming", W. Richard Stevens,
 
4751
                Prentice-Hall, 1990, pages 96-101.
 
4752
 
 
4753
                There is much to do here.
 
4754
 
 
4755
                1) UUCP style locks (done)
 
4756
                        /var/spool/uucp
 
4757
                2) SVR4 locks
 
4758
                        /var/spool/locks
 
4759
                3) FSSTND locks (done)
 
4760
                        /var/lock
 
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
 
4765
                   numbers...
 
4766
                7) Stevens recommends LCK..<pid>
 
4767
 
 
4768
                most are caught above.  If they turn out to be problematic
 
4769
                rather than an exercise, we will handle them.
 
4770
 
 
4771
----------------------------------------------------------*/
 
4772
int uucp_lock( const char *filename, int pid )
 
4773
{
 
4774
        char lockfilename[80], lockinfo[12], message[80];
 
4775
        char name[80];
 
4776
        int fd;
 
4777
        struct stat buf;
 
4778
 
 
4779
        sprintf( message, "uucp_lock( %s );\n", filename ); 
 
4780
        report( message );
 
4781
 
 
4782
        if ( check_lock_status( filename ) )
 
4783
        {
 
4784
                report( "RXTX uucp check_lock_status true\n" );
 
4785
                return 1;
 
4786
        }
 
4787
        if ( stat( LOCKDIR, &buf ) != 0 )
 
4788
        {
 
4789
                report( "RXTX uucp_lock() could not find lock directory.\n" );
 
4790
                return 1;
 
4791
        }
 
4792
        if ( stat( filename, &buf ) != 0 )
 
4793
        {
 
4794
                report( "RXTX uucp_lock() could not find device.\n" );
 
4795
                sprintf( message, "uucp_lock: device was %s\n", name );
 
4796
                report( message );
 
4797
                return 1;
 
4798
        }
 
4799
        sprintf( lockfilename, "%s/LK.%03d.%03d.%03d",
 
4800
                LOCKDIR,
 
4801
                (int) major( buf.st_dev ),
 
4802
                (int) major( buf.st_rdev ),
 
4803
                (int) minor( buf.st_rdev )
 
4804
        );
 
4805
        sprintf( lockinfo, "%10d\n", (int) getpid() );
 
4806
        if ( stat( lockfilename, &buf ) == 0 )
 
4807
        {
 
4808
                sprintf( message, "RXTX uucp_lock() %s is there\n",
 
4809
                        lockfilename );
 
4810
                report( message );
 
4811
                report_error( message );
 
4812
                return 1;
 
4813
        }
 
4814
        fd = open( lockfilename, O_CREAT | O_WRONLY | O_EXCL, 0444 );
 
4815
        if( fd < 0 )
 
4816
        {
 
4817
                sprintf( message,
 
4818
                        "RXTX uucp_lock() Error: creating lock file: %s\n",
 
4819
                        lockfilename );
 
4820
                report_error( message );
 
4821
                return 1;
 
4822
        }
 
4823
        write( fd, lockinfo,11 );
 
4824
        close( fd );
 
4825
        return 0;
 
4826
}
 
4827
 
 
4828
/*----------------------------------------------------------
 
4829
 check_lock_status
 
4830
 
 
4831
   accept:      the lock name in question
 
4832
   perform:     Make sure everything is sane
 
4833
   return:      0 on success
 
4834
   exceptions:  none
 
4835
   comments:    
 
4836
----------------------------------------------------------*/
 
4837
int check_lock_status( const char *filename )
 
4838
{
 
4839
        struct stat buf;
 
4840
        /*  First, can we find the directory? */
 
4841
 
 
4842
        if ( stat( LOCKDIR, &buf ) != 0 )
 
4843
        {
 
4844
                report( "check_lock_status: could not find lock directory.\n" );
 
4845
                return 1;
 
4846
        }
 
4847
 
 
4848
        /*  OK.  Are we able to write to it?  If not lets bail */
 
4849
 
 
4850
        if ( check_group_uucp() )
 
4851
        {
 
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" );
 
4853
                return(1);
 
4854
        }
 
4855
 
 
4856
        /* is the device alread locked */
 
4857
 
 
4858
        if ( is_device_locked( filename ) )
 
4859
        {
 
4860
                report( "check_lock_status: device is locked by another application\n" );
 
4861
                return 1;       
 
4862
        }
 
4863
        return 0;
 
4864
        
 
4865
}
 
4866
 
 
4867
/*----------------------------------------------------------
 
4868
 fhs_unlock
 
4869
 
 
4870
   accept:      The name of the device to unlock
 
4871
   perform:     delete the lock file
 
4872
   return:      none
 
4873
   exceptions:  none
 
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 )
 
4879
{
 
4880
        char file[80],*p;
 
4881
        int i;
 
4882
 
 
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 );
 
4888
 
 
4889
        if( !check_lock_pid( file, openpid ) )
 
4890
        {
 
4891
                unlink(file);
 
4892
                report("fhs_unlock: Removing LockFile\n");
 
4893
        }
 
4894
        else
 
4895
        {
 
4896
                report("fhs_unlock: Unable to remove LockFile\n");
 
4897
        }
 
4898
}
 
4899
 
 
4900
/*----------------------------------------------------------
 
4901
 uucp_unlock
 
4902
 
 
4903
   accept:     char *filename the device that is locked      
 
4904
   perform:    remove the uucp lockfile if it exists 
 
4905
   return:     none 
 
4906
   exceptions: none 
 
4907
   comments:   http://docs.freebsd.org/info/uucp/uucp.info.UUCP_Lock_Files.html 
 
4908
----------------------------------------------------------*/
 
4909
void uucp_unlock( const char *filename, int openpid )
 
4910
{
 
4911
        struct stat buf;
 
4912
        char file[80], message[80];
 
4913
        /* FIXME */
 
4914
 
 
4915
        sprintf( message, "uucp_unlock( %s );\n", filename );
 
4916
        report( message );
 
4917
 
 
4918
        if ( stat( filename, &buf ) != 0 ) 
 
4919
        {
 
4920
                /* hmm the file is not there? */
 
4921
                report( "uucp_unlock() no such device\n" );
 
4922
                return;
 
4923
        }
 
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 )
 
4928
        );
 
4929
        if ( stat( file, &buf ) != 0 ) 
 
4930
        {
 
4931
                /* hmm the file is not there? */
 
4932
                report( "uucp_unlock no such lockfile\n" );
 
4933
                return;
 
4934
        }
 
4935
        if( !check_lock_pid( file, openpid ) )
 
4936
        { 
 
4937
                sprintf( message, "uucp_unlock: unlinking %s\n", file );
 
4938
                report( message );
 
4939
                unlink(file);
 
4940
        }
 
4941
        else
 
4942
        {
 
4943
                sprintf( message, "uucp_unlock: unlinking failed %s\n", file );
 
4944
                report( message );
 
4945
        }
 
4946
}
 
4947
 
 
4948
/*----------------------------------------------------------
 
4949
 check_lock_pid
 
4950
 
 
4951
   accept:     the name of the lockfile 
 
4952
   perform:    make sure the lock file is ours.
 
4953
   return:     0 on success
 
4954
   exceptions: none
 
4955
   comments:   
 
4956
----------------------------------------------------------*/
 
4957
int check_lock_pid( const char *file, int openpid )
 
4958
{
 
4959
        int fd, lockpid;
 
4960
        char pid_buffer[12];
 
4961
        char message[80];
 
4962
 
 
4963
        fd=open( file, O_RDONLY );
 
4964
        if ( fd < 0 )
 
4965
        {
 
4966
                return( 1 );
 
4967
        }
 
4968
        if ( read( fd, pid_buffer, 11 ) < 0 )
 
4969
        {
 
4970
                close( fd );
 
4971
                return( 1 );
 
4972
        }
 
4973
        close( fd );
 
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 )
 
4978
        {
 
4979
                sprintf(message, "check_lock_pid: lock = %s pid = %i gpid=%i openpid=%i\n",
 
4980
                        pid_buffer, (int) getpid(), (int) getppid(), openpid );
 
4981
                report( message );
 
4982
                return( 1 );
 
4983
        }
 
4984
        return( 0 );
 
4985
}
 
4986
 
 
4987
/*----------------------------------------------------------
 
4988
 check_group_uucp
 
4989
 
 
4990
   accept:     none
 
4991
   perform:    check if the user is root or in group uucp
 
4992
   return:     0 on success 
 
4993
   exceptions: none 
 
4994
   comments:   
 
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.
 
4998
 
 
4999
                if someone really wants to override this they can use the                       USER_LOCK_DIRECTORY --not recommended.
 
5000
 
 
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.
 
5004
 
 
5005
                * Modified to support Debian *
 
5006
 
 
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.
 
5014
 
 
5015
                Villa Valerio <valerio.villa@siemens.com>
 
5016
----------------------------------------------------------*/
 
5017
int check_group_uucp()
 
5018
{
 
5019
#ifndef USER_LOCK_DIRECTORY
 
5020
        FILE *testLockFile ;
 
5021
        char testLockFileDirName[] = LOCKDIR;
 
5022
        char testLockFileName[] = "tmpXXXXXX";
 
5023
        char *testLockAbsFileName;
 
5024
 
 
5025
        testLockAbsFileName = ( char * ) calloc(strlen(testLockFileDirName)
 
5026
                        + strlen(testLockFileName) + 2, sizeof(char));
 
5027
        if ( NULL == testLockAbsFileName )
 
5028
        {
 
5029
                report_error("check_group_uucp(): Insufficient memory");
 
5030
                return 1;  
 
5031
        }
 
5032
        strcat(testLockAbsFileName, testLockFileDirName);
 
5033
        strcat(testLockAbsFileName, "/");
 
5034
        strcat(testLockAbsFileName, testLockFileName);
 
5035
        if ( NULL == mkstemp(testLockAbsFileName) )
 
5036
        {
 
5037
                free(testLockAbsFileName);
 
5038
                report_error("check_group_uucp(): mktemp malformed string - \
 
5039
                        should not happen");
 
5040
 
 
5041
                return 1;
 
5042
        }
 
5043
        testLockFile = fopen (testLockAbsFileName, "w+");
 
5044
        if (NULL == testLockFile)
 
5045
        {
 
5046
                report_error("check_group_uucp(): error testing lock file \
 
5047
                        creation Error details: ");
 
5048
                report_error(strerror(errno));
 
5049
 
 
5050
                free(testLockAbsFileName);
 
5051
                return 1;
 
5052
        }
 
5053
 
 
5054
        fclose (testLockFile);
 
5055
        unlink (testLockAbsFileName);           
 
5056
        free(testLockAbsFileName);
 
5057
 
 
5058
#endif /* USER_LOCK_DIRECTORY */
 
5059
        return 0;
 
5060
 
 
5061
#ifdef USE_OLD_CHECK_GROUP_UUCP
 
5062
int check_group_uucp()
 
5063
{
 
5064
#ifndef USER_LOCK_DIRECTORY
 
5065
        int group_count;
 
5066
        struct passwd *user = getpwuid( geteuid() );
 
5067
        struct stat buf;
 
5068
        char msg[80];
 
5069
        gid_t list[ NGROUPS_MAX ];
 
5070
 
 
5071
        if( stat( LOCKDIR, &buf) )
 
5072
        {
 
5073
                sprintf( msg, "check_group_uucp:  Can not find Lock Directory: %s\n", LOCKDIR );
 
5074
                report_error( msg );
 
5075
                return( 1 );
 
5076
        }
 
5077
        group_count = getgroups( NGROUPS_MAX, list );
 
5078
        list[ group_count ] = geteuid();
 
5079
 
 
5080
        /* JJO changes start */
 
5081
        if( user == NULL )
 
5082
        {
 
5083
                report_error( "Not able to get user groups.\n" );
 
5084
                return 1;
 
5085
        } else
 
5086
        /* JJO changes stop */
 
5087
 
 
5088
 
 
5089
        if( user->pw_gid )
 
5090
        {
 
5091
                while( group_count >= 0 && buf.st_gid != list[ group_count ] )
 
5092
                {
 
5093
                        group_count--; 
 
5094
                }
 
5095
                if( buf.st_gid == list[ group_count ] )
 
5096
                        return 0;
 
5097
                sprintf( msg, "%i %i\n", buf.st_gid, list[ group_count ] );
 
5098
                report_error( msg );
 
5099
                report_error( UUCP_ERROR );
 
5100
                return 1;
 
5101
        }
 
5102
        return 0;
 
5103
/*
 
5104
        if( strcmp( user->pw_name, "root" ) )
 
5105
        {
 
5106
                while( *g->gr_mem )
 
5107
                {
 
5108
                        if( !strcmp( *g->gr_mem, user->pw_name ) )
 
5109
                        {
 
5110
                                break;
 
5111
                        }
 
5112
                        (void) *g->gr_mem++;
 
5113
                }
 
5114
                if( !*g->gr_mem )
 
5115
                {
 
5116
                        report( UUCP_ERROR );
 
5117
                        return 1;
 
5118
                }
 
5119
        }
 
5120
*/
 
5121
#endif /* USER_LOCK_DIRECTORY */
 
5122
        return 0;
 
5123
#endif /* USE_OLD_CHECK_GROUP_UUCP */
 
5124
}
 
5125
 
 
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
 
5129
 for information.
 
5130
 
 
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)
 
5135
{
 
5136
        char real_ld[MAXPATHLEN];
 
5137
        char real_LOCKDIR[MAXPATHLEN];
 
5138
        if (strncmp(ld, LOCKDIR, strlen(ld)) == 0)
 
5139
                return 0;
 
5140
        if (realpath(ld, real_ld) == NULL)
 
5141
                return 1;
 
5142
        if (realpath(LOCKDIR, real_LOCKDIR) == NULL)
 
5143
                return 1;
 
5144
        if (strncmp(real_ld, real_LOCKDIR, strlen(real_ld)) == 0)
 
5145
                return 0;
 
5146
        else
 
5147
                return 1;
 
5148
}
 
5149
*/
 
5150
 
 
5151
/*----------------------------------------------------------
 
5152
 is_device_locked
 
5153
 
 
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.
 
5159
   exceptions:  none
 
5160
   comments:    check if the device is already locked
 
5161
----------------------------------------------------------*/
 
5162
int is_device_locked( const char *port_filename )
 
5163
{
 
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",
 
5168
                LOCKDIR, NULL
 
5169
        };
 
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;
 
5173
        struct stat buf;
 
5174
        struct stat buf2;
 
5175
 
 
5176
        j = strlen( port_filename );
 
5177
        p = ( char * ) port_filename+j;
 
5178
        while( *( p-1 ) != '/' && j-- !=1 ) p--;
 
5179
 
 
5180
        while( lockdirs[i] )
 
5181
        {
 
5182
                /*
 
5183
                   Look for lockfiles in all known places other than the
 
5184
                   defined lock directory for this system
 
5185
                   report any unexpected lockfiles.
 
5186
 
 
5187
                   Is the suspect lockdir there?
 
5188
                   if it is there is it not the expected lock dir?
 
5189
                */
 
5190
                if( !stat( lockdirs[i], &buf2 ) &&
 
5191
                        strncmp( lockdirs[i], LOCKDIR, strlen( lockdirs[i] ) ) )
 
5192
                {
 
5193
                        j = strlen( port_filename );
 
5194
                        p = ( char *  ) port_filename + j;
 
5195
                /*
 
5196
                   SCO Unix use lowercase all the time
 
5197
                        taj
 
5198
                */
 
5199
                        while( *( p - 1 ) != '/' && j-- != 1 )
 
5200
                        {
 
5201
#if defined ( __unixware__ )
 
5202
                                *p = tolower( *p );
 
5203
#endif /* __unixware__ */
 
5204
                                p--;
 
5205
                        }
 
5206
                        k=0;
 
5207
                        while ( lockprefixes[k] )
 
5208
                        {
 
5209
                                /* FHS style */
 
5210
                                sprintf( file, "%s/%s%s", lockdirs[i],
 
5211
                                        lockprefixes[k], p );
 
5212
                                if( stat( file, &buf ) == 0 )
 
5213
                                {
 
5214
                                        sprintf( message, UNEXPECTED_LOCK_FILE,
 
5215
                                                file );
 
5216
                                        report_warning( message );
 
5217
                                        return 1;
 
5218
                                }
 
5219
 
 
5220
                                /* UUCP style */
 
5221
                                stat(port_filename , &buf );
 
5222
                                sprintf( file, "%s/%s%03d.%03d.%03d",
 
5223
                                        lockdirs[i],
 
5224
                                        lockprefixes[k],
 
5225
                                        (int) major( buf.st_dev ),
 
5226
                                        (int) major( buf.st_rdev ),
 
5227
                                        (int) minor( buf.st_rdev )
 
5228
                                );
 
5229
                                if( stat( file, &buf ) == 0 )
 
5230
                                {
 
5231
                                        sprintf( message, UNEXPECTED_LOCK_FILE,
 
5232
                                                file );
 
5233
                                        report_warning( message );
 
5234
                                        return 1;
 
5235
                                }
 
5236
                                k++;
 
5237
                        }
 
5238
                }
 
5239
                i++;
 
5240
        }
 
5241
 
 
5242
        /*
 
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
 
5245
                removed.
 
5246
        */
 
5247
                 
 
5248
#ifdef FHS
 
5249
        /*  FHS standard locks */
 
5250
        i = strlen( port_filename );
 
5251
        p = ( char * ) port_filename + i;
 
5252
        while( *(p-1) != '/' && i-- != 1)
 
5253
        {
 
5254
#if defined ( __unixware__ )
 
5255
                *p = tolower( *p );
 
5256
#endif /* __unixware__ */
 
5257
                p--;
 
5258
        }
 
5259
        sprintf( file, "%s/%s%s", LOCKDIR, LOCKFILEPREFIX, p );
 
5260
#else 
 
5261
        /*  UUCP standard locks */
 
5262
        if ( stat( port_filename, &buf ) != 0 )
 
5263
        {
 
5264
                report( "RXTX is_device_locked() could not find device.\n" );
 
5265
                        return 1;
 
5266
        }
 
5267
        sprintf( file, "%s/LK.%03d.%03d.%03d",
 
5268
                LOCKDIR,
 
5269
                (int) major( buf.st_dev ),
 
5270
                (int) major( buf.st_rdev ),
 
5271
                (int) minor( buf.st_rdev )
 
5272
        );
 
5273
 
 
5274
#endif /* FHS */
 
5275
 
 
5276
        if( stat( file, &buf ) == 0 )
 
5277
        {
 
5278
 
 
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 */
 
5283
                close( fd );
 
5284
                sscanf( pid_buffer, "%d", &pid );
 
5285
 
 
5286
                if( kill( (pid_t) pid, 0 ) && errno==ESRCH )
 
5287
                {
 
5288
                        sprintf( message,
 
5289
                                "RXTX Warning:  Removing stale lock file. %s\n",
 
5290
                                file );
 
5291
                        report_warning( message );
 
5292
                        if( unlink( file ) != 0 )
 
5293
                        {
 
5294
                                snprintf( message, 80, "RXTX Error:  Unable to \
 
5295
                                        remove stale lock file: %s\n",
 
5296
                                        file
 
5297
                                );
 
5298
                                report_warning( message );
 
5299
                                return 1;
 
5300
                        }
 
5301
                }
 
5302
        }
 
5303
        return 0;
 
5304
}
 
5305
#endif /* WIN32 */
 
5306
 
 
5307
/*----------------------------------------------------------
 
5308
 system_does_not_lock
 
5309
 
 
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 ;)
 
5313
   exceptions:  none
 
5314
   comments:    OS's like Win32 may not have lock files.
 
5315
----------------------------------------------------------*/
 
5316
int system_does_not_lock( const char * filename, int pid )
 
5317
{
 
5318
        return 0;
 
5319
}
 
5320
 
 
5321
/*----------------------------------------------------------
 
5322
 system_does_not_unlock
 
5323
 
 
5324
   accept:      the filename the system thinks should be locked.
 
5325
   perform:     avoid trying to create lock files on systems that dont use them
 
5326
   return:      none
 
5327
   exceptions:  none
 
5328
   comments:    OS's like Win32 may not have lock files.
 
5329
----------------------------------------------------------*/
 
5330
void system_does_not_unlock( const char * filename, int openpid )
 
5331
{
 
5332
        return;
 
5333
}
 
5334
 
 
5335
/*----------------------------------------------------------
 
5336
 dump_termios
 
5337
 
 
5338
   accept:      string to indicate where this was called.
 
5339
                termios struct
 
5340
   perform:     print the termios struct to stderr.
 
5341
   return:      none
 
5342
   exceptions:  none
 
5343
   comments:    used to debug the termios struct.
 
5344
----------------------------------------------------------*/
 
5345
void dump_termios(char *foo,struct termios *ttyset)
 
5346
{
 
5347
#ifdef DEBUG
 
5348
        int i;
 
5349
 
 
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++)
 
5356
        {
 
5357
                fprintf(stderr,"%d=%x ", i, ttyset->c_cc[i]);
 
5358
        }
 
5359
        fprintf(stderr,"\n" );
 
5360
#endif /* DEBUG */
 
5361
}
 
5362
/*----------------------------------------------------------
 
5363
printj
 
5364
 
 
5365
   accept:      like vwprintf()
 
5366
   return:      number of jchars written or -1
 
5367
   exceptions:  none
 
5368
   comments:    prints data using System.out.print()
 
5369
 
 
5370
   for gcj + CNI
 
5371
   Just use java::lang::System::out->println(s);
 
5372
----------------------------------------------------------*/
 
5373
int printj(
 
5374
        wchar_t *fmt,
 
5375
        ...
 
5376
)
 
5377
{
 
5378
        return(0);
 
5379
}
 
5380
/* for gcj compiles */
 
5381
 
 
5382
jboolean gnu::io::RXTXPort::nativeSetCallOutHangup( jboolean NoHup )
 
5383
{
 
5384
        return( true );
 
5385
}
 
5386
jboolean gnu::io::RXTXPort::nativeGetCallOutHangup( )
 
5387
{
 
5388
        return( true );
 
5389
}
 
5390
jboolean gnu::io::RXTXPort::nativeSetLowLatency( )
 
5391
{
 
5392
        return( true );
 
5393
}
 
5394
jboolean gnu::io::RXTXPort::nativeGetLowLatency( )
 
5395
{
 
5396
        return( true );
 
5397
}
 
5398
jboolean gnu::io::RXTXPort::nativeSetUartType( jstring ty, jboolean te )
 
5399
{
 
5400
        return( true );
 
5401
}
 
5402
jstring  gnu::io::RXTXPort::nativeGetUartType( )
 
5403
{
 
5404
        return JvNewStringUTF( "RXTX-2.1-7pre13 SAM I AM" );
 
5405
}