Subversion Repositories Programming Utils

Rev

Rev 40 | Rev 55 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
13 rm5248 1
#ifdef _WIN32
2
        #include <windows.h>
3
 
4
        #define SPEED_SWITCH(SPD,io) case SPD: io.BaudRate = CBR_##SPD; break;
23 rm5248 5
        #define GET_SPEED_SWITCH(SPD,io) case CBR_##SPD: return SPD;
13 rm5248 6
 
7
        #define GET_SERIAL_PORT_STRUCT( port, io_name ) DCB io_name = {0};\
8
                                                                                                io_name.DCBlength = sizeof( io_name ); \
9
                                                                                                if (!GetCommState( port, &io_name ) ) { \
27 rm5248 10
                                                                                                printf("bad get comm\n");\
13 rm5248 11
                                                                                                        return -1;\
12
                                                                                                }
13
        #define SET_SERIAL_PORT_STRUCT( port, io_name )         if( !SetCommState( port, &io_name ) ){\
27 rm5248 14
        printf("bad set comm\n");\
13 rm5248 15
                                                                                                                        return 0;\
16
                                                                                                                }
8 rm5248 17
#else
18
        #include <termio.h>
19
        #include <termios.h>
20
        #include <unistd.h>
21
        #include <fcntl.h>
14 rm5248 22
 
23
        #ifdef CRTSCTS
24
                #define HW_FLOW CRTSCTS
25
        #elif CNEW_RTSCTS
26
                #define HW_FLOW CNEW_RTSCTS
27
        #endif
8 rm5248 28
 
20 rm5248 29
        #define SPEED_SWITCH(SPD,io) case SPD: cfsetospeed( &io, B##SPD ); cfsetispeed( &io, B##SPD ); break;
30
        #define GET_SPEED_SWITCH(SPD,io) case B##SPD: return SPD;
13 rm5248 31
 
32
 
33
        #define GET_SERIAL_PORT_STRUCT( port, io_name ) struct termios io_name; \
34
                                                                                                        if( tcgetattr( port, &io_name ) < 0 ){ \
35
                                                                                                                return -1; \
36
                                                                                                        }
37
        #define SET_SERIAL_PORT_STRUCT( port, io_name )         if( tcsetattr( port, TCSANOW, &io_name ) < 0 ){\
38
                                                                                                                        return 0;\
39
                                                                                                                }
40
 
8 rm5248 41
#endif
13 rm5248 42
 
54 rm5248 43
/**
44
 * TODO actually make this an inline function
45
 */
46
#define GET_PORT_DESCRIPTOR( array_pos, desc, env, obj ) array_pos = get_handle( env, obj ); \
47
        if( array_pos < 0 || array_pos > port_list_size ){ \
48
                throw_io_exception_message( env, "Unable to get handle" );\
49
                return 0; \
50
        } \
51
        desc = port_list[ array_pos ]; \
52
        if( desc == NULL ){ \
53
                throw_io_exception_message( env, "Unable to get descriptor" ); \
54
                return 0; \
55
        }
56
 
8 rm5248 57
#include <stdlib.h>
58
#include <errno.h>
59
#include <string.h>
60
 
61
//
62
// Local Includes
63
//
64
#include "com_rm5248_serial_SerialPort.h"
18 rm5248 65
#include "com_rm5248_serial_SerialInputStream.h"
66
#include "com_rm5248_serial_SerialOutputStream.h"
8 rm5248 67
 
68
//
69
// Struct Definitions
70
//
71
struct port_descriptor{
13 rm5248 72
#ifdef _WIN32
8 rm5248 73
        HANDLE port;
74
#else
75
        int port;
76
#endif
77
};
78
 
79
//
80
// Local Variables
81
//
82
struct port_descriptor** port_list = NULL;
83
int port_list_size;
84
 
85
//
86
// Helper Methods
87
//
40 rm5248 88
static jint get_handle(JNIEnv * env, jobject obj){
8 rm5248 89
        jfieldID fid;
90
        jint array_pos;
91
        jclass cls = (*env)->GetObjectClass( env, obj );
92
 
93
        fid = (*env)->GetFieldID( env, cls, "handle", "I" );
94
        if( fid == 0 ){
95
                return -1;
96
        }
97
 
18 rm5248 98
        array_pos = (*env)->GetIntField( env, obj, fid );
8 rm5248 99
 
100
        return array_pos;
101
}
102
 
40 rm5248 103
static jboolean get_bool( JNIEnv* env, jobject obj, const char* name ){
104
        jfieldID fid;
105
        jboolean boolVal;
106
        jclass cls = (*env)->GetObjectClass( env, obj );
107
 
108
        fid = (*env)->GetFieldID( env, cls, name, "Z" );
109
        if( fid == 0 ){
110
                return 0; //not really sure what error to set here...
111
        }
112
 
113
        boolVal = (*env)->GetBooleanField( env, obj, fid );
114
 
115
        return boolVal;
116
}
117
 
13 rm5248 118
static int set_baud_rate( struct port_descriptor* desc, int baud_rate ){
119
        GET_SERIAL_PORT_STRUCT( desc->port, newio );
11 rm5248 120
 
121
        switch( baud_rate ){
13 rm5248 122
#ifndef _WIN32
123
/* Note that Windows only supports speeds of 110 and above */
11 rm5248 124
                SPEED_SWITCH(0,newio);
125
                SPEED_SWITCH(50,newio);
126
                SPEED_SWITCH(75,newio);
13 rm5248 127
#endif
11 rm5248 128
                SPEED_SWITCH(110,newio);
13 rm5248 129
#ifndef _WIN32
130
/* Windows does not support speeds of 134, 150, or 200 */
11 rm5248 131
                SPEED_SWITCH(134,newio);
132
                SPEED_SWITCH(150,newio);
133
                SPEED_SWITCH(200,newio);
13 rm5248 134
#endif
11 rm5248 135
                SPEED_SWITCH(300,newio);
136
                SPEED_SWITCH(600,newio);
137
                SPEED_SWITCH(1200,newio);
13 rm5248 138
#ifndef _WIN32
139
/* Windows does not support 1800 */
11 rm5248 140
                SPEED_SWITCH(1800,newio);
13 rm5248 141
#endif
11 rm5248 142
                SPEED_SWITCH(2400,newio);
143
                SPEED_SWITCH(4800,newio);
144
                SPEED_SWITCH(9600,newio);
145
                SPEED_SWITCH(19200,newio);
146
                SPEED_SWITCH(38400,newio);
147
                SPEED_SWITCH(115200,newio);
148
        }
149
 
13 rm5248 150
        SET_SERIAL_PORT_STRUCT( desc->port, newio );
151
 
152
        return 1;
153
}
154
 
14 rm5248 155
static int set_raw_input( struct port_descriptor* desc ){
156
        GET_SERIAL_PORT_STRUCT( desc->port, newio );
157
 
158
#ifdef _WIN32
23 rm5248 159
        newio.fBinary = TRUE;
160
        newio.fParity = TRUE;
161
        newio.fOutxCtsFlow = FALSE;
162
        newio.fOutxDsrFlow = FALSE;
163
        newio.fDtrControl = DTR_CONTROL_DISABLE;
164
        newio.fDsrSensitivity = FALSE;
165
        newio.fOutX = FALSE;
166
        newio.fInX = FALSE;
167
        newio.fNull = FALSE;
168
        newio.fRtsControl = FALSE;
169
 
170
        //Set the timeouts
171
        {
172
                COMMTIMEOUTS timeouts = {0};
27 rm5248 173
                timeouts.ReadIntervalTimeout = MAXDWORD;
23 rm5248 174
                timeouts.ReadTotalTimeoutMultiplier = 0;
175
                timeouts.ReadTotalTimeoutConstant = 0;
27 rm5248 176
                timeouts.WriteTotalTimeoutMultiplier = 0;
177
                timeouts.WriteTotalTimeoutConstant = 0;
23 rm5248 178
                if( SetCommTimeouts( desc->port, &timeouts ) == 0 ){
179
                printf("bad timeout\n"); fflush(stdout);}
180
        }
14 rm5248 181
#else
182
        newio.c_iflag |= IGNBRK;
183
        newio.c_iflag &= ~BRKINT;
184
        newio.c_iflag &= ~ICRNL;
185
        newio.c_oflag = 0;
186
        newio.c_lflag = 0;
187
        newio.c_cc[VTIME] = 0;
188
        newio.c_cc[VMIN] = 1;
189
#endif
190
 
191
        SET_SERIAL_PORT_STRUCT( desc->port, newio );
192
 
193
        return 1;
194
}
195
 
