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

« back to all changes in this revision

Viewing changes to src/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
1
/*-------------------------------------------------------------------------
2
2
|   rxtx is a native interface to serial ports in java.
3
 
|   Copyright 1997-2002 by Trent Jarvi taj@www.linux.org.uk
 
3
|   Copyright 1997-2004 by Trent Jarvi taj@www.linux.org.uk
4
4
|
5
5
|   This library is free software; you can redistribute it and/or
6
6
|   modify it under the terms of the GNU Library General Public
19
19
#if defined(__MWERKS__) /* dima */
20
20
#include "RXTXPort.h" /* dima */
21
21
#else  /* dima */
22
 
#include "config.h"
 
22
#ifndef WIN32
 
23
#       include "config.h"
 
24
#endif
23
25
#include "gnu_io_RXTXPort.h"
24
26
#endif /* dima */
25
 
#ifndef __LCC__
26
 
#   include <unistd.h>
27
 
#else /* windows lcc compiler for fd_set. probably wrong */
 
27
#ifdef __LCC__ /* windows lcc compiler for fd_set. probably wrong */
28
28
#   include<winsock.h>
29
29
#endif /* __LCC__ */
30
 
#include <time.h>
31
30
#include <stdio.h>
32
31
#include <string.h>
33
32
#include <stdlib.h>
 
33
#include <time.h>
34
34
#include <errno.h>
35
35
#include <limits.h>
36
36
#include <sys/stat.h>
37
37
#ifndef WIN32
 
38
#include <unistd.h>
38
39
#include <sys/ioctl.h>
39
40
#include <sys/param.h>
40
41
#include <sys/utsname.h>
41
42
#include <pthread.h>
42
43
#else
43
 
#       include <win32termios.h>
 
44
#       include "win32termios.h"
44
45
/*  FIXME  returns 0 in all cases on win32
45
46
#define S_ISCHR(m)      (((m)&S_IFMT) == S_IFCHR)
46
47
*/
103
104
#include        <grp.h>
104
105
#endif /* HAVE_GRP_H */
105
106
#include <math.h>
 
107
#ifdef LIBLOCKDEV
 
108
#include        <lockdev.h>
 
109
#endif /* LIBLOCKDEV */
106
110
 
107
111
extern int errno;
108
 
#ifdef TRENT_IS_HERE
109
 
#define DEBUG
110
 
#define TRACE
111
 
#define DEBUG_MW
112
 
#define DEBUG_VERBOSE
113
 
#undef TIOCSERGETLSR
114
 
#endif /* TRENT_IS_HERE */
 
112
 
115
113
#include "SerialImp.h"
116
114
 
 
115
JavaVM *javaVM = NULL;
 
116
 
117
117
 
118
118
struct preopened *preopened_port = NULL;
119
119
 
121
121
 * It will eventually be removed.
122
122
 * */
123
123
#define RXTXPort(foo) Java_gnu_io_RXTXPort_ ## foo
 
124
#define RXTXVersion(foo) Java_gnu_io_RXTXVersion_ ## foo
124
125
#define RXTXCommDriver(foo) Java_gnu_io_RXTXCommDriver_ ## foo
125
126
 
126
127
#if defined(__sun__) || defined(__hpux__)
185
186
 
186
187
struct event_info_struct *master_index = NULL;
187
188
 
 
189
 
 
190
/*----------------------------------------------------------
 
191
RXTXPort.Initialize
 
192
 
 
193
   accept:      The JNIEnv and jobj of the thread, the original eis.
 
194
   perform:     fill in the needed variables with this threads values
 
195
   return:      none
 
196
   exceptions:  none
 
197
   comments:    java variables (especially JNIEnv) should not be shared
 
198
                between threads.  Right now we build a local struct with
 
199
                the thread's info before using the variabls.  This is
 
200
                especially true for send_event.
 
201
 
 
202
                See also JNI_OnLoad() if the thread does not have the values
 
203
----------------------------------------------------------*/
 
204
struct event_info_struct build_threadsafe_eis(
 
205
        JNIEnv *env,
 
206
        jobject *jobj,
 
207
        struct event_info_struct *eis
 
208
)
 
209
{
 
210
        struct event_info_struct myeis = *eis;
 
211
 
 
212
        myeis.env = env;
 
213
        myeis.jclazz = (*env)->GetObjectClass( env, *jobj );
 
214
        myeis.jobj = jobj;
 
215
        myeis.fd = get_java_var( env, *jobj, "fd", "I" );
 
216
        myeis.send_event = (*env)->GetMethodID(
 
217
                env,
 
218
                myeis.jclazz,
 
219
                "sendEvent",
 
220
                "(IZ)Z"
 
221
        );
 
222
        return( myeis );
 
223
}
 
224
 
188
225
/*----------------------------------------------------------
189
226
RXTXPort.Initialize
190
227
 
395
432
                case B2400:  return 2400;
396
433
                case B4800:  return 4800;
397
434
                case B9600:  return 9600;
 
435
#ifdef B14400
 
436
                case B14400: return 14400;
 
437
#endif /* B14400 */
398
438
                case B19200: return 19200;
 
439
#ifdef B28800
 
440
                case B28800: return 28800;
 
441
#endif /* B28800 */
399
442
                case B38400: return 38400;
400
443
                case B57600: return 57600;
 
444
/* I don't think this is universal.. older UARTs never did these.  taj */
 
445
#ifdef B115200
 
446
                case B115200: return 115200;
 
447
#endif /*  B115200 */
 
448
#ifdef B128000  /* dima */
 
449
                case B128000: return 128000;
 
450
#endif  /* dima */
 
451
#ifdef B230400
 
452
                case B230400: return 230400;
 
453
#endif /* B230400 */
 
454
#ifdef B256000  /* dima */
 
455
                case B256000: return 256000;
 
456
#endif  /* dima */
 
457
#ifdef B460800
 
458
                case B460800: return 460800;
 
459
#endif /* B460800 */
 
460
#ifdef B500000
 
461
                case B500000: return 500000;
 
462
#endif /* B500000 */
 
463
#ifdef B576000
 
464
                case B576000: return 576000;
 
465
#endif /* B576000 */
 
466
#ifdef B921600
 
467
                case B921600: return 921600;
 
468
#endif /* B921600 */
 
469
#ifdef B1000000
 
470
                case B1000000: return 1000000;
 
471
#endif /* B1000000 */
 
472
#ifdef B1152000
 
473
                case B1152000: return 1152000;
 
474
#endif /* B1152000 */
 
475
#ifdef B1500000
 
476
                case B1500000: return 1500000;
 
477
#endif /* B1500000 */
 
478
#ifdef B2000000
 
479
                case B2000000: return 2000000;
 
480
#endif /* B2000000 */
 
481
#ifdef B2500000
 
482
                case B2500000: return 2500000;
 
483
#endif /* B2500000 */
 
484
#ifdef B3000000
 
485
                case B3000000: return 3000000;
 
486
#endif /* B3000000 */
 
487
#ifdef B3500000
 
488
                case B3500000: return 3500000;
 
489
#endif /* B3500000 */
 
490
#ifdef B4000000
 
491
                case B4000000: return 4000000;
 
492
#endif /* B4000000 */
401
493
                default: return -1;
402
494
        }
403
495
}
664
756
                return(1);
665
757
        }
666
758
 
667
 
        if( !translate_data_bits( env, &(ttyset.c_cflag), dataBits ) )
 
759
        if( translate_data_bits( env, &(ttyset.c_cflag), dataBits ) )
668
760
        {
669
761
                report( "set_port_params: Invalid Data Bits Selected\n" );
670
762
                return(1);
671
763
        }
672
764
 
673
 
        if( !translate_stop_bits( env, &(ttyset.c_cflag), stopBits ) )
 
765
        if( translate_stop_bits( env, &(ttyset.c_cflag), stopBits ) )
674
766
        {
675
767
                report( "set_port_params: Invalid Stop Bits Selected\n" );
676
768
                return(1);
677
769
        }
678
770
 
679
 
        if( !translate_parity( env, &(ttyset.c_cflag), parity ) )
 
771
        if( translate_parity( env, &(ttyset.c_cflag), parity ) )
