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 |