23 rm5248 196
/**
197
 * @param data_bits The number of data bits
198
 */
13 rm5248 199
static int set_data_bits( struct port_descriptor* desc, int data_bits ){
200
        GET_SERIAL_PORT_STRUCT( desc->port, newio );
201
 
202
#ifdef _WIN32 
203
        newio.ByteSize = data_bits;
204
#else
14 rm5248 205
        newio.c_cflag &= ~CSIZE;
206
        if( data_bits == 8 ){
207
                newio.c_cflag |= CS8;
208
        }else if( data_bits == 7 ){
209
                newio.c_cflag |= CS7;
210
        }else if( data_bits == 6 ){
211
                newio.c_cflag |= CS6;
212
        }else if( data_bits == 5 ){
213
                newio.c_cflag |= CS5;
214
        }
13 rm5248 215
#endif
216
 
217
        SET_SERIAL_PORT_STRUCT( desc->port, newio );
218
 
219
        return 1;
220
}
221
 
23 rm5248 222
/**
223
 * @param stop_bits 1 for 1, 2 for 2
224
 */
13 rm5248 225
static int set_stop_bits( struct port_descriptor* desc, int stop_bits ){
226
        GET_SERIAL_PORT_STRUCT( desc->port, newio );
227
 
228
#ifdef _WIN32 
229
        if( stop_bits == 1 ){
230
                newio.StopBits = ONESTOPBIT;
231
        }else if( stop_bits == 2 ){
232
                newio.StopBits = TWOSTOPBITS;
11 rm5248 233
        }
13 rm5248 234
#else
14 rm5248 235
        if( stop_bits == 1 ){
236
                newio.c_cflag &= ~CSTOPB;
237
        }else if( stop_bits == 2 ){
238
                newio.c_cflag |= CSTOPB;
239
        }
13 rm5248 240
#endif
241
 
242
        SET_SERIAL_PORT_STRUCT( desc->port, newio );
11 rm5248 243
 
244
        return 1;
13 rm5248 245
}
11 rm5248 246
 
23 rm5248 247
/**
248
 * @param parity 0 for no parity, 1 for odd parity, 2 for even parity
249
 */
13 rm5248 250
static int set_parity( struct port_descriptor* desc, int parity ){
251
        GET_SERIAL_PORT_STRUCT( desc->port, newio );
252
 
253
#ifdef _WIN32 
254
        if( parity == 0 ){
255
                newio.Parity = NOPARITY;
256
        }else if( parity == 1 ){
257
                newio.Parity = ODDPARITY;
258
        }else if( parity == 2 ){
259
                newio.Parity = EVENPARITY;
260
        }
261
#else
14 rm5248 262
        if( parity == 0 ){
263
                newio.c_cflag |= IGNPAR;
264
        }else if( parity == 1 ){
265
                newio.c_cflag |= PARODD;
266
        }else if( parity == 2 ){
267
                newio.c_cflag |= PARENB;
268
        }
13 rm5248 269
#endif
270
 
271
        SET_SERIAL_PORT_STRUCT( desc->port, newio );
272
 
273
        return 1;
11 rm5248 274
}
275
 
23 rm5248 276
/**
277
 * @param flow_control 0 for none, 1 for hardware, 2 for software
278
 */
13 rm5248 279
static int set_flow_control( struct port_descriptor* desc, int flow_control ){
280
        GET_SERIAL_PORT_STRUCT( desc->port, newio );
281
 
23 rm5248 282
#ifdef _WIN32
283
        if( flow_control == 0 ){
30 rm5248 284
                newio.fOutxCtsFlow = FALSE;
285
                newio.fRtsControl = FALSE;
286
                newio.fOutX = FALSE;
287
                newio.fInX = FALSE;
23 rm5248 288
        }else if( flow_control == 1 ){
30 rm5248 289
                newio.fOutxCtsFlow = TRUE;
290
                newio.fRtsControl = TRUE;
291
                newio.fOutX = FALSE;
292
                newio.fInX = FALSE;
23 rm5248 293
        }else if( flow_control == 2 ){
30 rm5248 294
                newio.fOutxCtsFlow = FALSE;
295
                newio.fRtsControl = FALSE;
296
                newio.fOutX = TRUE;
297
                newio.fInX = TRUE;
23 rm5248 298
        }
13 rm5248 299
#else
14 rm5248 300
        if( flow_control == 0 ){
301
                newio.c_cflag &= ~( IXON | IXOFF | IXANY );
302
        }else if( flow_control == 1 ){
303
                newio.c_cflag |= HW_FLOW;
304
        }else if( flow_control == 2 ){
305
                newio.c_cflag |= ( IXON | IXOFF | IXANY );
306
        }
13 rm5248 307
#endif
308
 
309
        SET_SERIAL_PORT_STRUCT( desc->port, newio );
310
 
311
        return 1;
312
}
313
 
27 rm5248 314
static void throw_io_exception( JNIEnv * env, int errorNumber ){
315
#ifdef _WIN32
316
        LPTSTR error_text = NULL;
317
        jclass exception_class;
318
        (*env)->ExceptionDescribe( env );
319
        (*env)->ExceptionClear( env );
320
        exception_class = (*env)->FindClass(env, "java/io/IOException");
321
 
322
        FormatMessage(
323
                FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
324
                NULL,
325
                errorNumber,
326
                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
327
                (LPTSTR)&error_text,
328
                0,
329
                NULL );
330
        (*env)->ThrowNew(env, exception_class, error_text );
331
        LocalFree( error_text );
332
#else
333
        jclass exception_class;
334
        (*env)->ExceptionDescribe( env );
335
        (*env)->ExceptionClear( env );
336
        exception_class = (*env)->FindClass(env, "java/io/IOException");
337
        (*env)->ThrowNew(env, exception_class, strerror( errorNumber ) );
338
#endif /* _WIN32 */
339
}
340
 
341
static void throw_io_exception_message( JNIEnv * env, const char* message ){
342
        jclass exception_class;
343
        (*env)->ExceptionDescribe( env );
344
        (*env)->ExceptionClear( env );
345
        exception_class = (*env)->FindClass(env, "java/io/IOException");
346
        (*env)->ThrowNew(env, exception_class, message );
347
}
348
 
8 rm5248 349
//
350
// JNI Methods
351
//
352
 
353
/*
354
 * Class:     com_rm5248_serial_SerialPort
355
 * Method:    openPort
11 rm5248 356
 * Signature: (Ljava/lang/String;IIIII)I
8 rm5248 357
 */