680
772
        {
681
773
                report( "set_port_params: Invalid Parity Selected\n" );
682
774
                return(1);
755
847
 
756
848
   accept:     speed, data bits, stop bits, parity
757
849
   perform:    set the serial port parameters
758
 
   return:     void
 
850
   return:     jboolean 1 on error
759
851
   exceptions: UnsupportedCommOperationException
760
852
----------------------------------------------------------*/
761
 
JNIEXPORT void JNICALL RXTXPort(nativeSetSerialPortParams)(
 
853
JNIEXPORT jboolean JNICALL RXTXPort(nativeSetSerialPortParams)(
762
854
        JNIEnv *env, jobject jobj, jint speed, jint dataBits, jint stopBits,
763
855
        jint parity )
764
856
{
771
863
        if (cspeed < 0 )
772
864
        {
773
865
                report(" invalid cspeed\n");
 
866
/*
 
867
    For some reason the native exceptions are not being caught.  Moving this
 
868
    to the Java side fixed the issue.  taj.
774
869
                throw_java_exception( env, UNSUPPORTED_COMM_OPERATION,
775
870
                        "", "BaudRate could not be set to the specified value" );
776
 
                return;
 
871
*/
 
872
                return(1);
777
873
        }
778
874
 
779
875
 
781
877
        {
782
878
                report("set_port_params failed\n");
783
879
                LEAVE( "RXTXPort:nativeSetSerialPortParams" );
 
880
/*
 
881
    For some reason the native exceptions are not being caught.  Moving this
 
882
    to the Java side fixed the issue.  taj.
784
883
                throw_java_exception( env, UNSUPPORTED_COMM_OPERATION,
785
884
                        "nativeSetSerialPortParams", strerror( errno ) );
 
885
*/
 
886
                return(1);
786
887
        }
787
888
 
788
889
        LEAVE( "RXTXPort:nativeSetSerialPortParams" );
789
890
        report_time_end( );
790
 
        return;
 
891
        return(0);
791
892
}
792
893
 
793
894
/*----------------------------------------------------------
819
920
                case 2400:      return B2400;
820
921
                case 4800:      return B4800;
821
922
                case 9600:      return B9600;
 
923
#ifdef B14400
 
924
                case 14400:     return B14400;
 
925
#endif /* B14400 */
822
926
                case 19200:     return B19200;
 
927
#ifdef B28800
 
928
                case 28800:     return B28800;
 
929
#endif /* B28800 */
823
930
                case 38400:     return B38400;
824
 
#ifdef B57600
825
931
                case 57600:     return B57600;
826
 
#endif /* B57600 */
 
932
/* I don't think this is universal.. older UARTs never did these.  taj */
827
933
#ifdef B115200
828
 
                case 115200:    return B115200;
829
 
#endif /* B115200 */
830
 
#ifdef B230400
831
 
                case 230400:    return B230400;
832
 
#endif /* B230400 */
833
 
#ifdef B460800
834
 
                case 460800:    return B460800;
835
 
#endif /* B460800 */
836
 
#ifdef B14400
837
 
                case 14400:     return B14400;
838
 
#endif /* B14400 */
839
 
#ifdef B28800
840
 
                case 28800:     return B28800;
841
 
#endif /* B28800 */
 
934
                case 115200: return B115200;
 
935
#endif /*  B115200 */
842
936
#ifdef B128000  /* dima */
843
937
                case 128000:    return B128000;
844
938
#endif  /* dima */
 
939
#ifdef B230400
 
940
                case 230400: return B230400;
 
941
#endif /* B230400 */
845
942
#ifdef B256000  /* dima */
846
943
                case 256000:    return B256000;
847
944
#endif  /* dima */
 
945
#ifdef B460800
 
946
                case 460800: return B460800;
 
947
#endif /* B460800 */
 
948
#ifdef B500000
 
949
                case 500000: return B500000;
 
950
#endif /* B500000 */
 
951
#ifdef B576000
 
952
                case 576000: return B576000;
 
953
#endif /* B57600 */
 
954
#ifdef B921600
 
955
                case 921600: return B921600;
 
956
#endif /* B921600 */
 
957
#ifdef B1000000
 
958
                case 1000000: return B1000000;
 
959
#endif /* B1000000 */
 
960
#ifdef B1152000
 
961
                case 1152000: return B1152000;
 
962
#endif /* B1152000 */
 
963
#ifdef B1500000
 
964
                case 1500000: return B1500000;
 
965
#endif /* B1500000 */
 
966
#ifdef B2000000
 
967
                case 2000000: return B2000000;
 
968
#endif /* B2000000 */
 
969
#ifdef B2500000
 
970
                case 2500000: return B2500000;
 
971
#endif /* B2500000 */
 
972
#ifdef B3000000
 
973
                case 3000000: return B3000000;
 
974
#endif /* B3000000 */
 
975
#ifdef B3500000
 
976
                case 3500000: return B3500000;
 
977
#endif /* B3500000 */
 
978
#ifdef B4000000
 
979
                case 4000000: return B4000000;
 
980
#endif /* B4000000 */
848
981
        }
849
982
 
850
983
        /* Handle custom speeds */
861
994
 
862
995
   accept:     gnu.io.SerialPort.DATABITS_* constant
863
996
   perform:    set proper termios c_cflag bits
864
 
   return:     1 if successful
865
 
                                        0 if an exception is thrown
 
997
   return:     1 on error
866
998
   exceptions: UnsupportedCommOperationException
867
999
----------------------------------------------------------*/
868
1000
int translate_data_bits( JNIEnv *env, tcflag_t *cflag, jint dataBits )
873
1005
        switch( dataBits ) {
874
1006
                case JDATABITS_5:
875
1007
                        (*cflag) = temp | CS5;
876
 
                        return 1;
 
1008
                        return 0;
877
1009
                case JDATABITS_6:
878
1010
                        (*cflag) = temp | CS6;
879
 
                        return 1;
 
1011
                        return 0;
880
1012
                case JDATABITS_7:
881
1013
                        (*cflag) = temp | CS7;
882
 
                        return 1;
 
1014
                        return 0;
883
1015
                case JDATABITS_8:
884
1016
                        (*cflag) = temp | CS8;
885
 
                        return 1;
 
1017
                        return 0;
886
1018
        }
887
1019
 
888
1020
        LEAVE( "RXTXPort:translate_date_bits" );
 
1021
/*
 
1022
    For some reason the native exceptions are not being caught.  Moving this
 
1023
    to the Java side fixed the issue.  taj.
889
1024
        throw_java_exception( env, UNSUPPORTED_COMM_OPERATION,
890
1025
                "", "databit value not supported" );
891
 
        return 0;
 
1026
*/
 
1027
        return 1;
892
1028
}
893
1029
 
894
1030
/*----------------------------------------------------------
896
1032
 
897
1033
   accept:     gnu.io.SerialPort.STOPBITS_* constant
898
1034
   perform:    set proper termios c_cflag bits
899
 
   return:     1 if successful
900
 
                                        0 if an exception is thrown
 
1035
   return:     1 on error
901
1036
   exceptions: UnsupportedCommOperationException
902
1037
   comments:   If you specify 5 data bits and 2 stop bits, the port will
903
1038
               allegedly use 1.5 stop bits.  Does anyone care?
909
1044
                case STOPBITS_1:
910
1045
                        (*cflag) &= ~CSTOPB;
911
1046
                        LEAVE( "RXTXPort:translate_stop_bits" );
912
 
                        return 1;
 
1047
                        return 0;
913
1048
                /*  ok.. lets try putting it in and see if anyone notices */
914
1049
                case STOPBITS_1_5:
915
 
                        translate_data_bits( env, cflag, JDATABITS_5 );
 
1050
                        if ( translate_data_bits( env, cflag, JDATABITS_5 ) )
 
1051
                                return( 1 );
 
1052
                        return 0;
916
1053
                case STOPBITS_2:
917
1054
                        (*cflag) |= CSTOPB;
918
1055
                        LEAVE( "RXTXPort:translate_stop_bits" );
919
 
                        return 1;
 
1056
                        return 0;
920
1057
        }
921
1058
 
922
1059
        LEAVE( "RXTXPort:translate_stop_bits" );
 
1060
/*
 
1061
    For some reason the native exceptions are not being caught.  Moving this
 
1062
    to the Java side fixed the issue.  taj.
923
1063
        throw_java_exception( env, UNSUPPORTED_COMM_OPERATION,
924
1064
                "", "stopbit value not supported" );
925
 
        return 0;
 
1065
*/
 
1066
        return 1;
 
1067
}
 
1068
JNIEXPORT jint JNICALL RXTXPort(nativeGetFlowControlMode)(JNIEnv *env, jobject jobj, jint fd)
 
