0,0 → 1,1779 |
#ifdef _WIN32 |
#include <windows.h> |
|
#define SPEED_SWITCH(SPD,io) case SPD: io.BaudRate = CBR_##SPD; break; |
#define GET_SPEED_SWITCH(SPD,io) case CBR_##SPD: return SPD; |
|
#define GET_SERIAL_PORT_STRUCT( port, io_name ) DCB io_name = {0};\ |
io_name.DCBlength = sizeof( io_name ); \ |
if (!GetCommState( port, &io_name ) ) { \ |
printf("bad get comm\n");\ |
return -1;\ |
} |
#define SET_SERIAL_PORT_STRUCT( port, io_name ) if( !SetCommState( port, &io_name ) ){\ |
printf("bad set comm\n");\ |
return 0;\ |
} |
#else |
#include <termio.h> |
#include <termios.h> |
#include <unistd.h> |
#include <fcntl.h> |
|
#ifdef CRTSCTS |
#define HW_FLOW CRTSCTS |
#elif CNEW_RTSCTS |
#define HW_FLOW CNEW_RTSCTS |
#endif |
|
#define SPEED_SWITCH(SPD,io) case SPD: cfsetospeed( &io, B##SPD ); cfsetispeed( &io, B##SPD ); break; |
#define GET_SPEED_SWITCH(SPD,io) case B##SPD: return SPD; |
|
|
#define GET_SERIAL_PORT_STRUCT( port, io_name ) struct termios io_name; \ |
if( tcgetattr( port, &io_name ) < 0 ){ \ |
return -1; \ |
} |
#define SET_SERIAL_PORT_STRUCT( port, io_name ) if( tcsetattr( port, TCSANOW, &io_name ) < 0 ){\ |
return 0;\ |
} |
|
#endif |
|
#include <stdlib.h> |
#include <errno.h> |
#include <string.h> |
|
// |
// Local Includes |
// |
#include "com_rm5248_serial_SerialPort.h" |
#include "com_rm5248_serial_SerialInputStream.h" |
#include "com_rm5248_serial_SerialOutputStream.h" |
|
// |
// Struct Definitions |
// |
struct port_descriptor{ |
#ifdef _WIN32 |
HANDLE port; |
#else |
int port; |
#endif |
}; |
|
// |
// Local Variables |
// |
struct port_descriptor** port_list = NULL; |
int port_list_size; |
|
// |
// Helper Methods |
// |
static jint get_handle(JNIEnv * env, jobject obj){ |
jfieldID fid; |
jint array_pos; |
jclass cls = (*env)->GetObjectClass( env, obj ); |
|
fid = (*env)->GetFieldID( env, cls, "handle", "I" ); |
if( fid == 0 ){ |
return -1; |
} |
|
array_pos = (*env)->GetIntField( env, obj, fid ); |
|
return array_pos; |
} |
|
static jboolean get_bool( JNIEnv* env, jobject obj, const char* name ){ |
jfieldID fid; |
jboolean boolVal; |
jclass cls = (*env)->GetObjectClass( env, obj ); |
|
fid = (*env)->GetFieldID( env, cls, name, "Z" ); |
if( fid == 0 ){ |
return 0; //not really sure what error to set here... |
} |
|
boolVal = (*env)->GetBooleanField( env, obj, fid ); |
|
return boolVal; |
} |
|
static int set_baud_rate( struct port_descriptor* desc, int baud_rate ){ |
GET_SERIAL_PORT_STRUCT( desc->port, newio ); |
|
switch( baud_rate ){ |
#ifndef _WIN32 |
/* Note that Windows only supports speeds of 110 and above */ |
SPEED_SWITCH(0,newio); |
SPEED_SWITCH(50,newio); |
SPEED_SWITCH(75,newio); |
#endif |
SPEED_SWITCH(110,newio); |
#ifndef _WIN32 |
/* Windows does not support speeds of 134, 150, or 200 */ |
SPEED_SWITCH(134,newio); |
SPEED_SWITCH(150,newio); |
SPEED_SWITCH(200,newio); |
#endif |
SPEED_SWITCH(300,newio); |
SPEED_SWITCH(600,newio); |
SPEED_SWITCH(1200,newio); |
#ifndef _WIN32 |
/* Windows does not support 1800 */ |
SPEED_SWITCH(1800,newio); |
#endif |
SPEED_SWITCH(2400,newio); |
SPEED_SWITCH(4800,newio); |
SPEED_SWITCH(9600,newio); |
SPEED_SWITCH(19200,newio); |
SPEED_SWITCH(38400,newio); |
SPEED_SWITCH(115200,newio); |
} |
|
SET_SERIAL_PORT_STRUCT( desc->port, newio ); |
|
return 1; |
} |
|
static int set_raw_input( struct port_descriptor* desc ){ |
GET_SERIAL_PORT_STRUCT( desc->port, newio ); |
|
#ifdef _WIN32 |
newio.fBinary = TRUE; |
newio.fParity = TRUE; |
newio.fOutxCtsFlow = FALSE; |
newio.fOutxDsrFlow = FALSE; |
newio.fDtrControl = DTR_CONTROL_DISABLE; |
newio.fDsrSensitivity = FALSE; |
newio.fOutX = FALSE; |
newio.fInX = FALSE; |
newio.fNull = FALSE; |
newio.fRtsControl = FALSE; |
|
//Set the timeouts |
{ |
COMMTIMEOUTS timeouts = {0}; |
timeouts.ReadIntervalTimeout = MAXDWORD; |
timeouts.ReadTotalTimeoutMultiplier = 0; |
timeouts.ReadTotalTimeoutConstant = 0; |
timeouts.WriteTotalTimeoutMultiplier = 0; |
timeouts.WriteTotalTimeoutConstant = 0; |
if( SetCommTimeouts( desc->port, &timeouts ) == 0 ){ |
printf("bad timeout\n"); fflush(stdout);} |
} |
#else |
newio.c_iflag |= IGNBRK; |
newio.c_iflag &= ~BRKINT; |
newio.c_iflag &= ~ICRNL; |
newio.c_oflag = 0; |
newio.c_lflag = 0; |
newio.c_cc[VTIME] = 0; |
newio.c_cc[VMIN] = 1; |
#endif |
|
SET_SERIAL_PORT_STRUCT( desc->port, newio ); |
|
return 1; |
} |
|
/** |
* @param data_bits The number of data bits |
*/ |
static int set_data_bits( struct port_descriptor* desc, int data_bits ){ |
GET_SERIAL_PORT_STRUCT( desc->port, newio ); |
|
#ifdef _WIN32 |
newio.ByteSize = data_bits; |
#else |
newio.c_cflag &= ~CSIZE; |
if( data_bits == 8 ){ |
newio.c_cflag |= CS8; |
}else if( data_bits == 7 ){ |
newio.c_cflag |= CS7; |
}else if( data_bits == 6 ){ |
newio.c_cflag |= CS6; |
}else if( data_bits == 5 ){ |
newio.c_cflag |= CS5; |
} |
#endif |
|
SET_SERIAL_PORT_STRUCT( desc->port, newio ); |
|
return 1; |
} |
|
/** |
* @param stop_bits 1 for 1, 2 for 2 |
*/ |
static int set_stop_bits( struct port_descriptor* desc, int stop_bits ){ |
GET_SERIAL_PORT_STRUCT( desc->port, newio ); |
|
#ifdef _WIN32 |
if( stop_bits == 1 ){ |
newio.StopBits = ONESTOPBIT; |
}else if( stop_bits == 2 ){ |
newio.StopBits = TWOSTOPBITS; |
} |
#else |
if( stop_bits == 1 ){ |
newio.c_cflag &= ~CSTOPB; |
}else if( stop_bits == 2 ){ |
newio.c_cflag |= CSTOPB; |
} |
#endif |
|
SET_SERIAL_PORT_STRUCT( desc->port, newio ); |
|
return 1; |
} |
|
/** |
* @param parity 0 for no parity, 1 for odd parity, 2 for even parity |
*/ |
static int set_parity( struct port_descriptor* desc, int parity ){ |
GET_SERIAL_PORT_STRUCT( desc->port, newio ); |
|
#ifdef _WIN32 |
if( parity == 0 ){ |
newio.Parity = NOPARITY; |
}else if( parity == 1 ){ |
newio.Parity = ODDPARITY; |
}else if( parity == 2 ){ |
newio.Parity = EVENPARITY; |
} |
#else |
if( parity == 0 ){ |
newio.c_cflag |= IGNPAR; |
}else if( parity == 1 ){ |
newio.c_cflag |= PARODD; |
}else if( parity == 2 ){ |
newio.c_cflag |= PARENB; |
} |
#endif |
|
SET_SERIAL_PORT_STRUCT( desc->port, newio ); |
|
return 1; |
} |
|
/** |
* @param flow_control 0 for none, 1 for hardware, 2 for software |
*/ |
static int set_flow_control( struct port_descriptor* desc, int flow_control ){ |
GET_SERIAL_PORT_STRUCT( desc->port, newio ); |
|
#ifdef _WIN32 |
if( flow_control == 0 ){ |
newio.fOutxCtsFlow = FALSE; |
newio.fRtsControl = FALSE; |
newio.fOutX = FALSE; |
newio.fInX = FALSE; |
}else if( flow_control == 1 ){ |
newio.fOutxCtsFlow = TRUE; |
newio.fRtsControl = TRUE; |
newio.fOutX = FALSE; |
newio.fInX = FALSE; |
}else if( flow_control == 2 ){ |
newio.fOutxCtsFlow = FALSE; |
newio.fRtsControl = FALSE; |
newio.fOutX = TRUE; |
newio.fInX = TRUE; |
} |
#else |
if( flow_control == 0 ){ |
newio.c_cflag &= ~( IXON | IXOFF | IXANY ); |
}else if( flow_control == 1 ){ |
newio.c_cflag |= HW_FLOW; |
}else if( flow_control == 2 ){ |
newio.c_cflag |= ( IXON | IXOFF | IXANY ); |
} |
#endif |
|
SET_SERIAL_PORT_STRUCT( desc->port, newio ); |
|
return 1; |
} |
|
static void throw_io_exception( JNIEnv * env, int errorNumber ){ |
#ifdef _WIN32 |
LPTSTR error_text = NULL; |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
|
FormatMessage( |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, |
NULL, |
errorNumber, |
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), |
(LPTSTR)&error_text, |
0, |
NULL ); |
(*env)->ThrowNew(env, exception_class, error_text ); |
LocalFree( error_text ); |
#else |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errorNumber ) ); |
#endif /* _WIN32 */ |
} |
|
static void throw_io_exception_message( JNIEnv * env, const char* message ){ |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, message ); |
} |
|
// |
// JNI Methods |
// |
|
/* |
* Class: com_rm5248_serial_SerialPort |
* Method: openPort |
* Signature: (Ljava/lang/String;IIIII)I |
*/ |
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_openPort |
(JNIEnv * env, jobject obj, jstring port, jint baudRate, jint dataBits, jint stopBits, jint parity, jint flowControl){ |
struct port_descriptor* new_port; |
int list_pos; |
int found = 0; |
const char* port_to_open; |
jboolean iscopy; |
|
port_to_open = (*env)->GetStringUTFChars( env, port, &iscopy ); |
|
if( port_list == NULL ){ |
port_list = malloc( sizeof( struct port_descriptor* ) * 10 ); |
port_list_size = 10; |
for( list_pos = 0; list_pos < port_list_size; ++list_pos ){ |
port_list[ list_pos ] = NULL; |
} |
} |
|
//Search thru the port_list, find the first one that is NULL |
for( list_pos = 0; list_pos < port_list_size; ++list_pos ){ |
if( port_list[ list_pos ] == NULL ){ |
found = 1; |
break; |
} |
} |
|
if( !found ){ |
//no free slots. Expand our array by 10 elements |
struct port_descriptor** tmpPortDesc; |
tmpPortDesc = malloc( sizeof( struct port_descriptor* ) * ( port_list_size + 10 ) ); |
|
//put all elements into the new array |
for( list_pos = 0; list_pos < port_list_size; ++list_pos ){ |
tmpPortDesc[ list_pos ] = port_list[ list_pos ]; |
} |
++list_pos; //put the place to insert the new record one past the old records |
|
port_list_size += 10; |
|
//free the old array, set it to the new one |
free( port_list ); |
port_list = tmpPortDesc; |
} |
|
//at this point, list_pos points to a NULL location in our array |
new_port = malloc( sizeof( struct port_descriptor ) ); |
|
//Now, let's get to the actual opening of our port |
#ifdef _WIN32 |
new_port->port = CreateFile( port_to_open, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0 ); |
if( new_port->port == INVALID_HANDLE_VALUE ){ |
if( GetLastError() == ERROR_FILE_NOT_FOUND ){ |
LPTSTR error_text = NULL; |
jclass exception_class; |
|
FormatMessage( |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, |
NULL, |
GetLastError(), |
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), |
(LPTSTR)&error_text, |
0, |
NULL ); |
|
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "com/rm5248/serial/NoSuchPortException"); |
(*env)->ThrowNew(env, exception_class, error_text ); |
free( new_port ); |
LocalFree( error_text ); |
return -1; |
} |
} |
|
{ |
//Let's check to see if this is a serial port |
DCB io_name = {0}; |
io_name.DCBlength = sizeof( io_name ); |
if (!GetCommState( new_port->port, &io_name ) ) { |
LPTSTR error_text = NULL; |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "com/rm5248/serial/NotASerialPortException"); |
(*env)->ThrowNew(env, exception_class, "You are attempting to open something which is not a serial port" ); |
free( new_port ); |
|
|
|
FormatMessage( |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, |
NULL, |
GetLastError(), |
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), |
(LPTSTR)&error_text, |
0, |
NULL ); |
printf("error is %s\n", error_text ); |
LocalFree( error_text ); |
return -1; |
} |
} |
|
#else |
new_port->port = open( port_to_open, O_RDWR ); |
if( new_port->port < 0 && errno == ENOENT ){ |
//That's not a valid serial port, error out |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "com/rm5248/serial/NoSuchPortException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
free( new_port ); |
return -1; |
}else if( new_port->port < 0 ){ |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "com/rm5248/serial/NoSuchPortException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
free( new_port ); |
return -1; |
} |
|
{ |
struct termios io_name; |
if( tcgetattr( new_port->port, &io_name ) < 0 ){ |
if( errno == ENOTTY ){ |
//This is apparently not a serial port |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "com/rm5248/serial/NotASerialPortException"); |
(*env)->ThrowNew(env, exception_class, "You are attempting to open something which is not a serial port" ); |
free( new_port ); |
return -1; |
} |
} |
} |
#endif /* __WIN32 */ |
|
|
|
//Set the baud rate |
set_baud_rate( new_port, baudRate ); |
set_raw_input( new_port ); |
//Set the data bits( character size ) |
set_data_bits( new_port, dataBits ); |
//Set the stop bits |
set_stop_bits( new_port, stopBits ); |
//Set the parity |
set_parity( new_port, parity ); |
//Set the flow control |
set_flow_control( new_port, flowControl ); |
|
//Only set the new_port to be in our array as the last instruction |
//If there are any errors, we will have returned long before this |
port_list[ list_pos ] = new_port; |
|
return list_pos; |
} |
|
/* |
* Class: com_rm5248_serial_SerialPort |
* Method: openPort |
* Signature: (Ljava/lang/String;)I |
*/ |
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_openPort__Ljava_lang_String_2 |
(JNIEnv * env, jobject obj, jstring port){ |
struct port_descriptor* new_port; |
int list_pos; |
int found = 0; |
const char* port_to_open; |
jboolean iscopy; |
|
port_to_open = (*env)->GetStringUTFChars( env, port, &iscopy ); |
|
if( port_list == NULL ){ |
port_list = malloc( sizeof( struct port_descriptor* ) * 10 ); |
port_list_size = 10; |
for( list_pos = 0; list_pos < port_list_size; ++list_pos ){ |
port_list[ list_pos ] = NULL; |
} |
} |
|
//Search thru the port_list, find the first one that is NULL |
for( list_pos = 0; list_pos < port_list_size; ++list_pos ){ |
if( port_list[ list_pos ] == NULL ){ |
found = 1; |
break; |
} |
} |
|
if( !found ){ |
//no free slots. Expand our array by 10 elements |
struct port_descriptor** tmpPortDesc; |
tmpPortDesc = malloc( sizeof( struct port_descriptor* ) * ( port_list_size + 10 ) ); |
|
//put all elements into the new array |
for( list_pos = 0; list_pos < port_list_size; ++list_pos ){ |
tmpPortDesc[ list_pos ] = port_list[ list_pos ]; |
} |
++list_pos; //put the place to insert the new record one past the old records |
|
port_list_size += 10; |
|
//free the old array, set it to the new one |
free( port_list ); |
port_list = tmpPortDesc; |
} |
|
//at this point, list_pos points to a NULL location in our array |
new_port = malloc( sizeof( struct port_descriptor ) ); |
|
//Now, let's get to the actual opening of our port |
#ifdef _WIN32 |
new_port->port = CreateFile( port_to_open, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0 ); |
if( new_port->port == INVALID_HANDLE_VALUE ){ |
if( GetLastError() == ERROR_FILE_NOT_FOUND ){ |
LPTSTR error_text = NULL; |
jclass exception_class; |
|
FormatMessage( |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, |
NULL, |
GetLastError(), |
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), |
(LPTSTR)&error_text, |
0, |
NULL ); |
|
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "com/rm5248/serial/NoSuchPortException"); |
(*env)->ThrowNew(env, exception_class, error_text ); |
free( new_port ); |
LocalFree( error_text ); |
return -1; |
} |
} |
|
{ |
//Let's check to see if this is a serial port |
DCB io_name = {0}; |
io_name.DCBlength = sizeof( io_name ); |
if (!GetCommState( new_port->port, &io_name ) ) { |
LPTSTR error_text = NULL; |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "com/rm5248/serial/NotASerialPortException"); |
(*env)->ThrowNew(env, exception_class, "You are attempting to open something which is not a serial port" ); |
free( new_port ); |
|
|
|
FormatMessage( |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, |
NULL, |
GetLastError(), |
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), |
(LPTSTR)&error_text, |
0, |
NULL ); |
printf("error is %s\n", error_text ); |
LocalFree( error_text ); |
return -1; |
} |
} |
#else |
new_port->port = open( port_to_open, O_RDWR ); |
if( new_port->port < 0 && errno == ENOENT ){ |
//That's not a valid serial port, error out |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "com/rm5248/serial/NoSuchPortException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
free( new_port ); |
return -1; |
}else if( new_port->port < 0 ){ |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "com/rm5248/serial/NoSuchPortException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
free( new_port ); |
return -1; |
} |
|
{ |
struct termios io_name; |
if( tcgetattr( new_port->port, &io_name ) < 0 ){ |
if( errno == ENOTTY ){ |
//This is apparently not a serial port |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "com/rm5248/serial/NotASerialPortException"); |
(*env)->ThrowNew(env, exception_class, "You are attempting to open something which is not a serial port" ); |
free( new_port ); |
return -1; |
} |
} |
} |
#endif /* __WIN32 */ |
|
|
//Only set the new_port to be in our array as the last instruction |
//If there are any errors, we will have returned long before this |
port_list[ list_pos ] = new_port; |
|
return list_pos; |
} |
|
/* |
* Class: com_rm5248_serial_SerialPort |
* Method: doClose |
* Signature: ()V |
*/ |
JNIEXPORT void JNICALL Java_com_rm5248_serial_SerialPort_doClose |
(JNIEnv * env, jobject obj){ |
jint array_pos; |
struct port_descriptor* desc; |
|
array_pos = get_handle( env, obj ); |
if( array_pos < 0 || array_pos > port_list_size ){ |
return; |
} |
|
desc = port_list[ array_pos ]; |
if( desc == NULL ){ |
return; |
} |
|
close( desc->port ); |
free( desc ); |
port_list[ array_pos ] = NULL; |
} |
|
/* |
* Class: com_rm5248_serial_SerialPort |
* Method: setBaudRate |
* Signature: (I)Z |
*/ |
JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setBaudRate |
(JNIEnv * env, jobject obj, jint baud_rate ){ |
jint array_pos; |
struct port_descriptor* desc; |
|
array_pos = get_handle( env, obj ); |
|
if( array_pos < 0 ){ |
//throw new exception |
int errNum; |
#ifdef _WIN32 |
errNum = GetLastError(); |
#else |
errNum = errno; |
#endif /* _WIN32 */ |
throw_io_exception( env, errNum ); |
return 0; |
} |
|
desc = port_list[ array_pos ]; |
|
if( desc == NULL ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, "Given bad positon in array. Internal SerialPort error." ); |
return 0; |
} |
|
return set_baud_rate( desc, baud_rate ); |
} |
|
/* |
* Class: com_rm5248_serial_SerialPort |
* Method: getBaudRateInternal |
* Signature: ()I |
*/ |
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getBaudRateInternal |
(JNIEnv * env, jobject obj){ |
jint array_pos; |
struct port_descriptor* desc; |
|
array_pos = get_handle( env, obj ); |
|
if( array_pos < 0 ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return 0; |
} |
|
desc = port_list[ array_pos ]; |
|
if( desc == NULL ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return 0; |
} |
|
//Now, let's get the baud rate information |
{ |
GET_SERIAL_PORT_STRUCT( desc->port, newio ); |
#ifdef _WIN32 |
GetCommState( desc->port, &newio ); |
switch( newio.BaudRate ){ |
#else |
switch( cfgetispeed( &newio ) ){ |
GET_SPEED_SWITCH( 0, newio ); |
GET_SPEED_SWITCH( 50, newio ); |
GET_SPEED_SWITCH( 75, newio ); |
#endif /* _WIN32 */ |
GET_SPEED_SWITCH( 110, newio ); |
#ifndef _WIN32 |
GET_SPEED_SWITCH( 134, newio ); |
GET_SPEED_SWITCH( 150, newio ); |
GET_SPEED_SWITCH( 200, newio ); |
#endif /* _WIN32 */ |
GET_SPEED_SWITCH( 300, newio ); |
GET_SPEED_SWITCH( 600, newio ); |
GET_SPEED_SWITCH( 1200, newio ); |
#ifndef _WIN32 |
GET_SPEED_SWITCH( 1800, newio ); |
#endif /* _WIN32 */ |
GET_SPEED_SWITCH( 2400, newio ); |
GET_SPEED_SWITCH( 4800, newio ); |
GET_SPEED_SWITCH( 9600, newio ); |
GET_SPEED_SWITCH( 19200, newio ); |
GET_SPEED_SWITCH( 38400, newio ); |
GET_SPEED_SWITCH( 115200, newio ); |
default: |
return 0; |
} /* end switch */ |
} |
|
} |
|
/* |
* Class: com_rm5248_serial_SerialPort |
* Method: setStopBits |
* Signature: (I)Z |
*/ |
JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setStopBits |
(JNIEnv * env, jobject obj, jint bits){ |
jint array_pos; |
struct port_descriptor* desc; |
|
array_pos = get_handle( env, obj ); |
|
desc = port_list[ array_pos ]; |
if( desc == NULL ){ |
return 0; |
} |
|
return set_stop_bits( desc, bits ); |
} |
|
/* |
* Class: com_rm5248_serial_SerialPort |
* Method: getStopBitsInternal |
* Signature: ()I |
*/ |
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getStopBitsInternal |
(JNIEnv * env, jobject obj){ |
jint array_pos; |
struct port_descriptor* desc; |
|
array_pos = get_handle( env, obj ); |
|
if( array_pos < 0 ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return 0; |
} |
|
desc = port_list[ array_pos ]; |
|
if( desc == NULL ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return 0; |
} |
|
{ |
GET_SERIAL_PORT_STRUCT( desc->port, newio ); |
#ifdef _WIN32 |
if( newio.StopBits == 1 ){ |
return 1; |
}else if( newio.StopBits == 2 ){ |
return 2; |
}else{ |
return -1; |
} |
#else |
if( newio.c_cflag & CSTOPB ){ |
return 2; |
}else{ |
return 1; |
} |
#endif |
} |
} |
/* |
* Class: com_rm5248_serial_SerialPort |
* Method: setCharSize |
* Signature: (I)Z |
*/ |
JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setCharSize |
(JNIEnv * env, jobject obj, jint size){ |
jint array_pos; |
struct port_descriptor* desc; |
|
array_pos = get_handle( env, obj ); |
|
desc = port_list[ array_pos ]; |
if( desc == NULL ){ |
return 0; |
} |
|
return set_data_bits( desc, size ); |
} |
|
/* |
* Class: com_rm5248_serial_SerialPort |
* Method: getCharSizeInternal |
* Signature: ()I |
*/ |
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getCharSizeInternal |
(JNIEnv * env, jobject obj){ |
jint array_pos; |
struct port_descriptor* desc; |
|
array_pos = get_handle( env, obj ); |
|
if( array_pos < 0 ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return 0; |
} |
|
desc = port_list[ array_pos ]; |
|
if( desc == NULL ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return 0; |
} |
|
//Now get the char size |
{ |
GET_SERIAL_PORT_STRUCT( desc->port, newio ); |
|
#ifdef _WIN32 |
return newio.ByteSize; |
#else |
if( ( newio.c_cflag | CS8 ) == CS8 ){ |
return 8; |
}else if( ( newio.c_cflag | CS7 ) == CS7 ){ |
return 7; |
}else if( ( newio.c_cflag | CS6 ) == CS6 ){ |
return 6; |
}else if( ( newio.c_cflag | CS5 ) == CS5 ){ |
return 5; |
}else{ |
return 0; |
} |
#endif |
} |
|
} |
|
/* |
* Class: com_rm5248_serial_SerialPort |
* Method: setParity |
* Signature: (I)Z |
*/ |
JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setParity |
(JNIEnv * env, jobject obj, jint parity){ |
jint array_pos; |
struct port_descriptor* desc; |
|
array_pos = get_handle( env, obj ); |
|
if( array_pos < 0 ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return 0; |
} |
|
desc = port_list[ array_pos ]; |
|
if( desc == NULL ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return 0; |
} |
|
return set_parity( desc, parity ); |
} |
|
/* |
* Class: com_rm5248_serial_SerialPort |
* Method: getParityInternal |
* Signature: ()I |
*/ |
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getParityInternal |
(JNIEnv * env, jobject obj){ |
jint array_pos; |
struct port_descriptor* desc; |
|
array_pos = get_handle( env, obj ); |
|
if( array_pos < 0 ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return 0; |
} |
|
desc = port_list[ array_pos ]; |
|
if( desc == NULL ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return 0; |
} |
|
{ |
GET_SERIAL_PORT_STRUCT( desc->port, newio ); |
#ifdef _WIN32 |
if( newio.Parity == NOPARITY ){ |
return 0; |
}else if( newio.Parity == ODDPARITY ){ |
return 1; |
}else if( newio.Parity == EVENPARITY ){ |
return 2; |
}else{ |
return -1; |
} |
#else |
if( !( newio.c_cflag & PARENB ) ){ |
//No parity |
return 0; |
}else if( newio.c_cflag & PARODD ){ |
//Odd parity |
return 1; |
}else if( !( newio.c_cflag & PARODD ) ){ |
//Even parity |
return 2; |
}else{ |
return -1; |
} |
#endif |
} |
|
} |
|
/* |
* Class: com_rm5248_serial_SerialPort |
* Method: setFlowControl |
* Signature: (I)Z |
*/ |
JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setFlowControl |
(JNIEnv * env, jobject obj, jint flow){ |
jint array_pos; |
struct port_descriptor* desc; |
|
array_pos = get_handle( env, obj ); |
|
if( array_pos < 0 ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return 0; |
} |
|
desc = port_list[ array_pos ]; |
|
if( desc == NULL ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return 0; |
} |
|
return set_flow_control( desc, flow ); |
} |
|
/* |
* Class: com_rm5248_serial_SerialPort |
* Method: getFlowControlInternal |
* Signature: ()I |
*/ |
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getFlowControlInternal |
(JNIEnv * env, jobject obj){ |
jint array_pos; |
struct port_descriptor* desc; |
|
array_pos = get_handle( env, obj ); |
|
if( array_pos < 0 ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return 0; |
} |
|
desc = port_list[ array_pos ]; |
|
if( desc == NULL ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return 0; |
} |
|
{ |
GET_SERIAL_PORT_STRUCT( desc->port, newio ); |
#ifdef _WIN32 |
if( newio.fOutX == TRUE && newio.fInX == TRUE ){ |
return 2; |
}else if( newio.fRtsControl == TRUE && newio.fOutxCtsFlow == TRUE ){ |
return 1; |
}else{ |
return 0; |
} |
#else |
if( newio.c_cflag & ~( IXON ) && |
newio.c_cflag & ~( IXOFF ) && |
newio.c_cflag & ~( IXANY ) ){ |
return 0; |
}else if( newio.c_cflag & HW_FLOW ){ |
return 1; |
}else if( newio.c_cflag & ( IXON ) && |
newio.c_cflag & ( IXOFF ) && |
newio.c_cflag & ( IXANY ) ){ |
return 2; |
} |
#endif /* _WIN32 */ |
} |
|
return -1; |
} |
|
/* |
* Class: com_rm5248_serial_SerialPort |
* Method: getSerialLineStateInternalNonblocking |
* Signature: ()I |
*/ |
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getSerialLineStateInternalNonblocking |
(JNIEnv * env, jobject obj ){ |
jint array_pos; |
struct port_descriptor* desc; |
jint ret_val; |
|
array_pos = get_handle( env, obj ); |
|
if( array_pos < 0 ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return 0; |
} |
|
desc = port_list[ array_pos ]; |
|
if( desc == NULL ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return 0; |
} |
|
ret_val = 0; |
|
{ |
#ifdef _WIN32 |
DWORD get_val; |
if( GetCommModemStatus( desc->port, &get_val ) == 0 ){ |
throw_io_exception( env, GetLastError() ); |
return -1; |
} |
|
if( get_val & MS_CTS_ON ){ |
// CTS |
ret_val |= ( 0x01 << 1 ); |
} |
|
if( get_val & MS_DSR_ON ){ |
// Data Set Ready |
ret_val |= ( 0x01 << 2 ); |
} |
|
if( get_val & MS_RING_ON ){ |
// Ring Indicator |
ret_val |= ( 0x01 << 5 ); |
} |
#else |
int get_val; |
if( ioctl( desc->port, TIOCMGET, &get_val ) < 0 ){ |
throw_io_exception( env, errno ); |
return -1; |
} |
|
if( get_val & TIOCM_CD ){ |
// Carrier detect |
ret_val |= 0x01; |
} |
|
if( get_val & TIOCM_CTS ){ |
// CTS |
ret_val |= ( 0x01 << 1 ); |
} |
|
if( get_val & TIOCM_DSR ){ |
// Data Set Ready |
ret_val |= ( 0x01 << 2 ); |
} |
|
if( get_val & TIOCM_DTR ){ |
// Data Terminal Ready |
ret_val |= ( 0x01 << 3 ); |
} |
|
if( get_val & TIOCM_RTS ){ |
// Request To Send |
ret_val |= ( 0x01 << 4 ); |
} |
|
if( get_val & TIOCM_RI ){ |
// Ring Indicator |
ret_val |= ( 0x01 << 5 ); |
} |
#endif |
} |
|
return ret_val; |
} |
|
/* |
* Class: com_rm5248_serial_SerialPort |
* Method: setSerialLineStateInternal |
* Signature: (Lcom/rm5248/serial/SerialLineState;)I |
*/ |
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_setSerialLineStateInternal |
(JNIEnv * env, jobject obj, jobject serial){ |
jint array_pos; |
struct port_descriptor* desc; |
jint ret_val; |
|
array_pos = get_handle( env, obj ); |
|
if( array_pos < 0 ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return 0; |
} |
|
desc = port_list[ array_pos ]; |
|
if( desc == NULL ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return 0; |
} |
|
ret_val = 0; |
|
#ifdef _WIN32 |
//Can't set CD on Windows |
if( get_bool( env, serial, "carrierDetect" ) ){ |
}else{ |
} |
|
//Can't set CTS on Windows |
if( get_bool( env, serial, "clearToSend" ) ){ |
}else{ |
} |
|
//Can't set in Windows |
if( get_bool( env, serial, "dataSetReady" ) ){ |
}else{ |
} |
|
if( get_bool( env, serial, "dataTerminalReady" ) ){ |
if( !EscapeCommFunction( desc->port, SETDTR ) ){ |
throw_io_exception_message( env, "Could not set DTR" ); |
return -1; |
} |
}else{ |
if( !EscapeCommFunction( desc->port, CLRDTR ) ){ |
throw_io_exception_message( env, "Could not set DTR" ); |
return -1; |
} |
} |
|
//Can't set in Windows |
if( get_bool( env, serial, "ringIndicator" ) ){ |
}else{ |
} |
|
if( get_bool( env, serial, "requestToSend" ) ){ |
if( !EscapeCommFunction( desc->port, SETRTS ) ){ |
throw_io_exception_message( env, "Could not set RTS" ); |
return -1; |
} |
}else{ |
if( !EscapeCommFunction( desc->port, CLRRTS ) ){ |
throw_io_exception_message( env, "Could not set RTS" ); |
return -1; |
} |
} |
#else |
if( get_bool( env, serial, "carrierDetect" ) ){ |
if( ioctl( desc->port, TIOCMBIS, TIOCM_CD ) < 0 ){ |
throw_io_exception_message( env, "Could not set CD" ); |
return -1; |
} |
}else{ |
if( ioctl( desc->port, TIOCMBIC, TIOCM_CD ) < 0 ){ |
throw_io_exception_message( env, "Could not set CD" ); |
return -1; |
} |
} |
|
if( get_bool( env, serial, "clearToSend" ) ){ |
if( ioctl( desc->port, TIOCMBIS, TIOCM_CTS ) < 0 ){ |
throw_io_exception_message( env, "Could not set CTS" ); |
return -1; |
} |
}else{ |
if( ioctl( desc->port, TIOCMBIC, TIOCM_CTS ) < 0 ){ |
throw_io_exception_message( env, "Could not set CTS" ); |
return -1; |
} |
} |
|
if( get_bool( env, serial, "dataSetReady" ) ){ |
if( ioctl( desc->port, TIOCMBIS, TIOCM_LE ) < 0 ){ |
throw_io_exception_message( env, "Could not set DSR" ); |
return -1; |
} |
}else{ |
if( ioctl( desc->port, TIOCMBIC, TIOCM_LE ) < 0 ){ |
throw_io_exception_message( env, "Could not set DSR" ); |
return -1; |
} |
} |
|
if( get_bool( env, serial, "dataTerminalReady" ) ){ |
if( ioctl( desc->port, TIOCMBIS, TIOCM_DTR ) < 0 ){ |
throw_io_exception_message( env, "Could not set DTR" ); |
return -1; |
} |
}else{ |
if( ioctl( desc->port, TIOCMBIC, TIOCM_DTR ) < 0 ){ |
throw_io_exception_message( env, "Could not set DTR" ); |
return -1; |
} |
} |
|
if( get_bool( env, serial, "ringIndicator" ) ){ |
if( ioctl( desc->port, TIOCMBIS, TIOCM_RNG ) < 0 ){ |
throw_io_exception_message( env, "Could not set Ring" ); |
return -1; |
} |
}else{ |
if( ioctl( desc->port, TIOCMBIC, TIOCM_RNG ) < 0 ){ |
throw_io_exception_message( env, "Could not set Ring" ); |
return -1; |
} |
} |
|
if( get_bool( env, serial, "requestToSend" ) ){ |
if( ioctl( desc->port, TIOCMBIS, TIOCM_RTS ) < 0 ){ |
throw_io_exception_message( env, "Could not set RTS" ); |
return -1; |
} |
}else{ |
if( ioctl( desc->port, TIOCMBIC, TIOCM_RTS ) < 0 ){ |
throw_io_exception_message( env, "Could not set RTS" ); |
return -1; |
} |
} |
#endif |
|
return ret_val; |
} |
|
// |
// ------------------------------------------------------------------------ |
// ------------------Input/Output methods below here----------------------- |
// ------------------------------------------------------------------------ |
// |
|
/* |
* Class: com_rm5248_serial_SerialInputStream |
* Method: readByte |
* Signature: ()I |
*/ |
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialInputStream_readByte |
(JNIEnv * env, jobject obj){ |
int stat; |
int ret_val; |
jint array_pos; |
struct port_descriptor* desc; |
int get_val = 0; |
#ifdef _WIN32 |
DWORD ret = 0; |
OVERLAPPED overlap = {0}; |
int current_available = 0; |
#endif |
|
array_pos = get_handle( env, obj ); |
if( array_pos < 0 ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return -1; |
} |
|
desc = port_list[ array_pos ]; |
|
if( desc == NULL ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return -1; |
} |
|
ret_val = 0; |
|
#ifdef _WIN32 |
{ |
DWORD comErrors = {0}; |
COMSTAT portStatus = {0}; |
if( !ClearCommError( desc->port, &comErrors, &portStatus ) ){ |
//return value zero = fail |
throw_io_exception( env, GetLastError() ); |
return -1; |
}else{ |
current_available = portStatus.cbInQue; |
} |
} |
|
if( !current_available ){ |
//If nothing is currently available, wait until we get an event of some kind. |
//This could be the serial lines changing state, or it could be some data |
//coming into the system. |
overlap.hEvent = CreateEvent( 0, TRUE, 0, 0 ); |
SetCommMask( desc->port, EV_RXCHAR | EV_CTS | EV_DSR | EV_RING ); |
WaitCommEvent( desc->port, &ret, &overlap ); |
WaitForSingleObject( overlap.hEvent, INFINITE ); |
}else{ |
//Data is available; set the RXCHAR mask so we try to read from the port |
ret = EV_RXCHAR; |
} |
|
if( ret & EV_RXCHAR ){ |
if( !ReadFile( desc->port, &ret_val, 1, &stat, &overlap) ){ |
throw_io_exception( env, GetLastError() ); |
return -1; |
} |
|
//This is a valid byte, set our valid bit |
ret_val |= ( 0x01 << 15 ); |
} |
|
//Always get the com lines no matter what |
if( GetCommModemStatus( desc->port, &get_val ) == 0 ){ |
throw_io_exception( env, GetLastError() ); |
return -1; |
} |
|
if( get_val & MS_CTS_ON ){ |
// CTS |
ret_val |= ( 0x01 << 10 ); |
} |
|
if( get_val & MS_DSR_ON ){ |
// Data Set Ready |
ret_val |= ( 0x01 << 11 ); |
} |
|
if( get_val & MS_RING_ON ){ |
// Ring Indicator |
ret_val |= ( 0x01 << 14 ); |
} |
|
#else |
fd_set fdset; |
|
FD_ZERO( &fdset ); |
FD_SET( desc->port, &fdset ); |
|
if( select( desc->port + 1, &fdset, NULL, NULL, NULL ) < 0 ){ |
throw_io_exception( env, errno ); |
return -1; |
} |
|
if( FD_ISSET( desc->port, &fdset ) ){ |
stat = read( desc->port, &ret_val, sizeof( ret_val ) ); |
if( stat < 0 ){ |
//throw new exception |
throw_io_exception( env, errno ); |
return -1; |
} |
|
//This is a valid byte, set our valid bit |
ret_val |= ( 0x01 << 15 ); |
} |
|
//Now that we have read in the character, let's get the serial port line state. |
//If it has changed, we will fire an event in Java. |
//Now, because we only read one byte at a time, we will use the lower 8 bytes to |
//return the character that we read. The other bytes will be used to return |
//information on our serial port state. |
if( ioctl( desc->port, TIOCMGET, &get_val ) < 0 ){ |
throw_io_exception( env, errno ); |
return -1; |
} |
|
if( get_val & TIOCM_CD ){ |
// Carrier detect |
ret_val |= ( 0x01 << 9 ); |
} |
|
if( get_val & TIOCM_CTS ){ |
// CTS |
ret_val |= ( 0x01 << 10 ); |
} |
|
if( get_val & TIOCM_DSR ){ |
// Data Set Ready |
ret_val |= ( 0x01 << 11 ); |
} |
|
if( get_val & TIOCM_DTR ){ |
// Data Terminal Ready |
ret_val |= ( 0x01 << 12 ); |
} |
|
if( get_val & TIOCM_RTS ){ |
// Request To Send |
ret_val |= ( 0x01 << 13 ); |
} |
|
if( get_val & TIOCM_RI ){ |
// Ring Indicator |
ret_val |= ( 0x01 << 14 ); |
} |
|
#endif |
|
return ret_val; |
} |
|
/* |
* Class: com_rm5248_serial_SerialInputStream |
* Method: getAvailable |
* Signature: ()I |
*/ |
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialInputStream_getAvailable |
(JNIEnv * env, jobject obj){ |
jint ret_val; |
jint array_pos; |
struct port_descriptor* desc; |
|
array_pos = get_handle( env, obj ); |
if( array_pos < 0 ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return -1; |
} |
|
desc = port_list[ array_pos ]; |
|
if( desc == NULL ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return -1; |
} |
|
#ifdef _WIN32 |
{ |
DWORD comErrors = {0}; |
COMSTAT portStatus = {0}; |
if( !ClearCommError( desc->port, &comErrors, &portStatus ) ){ |
//return value zero = fail |
throw_io_exception( env, GetLastError() ); |
return -1; |
}else{ |
ret_val = portStatus.cbInQue; |
} |
} |
#else |
if( ioctl( desc->port, FIONREAD, &ret_val ) < 0 ){ |
//throw new exception |
throw_io_exception( env, errno ); |
return -1; |
} |
#endif |
return ret_val; |
} |
|
/* |
* Class: com_rm5248_serial_SerialOutputStream |
* Method: writeByte |
* Signature: (I)V |
*/ |
JNIEXPORT void JNICALL Java_com_rm5248_serial_SerialOutputStream_writeByte |
(JNIEnv * env, jobject obj, jint byte){ |
struct port_descriptor* desc; |
jint array_pos; |
char byte_write; |
#ifdef _WIN32 |
DWORD bytes_written; |
OVERLAPPED overlap; |
#else |
int bytes_written; |
#endif |
|
byte_write = byte; |
|
array_pos = get_handle( env, obj ); |
if( array_pos < 0 ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return; |
} |
|
desc = port_list[ array_pos ]; |
|
if( desc == NULL ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return; |
} |
|
#ifdef _WIN32 |
memset( &overlap, 0, sizeof( overlap ) ); |
overlap.hEvent = CreateEvent( 0, TRUE, 0, 0 ); |
if( !WriteFile( desc->port, &byte_write, sizeof( byte_write ), &bytes_written, &overlap ) ){ |
if( GetLastError() == ERROR_IO_PENDING ){ |
//Not in fact an error, we're just doing this asynchronously |
WaitForSingleObject( overlap.hEvent, INFINITE ); |
}else{ |
//throw new exception |
throw_io_exception( env, GetLastError() ); |
return; |
} |
} |
#else |
bytes_written = write( desc->port, &byte_write, sizeof( byte_write ) ); |
if( bytes_written < 0 ){ |
//throw new exception |
throw_io_exception( env, errno ); |
return; |
} |
#endif |
|
} |
|
/* |
* Class: com_rm5248_serial_SerialOutputStream |
* Method: writeByteArray |
* Signature: ([B)V |
*/ |
JNIEXPORT void JNICALL Java_com_rm5248_serial_SerialOutputStream_writeByteArray |
(JNIEnv * env, jobject obj, jbyteArray arr){ |
jbyte* data; |
jint len; |
jint array_pos; |
int my_errnum; |
struct port_descriptor* desc; |
#ifdef _WIN32 |
DWORD bytes_written; |
OVERLAPPED overlap; |
#else |
int bytes_written; |
#endif |
|
array_pos = get_handle( env, obj ); |
if( array_pos < 0 ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return; |
} |
|
desc = port_list[ array_pos ]; |
|
if( desc == NULL ){ |
//throw new exception |
jclass exception_class; |
(*env)->ExceptionDescribe( env ); |
(*env)->ExceptionClear( env ); |
exception_class = (*env)->FindClass(env, "java/io/IOException"); |
(*env)->ThrowNew(env, exception_class, strerror( errno ) ); |
return; |
} |
|
len = (*env)->GetArrayLength( env, arr ); |
data = (*env)->GetByteArrayElements(env, arr, 0); |
|
#ifdef _WIN32 |
memset( &overlap, 0, sizeof( overlap ) ); |
overlap.hEvent = CreateEvent( 0, TRUE, 0, 0 ); |
if( !WriteFile( desc->port, data, len, &bytes_written, &overlap ) ){ |
if( GetLastError() == ERROR_IO_PENDING ){ |
//Not in fact an error, we're just doing this asynchronously |
WaitForSingleObject( overlap.hEvent, INFINITE ); |
}else{ |
my_errnum = GetLastError(); |
} |
} |
#else |
bytes_written = write( desc->port, data, len ); |
if( bytes_written < 0 ){ |
my_errnum = errno; |
} |
#endif |
|
(*env)->ReleaseByteArrayElements(env, arr, data, 0); |
|
if( bytes_written != len ){ |
//OH SNAP AN ERROR |
throw_io_exception( env, my_errnum ); |
} |
} |
|
//BOOL EscapeCommFunction(HANDLE, DWORD). |
/* |
1. CLRDTR |
2. SETDTR |
3. SETRTS |
4. CLRRTS |
5. SETBREAK |
6. CLRBREAK |
*/ |
|