358
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_openPort
11 rm5248 359
  (JNIEnv * env, jobject obj, jstring port, jint baudRate, jint dataBits, jint stopBits, jint parity, jint flowControl){
8 rm5248 360
        struct port_descriptor* new_port;
361
        int list_pos;
362
        int found = 0;
363
        const char* port_to_open;
364
        jboolean iscopy;
365
 
366
        port_to_open = (*env)->GetStringUTFChars( env, port, &iscopy );
367
 
368
        if( port_list == NULL ){
369
                port_list = malloc( sizeof( struct port_descriptor* ) * 10 );
370
                port_list_size = 10;
371
                for( list_pos = 0; list_pos < port_list_size; ++list_pos ){
372
                        port_list[ list_pos ] = NULL;
373
                }
374
        }
375
 
18 rm5248 376
        //Search thru the port_list, find the first one that is NULL
8 rm5248 377
        for( list_pos = 0; list_pos < port_list_size; ++list_pos ){
18 rm5248 378
                if( port_list[ list_pos ] == NULL ){
8 rm5248 379
                        found = 1;
380
                        break;
381
                }
382
        }
383
 
384
        if( !found ){
385
                //no free slots.  Expand our array by 10 elements
386
                struct port_descriptor** tmpPortDesc;
387
                tmpPortDesc = malloc( sizeof( struct port_descriptor* ) * ( port_list_size + 10 ) );
388
 
389
                //put all elements into the new array
390
                for( list_pos = 0; list_pos < port_list_size; ++list_pos ){
391
                        tmpPortDesc[ list_pos ] = port_list[ list_pos ];
392
                }
393
                ++list_pos; //put the place to insert the new record one past the old records
394
 
395
                port_list_size += 10;
396
 
397
                //free the old array, set it to the new one
398
                free( port_list );
399
                port_list = tmpPortDesc;
400
        }
401
 
402
        //at this point, list_pos points to a NULL location in our array
403
        new_port = malloc( sizeof( struct port_descriptor ) );
404
 
405
        //Now, let's get to the actual opening of our port
13 rm5248 406
#ifdef _WIN32
27 rm5248 407
        new_port->port = CreateFile( port_to_open, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0 );
13 rm5248 408
        if( new_port->port == INVALID_HANDLE_VALUE ){
409
                if( GetLastError() == ERROR_FILE_NOT_FOUND ){
410
                        LPTSTR error_text = NULL;
411
                        jclass exception_class;
412
 
413
                        FormatMessage(
414
                                FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
415
                                NULL,
416
                                GetLastError(),
417
                                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
418
                                (LPTSTR)&error_text,
419
                                0,
420
                                NULL );
421
 
422
                        (*env)->ExceptionDescribe( env );
423
                        (*env)->ExceptionClear( env );
424
                        exception_class = (*env)->FindClass(env, "com/rm5248/serial/NoSuchPortException");
425
                        (*env)->ThrowNew(env, exception_class, error_text );
426
                        free( new_port );
427
                        LocalFree( error_text );
428
                        return -1;
429
                }
430
        }
27 rm5248 431
 
54 rm5248 432
        {
27 rm5248 433
                //Let's check to see if this is a serial port
434
                DCB io_name = {0};
435
                io_name.DCBlength = sizeof( io_name );
436
                if (!GetCommState( new_port->port, &io_name ) ) {
437
                LPTSTR error_text = NULL;
438
                        jclass exception_class;
439
                        (*env)->ExceptionDescribe( env );
440
                        (*env)->ExceptionClear( env );
441
                        exception_class = (*env)->FindClass(env, "com/rm5248/serial/NotASerialPortException");
442
                        (*env)->ThrowNew(env, exception_class, "You are attempting to open something which is not a serial port" );
443
                        free( new_port );
444
 
445
 
446
 
447
                        FormatMessage(
448
                                FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
449
                                NULL,
450
                                GetLastError(),
451
                                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
452
                                (LPTSTR)&error_text,
453
                                0,
454
                                NULL );
455
                                printf("error is %s\n", error_text );
456
                                        LocalFree( error_text );
457
                        return -1;
458
                }
459
        }
460
 
8 rm5248 461
#else
462
        new_port->port = open( port_to_open, O_RDWR );
463
        if( new_port->port < 0 && errno == ENOENT ){
464
                //That's not a valid serial port, error out
465
                jclass exception_class;
466
                (*env)->ExceptionDescribe( env );
467
                (*env)->ExceptionClear( env );
468
                exception_class = (*env)->FindClass(env, "com/rm5248/serial/NoSuchPortException");
469
                (*env)->ThrowNew(env, exception_class, strerror( errno ) );
470
                free( new_port );
13 rm5248 471
                return -1;
8 rm5248 472
        }else if( new_port->port < 0 ){
473
                jclass exception_class;
474
                (*env)->ExceptionDescribe( env );
475
                (*env)->ExceptionClear( env );
476
                exception_class = (*env)->FindClass(env, "com/rm5248/serial/NoSuchPortException");
477
                (*env)->ThrowNew(env, exception_class, strerror( errno ) );
478
                free( new_port );
13 rm5248 479
                return -1;
8 rm5248 480
        }
27 rm5248 481
 
482
        {
483
                struct termios io_name;
28 rm5248 484
                if( tcgetattr( new_port->port, &io_name ) < 0 ){
32 rm5248 485
                        if( errno == ENOTTY ){
27 rm5248 486
                                //This is apparently not a serial port
487
                                jclass exception_class;
488
                                (*env)->ExceptionDescribe( env );
489
                                (*env)->ExceptionClear( env );
490
                                exception_class = (*env)->FindClass(env, "com/rm5248/serial/NotASerialPortException");
491
                                (*env)->ThrowNew(env, exception_class, "You are attempting to open something which is not a serial port" );
492
                                free( new_port );
493
                                return -1;
494
                        }
495
                }
496
        }
8 rm5248 497
#endif /* __WIN32 */
498
 
499
 
27 rm5248 500
 
11 rm5248 501
        //Set the baud rate
27 rm5248 502
        set_baud_rate( new_port, baudRate );
503
        set_raw_input( new_port );
504
        //Set the data bits( character size )
505
        set_data_bits( new_port, dataBits );
506
        //Set the stop bits
507
        set_stop_bits( new_port, stopBits );
508
        //Set the parity
509
        set_parity( new_port, parity );
510
        //Set the flow control
511
        set_flow_control( new_port, flowControl );
512
 
513
        //Only set the new_port to be in our array as the last instruction
514
        //If there are any errors, we will have returned long before this
515
        port_list[ list_pos ] = new_port;
516
 
517
        return list_pos;
518
}
519
 
520
/*
521
 * Class:     com_rm5248_serial_SerialPort
522
 * Method:    openPort
523
 * Signature: (Ljava/lang/String;)I
524
 */