1069
{
 
1070
        struct termios ttyset;
 
1071
        int ret = 0;
 
1072
 
 
1073
        tcgetattr( fd, &ttyset );
 
1074
        
 
1075
        if( ttyset.c_cflag & HARDWARE_FLOW_CONTROL )
 
1076
        {
 
1077
                ret |= ( FLOWCONTROL_RTSCTS_IN | FLOWCONTROL_RTSCTS_OUT );
 
1078
        }
 
1079
        if ( ttyset.c_iflag & IXOFF )
 
1080
        {
 
1081
                ret |= FLOWCONTROL_XONXOFF_IN;
 
1082
        }
 
1083
        if ( ttyset.c_iflag & IXON )
 
1084
        {
 
1085
                ret |= FLOWCONTROL_XONXOFF_OUT;
 
1086
        }
 
1087
        return( (jint) ret );
 
1088
}
 
1089
JNIEXPORT jint JNICALL RXTXPort(nativeGetParity)(JNIEnv *env, jobject jobj, jint fd)
 
1090
{
 
1091
        struct termios ttyset;
 
1092
 
 
1093
        if( tcgetattr( fd, &ttyset ) < 0 )
 
1094
        {
 
1095
                report("nativeGetParity:  tcgetattr failed\n");
 
1096
                return( -1 );
 
1097
        }
 
1098
#ifdef  CMSPAR 
 
1099
        if ( ( ttyset.c_cflag & PARENB ) &&
 
1100
                ( ttyset.c_cflag & PARODD ) &&
 
1101
                ( ttyset.c_cflag & CMSPAR ) )
 
1102
        {
 
1103
                return( JPARITY_MARK );
 
1104
        }
 
1105
        else if ( ttyset.c_cflag & ( PARENB &&
 
1106
                ttyset.c_cflag & CMSPAR ) )
 
1107
        {
 
1108
                return( JPARITY_SPACE );
 
1109
        }
 
1110
#endif /* CMSPAR */
 
1111
        if ( ttyset.c_cflag & PARENB &&
 
1112
                ttyset.c_cflag & PARODD )
 
1113
        {
 
1114
                return( JPARITY_ODD );
 
1115
        }
 
1116
        else if ( ttyset.c_cflag & PARENB )
 
1117
        {
 
1118
                return( JPARITY_EVEN );
 
1119
        }
 
1120
        else
 
1121
        {
 
1122
                return( JPARITY_NONE );
 
1123
        }
926
1124
}
927
1125
 
928
1126
/*----------------------------------------------------------
929
1127
 translate_parity
930
1128
 
931
 
   accept:     javx.comm.SerialPort.PARITY_* constant
 
1129
   accept:     javax.comm.SerialPort.PARITY_* constant
932
1130
   perform:    set proper termios c_cflag bits
933
 
   return:     1 if successful
934
 
               0 if an exception is thrown
 
1131
   return:     1 on error
935
1132
   exceptions: UnsupportedCommOperationException
936
1133
   comments:   The CMSPAR bit should be used for 'mark' and 'space' parity,
937
1134
               but it's not in glibc's includes.  Oh well, rarely used anyway.
939
1136
int translate_parity( JNIEnv *env, tcflag_t *cflag, jint parity )
940
1137
{
941
1138
        ENTER( "translate_parity" );
942
 
        (*cflag) &= ~(PARENB | PARODD);
 
1139
#ifdef CMSPAR
 
1140
        (*cflag) &= ~(PARENB | PARODD | CMSPAR );
 
1141
#endif /* CMSPAR */
943
1142
        switch( parity ) {
944
1143
                case JPARITY_NONE:
945
1144
                        LEAVE( "translate_parity" );
946
 
                        return 1;
 
1145
                        return 0;
947
1146
                case JPARITY_EVEN:
948
1147
                        (*cflag) |= PARENB;
949
1148
                        LEAVE( "translate_parity" );
950
 
                        return 1;
 
1149
                        return 0;
951
1150
                case JPARITY_ODD:
952
1151
                        (*cflag) |= PARENB | PARODD;
953
1152
                        LEAVE( "translate_parity" );
954
 
                        return 1;
 
1153
                        return 0;
955
1154
#ifdef CMSPAR
956
1155
                case JPARITY_MARK:
957
1156
                        (*cflag) |= PARENB | PARODD | CMSPAR;
958
1157
                        LEAVE( "translate_parity" );
959
 
                        return 1;
 
1158
                        return 0;
960
1159
                case JPARITY_SPACE:
961
1160
                        (*cflag) |= PARENB | CMSPAR;
962
1161
                        LEAVE( "translate_parity" );
963
 
                        return 1;
 
1162
                        return 0;
964
1163
#endif /* CMSPAR */
965
1164
                default:
966
1165
                        printf("Parity missed %i\n", (int) parity );
967
1166
        }
968
1167
 
969
1168
        LEAVE( "translate_parity" );
 
1169
/*
 
1170
    For some reason the native exceptions are not being caught.  Moving this
 
1171
    to the Java side fixed the issue.  taj.
970
1172
        throw_java_exception( env, UNSUPPORTED_COMM_OPERATION,
971
1173
                "", "parity value not supported" );
972
 
        return 0;
 
1174
*/
 
1175
        return 1;
973
1176
}
974
1177
#if !defined(TIOCSERGETLSR) && !defined(WIN32)
975
1178
/*----------------------------------------------------------
1132
1335
        pthread_detach( tid );
1133
1336
#endif /* TIOCSERGETLSR */
1134
1337
        report("init_threads: get eis\n");
1135
 
        jeis  = (*eis->env)->GetFieldID( eis->env, eis->jclazz, "eis", "I" );
 
1338
        jeis  = (*eis->env)->GetFieldID( eis->env, eis->jclazz, "eis", "J" );
1136
1339
        report("init_threads: set eis\n");
1137
 
        (*eis->env)->SetIntField(eis->env, *eis->jobj, jeis, ( jint ) eis );
 
1340
        (*eis->env)->SetIntField(eis->env, *eis->jobj, jeis, ( size_t ) eis );
1138
1341
        report("init_threads:  stop\n");
1139
1342
        report_time_end( );
1140
1343
        return( 1 );
1168
1371
        do {
1169
1372
                sprintf( msg, "writeByte %c>>\n", byte );
1170
1373
                report( msg );
1171
 
                result=WRITE (fd, &byte, sizeof(unsigned char));
 
1374
                result=WRITE (fd, (void * ) &byte, sizeof(unsigned char));
1172
1375
        }  while (result < 0 && errno==EINTR);
 
1376
        if( result < 0 )
 
1377
        {
 
1378
                /* mexPrintf("GOT IT!!!\n"); */
 
1379
                goto fail;
 
1380
        }
1173
1381
/*
1174
1382
        This makes write for win32, glinux and Sol behave the same
1175
1383
#if defined ( __sun__ )
1178
1386
                result=tcdrain(fd);
1179
1387
                count++;
1180
1388
        }  while (result && errno==EINTR && count <3);
1181
 
#endif *//* __sun __ */
 
1389
#endif */ /* __sun __ */
1182
1390
#ifndef TIOCSERGETLSR
1183
1391
        if( ! interrupted )
1184
1392
        {
1200
1408
                report_time_end();
1201
1409
                return;
1202
1410
        }
 
1411
fail:
1203
1412
        throw_java_exception( env, IO_EXCEPTION, "writeByte",
1204
1413
                strerror( errno ) );
1205
1414
}
1239
1448
#endif /* __sun__ */
1240
1449
        fd = get_java_var( env, jobj,"fd","I" );
1241
1450
        body = (*env)->GetByteArrayElements( env, jbarray, 0 );
 
1451
        /* result=WRITE (fd, body + total + offset, count - total); 
 
1452
        (*env)->ReleaseByteArrayElements( env, jbarray, body, 0 ); */
 
1453
/* return; OH CRAP */
1242
1454
 
1243
1455
        report_time_start();
1244
1456
        ENTER( "writeArray" );
1249
1461
        */
1250
1462
 
1251
1463
        do {
1252
 
                result=WRITE (fd, body + total + offset, count - total); /* dima */
 
1464
                result=WRITE (fd, (void * ) ((char *) body + total + offset), count - total); /* dima */
1253
1465
                if(result >0){
1254
1466
                        total += result;
1255
1467
                }
1256
1468
                report("writeArray()\n");
1257
 
        }  while ( ( total < count ) || (result < 0 && errno==EINTR ) );
 
1469
        }  while ( ( total < count ) && (result < 0 && errno==EINTR ) );
 
1470
        if( result < 0 )
 
1471
        {
 
1472
                /* mexPrintf("GOT IT!!!\n"); */
 
1473
                goto fail;
 
1474
        }
1258
1475
/*
1259
1476
        This makes write for win32, glinux and Sol behave the same
1260
1477
#if defined ( __sun__ )
1263
1480
                result=tcdrain(fd);
1264
1481
                icount++;
1265
1482
        }  while (result && errno==EINTR && icount <3);
1266
 
#endif *//* __sun__ */
 
1483
#endif */ /* __sun__ */
1267
1484
        (*env)->ReleaseByteArrayElements( env, jbarray, body, 0 );
1268
1485
#ifndef TIOCSERGETLSR
1269
1486
        if( !interrupted )
1291
1508
        */
1292
1509
        LEAVE( "RXTXPort:writeArray" );
1293
1510
        report_time_end();
 
1511
fail:
1294
1512
        if( result < 0 ) throw_java_exception( env, IO_EXCEPTION,
1295
1513
                "writeArray", strerror( errno ) );
1296
1514
}
1312
1530
        jobject jobj, jboolean interrupted )
1313
1531
{
1314
1532
        int fd = get_java_var( env, jobj,"fd","I" );
1315
 
        struct event_info_struct *eis = ( struct event_info_struct * ) get_java_var( env, jobj, "eis", "I" );
 
1533
        struct event_info_struct *eis = ( struct event_info_struct * ) get_java_var( env, jobj, "eis", "J" );
1316
1534
        int result, count=0;
1317
1535
 
1318
1536
        char message[80];
1344
1562
#endif /* !TIOCSERGETLSR !WIN32 */
1345
1563
        if( eis && eis->eventflags[SPE_OUTPUT_BUFFER_EMPTY] )
1346
1564
        {
1347
 
                send_event( eis, SPE_OUTPUT_BUFFER_EMPTY, 1 );
 
1565
                struct event_info_struct myeis =
 
1566
                        build_threadsafe_eis( env, &jobj, eis );
 
1567
                send_event( &myeis, SPE_OUTPUT_BUFFER_EMPTY, 1 );
1348
1568
        }
1349
1569
        report_time_end( );
1350
1570
        return( JNI_FALSE );
1747
1967
        int fd = get_java_var( env, jobj,"fd","I" );
1748
1968
        struct serial_struct sstruct;
1749
1969
 
 
1970
        if ( ioctl( fd, TIOCGSERIAL, &sstruct ) < 0 )
 
1971
        {
 
1972
                goto fail;
 
1973
        }
 
1974
 
 
1975
        sstruct.baud_base =  (int) BaudBase;
 
1976
 
1750
1977
        if (    sstruct.baud_base < 1 ||
1751
1978
                ioctl( fd, TIOCSSERIAL, &sstruct ) < 0 )
1752
1979
        {
1753
 
                return( JNI_TRUE );
 
1980
                goto fail;
1754
1981
        }
1755
 
        return( JNI_FALSE );
 
1982
        return( ( jboolean ) 0 );
 
1983
fail:
 
1984
        throw_java_exception( env, IO_EXCEPTION, "nativeSetBaudBase",
 
1985
                strerror( errno ) );
 
1986
        return( ( jboolean ) 1 );
1756
1987
#else
1757
1988
        throw_java_exception( env, UNSUPPORTED_COMM_OPERATION,
1758
1989
                "nativeSetBaudBase", strerror( errno ) );
1759
 
        return( JNI_TRUE );
 
1990
        return( ( jboolean ) 1 );
1760
1991
#endif /* TIOCGSERIAL */
1761
1992
}
1762
1993
 
1784
2015
 
1785
2016
        if ( ioctl( fd, TIOCGSERIAL, &sstruct ) < 0 )
1786
2017
        {
1787
 
                return( ( jint ) -1 );
 
2018
                goto fail;
1788
2019
        }
1789
2020
        return( ( jint ) ( sstruct.baud_base ) );
 
2021
fail:
 
2022
        throw_java_exception( env, IO_EXCEPTION, "nativeGetBaudBase",
 
2023
                strerror( errno ) );
 
2024
        return( ( jint ) -1 );
1790
2025
#else
1791
2026
        throw_java_exception( env, UNSUPPORTED_COMM_OPERATION,
1792
2027
                "nativeGetBaudBase", strerror( errno ) );
1820
2055
 
1821
2056
        if ( ioctl( fd, TIOCGSERIAL, &sstruct ) < 0 )
1822
2057
        {
1823
 
                return( JNI_TRUE );
 
2058
                goto fail;
1824
2059
        }
1825
2060
 
1826
2061
        if (    sstruct.custom_divisor < 1 ||
1827
2062
                ioctl( fd, TIOCSSERIAL, &sstruct ) < 0 )
1828
2063
        {
1829
 
                return( JNI_TRUE );
 
2064
                goto fail;
1830
2065
        }
1831
 
        return( JNI_FALSE );
 
2066
        return( ( jboolean ) 0 );
 
2067
fail:
 
2068
        throw_java_exception( env, IO_EXCEPTION, "nativeSetDivisor",
 
2069
                strerror( errno ) );
 
2070
        return( ( jboolean ) 1 );
1832
2071
#else
1833
2072
        throw_java_exception( env, UNSUPPORTED_COMM_OPERATION,
1834
2073
                "nativeSetDivisor", strerror( errno ) );
1835
 
        return( JNI_TRUE );
 
2074
        return( ( jboolean ) 1 );
1836
2075
#endif /* TIOCGSERIAL */
1837
2076
}
1838
2077
 
1841
2080
 
1842
2081
   accept:      none
1843
2082
   perform:     Find the Divisor used for custom speeds
1844
 
   return:      Divisor
 
2083
   return:      Divisor negative value on error.
1845
2084
   exceptions:  Unsupported Comm Operation on systems not supporting
1846
2085
                TIOCGSERIAL
1847
2086
   comments:    
1860
2099
 
1861
2100
        if ( ioctl( fd, TIOCGSERIAL, &sstruct ) < 0 )
1862
2101
        {
1863
 
                return( ( jint ) -1 );
 
2102
                goto fail;
1864
2103
        }
1865
2104
 
1866
2105
        return( ( jint ) sstruct.custom_divisor );
 
2106
fail:
 
2107
        throw_java_exception( env, IO_EXCEPTION, "nativeGetDivisor",
 
2108
                strerror( errno ) );
 
2109
        return( ( jint ) -1 );
1867
2110
#else
1868
2111
        throw_java_exception( env, UNSUPPORTED_COMM_OPERATION,
1869
2112
                "nativeGetDivisor", strerror( errno ) );
1902
2145
 
1903
2146
        /* Open and lock the port so nothing else changes the setting */
1904
2147
 
1905
 
        if ( LOCK( filename, pid ) ) goto fail;;
 
2148
        if ( LOCK( filename, pid ) ) goto fail;
1906
2149
        
1907
2150
        fd = find_preopened_ports( filename );
1908
2151
        if( !fd )
2027
2270
        const char *filename = (*env)->GetStringUTFChars( env, jstr, 0 );
2028
2271
        int cspeed = translate_speed( env, baudrate );
2029
2272
 
 
2273
 
2030
2274
        ENTER( "RXTXPort:nativeStaticSetSerialPortParams" );
2031
2275
#ifndef WIN32
2032
2276
        pid = getpid();