525
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_openPort__Ljava_lang_String_2
526
  (JNIEnv * env, jobject obj, jstring port){
527
        struct port_descriptor* new_port;
528
        int list_pos;
529
        int found = 0;
530
        const char* port_to_open;
531
        jboolean iscopy;
532
 
533
        port_to_open = (*env)->GetStringUTFChars( env, port, &iscopy );
534
 
535
        if( port_list == NULL ){
536
                port_list = malloc( sizeof( struct port_descriptor* ) * 10 );
537
                port_list_size = 10;
538
                for( list_pos = 0; list_pos < port_list_size; ++list_pos ){
539
                        port_list[ list_pos ] = NULL;
540
                }
541
        }
542
 
543
        //Search thru the port_list, find the first one that is NULL
544
        for( list_pos = 0; list_pos < port_list_size; ++list_pos ){
545
                if( port_list[ list_pos ] == NULL ){
546
                        found = 1;
547
                        break;
548
                }
549
        }
550
 
551
        if( !found ){
552
                //no free slots.  Expand our array by 10 elements
553
                struct port_descriptor** tmpPortDesc;
554
                tmpPortDesc = malloc( sizeof( struct port_descriptor* ) * ( port_list_size + 10 ) );
555
 
556
                //put all elements into the new array
557
                for( list_pos = 0; list_pos < port_list_size; ++list_pos ){
558
                        tmpPortDesc[ list_pos ] = port_list[ list_pos ];
559
                }
560
                ++list_pos; //put the place to insert the new record one past the old records
561
 
562
                port_list_size += 10;
563
 
564
                //free the old array, set it to the new one
565
                free( port_list );
566
                port_list = tmpPortDesc;
567
        }
568
 
569
        //at this point, list_pos points to a NULL location in our array
570
        new_port = malloc( sizeof( struct port_descriptor ) );
571
 
572
        //Now, let's get to the actual opening of our port
573
#ifdef _WIN32
574
        new_port->port = CreateFile( port_to_open, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0 );
575
        if( new_port->port == INVALID_HANDLE_VALUE ){
576
                if( GetLastError() == ERROR_FILE_NOT_FOUND ){
577
                        LPTSTR error_text = NULL;
578
                        jclass exception_class;
579
 
580
                        FormatMessage(
581
                                FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
582
                                NULL,
583
                                GetLastError(),
584
                                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
585
                                (LPTSTR)&error_text,
586
                                0,
587
                                NULL );
588
 
589
                        (*env)->ExceptionDescribe( env );
590
                        (*env)->ExceptionClear( env );
591
                        exception_class = (*env)->FindClass(env, "com/rm5248/serial/NoSuchPortException");
592
                        (*env)->ThrowNew(env, exception_class, error_text );
593
                        free( new_port );
594
                        LocalFree( error_text );
595
                        return -1;
596
                }
597
        }
598
 
599
        {
600
                //Let's check to see if this is a serial port
601
                DCB io_name = {0};
602
                io_name.DCBlength = sizeof( io_name );
603
                if (!GetCommState( new_port->port, &io_name ) ) {
604
                LPTSTR error_text = NULL;
605
                        jclass exception_class;
606
                        (*env)->ExceptionDescribe( env );
607
                        (*env)->ExceptionClear( env );
608
                        exception_class = (*env)->FindClass(env, "com/rm5248/serial/NotASerialPortException");
609
                        (*env)->ThrowNew(env, exception_class, "You are attempting to open something which is not a serial port" );
610
                        free( new_port );
611
 
612
 
613
 
614
                        FormatMessage(
615
                                FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
616
                                NULL,
617
                                GetLastError(),
618
                                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
619
                                (LPTSTR)&error_text,
620
                                0,
621
                                NULL );
622
                                printf("error is %s\n", error_text );
623
                                        LocalFree( error_text );
624
                        return -1;
625
                }
626
        }
627
#else
628
        new_port->port = open( port_to_open, O_RDWR );
629
        if( new_port->port < 0 && errno == ENOENT ){
630
                //That's not a valid serial port, error out
13 rm5248 631
                jclass exception_class;
632
                (*env)->ExceptionDescribe( env );
633
                (*env)->ExceptionClear( env );
27 rm5248 634
                exception_class = (*env)->FindClass(env, "com/rm5248/serial/NoSuchPortException");
635
                (*env)->ThrowNew(env, exception_class, strerror( errno ) );
13 rm5248 636
                free( new_port );
27 rm5248 637
                return -1;
638
        }else if( new_port->port < 0 ){
13 rm5248 639
                jclass exception_class;
640
                (*env)->ExceptionDescribe( env );
641
                (*env)->ExceptionClear( env );
27 rm5248 642
                exception_class = (*env)->FindClass(env, "com/rm5248/serial/NoSuchPortException");
643
                (*env)->ThrowNew(env, exception_class, strerror( errno ) );
13 rm5248 644
                free( new_port );
645
                return -1;
646
        }
27 rm5248 647
 
648
        {
649
                struct termios io_name;
28 rm5248 650
                if( tcgetattr( new_port->port, &io_name ) < 0 ){
32 rm5248 651
                        if( errno == ENOTTY ){
27 rm5248 652
                                //This is apparently not a serial port
653
                                jclass exception_class;
654
                                (*env)->ExceptionDescribe( env );
655
                                (*env)->ExceptionClear( env );
656
                                exception_class = (*env)->FindClass(env, "com/rm5248/serial/NotASerialPortException");
657
                                (*env)->ThrowNew(env, exception_class, "You are attempting to open something which is not a serial port" );
658
                                free( new_port );
659
                                return -1;
660
                        }
661
                }
662
        }
663
#endif /* __WIN32 */
11 rm5248 664
 
27 rm5248 665
 
13 rm5248 666
        //Only set the new_port to be in our array as the last instruction
667
        //If there are any errors, we will have returned long before this
668
        port_list[ list_pos ] = new_port;
27 rm5248 669
 
8 rm5248 670
        return list_pos;
671
}
672
 
673
/*
674
 * Class:     com_rm5248_serial_SerialPort
27 rm5248 675
 * Method:    doClose
676
 * Signature: ()V
677
 */
678
JNIEXPORT void JNICALL Java_com_rm5248_serial_SerialPort_doClose
679
  (JNIEnv * env, jobject obj){
680
        jint array_pos;
681
        struct port_descriptor* desc;
682
 
683
        array_pos = get_handle( env, obj );
684
        if( array_pos < 0 || array_pos > port_list_size ){
685
                return;
686
        }
687
 
688
        desc = port_list[ array_pos ];
689
        if( desc == NULL ){
690
                return;
691
        }
692
 
693
        close( desc->port );
694
        free( desc );
695
        port_list[ array_pos ] = NULL;
696
}
697
 
698
/*
699
 * Class:     com_rm5248_serial_SerialPort
8 rm5248 700
 * Method:    setBaudRate
701
 * Signature: (I)Z
702
 */
703
JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setBaudRate
704
  (JNIEnv * env, jobject obj, jint baud_rate ){
705
        jint array_pos;
706
        struct port_descriptor* desc;
707
 
54 rm5248 708
        GET_PORT_DESCRIPTOR( array_pos, desc, env, obj );
8 rm5248 709
 
11 rm5248 710
        return set_baud_rate( desc, baud_rate );
8 rm5248 711
}
712
 
713
/*
714
 * Class:     com_rm5248_serial_SerialPort
20 rm5248 715
 * Method:    getBaudRateInternal
716
 * Signature: ()I
717
 */