2689
2933
{
2690
2934
        int ret, left, bytes = 0;
2691
2935
        long timeLeft, now = 0, start = 0;
2692
 
        char msg[80];
 
2936
        /* char msg[80]; */
2693
2937
        struct timeval tv, *tvP;
2694
2938
        fd_set rset;
2695
 
 
 
2939
        /* TRENT */
 
2940
        int flag, count = 0;
 
2941
        struct event_info_struct *eis = ( struct event_info_struct * )
 
2942
                get_java_var( env, *jobj,"eis","J" );
 
2943
        
2696
2944
        report_time_start();
 
2945
        flag = eis->eventflags[SPE_DATA_AVAILABLE];
 
2946
        eis->eventflags[SPE_DATA_AVAILABLE] = 0;
 
2947
/*
2697
2948
        ENTER( "read_byte_array" );
2698
2949
        sprintf(msg, "read_byte_array requests %i\n", length);
2699
2950
        report( msg );
 
2951
*/
2700
2952
        left = length;
2701
2953
        if (timeout >= 0)
2702
2954
                start = GetTickCount();
2703
 
        while( bytes < length )
 
2955
        while( bytes < length &&  count++ < 20 ) /* && !is_interrupted( eis ) )*/
2704
2956
        {
2705
2957
                if (timeout >= 0) {
2706
2958
                        now = GetTickCount();
2707
2959
                        if ( now-start >= timeout )
 
2960
                        {
 
2961
                                eis->eventflags[SPE_DATA_AVAILABLE] = flag;
2708
2962
                                return bytes;
 
2963
                        }
2709
2964
                }
2710
2965
 
2711
2966
                FD_ZERO(&rset);
2720
2975
                else{
2721
2976
                        tvP = NULL;
2722
2977
                }
2723
 
 
2724
 
                ret = SELECT(fd + 1, &rset, NULL, NULL, tvP);
 
2978
                /* FIXME HERE Trent */
 
2979
#ifndef WIN32
 
2980
                ret = SELECT( fd + 1, &rset, NULL, NULL, tvP );
 
2981
#else
 
2982
                ret = 1;
 
2983
#endif /* WIN32 */
2725
2984
                if (ret == -1){
2726
2985
                        report( "read_byte_array: select returned -1\n" );
2727
2986
                        LEAVE( "read_byte_array" );
 
2987
                        eis->eventflags[SPE_DATA_AVAILABLE] = flag;
2728
2988
                        return -1;
2729
2989
                }
2730
 
                else if (ret > 0){
 
2990
                else if (ret > 0)
 
2991
                {
2731
2992
                        if ((ret = READ( fd, buffer + bytes, left )) < 0 ){
2732
2993
                                if (errno != EINTR && errno != EAGAIN){
2733
2994
                                        report( "read_byte_array: read returned -1\n" );
2734
2995
                                        LEAVE( "read_byte_array" );
 
2996
                                        eis->eventflags[SPE_DATA_AVAILABLE] = flag;
2735
2997
                                        return -1;
2736
2998
                                }
 
2999
                                eis->eventflags[SPE_DATA_AVAILABLE] = flag;
 
3000
                                return -1;
2737
3001
                        }
2738
3002
                        else if ( ret ) {
2739
3003
                                bytes += ret;
2750
3014
                Nicolas <ripley@8d.com>
2751
3015
                */
2752
3016
                        else {
2753
 
                                usleep(10);
 
3017
                                /* usleep(10); */
 
3018
                                usleep(1000);
2754
3019
                        }
2755
3020
                }
2756
3021
        }
2757
3022
 
 
3023
/*
 
3024
        if( count > 19 )
 
3025
        {
 
3026
                throw_java_exception( env, IO_EXCEPTION, "read_byte_array",
 
3027
                        "No data available" );
 
3028
        }
 
3029
 
2758
3030
        sprintf(msg, "read_byte_array returns %i\n", bytes);
2759
3031
        report( msg );
2760
3032
        LEAVE( "read_byte_array" );
2761
3033
        report_time_end();
 
3034
*/
 
3035
        eis->eventflags[SPE_DATA_AVAILABLE] = flag;
2762
3036
        return bytes;
2763
3037
}
2764
3038
 
2805
3079
        report_time_end();
2806
3080
        return bytes;
2807
3081
}
 
3082
 
 
3083
 
2808
3084
int read_byte_array(    JNIEnv *env,
2809
3085
                        jobject *jobj,  
2810
3086
                        int fd,
2816
3092
        /* int count = 0; */
2817
3093
        fd_set rfds;
2818
3094
        struct timeval sleep;
 
3095
        struct event_info_struct *eis = find_eis( fd );
 
3096
        
2819
3097
#ifndef WIN32
2820
3098
        struct timeval *psleep=&sleep;
2821
3099
#endif /* WIN32 */
2846
3124
                    work on win32.  The select code cannot be accessed
2847
3125
                    from both the Monitor Thread and the Reading Thread.
2848
3126
 
2849
 
                    This keeps the cpu from racing but the select() code
2850
 
                    will have to be fixed at some point.
2851
3127
                */
2852
3128
                ret = RXTXPort(nativeavailable)( env, *jobj );
2853
3129
#endif /* WIN32 */
3067
3343
        unsigned char buffer[ 1 ];
3068
3344
        int fd = get_java_var( env, jobj,"fd","I" );
3069
3345
        int timeout = get_java_var( env, jobj, "timeout", "I" );
3070
 
        char msg[80];
 
3346
        /* char msg[80]; */
3071
3347
 
 
3348
/*
3072
3349
        ENTER( "RXTXPort:readByte" );
3073
3350
        report_time_start( );
 
3351
*/
3074
3352
        bytes = read_byte_array( env, &jobj, fd, buffer, 1, timeout );
3075
3353
        if( bytes < 0 ) {
3076
3354
                LEAVE( "RXTXPort:readByte" );
3078
3356
                        strerror( errno ) );
3079
3357
                return -1;
3080
3358
        }
 
3359
/*
3081
3360
        LEAVE( "RXTXPort:readByte" );
3082
3361
        sprintf( msg, "readByte return(%i)\n", bytes ? buffer[ 0 ] : -1 );
3083
3362
        report( msg );
3084
3363
        report_time_end( );
 
3364
*/
3085
3365
        return (bytes ? (jint)buffer[ 0 ] : -1);
3086
3366
}
3087
3367
 
3102
3382
{
3103
3383
        int bytes;
3104
3384
        jbyte *body;
3105
 
        char msg[80];
 
3385
        /* char msg[80]; */
3106
3386
        int fd = get_java_var( env, jobj, "fd", "I" );
3107
3387
        int timeout = get_java_var( env, jobj, "timeout", "I" );
3108
3388
 
 
3389
/*
3109
3390
        ENTER( "readArray" );
3110
3391
        report_time_start( );
3111
 
        if( length > SSIZE_MAX || length < 0 ) {
 
3392
*/
 
3393
        if( (size_t) length > SSIZE_MAX || (size_t) length < 0 ) {
3112
3394
                report( "RXTXPort:readArray length > SSIZE_MAX" );
3113
3395
                LEAVE( "RXTXPort:readArray" );
3114
3396
                throw_java_exception( env, ARRAY_INDEX_OUT_OF_BOUNDS,
3125
3407
                        strerror( errno ) );
3126
3408
                return -1;
3127
3409
        }
3128
 
        sprintf( msg, "RXTXPort:readArray: %i %i\n", (int) length, bytes);
3129
 
        report( msg );
3130
 
        report_time_end( );
3131
 
        LEAVE( "RXTXPort:readArray" );
 
3410
/*
 
3411
        sprintf( msg, "RXTXPort:readArray: %i %i\n", (int) length, bytes);
 
3412
        report( msg );
 
3413
        report_time_end( );
 
3414
        LEAVE( "RXTXPort:readArray" );
 
3415
*/
 
3416
        return (bytes);
 
3417
}
 
3418
 
 
3419
/*----------------------------------------------------------
 
3420
RXTXPort.nativeClearCommInput
 
3421
 
 
3422
   accept:       none
 
3423
   perform:      try to clear the input.
 
3424
   return:       true on success, false on error
 
3425
   exceptions:   none
 
3426
   comments:     This is an extension to commapi.
 
3427
----------------------------------------------------------*/
 
3428
JNIEXPORT jboolean JNICALL RXTXPort(nativeClearCommInput)( JNIEnv *env,
 
3429
        jobject jobj )
 
3430
{
 
3431
        int fd = get_java_var( env, jobj, "fd", "I" );
 
3432
        if ( tcflush( fd, TCIFLUSH ) )
 
3433
                return( JNI_FALSE );
 
3434
        return( JNI_TRUE );
 
3435
}
 
3436
/*----------------------------------------------------------
 
3437
RXTXPort.readTerminatedArray
 
3438
 
 
3439
   accept:       offset (offset to start storing data in the jbarray) and
 
3440
                 Length (bytes to read).  Terminator - 2 bytes that we
 
3441
                 dont read past
 
3442
   perform:      read bytes from the port into a byte array
 
3443
   return:       bytes read on success
 
3444
                 0 on read timeout
 
3445
   exceptions:   IOException
 
3446
   comments:     throws ArrayIndexOutOfBoundsException if asked to
 
3447
                 read more than SSIZE_MAX bytes
 
3448
                 timeout is not properly handled
 
3449
 
 
3450
                 This is an extension to commapi.
 
3451
----------------------------------------------------------*/
 
3452
JNIEXPORT jint JNICALL RXTXPort(readTerminatedArray)( JNIEnv *env,
 
3453
        jobject jobj, jbyteArray jbarray, jint offset, jint length,
 
3454
        jbyteArray jterminator )
 
3455
{
 
3456
        int bytes, total = 0;
 
3457
        jbyte *body, *terminator;
 
3458
        /* char msg[80]; */
 
3459
        int fd = get_java_var( env, jobj, "fd", "I" );
 
3460
        int timeout = get_java_var( env, jobj, "timeout", "I" );
 
3461
 
 
3462
/*
 
3463
        ENTER( "readArray" );
 
3464
        report_time_start( );
 
3465
*/
 
3466
        if( (size_t) length > SSIZE_MAX || (size_t) length < 0 ) {
 
3467
                report( "RXTXPort:readArray length > SSIZE_MAX" );
 
3468
                LEAVE( "RXTXPort:readArray" );
 
3469
                throw_java_exception( env, ARRAY_INDEX_OUT_OF_BOUNDS,
 
3470
                        "readArray", "Invalid length" );
 
3471
                return -1;
 
3472
        }
 
3473
        body = (*env)->GetByteArrayElements( env, jbarray, 0 );
 
3474
        terminator = (*env)->GetByteArrayElements( env, jterminator, 0 );
 
3475
        do
 
3476
        {
 
3477
                bytes = read_byte_array( env, &jobj, fd, (unsigned char *)(body+offset + total ), 1 , timeout );/* dima */
 
3478
                total += bytes;
 
3479
                if( bytes < 0 ) {
 
3480
                        report( "RXTXPort:readArray bytes < 0" );
 
3481
                        LEAVE( "RXTXPort:readArray" );
 
3482
                        throw_java_exception( env, IO_EXCEPTION, "readArray",
 
3483
                                strerror( errno ) );
 
3484
                        return -1;
 
3485
                }
 
3486
                if ( total > 1 && terminator[1] ==  body[total -1] &&
 
3487
                        terminator[ 0 ] == body[ total -2 ]
 
3488
                )
 
3489
                {
 
3490
                        report("Got terminator!\n" );
 
3491
                        break;          
 
3492
                }
 
3493
                        
 
3494
        } while ( bytes > 0 && total < length );
 
3495
        (*env)->ReleaseByteArrayElements( env, jbarray, body, 0 );
 
3496
/*
 
3497
        sprintf( msg, "RXTXPort:readArray: %i %i\n", (int) length, bytes);
 
3498
        report( msg );
 
3499
        report_time_end( );
 
3500
        LEAVE( "RXTXPort:readArray" );
 
3501
*/
3132
3502
        return (bytes);
3133
3503
}
3134
3504
 
3146
3516
{
3147
3517
        int fd = get_java_var( env, jobj,"fd","I" );
3148
3518
        int result;
 
3519
/*
3149
3520
        char message[80];
3150
3521
 
3151
 
/*
 
3522
 
3152
3523
        ENTER( "RXTXPort:nativeavailable" );
3153
3524
 
3154
3525
    On SCO OpenServer FIONREAD always fails for serial devices,
3165
3536
                goto fail;
3166
3537
        }
3167
3538
#endif /* FIORDCHK */
 
3539
        if (result == -1) {
 
3540
                goto fail;
 
3541
        }
 
3542
/*
3168
3543
        sprintf(message, "    nativeavailable: FIORDCHK result %d, \
3169
3544
                errno %d\n", result , result == -1 ? errno : 0);
3170
3545
        report_verbose( message );
3171
 
        if (result == -1) {
3172
 
                goto fail;
3173
 
        }
3174
3546
        if( result )
3175
3547
        {
3176
3548
                sprintf(message, "    nativeavailable: FIORDCHK result %d, \
3177
3549
                                errno %d\n", result , result == -1 ? errno : 0);
3178
3550
                report( message );
3179
3551
        }
3180
 
/*
3181
3552
        LEAVE( "RXTXPort:nativeavailable" );
3182
3553
*/
3183
3554
        return (jint)result;
3216
3587
        if( tcgetattr( fd, &ttyset ) ) goto fail;
3217
3588
        
3218
3589
        if ( flowmode & ( FLOWCONTROL_RTSCTS_IN | FLOWCONTROL_RTSCTS_OUT ) )
 
3590
        {
3219
3591
                ttyset.c_cflag |= HARDWARE_FLOW_CONTROL;
 
3592
        }
3220
3593
        else ttyset.c_cflag &= ~HARDWARE_FLOW_CONTROL;
3221
3594
 
3222
3595
        ttyset.c_iflag &= ~IXANY;
3223
3596
 
3224
3597
        if ( flowmode & FLOWCONTROL_XONXOFF_IN )
 
3598
        {
3225
3599
                ttyset.c_iflag |= IXOFF;
 
3600
        }
3226
3601
        else ttyset.c_iflag &= ~IXOFF;
3227
3602
 
3228
3603
        if ( flowmode & FLOWCONTROL_XONXOFF_OUT )
 
3604
        {
 
3605
                
3229
3606
                ttyset.c_iflag |= IXON;
 
3607
        }
3230
3608
        else ttyset.c_iflag &= ~IXON;
3231
 
 
 
3609
/* TRENT */
3232
3610
        if( tcsetattr( fd, TCSANOW, &ttyset ) ) goto fail;
3233
3611
        LEAVE( "RXTXPort:setflowcontrol" );
3234
3612
        return;
3252
3630
void unlock_monitor_thread( struct event_info_struct *eis )
3253
3631
{
3254
3632
        JNIEnv *env = eis->env;
 
3633
        jobject jobj = *(eis->jobj);
3255
3634
 
3256
 
        jfieldID jfid = (*env)->GetFieldID( env, eis->jclazz,
3257
 
                "MonitorThreadLock", "Z" );
3258
 
        (*env)->SetBooleanField( env, *eis->jobj, jfid, JNI_FALSE );
 
3635
        jfieldID jfid = (*env)->GetFieldID( env, (*env)->GetObjectClass( env, jobj ), "MonitorThreadLock", "Z" );
 
3636
        (*env)->SetBooleanField( env, jobj, jfid, (jboolean) 0 );
3259
3637
}
3260
3638
 
3261
3639
/*----------------------------------------------------------
3274
3652
 
3275
3653
        if( ! eis->eventflags[SPE_OUTPUT_BUFFER_EMPTY] )
3276
3654
        {
3277
 
                report( "check_line_status_registe OUPUT_BUFFER_EMPTY not set\n" );
 
3655
                /* This occurs constantly so remove for now
 
3656
                 * report( "check_line_status_registe OUPUT_BUFFER_EMPTY not set\n" );
 
3657
                 */
3278
3658
                return 0;
3279
3659
        }
3280
3660
        if ( fstat( eis->fd, &fstatbuf ) )
3543
3923
                if( check_line_status_register( eis ) )
3544
3924
                        return;
3545
3925
 
3546
 
#ifndef WIN32 /* something is wrong here */
3547
3926
        if ( eis && eis->has_tiocgicount )
3548
3927
                check_cgi_count( eis );
 
3928
#ifndef WIN32 /* something is wrong here */
3549
3929
#endif /* WIN32 */
3550
3930
 
3551
3931
        check_tiocmget_changes( eis );
3552
 
 
3553
3932
        if( eis && port_has_changed_fionread( eis ) )
3554
3933
        {
3555
3934
                if(!eis->eventflags[SPE_DATA_AVAILABLE] )
3558
3937
/*
3559
3938
                        report(".");
3560
3939
*/
 
3940
                        usleep(20000);
3561
3941
#if !defined(__sun__)
3562
3942
        /* FIXME: No time to test on all OS's for production */
3563
3943
                        usleep(20000);
3568
3948
                if(!send_event( eis, SPE_DATA_AVAILABLE, 1 ))
3569
3949
                {
3570
3950
                        /* select wont block */
 
3951
        /* FIXME: No time to test on all OS's for production */
 
3952
/* REMOVE goes around usleep */
3571
3953
#if !defined(__sun__)
3572
 
        /* FIXME: No time to test on all OS's for production */
3573
 
                        usleep(20000);
3574
3954
#endif /* !__sun__ */
3575
 
/*
3576
 
                        system_wait();
3577
 
*/
3578
3955
                }
 
3956
                usleep(20000);
3579
3957
        }
3580
3958
}
3581
3959
 