718
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getBaudRateInternal
719
  (JNIEnv * env, jobject obj){
720
        jint array_pos;
721
        struct port_descriptor* desc;
722
 
54 rm5248 723
        GET_PORT_DESCRIPTOR( array_pos, desc, env, obj );
20 rm5248 724
 
725
        //Now, let's get the baud rate information
726
        {
727
                GET_SERIAL_PORT_STRUCT( desc->port, newio );
728
#ifdef _WIN32
23 rm5248 729
                GetCommState( desc->port, &newio );
730
                switch( newio.BaudRate ){
20 rm5248 731
#else
732
                switch( cfgetispeed( &newio ) ){
733
                GET_SPEED_SWITCH( 0, newio );
734
                GET_SPEED_SWITCH( 50, newio );
735
                GET_SPEED_SWITCH( 75, newio );
23 rm5248 736
#endif /* _WIN32 */
20 rm5248 737
                GET_SPEED_SWITCH( 110, newio );
23 rm5248 738
#ifndef _WIN32
20 rm5248 739
                GET_SPEED_SWITCH( 134, newio );
740
                GET_SPEED_SWITCH( 150, newio );
741
                GET_SPEED_SWITCH( 200, newio );
23 rm5248 742
#endif /* _WIN32 */
20 rm5248 743
                GET_SPEED_SWITCH( 300, newio );
744
                GET_SPEED_SWITCH( 600, newio );
745
                GET_SPEED_SWITCH( 1200, newio );
23 rm5248 746
#ifndef _WIN32
20 rm5248 747
                GET_SPEED_SWITCH( 1800, newio );
23 rm5248 748
#endif /* _WIN32 */
20 rm5248 749
                GET_SPEED_SWITCH( 2400, newio );
750
                GET_SPEED_SWITCH( 4800, newio );
751
                GET_SPEED_SWITCH( 9600, newio );
752
                GET_SPEED_SWITCH( 19200, newio );
753
                GET_SPEED_SWITCH( 38400, newio );
754
                GET_SPEED_SWITCH( 115200, newio );
755
                default:
756
                        return 0;
757
                } /* end switch */
758
        }
759
 
760
}
761
 
762
/*
763
 * Class:     com_rm5248_serial_SerialPort
8 rm5248 764
 * Method:    setStopBits
765
 * Signature: (I)Z
766
 */
767
JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setStopBits
768
  (JNIEnv * env, jobject obj, jint bits){
13 rm5248 769
                jint array_pos;
770
        struct port_descriptor* desc;
771
 
772
        array_pos = get_handle( env, obj );
54 rm5248 773
        if( array_pos < 0 ){
774
                //throw new exception
775
                throw_io_exception_message( env, "Unable to get handle" );
776
                return 0;
777
        }
13 rm5248 778
 
779
        desc = port_list[ array_pos ];
54 rm5248 780
 
13 rm5248 781
        if( desc == NULL ){
54 rm5248 782
                //throw new exception
783
                throw_io_exception_message( env, "Unable to get descriptor" );
13 rm5248 784
                return 0;
785
        }
8 rm5248 786
 
13 rm5248 787
        return set_stop_bits( desc, bits );
8 rm5248 788
}
789
 
790
/*
791
 * Class:     com_rm5248_serial_SerialPort
20 rm5248 792
 * Method:    getStopBitsInternal
793
 * Signature: ()I
794
 */
795
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getStopBitsInternal
796
  (JNIEnv * env, jobject obj){
797
        jint array_pos;
798
        struct port_descriptor* desc;
799
 
800
        array_pos = get_handle( env, obj );
801
        if( array_pos < 0 ){
802
                //throw new exception
54 rm5248 803
                throw_io_exception_message( env, "Unable to get handle" );
20 rm5248 804
                return 0;
805
        }
806
 
807
        desc = port_list[ array_pos ];
808
 
809
        if( desc == NULL ){
810
                //throw new exception
54 rm5248 811
                throw_io_exception_message( env, "Unable to get descriptor" );
20 rm5248 812
                return 0;
813
        }
814
 
815
        {
816
                GET_SERIAL_PORT_STRUCT( desc->port, newio );
817
#ifdef _WIN32
23 rm5248 818
                if( newio.StopBits == 1 ){
819
                        return 1;
820
                }else if( newio.StopBits == 2 ){
821
                        return 2;
822
                }else{
823
                        return -1;
824
                }
20 rm5248 825
#else
826
                if( newio.c_cflag & CSTOPB ){
827
                        return 2;
828
                }else{
829
                        return 1;
830
                }
831
#endif
832
        }
833
}
834
/*
835
 * Class:     com_rm5248_serial_SerialPort
8 rm5248 836
 * Method:    setCharSize
837
 * Signature: (I)Z
838
 */
839
JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setCharSize
840
  (JNIEnv * env, jobject obj, jint size){
13 rm5248 841
        jint array_pos;
842
        struct port_descriptor* desc;
8 rm5248 843
 
13 rm5248 844
        array_pos = get_handle( env, obj );
54 rm5248 845
        if( array_pos < 0 ){
846
                //throw new exception
847
                throw_io_exception_message( env, "Unable to get handle" );
848
                return 0;
849
        }
13 rm5248 850
 
851
        desc = port_list[ array_pos ];
54 rm5248 852
 
13 rm5248 853
        if( desc == NULL ){
54 rm5248 854
                //throw new exception
855
                throw_io_exception_message( env, "Unable to get descriptor" );
13 rm5248 856
                return 0;
857
        }
858
 
859
        return set_data_bits( desc, size );
8 rm5248 860
}
861
 
862
/*
11 rm5248 863
 * Class:     com_rm5248_serial_SerialPort
20 rm5248 864
 * Method:    getCharSizeInternal
865
 * Signature: ()I
866
 */
867
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getCharSizeInternal
868
  (JNIEnv * env, jobject obj){
869
        jint array_pos;
870
        struct port_descriptor* desc;
871
 
872
        array_pos = get_handle( env, obj );
873
        if( array_pos < 0 ){
874
                //throw new exception
54 rm5248 875
                throw_io_exception_message( env, "Unable to get handle" );
20 rm5248 876
                return 0;
877
        }
878
 
879
        desc = port_list[ array_pos ];
880
 
881
        if( desc == NULL ){
882
                //throw new exception
54 rm5248 883
                throw_io_exception_message( env, "Unable to get descriptor" );
20 rm5248 884
                return 0;
885
        }
886
 
887
        //Now get the char size
888
        {
889
                GET_SERIAL_PORT_STRUCT( desc->port, newio );
890
 
891
#ifdef _WIN32
23 rm5248 892
                return newio.ByteSize;
20 rm5248 893
#else
894
                if( ( newio.c_cflag | CS8 ) == CS8 ){
895
                        return 8;
896
                }else if( ( newio.c_cflag | CS7 ) == CS7 ){
897
                        return 7;
898
                }else if( ( newio.c_cflag | CS6 ) == CS6 ){
899
                        return 6;
900
                }else if( ( newio.c_cflag | CS5 ) == CS5 ){
901
                        return 5;
902
                }else{
903
                        return 0;
904
                }
905
#endif
906
        }
907
 
908
}
909
 
910
/*
911
 * Class:     com_rm5248_serial_SerialPort
11 rm5248 912
 * Method:    setParity
913
 * Signature: (I)Z
914
 */
915
JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setParity
916
  (JNIEnv * env, jobject obj, jint parity){
13 rm5248 917
        jint array_pos;
918
        struct port_descriptor* desc;
11 rm5248 919
 
54 rm5248 920
        array_pos = get_handle( env, obj );
30 rm5248 921
        if( array_pos < 0 ){
922
                //throw new exception
54 rm5248 923
                throw_io_exception_message( env, "Unable to get handle" );
30 rm5248 924
                return 0;
925
        }
13 rm5248 926
 
927
        desc = port_list[ array_pos ];
30 rm5248 928
 
13 rm5248 929
        if( desc == NULL ){
30 rm5248 930
                //throw new exception
54 rm5248 931
                throw_io_exception_message( env, "Unable to get descriptor" );
13 rm5248 932
                return 0;
30 rm5248 933
        }      
13 rm5248 934
 
935
        return set_parity( desc, parity );
11 rm5248 936
}
937
 
20 rm5248 938
/*
939
 * Class:     com_rm5248_serial_SerialPort
940
 * Method:    getParityInternal
941
 * Signature: ()I
942
 */
943
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getParityInternal
944
  (JNIEnv * env, jobject obj){
945
        jint array_pos;
946
        struct port_descriptor* desc;
947
 
948
        array_pos = get_handle( env, obj );
949
        if( array_pos < 0 ){
950
                //throw new exception
54 rm5248 951
                throw_io_exception_message( env, "Unable to get handle" );
20 rm5248 952
                return 0;
953
        }
954
 
955
        desc = port_list[ array_pos ];
956
 
957
        if( desc == NULL ){
958
                //throw new exception
54 rm5248 959
                throw_io_exception_message( env, "Unable to get descriptor" );
20 rm5248 960
                return 0;
961
        }
962
 
963
        {
964
                GET_SERIAL_PORT_STRUCT( desc->port, newio );
965
#ifdef _WIN32
23 rm5248 966
                if( newio.Parity == NOPARITY ){
967
                        return 0;
968
                }else if( newio.Parity == ODDPARITY ){
969
                        return 1;
970
                }else if( newio.Parity == EVENPARITY ){
971
                        return 2;
972
                }else{
973
                        return -1;
974
                }
20 rm5248 975
#else
976
                if( !( newio.c_cflag & PARENB ) ){
977
                        //No parity
978
                        return 0;
979
                }else if( newio.c_cflag & PARODD ){
980
                        //Odd parity
981
                        return 1;
982
                }else if( !( newio.c_cflag & PARODD ) ){
983
                        //Even parity
984
                        return 2;
985
                }else{
986
                        return -1;
987
                }
988
#endif
989
        }
990
 
991
}
992
 
27 rm5248 993
/*
994
 * Class:     com_rm5248_serial_SerialPort
995
 * Method:    setFlowControl
996
 * Signature: (I)Z
997
 */
998
JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setFlowControl
999
  (JNIEnv * env, jobject obj, jint flow){
30 rm5248 1000
        jint array_pos;
1001
        struct port_descriptor* desc;
1002
 
1003
        array_pos = get_handle( env, obj );
1004
        if( array_pos < 0 ){
1005
                //throw new exception
54 rm5248 1006
                throw_io_exception_message( env, "Unable to get handle" );
30 rm5248 1007
                return 0;
1008
        }
1009
 
1010
        desc = port_list[ array_pos ];
1011
 
1012
        if( desc == NULL ){
1013
                //throw new exception
54 rm5248 1014
                throw_io_exception_message( env, "Unable to get descriptor" );
30 rm5248 1015
                return 0;
1016
        }
1017
 
31 rm5248 1018
        return set_flow_control( desc, flow );
27 rm5248 1019
}
1020
 
1021
/*
1022
 * Class:     com_rm5248_serial_SerialPort
1023
 * Method:    getFlowControlInternal
1024
 * Signature: ()I
1025
 */
1026
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getFlowControlInternal
1027
  (JNIEnv * env, jobject obj){
1028
        jint array_pos;
1029
        struct port_descriptor* desc;
1030
 
1031
        array_pos = get_handle( env, obj );
30 rm5248 1032
        if( array_pos < 0 ){
1033
                //throw new exception
54 rm5248 1034
                throw_io_exception_message( env, "Unable to get handle" );
30 rm5248 1035
                return 0;
1036
        }
1037
 
1038
        desc = port_list[ array_pos ];
1039
 
1040
        if( desc == NULL ){
1041
                //throw new exception
54 rm5248 1042
                throw_io_exception_message( env, "Unable to get descriptor" );
30 rm5248 1043
                return 0;
1044
        }
1045
 
27 rm5248 1046
        {
1047
                GET_SERIAL_PORT_STRUCT( desc->port, newio );
1048
#ifdef _WIN32
30 rm5248 1049
                if( newio.fOutX == TRUE && newio.fInX == TRUE ){
1050
                        return 2;
1051
                }else if( newio.fRtsControl == TRUE && newio.fOutxCtsFlow == TRUE ){
1052
                        return 1;
1053
                }else{
1054
                        return 0;
1055
                }
27 rm5248 1056
#else
32 rm5248 1057
                if( newio.c_cflag & ~( IXON ) &&
1058
                        newio.c_cflag & ~( IXOFF ) &&
1059
                        newio.c_cflag & ~( IXANY ) ){
1060
                        return 0;
1061
                }else if( newio.c_cflag & HW_FLOW ){
1062
                        return 1;
1063
                }else if( newio.c_cflag & ( IXON ) &&
1064
                        newio.c_cflag & ( IXOFF ) &&
1065
                        newio.c_cflag & ( IXANY ) ){
1066
                        return 2;
1067
                }
27 rm5248 1068
#endif /* _WIN32 */
1069
        }
32 rm5248 1070
 
1071
        return -1;
27 rm5248 1072
}
1073
 
31 rm5248 1074
/*
1075
 * Class:     com_rm5248_serial_SerialPort
1076
 * Method:    getSerialLineStateInternalNonblocking
1077
 * Signature: ()I
1078
 */
1079
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getSerialLineStateInternalNonblocking
1080
  (JNIEnv * env, jobject obj ){
34 rm5248 1081
        jint array_pos;
1082
        struct port_descriptor* desc;
35 rm5248 1083
        jint ret_val;
31 rm5248 1084
 
34 rm5248 1085
        array_pos = get_handle( env, obj );
1086
        if( array_pos < 0 ){
1087
                //throw new exception
54 rm5248 1088
                throw_io_exception_message( env, "Unable to get handle" );
34 rm5248 1089
                return 0;
1090
        }
1091
 
1092
        desc = port_list[ array_pos ];
1093
 
1094
        if( desc == NULL ){
1095
                //throw new exception
54 rm5248 1096
                throw_io_exception_message( env, "Unable to get descriptor" );
34 rm5248 1097
                return 0;
1098
        }
1099
 
36 rm5248 1100
        ret_val = 0;
1101
 
1102
        {      
35 rm5248 1103
#ifdef _WIN32
36 rm5248 1104
                DWORD get_val;
1105
                if( GetCommModemStatus( desc->port, &get_val ) == 0 ){
1106
                        throw_io_exception( env, GetLastError() );
1107
                        return -1;
1108
                }
1109
 
1110
                if( get_val & MS_CTS_ON ){
1111
                        // CTS
1112
                        ret_val |= ( 0x01 << 1 );
1113
                }
1114
 
1115
                if( get_val & MS_DSR_ON ){
1116
                        // Data Set Ready
1117
                        ret_val |= ( 0x01 << 2 );
1118
                }
1119
 
1120
                if( get_val & MS_RING_ON ){
1121
                        // Ring Indicator
1122
                        ret_val |= ( 0x01 << 5 );
1123
                }
35 rm5248 1124
#else
36 rm5248 1125
                int get_val;
35 rm5248 1126
                if( ioctl( desc->port, TIOCMGET, &get_val ) < 0 ){
1127
                        throw_io_exception( env, errno );
1128
                        return -1;
1129
                }
1130
 
1131
                if( get_val & TIOCM_CD ){
1132
                        // Carrier detect
1133
                        ret_val |= 0x01;
1134
                }
1135
 
1136
                if( get_val & TIOCM_CTS ){
1137
                        // CTS
1138
                        ret_val |= ( 0x01 << 1 );
1139
                }
1140
 
1141
                if( get_val & TIOCM_DSR ){
1142
                        // Data Set Ready
1143
                        ret_val |= ( 0x01 << 2 );
1144
                }
1145
 
1146
                if( get_val & TIOCM_DTR ){
1147
                        // Data Terminal Ready
1148
                        ret_val |= ( 0x01 << 3 );
1149
                }
1150
 
1151
                if( get_val & TIOCM_RTS ){
1152
                        // Request To Send
1153
                        ret_val |= ( 0x01 << 4 );
1154
                }
1155
 
1156
                if( get_val & TIOCM_RI ){
1157
                        // Ring Indicator
1158
                        ret_val |= ( 0x01 << 5 );
1159
                }
1160
#endif
1161
        }
1162
 
1163
        return ret_val;
31 rm5248 1164
}
1165
 
40 rm5248 1166
/*
1167
 * Class:     com_rm5248_serial_SerialPort
1168
 * Method:    setSerialLineStateInternal
1169
 * Signature: (Lcom/rm5248/serial/SerialLineState;)I
1170
 */
1171
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_setSerialLineStateInternal
1172
  (JNIEnv * env, jobject obj, jobject serial){
1173
        jint array_pos;
1174
        struct port_descriptor* desc;
1175
        jint ret_val;
1176
 
1177
        array_pos = get_handle( env, obj );
1178
        if( array_pos < 0 ){
1179
                //throw new exception
54 rm5248 1180
                throw_io_exception_message( env, "Unable to get handle" );
40 rm5248 1181
                return 0;
1182
        }
1183
 
1184
        desc = port_list[ array_pos ];
1185
 
1186
        if( desc == NULL ){
1187
                //throw new exception
54 rm5248 1188
                throw_io_exception_message( env, "Unable to get descriptor" );
40 rm5248 1189
                return 0;
1190
        }
1191
 
1192
        ret_val = 0;
1193
 
1194
#ifdef _WIN32
1195
        //Can't set CD on Windows
1196
        if( get_bool( env, serial, "carrierDetect" ) ){
1197
        }else{
1198
        }
1199
 
1200
        //Can't set CTS on Windows
1201
        if( get_bool( env, serial, "clearToSend" ) ){
1202
        }else{
1203
        }
1204
 
1205
        //Can't set in Windows
1206
        if( get_bool( env, serial, "dataSetReady" ) ){
1207
        }else{
1208
        }
1209
 
1210
        if( get_bool( env, serial, "dataTerminalReady" ) ){
1211
                if( !EscapeCommFunction( desc->port, SETDTR ) ){
1212
                        throw_io_exception_message( env, "Could not set DTR" );
1213
                        return -1;
1214
                }
1215
        }else{
1216
                if( !EscapeCommFunction( desc->port, CLRDTR ) ){
1217
                        throw_io_exception_message( env, "Could not set DTR" );
1218
                        return -1;
1219
                }
1220
        }
1221
 
1222
        //Can't set in Windows
1223
        if( get_bool( env, serial, "ringIndicator" ) ){
1224
        }else{
1225
        }
1226
 
1227
        if( get_bool( env, serial, "requestToSend" ) ){
1228
                if( !EscapeCommFunction( desc->port, SETRTS ) ){
1229
                        throw_io_exception_message( env, "Could not set RTS" );
1230
                        return -1;
1231
                }
1232
        }else{
1233
                if( !EscapeCommFunction( desc->port, CLRRTS ) ){
1234
                        throw_io_exception_message( env, "Could not set RTS" );
1235
                        return -1;
1236
                }
1237
        }
1238
#else
1239
        if( get_bool( env, serial, "carrierDetect" ) ){
1240
                if( ioctl( desc->port, TIOCMBIS, TIOCM_CD ) < 0 ){
1241
                        throw_io_exception_message( env, "Could not set CD" );
1242
                        return -1;
1243
                }
1244
        }else{
1245
                if( ioctl( desc->port, TIOCMBIC, TIOCM_CD ) < 0 ){
1246
                        throw_io_exception_message( env, "Could not set CD" );
1247
                        return -1;
1248
                }
1249
        }
1250
 
1251
        if( get_bool( env, serial, "clearToSend" ) ){
1252
                if( ioctl( desc->port, TIOCMBIS, TIOCM_CTS ) < 0 ){
1253
                        throw_io_exception_message( env, "Could not set CTS" );
1254
                        return -1;
1255
                }
1256
        }else{
1257
                if( ioctl( desc->port, TIOCMBIC, TIOCM_CTS ) < 0 ){
1258
                        throw_io_exception_message( env, "Could not set CTS" );
1259
                        return -1;
1260
                }
1261
        }
1262
 
1263
        if( get_bool( env, serial, "dataSetReady" ) ){
1264
                if( ioctl( desc->port, TIOCMBIS, TIOCM_LE ) < 0 ){
1265
                        throw_io_exception_message( env, "Could not set DSR" );
1266
                        return -1;
1267
                }
1268
        }else{
1269
                if( ioctl( desc->port, TIOCMBIC, TIOCM_LE ) < 0 ){
1270
                        throw_io_exception_message( env, "Could not set DSR" );
1271
                        return -1;
1272
                }
1273
        }
1274
 
1275
        if( get_bool( env, serial, "dataTerminalReady" ) ){
1276
                if( ioctl( desc->port, TIOCMBIS, TIOCM_DTR ) < 0 ){
1277
                        throw_io_exception_message( env, "Could not set DTR" );
1278
                        return -1;
1279
                }
1280
        }else{
1281
                if( ioctl( desc->port, TIOCMBIC, TIOCM_DTR ) < 0 ){
1282
                        throw_io_exception_message( env, "Could not set DTR" );
1283
                        return -1;
1284
                }
1285
        }
1286
 
1287
        if( get_bool( env, serial, "ringIndicator" ) ){
1288
                if( ioctl( desc->port, TIOCMBIS, TIOCM_RNG ) < 0 ){
1289
                        throw_io_exception_message( env, "Could not set Ring" );
1290
                        return -1;
1291
                }
1292
        }else{
1293
                if( ioctl( desc->port, TIOCMBIC, TIOCM_RNG ) < 0 ){
1294
                        throw_io_exception_message( env, "Could not set Ring" );
1295
                        return -1;
1296
                }
1297
        }
1298
 
1299
        if( get_bool( env, serial, "requestToSend" ) ){
1300
                if( ioctl( desc->port, TIOCMBIS, TIOCM_RTS ) < 0 ){
1301
                        throw_io_exception_message( env, "Could not set RTS" );
1302
                        return -1;
1303
                }
1304
        }else{
1305
                if( ioctl( desc->port, TIOCMBIC, TIOCM_RTS ) < 0 ){
1306
                        throw_io_exception_message( env, "Could not set RTS" );
1307
                        return -1;
1308
                }
1309
        }
1310
#endif
1311
 
1312
        return ret_val;
1313
}
1314
 
38 rm5248 1315
//
1316
// ------------------------------------------------------------------------
1317
// ------------------Input/Output methods below here-----------------------
1318
// ------------------------------------------------------------------------
1319
//
1320
 
31 rm5248 1321
/*
38 rm5248 1322
 * Class:     com_rm5248_serial_SerialInputStream
1323
 * Method:    readByte
31 rm5248 1324
 * Signature: ()I
1325
 */
38 rm5248 1326
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialInputStream_readByte
31 rm5248 1327
  (JNIEnv * env, jobject obj){
38 rm5248 1328
        int stat;
1329
        int ret_val;
34 rm5248 1330
        jint array_pos;
1331
        struct port_descriptor* desc;
38 rm5248 1332
        int get_val = 0;
1333
#ifdef _WIN32
1334
        DWORD ret = 0;
1335
        OVERLAPPED overlap = {0};
1336
        int current_available = 0;
1337
#endif 
31 rm5248 1338
 
34 rm5248 1339
        array_pos = get_handle( env, obj );
1340
        if( array_pos < 0 ){
1341
                //throw new exception
54 rm5248 1342
                throw_io_exception_message( env, "Unable to get handle" );
38 rm5248 1343
                return -1;
34 rm5248 1344
        }
1345
 
1346
        desc = port_list[ array_pos ];
1347
 
1348
        if( desc == NULL ){
1349
                //throw new exception
54 rm5248 1350
                throw_io_exception_message( env, "Unable to get descriptor" );
38 rm5248 1351
                return -1;
34 rm5248 1352
        }
1353
 
35 rm5248 1354
        ret_val = 0;
38 rm5248 1355
 
1356
#ifdef _WIN32
35 rm5248 1357
        {
38 rm5248 1358
                DWORD comErrors = {0};
1359
                COMSTAT portStatus = {0};
1360
                if( !ClearCommError( desc->port, &comErrors, &portStatus ) ){
1361
                        //return value zero = fail
1362
                        throw_io_exception( env, GetLastError() );
1363
                        return -1;
1364
                }else{
1365
                        current_available = portStatus.cbInQue;
1366
                }
1367
        }
1368
 
1369
        if( !current_available ){
1370
                //If nothing is currently available, wait until we get an event of some kind.
1371
                //This could be the serial lines changing state, or it could be some data
1372
                //coming into the system.
36 rm5248 1373
                overlap.hEvent = CreateEvent( 0, TRUE, 0, 0 );
38 rm5248 1374
                SetCommMask( desc->port, EV_RXCHAR | EV_CTS | EV_DSR | EV_RING );
1375
                WaitCommEvent( desc->port, &ret, &overlap );
1376
                WaitForSingleObject( overlap.hEvent, INFINITE );
1377
        }else{
1378
                //Data is available; set the RXCHAR mask so we try to read from the port
1379
                ret = EV_RXCHAR;
1380
        }
36 rm5248 1381
 
38 rm5248 1382
        if( ret & EV_RXCHAR ){
1383
                if( !ReadFile( desc->port, &ret_val, 1, &stat, &overlap) ){
36 rm5248 1384
                        throw_io_exception( env, GetLastError() );
1385
                        return -1;
1386
                }
1387
 
38 rm5248 1388
                //This is a valid byte, set our valid bit
1389
                ret_val |= ( 0x01 << 15 );
1390
        }
1391
 
1392
        //Always get the com lines no matter what       
1393
        if( GetCommModemStatus( desc->port, &get_val ) == 0 ){
1394
                throw_io_exception( env, GetLastError() );
1395
                return -1;
1396
        }
36 rm5248 1397
 
38 rm5248 1398
        if( get_val & MS_CTS_ON ){
1399
                // CTS
1400
                ret_val |= ( 0x01 << 10 );
1401
        }
36 rm5248 1402
 
38 rm5248 1403
        if( get_val & MS_DSR_ON ){
1404
                // Data Set Ready
1405
                ret_val |= ( 0x01 << 11 );
1406
        }
36 rm5248 1407
 
38 rm5248 1408
        if( get_val & MS_RING_ON ){
1409
                // Ring Indicator
1410
                ret_val |= ( 0x01 << 14 );
1411
        }
1412
 
35 rm5248 1413
#else
38 rm5248 1414
        fd_set fdset;
35 rm5248 1415
 
38 rm5248 1416
        FD_ZERO( &fdset );
1417
        FD_SET( desc->port, &fdset );
35 rm5248 1418
 
40 rm5248 1419
        if( select( desc->port + 1, &fdset, NULL, NULL, NULL ) < 0 ){
38 rm5248 1420
                throw_io_exception( env, errno );
1421
                return -1;
1422
        }
1423
 
1424
        if( FD_ISSET( desc->port, &fdset ) ){
1425
                stat = read( desc->port, &ret_val, sizeof( ret_val ) );
1426
                if( stat < 0 ){
1427
                        //throw new exception
35 rm5248 1428
                        throw_io_exception( env, errno );
1429
                        return -1;
1430
                }
38 rm5248 1431
 
1432
                //This is a valid byte, set our valid bit
1433
                ret_val |= ( 0x01 << 15 );
1434
        }
35 rm5248 1435
 
38 rm5248 1436
        //Now that we have read in the character, let's get the serial port line state.
1437
        //If it has changed, we will fire an event in Java.
1438
        //Now, because we only read one byte at a time, we will use the lower 8 bytes to 
1439
        //return the character that we read.  The other bytes will be used to return
1440
        //information on our serial port state.
1441
        if( ioctl( desc->port, TIOCMGET, &get_val ) < 0 ){
1442
                throw_io_exception( env, errno );
1443
                return -1;
1444
        }
35 rm5248 1445
 
38 rm5248 1446
        if( get_val & TIOCM_CD ){
1447
                // Carrier detect
1448
                ret_val |= ( 0x01 << 9 );
1449
        }
35 rm5248 1450
 
38 rm5248 1451
        if( get_val & TIOCM_CTS ){
1452
                // CTS
1453
                ret_val |= ( 0x01 << 10 );
35 rm5248 1454
        }
31 rm5248 1455
 
38 rm5248 1456
        if( get_val & TIOCM_DSR ){
1457
                // Data Set Ready
1458
                ret_val |= ( 0x01 << 11 );
8 rm5248 1459
        }
1460
 
38 rm5248 1461
        if( get_val & TIOCM_DTR ){
1462
                // Data Terminal Ready
1463
                ret_val |= ( 0x01 << 12 );
8 rm5248 1464
        }
27 rm5248 1465
 
38 rm5248 1466
        if( get_val & TIOCM_RTS ){
1467
                // Request To Send
1468
                ret_val |= ( 0x01 << 13 );
23 rm5248 1469
        }
38 rm5248 1470
 
1471
        if( get_val & TIOCM_RI ){
1472
                // Ring Indicator
1473
                ret_val |= ( 0x01 << 14 );
8 rm5248 1474
        }
38 rm5248 1475
 
8 rm5248 1476
#endif
38 rm5248 1477
 
8 rm5248 1478
        return ret_val;
1479
}
1480
 
1481
/*
18 rm5248 1482
 * Class:     com_rm5248_serial_SerialInputStream
8 rm5248 1483
 * Method:    getAvailable
1484
 * Signature: ()I
1485
 */
18 rm5248 1486
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialInputStream_getAvailable
8 rm5248 1487
  (JNIEnv * env, jobject obj){
1488
        jint ret_val;
1489
        jint array_pos;
1490
        struct port_descriptor* desc;
1491
 
1492
        array_pos = get_handle( env, obj );
1493
        if( array_pos < 0 ){
1494
                //throw new exception
54 rm5248 1495
                throw_io_exception_message( env, "Unable to get handle" );
13 rm5248 1496
                return -1;
8 rm5248 1497
        }
1498
 
1499
        desc = port_list[ array_pos ];
1500
 
1501
        if( desc == NULL ){
1502
                //throw new exception
54 rm5248 1503
                throw_io_exception_message( env, "Unable to get descriptor" );
13 rm5248 1504
                return -1;
8 rm5248 1505
        }
1506
 
13 rm5248 1507
#ifdef _WIN32
23 rm5248 1508
        {
38 rm5248 1509
                DWORD comErrors = {0};
1510
                COMSTAT portStatus = {0};
1511
                if( !ClearCommError( desc->port, &comErrors, &portStatus ) ){
23 rm5248 1512
                        //return value zero = fail
27 rm5248 1513
                        throw_io_exception( env, GetLastError() );
23 rm5248 1514
                        return -1;
1515
                }else{
38 rm5248 1516
                        ret_val = portStatus.cbInQue;
23 rm5248 1517
                }
1518
        }
8 rm5248 1519
#else
1520
        if( ioctl( desc->port, FIONREAD, &ret_val ) < 0 ){
1521
                //throw new exception
27 rm5248 1522
                throw_io_exception( env, errno );
13 rm5248 1523
                return -1;
8 rm5248 1524
        }
1525
#endif
1526
        return ret_val;
1527
}
1528
 
1529
/*
18 rm5248 1530
 * Class:     com_rm5248_serial_SerialOutputStream
8 rm5248 1531
 * Method:    writeByte
1532
 * Signature: (I)V
1533
 */
18 rm5248 1534
JNIEXPORT void JNICALL Java_com_rm5248_serial_SerialOutputStream_writeByte
8 rm5248 1535
  (JNIEnv * env, jobject obj, jint byte){
1536
        struct port_descriptor* desc;
1537
        jint array_pos;
1538
        char byte_write;
13 rm5248 1539
#ifdef _WIN32
1540
        DWORD bytes_written;
27 rm5248 1541
        OVERLAPPED overlap;
13 rm5248 1542
#else
1543
        int bytes_written;
1544
#endif
8 rm5248 1545
 
1546
        byte_write = byte;
1547
 
1548
        array_pos = get_handle( env, obj );
1549
        if( array_pos < 0 ){
1550
                //throw new exception
54 rm5248 1551
                throw_io_exception_message( env, "Unable to get handle" );
8 rm5248 1552
                return;
1553
        }
1554
 
1555
        desc = port_list[ array_pos ];
1556
 
1557
        if( desc == NULL ){
1558
                //throw new exception
54 rm5248 1559
                throw_io_exception_message( env, "Unable to get descriptor" );
8 rm5248 1560
                return;
1561
        }
1562
 
13 rm5248 1563
#ifdef _WIN32
27 rm5248 1564
        memset( &overlap, 0, sizeof( overlap ) );
1565
        overlap.hEvent = CreateEvent( 0, TRUE, 0, 0 );
1566
        if( !WriteFile( desc->port, &byte_write, sizeof( byte_write ), &bytes_written, &overlap ) ){
1567
                if( GetLastError() == ERROR_IO_PENDING ){
1568
                        //Not in fact an error, we're just doing this asynchronously
1569
                        WaitForSingleObject( overlap.hEvent, INFINITE );
1570
                }else{
1571
                        //throw new exception
1572
                        throw_io_exception( env, GetLastError() );
1573
                        return;
1574
                }
13 rm5248 1575
        }
8 rm5248 1576
#else
13 rm5248 1577
        bytes_written = write( desc->port, &byte_write, sizeof( byte_write ) );
1578
        if( bytes_written < 0 ){
8 rm5248 1579
                //throw new exception
32 rm5248 1580
                throw_io_exception( env, errno );
8 rm5248 1581
                return;
1582
        }
1583
#endif
1584
 
1585
}
1586
 
40 rm5248 1587
/*
1588
 * Class:     com_rm5248_serial_SerialOutputStream
1589
 * Method:    writeByteArray
1590
 * Signature: ([B)V
1591
 */
1592
JNIEXPORT void JNICALL Java_com_rm5248_serial_SerialOutputStream_writeByteArray
1593
  (JNIEnv * env, jobject obj, jbyteArray arr){
1594
        jbyte* data;
1595
        jint len;
1596
        jint array_pos;
1597
        int my_errnum;
1598
        struct port_descriptor* desc;
1599
#ifdef _WIN32
1600
        DWORD bytes_written;
1601
        OVERLAPPED overlap;
1602
#else
1603
        int bytes_written;
1604
#endif
1605
 
1606
        array_pos = get_handle( env, obj );
1607
        if( array_pos < 0 ){
1608
                //throw new exception
54 rm5248 1609
                throw_io_exception_message( env, "Unable to get handle" );
40 rm5248 1610
                return;
1611
        }
1612
 
1613
        desc = port_list[ array_pos ];
1614
 
1615
        if( desc == NULL ){
1616
                //throw new exception
54 rm5248 1617
                throw_io_exception_message( env, "Unable to get descriptor" );
40 rm5248 1618
                return;
1619
        }
1620
 
1621
        len = (*env)->GetArrayLength( env, arr );
1622
        data = (*env)->GetByteArrayElements(env, arr, 0);
1623
 
1624
#ifdef _WIN32
1625
        memset( &overlap, 0, sizeof( overlap ) );
1626
        overlap.hEvent = CreateEvent( 0, TRUE, 0, 0 );
1627
        if( !WriteFile( desc->port, data, len, &bytes_written, &overlap ) ){
1628
                if( GetLastError() == ERROR_IO_PENDING ){
1629
                        //Not in fact an error, we're just doing this asynchronously
1630
                        WaitForSingleObject( overlap.hEvent, INFINITE );
1631
                }else{
1632
                        my_errnum = GetLastError();
1633
                }
1634
        }
1635
#else
1636
        bytes_written = write( desc->port, data, len );
1637
        if( bytes_written < 0 ){
1638
                my_errnum = errno;
1639
        }
1640
#endif
1641
 
1642
        (*env)->ReleaseByteArrayElements(env, arr, data, 0);
1643
 
1644
        if( bytes_written != len ){
1645
                //OH SNAP AN ERROR
1646
                throw_io_exception( env, my_errnum );
1647
        }
1648
}
1649