3693
4071
----------------------------------------------------------*/
3694
4072
JNIEXPORT void JNICALL RXTXPort(eventLoop)( JNIEnv *env, jobject jobj )
3695
4073
{
 
4074
#ifdef WIN32
 
4075
        int i = 0;
 
4076
#endif /* WIN32 */
3696
4077
        struct event_info_struct eis;
3697
 
        jclass jclazz = (*env)->GetObjectClass( env, jobj );
3698
 
        jfieldID jfid = (*env)->GetFieldID( env, jclazz,
3699
 
                                                "MonitorThreadCloseLock", "Z" );
3700
 
        eis.jclazz = jclazz;
 
4078
        eis.jclazz = (*env)->GetObjectClass( env, jobj );
3701
4079
        eis.env = env;
3702
4080
        eis.jobj = &jobj;
3703
4081
        eis.initialised = 0;
3709
4087
        do{
3710
4088
                report_time_eventLoop( );
3711
4089
                do {
3712
 
                        /* report( "." ); */
3713
 
                        eis.ret = SELECT( eis.fd + 1, &eis.rfds, NULL, NULL,
3714
 
                                        &eis.tv_sleep );
3715
4090
                        /* nothing goes between this call and select */
3716
4091
                        if( eis.closing )
3717
4092
                        {
3718
4093
                                report("eventLoop: got interrupt\n");
3719
4094
                                finalize_threads( &eis );
3720
4095
                                finalize_event_info_struct( &eis );
3721
 
                                (*env)->SetBooleanField( env, jobj,
3722
 
                                                        jfid, JNI_FALSE );
3723
4096
                                LEAVE("eventLoop");
3724
4097
                                return;
3725
4098
                        }
3726
 
                        usleep(20000);
 
4099
#ifndef WIN32
 
4100
                        /* report( "." ); */
 
4101
                        eis.ret = SELECT( eis.fd + 1, &eis.rfds, NULL, NULL,
 
4102
                                        &eis.tv_sleep );
 
4103
#else
 
4104
                        /*
 
4105
                            termios.c:serial_select is instable for some
 
4106
                            reason
 
4107
 
 
4108
                            polling is not blowing up.
 
4109
                        */
3727
4110
/*
3728
 
                         Trent system_wait();
 
4111
                        usleep(5000);
3729
4112
*/
 
4113
                        eis.ret=1;
 
4114
                        while( i++ < 5 )
 
4115
                        {
 
4116
                                if(eis.eventflags[SPE_DATA_AVAILABLE] )
 
4117
                                {
 
4118
                                        if( port_has_changed_fionread( &eis ) )
 
4119
                                        {
 
4120
                                                send_event( &eis, SPE_DATA_AVAILABLE, 1 );
 
4121
                                        }
 
4122
                                }
 
4123
                                usleep(1000);
 
4124
                        }
 
4125
                        i = 0;
 
4126
#endif /* WIN32 */
3730
4127
                }  while ( eis.ret < 0 && errno == EINTR );
3731
4128
                if( eis.ret >= 0 )
3732
4129
                {
3739
4136
}
3740
4137
 
3741
4138
/*----------------------------------------------------------
3742
 
RXTXCommDriver.nativeGetVersion
 
4139
RXTXVersion.nativeGetVersion
3743
4140
 
3744
4141
   accept:      none
3745
4142
   perform:     return the current version 
3748
4145
   comments:    This is used to avoid mixing versions of the .jar and
3749
4146
                native library.
3750
4147
                First introduced in rxtx-1.5-9
 
4148
                Moved from RXTXCommDriver to RXTXVersion in rxtx-2.1-7
3751
4149
                
3752
4150
----------------------------------------------------------*/
3753
 
JNIEXPORT jstring JNICALL RXTXCommDriver(nativeGetVersion) (JNIEnv *env,
 
4151
JNIEXPORT jstring JNICALL RXTXVersion(nativeGetVersion) (JNIEnv *env,
3754
4152
        jclass jclazz )
3755
4153
{
3756
 
        return (*env)->NewStringUTF( env, "RXTX-2.1-6" );
 
4154
        return (*env)->NewStringUTF( env, "RXTX-2.1-7" );
3757
4155
}
3758
4156
 
3759
4157
/*----------------------------------------------------------
3787
4185
        /* We opened the file in this thread, use this pid to unlock */
3788
4186
#ifndef WIN32
3789
4187
        pid = getpid();
 
4188
#else
 
4189
        char full_windows_name[80];
3790
4190
#endif /* WIN32 */
3791
4191
 
3792
4192
        ENTER( "RXTXPort:testRead" );
3793
4193
#ifdef TRENT_IS_HERE_DEBUGGING_ENUMERATION
3794
4194
        /* vmware lies about which ports are there causing irq conflicts */
3795
4195
        /* this is for testing only */
3796
 
        if( !strcmp( name, "COM1" ) )
 
4196
        if( !strcmp( name, "COM1" ) || !strcmp( name, "COM2") )
3797
4197
        {
 
4198
                printf("%s is good\n",name);
3798
4199
                sprintf( message, "testRead: %s is good!\n", name );
3799
4200
                report( message );
3800
4201
                (*env)->ReleaseStringUTFChars( env, tty_name, name );
3804
4205
        return( JNI_FALSE );
3805
4206
#endif /* TRENT_IS_HERE_DEBUGGING_ENUMERATION */
3806
4207
#ifdef WIN32
3807
 
        ret = serial_test((char *) name );
 
4208
        strcpy( full_windows_name, DEVICEDIR );
 
4209
        strcat( full_windows_name, name );
 
4210
        ret = serial_test((char *) full_windows_name );
3808
4211
        (*env)->ReleaseStringUTFChars( env, tty_name, name );
3809
4212
        return(ret);
3810
4213
#endif /* WIN32 */
4470
4873
   exceptions:  none
4471
4874
   comments:
4472
4875
----------------------------------------------------------*/
4473
 
int get_java_var( JNIEnv *env, jobject jobj, char *id, char *type )
 
4876
size_t get_java_var( JNIEnv *env, jobject jobj, char *id, char *type )
4474
4877
{
4475
4878
        int result = 0;
4476
4879
        jclass jclazz = (*env)->GetObjectClass( env, jobj );
4696
5099
#endif /* LFS */
4697
5100
 
4698
5101
/*----------------------------------------------------------
 
5102
 lib_lock_dev_unlock
 
5103
 
 
5104
   accept:      The name of the device to try to unlock
 
5105
   perform:     Remove a lock file if there is one using a
 
5106
                lock file server.
 
5107
   return:      1 on failure 0 on success
 
5108
   exceptions:  none
 
5109
   comments:    This is for use with liblockdev which comes with Linux
 
5110
                distros.  I suspect it will be problematic with embeded
 
5111
                Linux.   taj
 
5112
 
 
5113
----------------------------------------------------------*/
 
5114
#ifdef LIBLOCKDEV
 
5115
int lib_lock_dev_unlock( const char *filename, int pid )
 
5116
{
 
5117
        if( dev_unlock( filename, pid ) )
 
5118
        {
 
5119
                report("fhs_unlock: Unable to remove LockFile\n");
 
5120
                return(1);
 
5121
        }
 
5122
        return(0);
 
5123
}
 
5124
#endif /* LIBLOCKDEV */
 
5125
 
 
5126
/*----------------------------------------------------------
 
5127
 lib_lock_dev_lock
 
5128
 
 
5129
   accept:      The name of the device to try to lock
 
5130
                termios struct
 
5131
   perform:     Create a lock file if there is not one already.
 
5132
   return:      1 on failure 0 on success
 
5133
   exceptions:  none
 
5134
   comments:    This is for use with liblockdev which comes with Linux
 
5135
                distros.  I suspect it will be problematic with embeded
 
5136
                Linux.   taj
 
5137
 
 
5138
                One could load the library here rather than link it and
 
5139
                always try to use this.
 
5140
 
 
5141
----------------------------------------------------------*/
 
5142
#ifdef LIBLOCKDEV
 
5143
int lib_lock_dev_lock( const char *filename, int pid )
 
5144
{
 
5145
        char message[80];
 
5146
        printf("LOCKING %s\n", filename);
 
5147
        if ( dev_testlock( filename ) )
 
5148
        {
 
5149
                report( "fhs_lock() lockstatus fail\n" );
 
5150
                return 1;
 
5151
        }
 
5152
        if ( dev_lock( filename ) )
 
5153
        {
 
5154
                sprintf( message,
 
5155
                        "RXTX fhs_lock() Error: creating lock file for: %s: %s\n",
 
5156
                        filename, strerror(errno) );
 
5157
                report_error( message );
 
5158
                return 1;
 
5159
        }
 
5160
        return( 0 );
 
5161
}
 
5162
#endif /* LIBLOCKDEV */
 
5163
 
 
5164
/*----------------------------------------------------------
4699
5165
 fhs_lock
4700
5166
 
4701
5167
   accept:      The name of the device to try to lock
5075
5541
        testLockFile = fopen (testLockAbsFileName, "w+");
5076
5542
        if (NULL == testLockFile)
5077
5543
        {
5078
 
                report_error("check_group_uucp(): error testing lock file creation Error details: ");
 
5544
                report_error("check_group_uucp(): error testing lock file "
 
5545
                        "creation Error details:");
5079
5546
                report_error(strerror(errno));
5080
 
 
5081
5547
                free(testLockAbsFileName);
5082
5548
                return 1;
5083
5549
        }
5201
5667
        const char *lockprefixes[] = { "LCK..", "lk..", "LK.", NULL }; 
5202
5668
        char *p, file[80], pid_buffer[20], message[80];
5203
5669
        int i = 0, j, k, fd , pid;
5204
 
        struct stat buf;
5205
 
        struct stat buf2;
 
5670
        struct stat buf, buf2, lockbuf;
5206
5671
 
5207
5672
        j = strlen( port_filename );
5208
5673
        p = ( char * ) port_filename+j;
5209
5674
        while( *( p-1 ) != '/' && j-- !=1 ) p--;
5210
5675
 
 
5676
        stat(LOCKDIR, &lockbuf);
 
5677
 
5211
5678
        while( lockdirs[i] )
5212
5679
        {
5213
5680
                /*
5219
5686
                   if it is there is it not the expected lock dir?
5220
5687
                */
5221
5688
                if( !stat( lockdirs[i], &buf2 ) &&
 
5689
                        buf2.st_ino != lockbuf.st_ino &&
5222
5690
                        strncmp( lockdirs[i], LOCKDIR, strlen( lockdirs[i] ) ) )
5223
5691
                {
5224
5692
                        j = strlen( port_filename );
5390
5858
        fprintf(stderr,"\n" );
5391
5859
#endif /* DEBUG */
5392
5860
}
 
5861
 
 
5862
/*----------------------------------------------------------
 
5863
get_java_environment
 
5864
 
 
5865
   accept:      pointer to the virtual machine
 
5866
                flag to know if we are attached
 
5867
   return:      pointer to the Java Environment
 
5868
   exceptions:  none
 
5869
   comments:    see JNI_OnLoad.  For getting the JNIEnv in the thread
 
5870
                used to monitor for output buffer empty.
 
5871
----------------------------------------------------------*/
 
5872
JNIEnv *get_java_environment(JavaVM *java_vm,  jboolean *was_attached){
 
5873
        void **env = NULL;
 
5874
        jint err_get_env;
 
5875
        if(java_vm == NULL) return (JNIEnv *) *env;
 
5876
        *was_attached = JNI_FALSE;
 
5877
 
 
5878
        err_get_env = (*java_vm)->GetEnv(
 
5879
                java_vm,
 
5880
                env,
 
5881
                JNI_VERSION_1_2
 
5882
        );
 
5883
        if(err_get_env == JNI_ERR) return NULL;
 
5884
        if(err_get_env == JNI_EDETACHED){
 
5885
                (*java_vm)->AttachCurrentThread(
 
5886
                        java_vm,
 
5887
                        env,
 
5888
                        (void **) NULL
 
5889
                );
 
5890
                if(*env != NULL) *was_attached = JNI_TRUE;
 
5891
        }else if(err_get_env != JNI_OK) return (JNIEnv *) NULL;
 
5892
        return (JNIEnv *) *env;
 
5893
}
 
5894
 
 
5895
/*----------------------------------------------------------
 
5896
JNI_OnLoad
 
5897
 
 
5898
   accept:      JavaVM pointer to the Vertial Machine
 
5899
                void * reserved ???
 
5900
   return:      jint JNI version used.
 
5901
   exceptions:  none
 
5902
   comments:    http://java.sun.com/j2se/1.4.2/docs/guide/jni/jni-14.html
 
5903
                http://java.sun.com/j2se/1.4.2/docs/guide/jni/jni-12.html
 
5904
                grab the Java VM pointer when the library loads for later use
 
5905
                in the drain thread.  Also lets Java know we are using the
 
5906
                1.4 API so we can get pointers later.
 
5907
----------------------------------------------------------*/
 
5908
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *java_vm, void *reserved)
 
5909
{
 
5910
        javaVM = java_vm;
 
5911
        printf("Experimental:  JNI_OnLoad called.\n");
 
5912
        return JNI_VERSION_1_2;  /* JNI API used */
 
5913
}
 
5914
 
 
5915
/*----------------------------------------------------------
 
5916
JNI_OnUnload
 
5917
 
 
5918
   accept:      JavaVM pointer to the Vertial Machine
 
5919
                void * reserved ???
 
5920
   return:      none
 
5921
   exceptions:  none
 
5922
   comments:    http://java.sun.com/j2se/1.4.2/docs/guide/jni/jni-14.html
 
5923
                http://java.sun.com/j2se/1.4.2/docs/guide/jni/jni-12.html
 
5924
                final library cleanup here.  
 
5925
----------------------------------------------------------*/
 
5926
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved)
 
5927
{
 
5928
        /* never called it appears */
 
5929
        printf("Experimental:  JNI_OnUnload called.\n");
 
5930
}
 
5931
 
 
5932
#ifdef asdf
 
5933
/*----------------------------------------------------------
 
5934
printj
 
5935
 
 
5936
   accept:      like vwprintf()
 
5937
   return:      number of jchars written or -1
 
5938
   exceptions:  none
 
5939
   comments:    prints data using System.out.print()
 
5940
----------------------------------------------------------*/
 
5941
int printj(JNIEnv *env, wchar_t *fmt, ...)
 
5942
{
 
5943
        wchar_t buf[1024];
 
5944
        int retval;
 
5945
        jstring jsBuf;
 
5946
        jclass clsSystem, clsOut;
 
5947
        jfieldID jfid;
 
5948
        jobject objOut;
 
5949
        jmethodID midPrint;
 
5950
 
 
5951
        va_list ap;
 
5952
        va_start(ap, fmt);
 
5953
        retval = _vsnwprintf(buf, 1024, fmt, ap);
 
5954
        va_end(ap);
 
5955
        buf[1023] = '\0';
 
5956
  
 
5957
        if((clsSystem = env->FindClass("java/lang/System")) == NULL)
 
5958
        {
 
5959
                IF_DEBUG
 
5960
                (
 
5961
                        env->ExceptionDescribe();
 
5962
                )
 
5963
                env->ExceptionClear();
 
5964
                return -1;
 
5965
        }
 
5966
  
 
5967
        if( ( jfid = env->GetStaticFieldID(clsSystem,
 
5968
                "out", "Ljava/io/PrintStream;" ) ) == NULL )
 
5969
        {
 
5970
                IF_DEBUG
 
5971
                (
 
5972
                        env->ExceptionDescribe();
 
5973
                )
 
5974
                env->ExceptionClear();
 
5975
                env->DeleteLocalRef(clsSystem);
 
5976
                return -1;
 
5977
        }
 
5978
  
 
5979
        objOut = env->GetStaticObjectField(clsSystem, jfid);
 
5980
        clsOut = env->GetObjectClass(objOut);
 
5981
 
 
5982
        if( ( midPrint = env->GetMethodID(clsOut, "print",
 
5983
                "(Ljava/lang/String;)V" ) ) == NULL )
 
5984
        {
 
5985
                IF_DEBUG
 
5986
                (
 
5987
                        env->ExceptionDescribe();
 
5988
                )
 
5989
                env->ExceptionClear();
 
5990
                env->DeleteLocalRef(clsOut);
 
5991
                env->DeleteLocalRef(clsSystem);
 
5992
                return -1;
 
5993
        }
 
5994
  
 
5995
        jsBuf = env->NewString(buf, wcslen(buf));
 
5996
 
 
5997
        env->CallVoidMethod(objOut, midPrint, jsBuf);
 
5998
 
 
5999
        env->DeleteLocalRef(jsBuf);
 
6000
        env->DeleteLocalRef(clsOut);
 
6001
        env->DeleteLocalRef(clsSystem);
 
6002
  
 
6003
        return retval;
 
6004
}
 
6005
/*
 
6006
        jclass cls = ( *env )->FindClass( env, "System.Thread" );
 
6007
        jmethodID mid = ( *env )->GetStaticMethodID( env, cls, "Sleep", "(I)V" );
 
6008
        (*env)->CallStaticVoidMethod(env, cls, mid, 1);
 
6009
*/
 
6010
#endif /* asdf */
 
6011