Subversion Repositories Programming Utils

Compare Revisions

Ignore whitespace Rev 110 → Rev 111

/tags/JavaSerial0.5/pom.xml
0,0 → 1,45
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.rm5248</groupId>
<artifactId>JavaSerial</artifactId>
<version>0.5-SNAPSHOT</version>
<description>A cross-platform way of accessing serial ports through Java. Supports Windows and Linux. Does not use the Java SerialAPI. Implementation uses the java.io API.</description>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>NativeCode</directory>
<includes>
<include>Linux/**</include>
<include>Windows/**</include>
</includes>
</resource>
</resources>
</build>
<url>http://programming.rm5248.com/</url>
<name>Java Serial</name>
<licenses>
<license>
<name>MIT</name>
<url>http://opensource.org/licenses/MIT</url>
<distribution>repo</distribution>
</license>
</licenses>
<scm>
<url>http://svn.rm5248.com/prog_utils/trunk/JavaSerial/</url>
<connection>svn</connection>
</scm>
<issueManagement>
<url>http://programming.rm5248.com/</url>
</issueManagement>
</project>
/tags/JavaSerial0.5/NativeCode/Windows/x86/javaserial.dll
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/JavaSerial0.5/NativeCode/Windows/x86/javaserial.dll
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: tags/JavaSerial0.5/NativeCode/Windows/amd64/javaserial.dll
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: tags/JavaSerial0.5/NativeCode/Windows/amd64/javaserial.dll
===================================================================
--- tags/JavaSerial0.5/NativeCode/Windows/amd64/javaserial.dll (nonexistent)
+++ tags/JavaSerial0.5/NativeCode/Windows/amd64/javaserial.dll (revision 111)
/tags/JavaSerial0.5/NativeCode/Windows/amd64/javaserial.dll
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: tags/JavaSerial0.5/NativeCode/SerialPortImpl.c
===================================================================
--- tags/JavaSerial0.5/NativeCode/SerialPortImpl.c (nonexistent)
+++ tags/JavaSerial0.5/NativeCode/SerialPortImpl.c (revision 111)
@@ -0,0 +1,1751 @@
+#ifdef _WIN32
+ #include <windows.h>
+
+ /* Make inline functions work */
+ #define inline __inline
+
+ #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;\
+ }
+
+ #define close(handle) CloseHandle(handle)
+#else
+ #include <termios.h>
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <unistd.h>
+ #include <dirent.h>
+ #include <pthread.h>
+ #include <sys/ioctl.h>
+ #include <errno.h>
+
+ #ifndef ENOMEDIUM
+ #define ENOMEDIUM ENODEV
+ #endif
+
+ #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 -1;\
+ }
+#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"
+#include "com_rm5248_serial_SimpleSerialInputStream.h"
+
+//
+// Struct Definitions
+//
+struct port_descriptor{
+#ifdef _WIN32
+ HANDLE port;
+#else
+ int port;
+ /* There appears to be a case where we can free() the port_descriptor
+ * after the select() call in SerialInputStream_readByte().
+ * This means that we segfault on the FD_SET() call.
+ * This mutex will keep us alive until we have exited the
+ * readByte() call.
+ */
+ pthread_mutex_t in_use;
+#endif
+};
+
+//
+// Local Variables
+//
+static struct port_descriptor** port_list = NULL;
+static int port_list_size;
+
+#ifdef _WIN32
+//Unfortunately, Windows does not let us get the state of the DTR/RTS lines.
+//So, we need to keep track of that manually.
+int winDTR = 0;
+int winRTS = 0;
+#endif
+
+//
+// Helper Methods
+//
+static inline 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 inline 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 inline 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 inline 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 inline 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 inline 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 inline 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
+ newio.c_iflag &= ~IGNPAR;
+ newio.c_cflag &= ~( PARODD | PARENB );
+ if( parity == 0 ){
+ newio.c_iflag |= 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 inline 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
+ newio.c_iflag &= ~( IXON | IXOFF | IXANY );
+ newio.c_cflag &= ~HW_FLOW;
+ if( flow_control == 0 ){
+ newio.c_iflag &= ~( IXON | IXOFF | IXANY );
+ }else if( flow_control == 1 ){
+ newio.c_cflag |= HW_FLOW;
+ }else if( flow_control == 2 ){
+ newio.c_iflag |= ( IXON | IXOFF | IXANY );
+ }
+#endif
+
+ SET_SERIAL_PORT_STRUCT( desc->port, newio );
+
+ return 1;
+}
+
+static inline 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 inline 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 );
+}
+
+static inline struct port_descriptor* get_port_descriptor( JNIEnv* env, jobject obj ){
+ int array_pos;
+ struct port_descriptor* desc;
+
+ array_pos = get_handle( env, obj );
+ if( array_pos < 0 || array_pos > port_list_size ){
+ throw_io_exception_message( env, "Unable to get handle" );
+ return NULL;
+ }
+ desc = port_list[ array_pos ];
+ if( desc == NULL ){
+ throw_io_exception_message( env, "Unable to get descriptor" );
+ return NULL;
+ }
+
+ return desc;
+}
+
+//
+// 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
+ {
+ //GOD DAMN IT WINDOWS http://support.microsoft.com/kb/115831
+ char* special_port = malloc( strlen( port_to_open ) + 5 );
+ memcpy( special_port, "\\\\.\\", 4 );
+ memcpy( special_port + 4, port_to_open, strlen( port_to_open ) + 1 );
+ new_port->port = CreateFile( special_port, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0 );
+ free( special_port );
+ }
+ 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 );
+ return -1;
+ }
+ }
+
+#else
+ pthread_mutex_init( &(new_port->in_use), NULL );
+ 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
+ if( set_baud_rate( new_port, baudRate ) < 0 ){
+ throw_io_exception_message( env, "Unable to set baud rate" );
+ return 0;
+ }
+ 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
+ {
+ char* special_port = malloc( strlen( port_to_open ) + 5 );
+ memcpy( special_port, "\\\\.\\", 4 );
+ memcpy( special_port + 4, port_to_open, strlen( port_to_open ) + 1 );
+ new_port->port = CreateFile( special_port, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0 );
+ free( special_port );
+ }
+ 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 );
+ return -1;
+ }
+ }
+#else
+ pthread_mutex_init( &(new_port->in_use), NULL );
+ 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){
+ //Note: We can't use get_serial_port_struct here, beacuse we need to set
+ //the position in the array to NULL
+ int array_pos;
+ struct port_descriptor* desc;
+
+ array_pos = get_handle( env, obj );
+ if( array_pos < 0 || array_pos > port_list_size ){
+ throw_io_exception_message( env, "Unable to get handle" );
+ return;
+ }
+ desc = port_list[ array_pos ];
+ if( desc == NULL ){
+ throw_io_exception_message( env, "Unable to get descriptor" );
+ return;
+ }
+
+ close( desc->port );
+#ifndef _WIN32
+ pthread_mutex_lock( &(desc->in_use) );
+ pthread_mutex_unlock( &(desc->in_use) );
+#endif
+ free( port_list[ array_pos ] );
+ 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 ){
+ struct port_descriptor* desc;
+
+ desc = get_port_descriptor( env, obj );
+
+ if( desc == NULL ){
+ 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){
+ struct port_descriptor* desc;
+
+ desc = get_port_descriptor( env, obj );
+ if( desc == NULL ){
+ 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){
+ struct port_descriptor* desc;
+
+ desc = get_port_descriptor( env, obj );
+ 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){
+ struct port_descriptor* desc;
+
+ desc = get_port_descriptor( env, obj );
+ if( desc == NULL ){
+ 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){
+ struct port_descriptor* desc;
+
+ desc = get_port_descriptor( env, obj );
+ 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){
+ struct port_descriptor* desc;
+
+ desc = get_port_descriptor( env, obj );
+ if( desc == NULL ){
+ 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){
+ struct port_descriptor* desc;
+
+ desc = get_port_descriptor( env, obj );
+ if( desc == NULL ){
+ 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){
+ struct port_descriptor* desc;
+
+ desc = get_port_descriptor( env, obj );
+ if( desc == NULL ){
+ 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){
+ struct port_descriptor* desc;
+
+ desc = get_port_descriptor( env, obj );
+ if( desc == NULL ){
+ 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){
+ struct port_descriptor* desc;
+
+ desc = get_port_descriptor( env, obj );
+ if( desc == NULL ){
+ 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 ){
+ struct port_descriptor* desc;
+ jint ret_val;
+
+ desc = get_port_descriptor( env, obj );
+ if( desc == NULL ){
+ 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( winDTR ){
+ ret_val |= ( 0x01 << 3 );
+ }
+
+ if( winRTS ){
+ ret_val |= ( 0x01 << 4 );
+ }
+
+ 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){
+ struct port_descriptor* desc;
+ jint ret_val;
+
+ desc = get_port_descriptor( env, obj );
+ if( desc == NULL ){
+ return 0;
+ }
+
+ ret_val = 0;
+
+#ifdef _WIN32
+ if( get_bool( env, serial, "dataTerminalReady" ) ){
+ if( !EscapeCommFunction( desc->port, SETDTR ) ){
+ throw_io_exception_message( env, "Could not set DTR" );
+ return -1;
+ }
+ winDTR = 1;
+ }else{
+ if( !EscapeCommFunction( desc->port, CLRDTR ) ){
+ throw_io_exception_message( env, "Could not set DTR" );
+ return -1;
+ }
+ winDTR = 0;
+ }
+
+ if( get_bool( env, serial, "requestToSend" ) ){
+ if( !EscapeCommFunction( desc->port, SETRTS ) ){
+ throw_io_exception_message( env, "Could not set RTS" );
+ return -1;
+ }
+ winRTS = 1;
+ }else{
+ if( !EscapeCommFunction( desc->port, CLRRTS ) ){
+ throw_io_exception_message( env, "Could not set RTS" );
+ return -1;
+ }
+ winRTS = 0;
+ }
+#else
+ int toSet = 0;
+
+ if( ioctl( desc->port, TIOCMGET, &toSet ) < 0 ){
+ throw_io_exception_message( env, "Could not get port settings" );
+ return -1;
+ }
+
+ if( get_bool( env, serial, "dataTerminalReady" ) ){
+ toSet |= TIOCM_DTR;
+ }else{
+ toSet &= ~TIOCM_DTR;
+ }
+
+ if( get_bool( env, serial, "requestToSend" ) ){
+ toSet |= TIOCM_RTS;
+ }else{
+ toSet &= ~TIOCM_RTS;
+ }
+
+ if( ioctl( desc->port, TIOCMSET, &toSet ) < 0 ){
+ throw_io_exception_message( env, "Could not set port settings" );
+ }
+#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;
+ struct port_descriptor* desc;
+ int get_val = 0;
+#ifdef _WIN32
+ DWORD ret = 0;
+ OVERLAPPED overlap = {0};
+ int current_available = 0;
+#endif
+
+ desc = get_port_descriptor( env, obj );
+ if( desc == NULL ){
+ return 0;
+ }
+
+ 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( winDTR ){
+ ret_val |= ( 0x01 << 12 );
+ }
+
+ if( winRTS ){
+ ret_val |= ( 0x01 << 13 );
+ }
+
+ if( get_val & MS_RING_ON ){
+ // Ring Indicator
+ ret_val |= ( 0x01 << 14 );
+ }
+
+#else
+
+ //Okay, this here is going to be a bit ugly.
+ //The problem here is that Linux/POSIX don't specify that TIOCMIWAIT
+ //has to exist. Also, the fact that if we use TIOCMIWAIT we don't
+ //timeout or anything. What would be very convenient in this case
+ //would be to have select() return when the state changed, but
+ //it's not possible. :(
+ //Ironically, this is one case in which the Windows serial API
+ //is better than the POSIX way.
+ fd_set fdset;
+ struct timeval timeout;
+ int originalState;
+ int selectStatus;
+
+ pthread_mutex_lock( &(desc->in_use) );
+
+ //first get the original state of the serial port lines
+ if( ioctl( desc->port, TIOCMGET, &originalState ) < 0 ){
+ throw_io_exception( env, errno );
+ pthread_mutex_unlock( &(desc->in_use) );
+ return -1;
+ }
+
+ while( 1 ){
+ FD_ZERO( &fdset );
+ FD_SET( desc->port, &fdset );
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 10000; // 10,000 microseconds = 10ms
+
+ selectStatus = select( desc->port + 1, &fdset, NULL, NULL, &timeout );
+ if( selectStatus < 0 ){
+ int errval;
+ if( errno == EBADF ){
+ // EOF
+ errval= 0;
+ }else{
+ throw_io_exception( env, errno );
+ errval = -1;
+ }
+ pthread_mutex_unlock( &(desc->in_use) );
+ return errval;
+ }
+
+ if( selectStatus == 0 ){
+ //This was a timeout
+ if( ioctl( desc->port, TIOCMGET, &get_val ) < 0 ){
+ throw_io_exception( env, errno );
+ pthread_mutex_unlock( &(desc->in_use) );
+ return -1;
+ }
+
+ if( get_val == originalState ){
+ //The state of the lines have not changed,
+ //continue on until something changes
+ continue;
+ }
+
+ }
+
+ if( FD_ISSET( desc->port, &fdset ) ){
+ stat = read( desc->port, &ret_val, 1 );
+ if( stat < 0 ){
+ //throw new exception
+ throw_io_exception( env, errno );
+ pthread_mutex_unlock( &(desc->in_use) );
+ return -1;
+ }
+
+ //This is a valid byte, set our valid bit
+ ret_val |= ( 0x01 << 15 );
+ }
+
+ //We get to this point if we either 1. have data or
+ //2. our state has changed
+ break;
+ }
+
+ //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 );
+ pthread_mutex_unlock( &(desc->in_use) );
+ 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 );
+ }
+
+ pthread_mutex_unlock( &(desc->in_use) );
+#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;
+ struct port_descriptor* desc;
+
+ desc = get_port_descriptor( env, obj );
+ if( desc == NULL ){
+ return 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{
+ 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_SimpleSerialInputStream
+ * Method: readByte
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_rm5248_serial_SimpleSerialInputStream_readByte
+ (JNIEnv * env, jobject obj){
+ struct port_descriptor* desc;
+ jint ret_val;
+ int stat;
+#ifdef _WIN32
+ DWORD ret = 0;
+ OVERLAPPED overlap = {0};
+ int current_available = 0;
+#endif
+
+ desc = get_port_descriptor( env, obj );
+ if( desc == NULL ){
+ return 0;
+ }
+
+ 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 );
+ 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;
+ }
+ }
+#else
+ pthread_mutex_lock( &(desc->in_use) );
+ stat = read( desc->port, &ret_val, 1 );
+ if( stat < 0 ){
+ throw_io_exception( env, errno );
+ pthread_mutex_unlock( &(desc->in_use) );
+ return -1;
+ }
+ pthread_mutex_unlock( &(desc->in_use) );
+#endif
+ return ret_val;
+}
+
+/*
+ * Class: com_rm5248_serial_SimpleSerialInputStream
+ * Method: getAvailable
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_rm5248_serial_SimpleSerialInputStream_getAvailable
+ (JNIEnv * env, jobject obj){
+ //use our already-existing method to get the available bytes, it already works
+ return Java_com_rm5248_serial_SerialInputStream_getAvailable( env, obj );
+}
+
+
+/*
+ * 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;
+ char byte_write;
+#ifdef _WIN32
+ DWORD bytes_written;
+ OVERLAPPED overlap;
+#else
+ int bytes_written;
+#endif
+
+ byte_write = byte;
+
+ desc = get_port_descriptor( env, obj );
+ if( desc == NULL ){
+ 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 ){
+ //Probably not an error, we're just doing this in an async fasion
+ if( WaitForSingleObject( overlap.hEvent, INFINITE ) == WAIT_FAILED ){
+ throw_io_exception( env, GetLastError() );
+ return;
+ }
+ }else{
+ 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;
+ struct port_descriptor* desc;
+#ifdef _WIN32
+ DWORD bytes_written;
+ OVERLAPPED overlap;
+#else
+ int bytes_written;
+#endif /* _WIN32 */
+
+ desc = get_port_descriptor( env, obj );
+ if( desc == NULL ){
+ 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 ){
+ //Probably not an error, we're just doing this in an async fasion
+ if( WaitForSingleObject( overlap.hEvent, INFINITE ) == WAIT_FAILED ){
+ throw_io_exception( env, GetLastError() );
+ return;
+ }
+ }else{
+ throw_io_exception( env, GetLastError() );
+ }
+ }
+
+#else
+ bytes_written = write( desc->port, data, len );
+ if( bytes_written < 0 ){
+ throw_io_exception( env, errno );
+ }
+#endif /* _WIN32 */
+
+ (*env)->ReleaseByteArrayElements(env, arr, data, 0);
+}
+
+
+//
+// ------------------------------------------------------------------------
+// ---------------------Static methods below here--------------------------
+// ------------------------------------------------------------------------
+//
+
+/*
+ * Class: com_rm5248_serial_SerialPort
+ * Method: getMajorNativeVersion
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getMajorNativeVersion
+ (JNIEnv * env, jclass cls){
+ return 0;
+}
+
+/*
+ * Class: com_rm5248_serial_SerialPort
+ * Method: getMinorNativeVersion
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getMinorNativeVersion
+ (JNIEnv * env, jclass cls){
+ return 5;
+}
+
+/*
+ * Class: com_rm5248_serial_SerialPort
+ * Method: getSerialPorts
+ * Signature: ()[Ljava/lang/String;
+ */
+JNIEXPORT jobjectArray JNICALL Java_com_rm5248_serial_SerialPort_getSerialPorts
+ (JNIEnv * env, jclass cls){
+ jclass stringClass;
+ jobjectArray array;
+ char** port_names;
+ int port_names_size;
+ int x;
+
+ port_names_size = 0;
+ port_names = malloc( sizeof( char* ) * 255 ); //max 255 serial ports
+#ifdef _WIN32
+ {
+ //Brute force, baby!
+ char* port_to_open = malloc( 11 );
+ HANDLE* port;
+ for( x = 0; x <= 255; x++ ){
+ _snprintf_s( port_to_open, 11, 11, "\\\\.\\COM%d", x );
+ port = CreateFile( port_to_open, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0 );
+ if( port != INVALID_HANDLE_VALUE ||
+ ( port == INVALID_HANDLE_VALUE &&
+ GetLastError() != ERROR_FILE_NOT_FOUND ) ){
+ //This is a valid port
+ //we could get INVALID_HANDLE_VALUE if the port is already open,
+ //so make sure we check to see if it is not that value
+ port_names[ port_names_size ] = malloc( 6 );
+ memcpy( port_names[ port_names_size ], port_to_open + 4, 6 );
+ port_names_size++;
+ }
+ CloseHandle( port );
+ }
+ free( port_to_open );
+ }
+#else
+ {
+ struct dirent *entry;
+ DIR* dir;
+ int fd;
+ char* deviceName;
+
+ deviceName = malloc( 100 );
+
+ dir = opendir( "/dev/" );
+ if( dir == NULL ){
+ throw_io_exception_message( env, "We can't open /dev." );
+ free( port_names );
+ free( deviceName );
+ return NULL;
+ }
+ while ( entry = readdir( dir ), entry != NULL) {
+ if( snprintf( deviceName, 100, "/dev/%s", entry->d_name ) >= 99 ){
+ fprintf( stderr, "WARNING: Ignoring file %s, filename too long\n", entry->d_name );
+ continue;
+ }
+ fd = open( deviceName, O_RDONLY );
+ if( fd < 0 ){
+ switch( errno ){
+ case EACCES:
+ case ENOMEDIUM:
+ //For some reason, I get errno 22 on my laptop
+ //when opening /dev/video0, which prints out
+ //"No such device or address"
+ //Not adding it here, because that does seem bad
+ break;
+ default:
+ perror( "open" );
+ fprintf( stderr, "ERROR: This is a very bad thing that should never happen %s:%d errno:%d\n", __FILE__, __LINE__, errno );
+ }
+ close( fd );
+ continue;
+ }
+
+ if( isatty( fd ) && port_names_size < 255 ){
+ port_names[ port_names_size ] = malloc( strlen( entry->d_name ) + 6 );
+ memcpy( port_names[ port_names_size ], "/dev/", 5 );
+ memcpy( port_names[ port_names_size ] + 5, entry->d_name, strlen( entry->d_name ) + 1 );
+ port_names_size++;
+ }
+
+ close( fd );
+ }
+ closedir( dir );
+ free( deviceName );
+ }
+#endif /* _WIN32 */
+
+ stringClass = (*env)->FindClass(env, "java/lang/String");
+ array = (*env)->NewObjectArray(env, port_names_size, stringClass, 0);
+
+ for( x = 0; x < port_names_size; x++ ){
+ (*env)->SetObjectArrayElement(env, array, x, (*env)->NewStringUTF( env, port_names[ x ] ) );
+ free( port_names[ x ] );
+ }
+
+ free( port_names );
+
+ return array;
+}
Index: tags/JavaSerial0.5/NativeCode/Linux/arm/libjavaserial.so
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: tags/JavaSerial0.5/NativeCode/Linux/arm/libjavaserial.so
===================================================================
--- tags/JavaSerial0.5/NativeCode/Linux/arm/libjavaserial.so (nonexistent)
+++ tags/JavaSerial0.5/NativeCode/Linux/arm/libjavaserial.so (revision 111)
/tags/JavaSerial0.5/NativeCode/Linux/arm/libjavaserial.so
Property changes:
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: tags/JavaSerial0.5/NativeCode/Linux/i386/libjavaserial.so
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: tags/JavaSerial0.5/NativeCode/Linux/i386/libjavaserial.so
===================================================================
--- tags/JavaSerial0.5/NativeCode/Linux/i386/libjavaserial.so (nonexistent)
+++ tags/JavaSerial0.5/NativeCode/Linux/i386/libjavaserial.so (revision 111)
/tags/JavaSerial0.5/NativeCode/Linux/i386/libjavaserial.so
Property changes:
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: tags/JavaSerial0.5/NativeCode/Linux/amd64/libjavaserial.so
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: tags/JavaSerial0.5/NativeCode/Linux/amd64/libjavaserial.so
===================================================================
--- tags/JavaSerial0.5/NativeCode/Linux/amd64/libjavaserial.so (nonexistent)
+++ tags/JavaSerial0.5/NativeCode/Linux/amd64/libjavaserial.so (revision 111)
/tags/JavaSerial0.5/NativeCode/Linux/amd64/libjavaserial.so
Property changes:
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: tags/JavaSerial0.5/NativeCode/Makefile
===================================================================
--- tags/JavaSerial0.5/NativeCode/Makefile (nonexistent)
+++ tags/JavaSerial0.5/NativeCode/Makefile (revision 111)
@@ -0,0 +1,104 @@
+#
+# Created by gmakemake x86 (Feb 24 2012) on Sat Aug 4 19:31:04 2012
+#
+
+#
+# Definitions
+#
+
+.SUFFIXES:
+.SUFFIXES: .a .o .c .C .cpp .s .S
+.c.o:
+ $(COMPILE.c) $< -o $@
+.C.o:
+ $(COMPILE.cc) $< -o $@
+.cpp.o:
+ $(COMPILE.cc) $< -o $@
+.S.s:
+ $(CPP) -o $*.s $<
+.s.o:
+ $(COMPILE.cc) $< -o $@
+.c.a:
+ $(COMPILE.c) -o $% $<
+ $(AR) $(ARFLAGS) $@ $%
+.C.a:
+ $(COMPILE.cc) -o $% $<
+ $(AR) $(ARFLAGS) $@ $%
+.cpp.a:
+ $(COMPILE.cc) -o $% $<
+ $(AR) $(ARFLAGS) $@ $%
+
+CC = gcc
+CXX = g++
+
+RM = rm -f
+AR = ar
+LINK.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)
+LINK.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS)
+COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) -c
+COMPILE.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c
+
+########## Default flags (redefine these with a header.mak file if desired)
+CPPFLAGS = -DPIC -I$(JNI_INCLUDE_DIR) -I$(JNI_INCLUDE_DIR)/linux
+CXXFLAGS =
+CFLAGS = -fPIC -Wall $(ARCH)
+CLIBFLAGS = -lm
+CCLIBFLAGS =
+########## End of default flags
+
+
+CPP_FILES =
+C_FILES = SerialPortImpl.c
+PS_FILES =
+S_FILES =
+H_FILES = com_rm5248_serial_SerialPort.h com_rm5248_serial_SerialPort_SerialInputStream.h com_rm5248_serial_SerialPort_SerialOutputStream.h
+SOURCEFILES = $(H_FILES) $(CPP_FILES) $(C_FILES) $(S_FILES)
+.PRECIOUS: $(SOURCEFILES)
+OBJFILES = SerialPortImpl.o
+
+JNI_INCLUDE_DIR = /usr/lib/jvm/java-7-openjdk-amd64/include
+JNI_INCLUDE_DIR_WIN=C:\Program Files (x86)\Java\jdk1.6.0_18\include
+
+#
+# Main targets
+#
+linux: SerialPortImpl.o
+ $(CC) -o libjavaserial.so $(ARCH) -shared -Wl,-soname,libjavaserial.so -I$(JNI_INCLUDE_DIR) -I$(JNI_INCLUDE_DIR)/linux -lc $(OBJFILES)
+
+linux-32:
+ $(MAKE) ARCH="-m32"
+linux-64:
+ $(MAKE) ARCH="-m64"
+
+windows:
+ cl -I"$(JNI_INCLUDE_DIR_WIN)" -I"$(JNI_INCLUDE_DIR_WIN)\win32" -I"." -MT -LD SerialPortImpl.c -Fejavaserial.dll
+#
+# Dependencies
+#
+
+SerialPortImpl.o: SerialPortImpl.c com_rm5248_serial_SerialPort.h \
+ com_rm5248_serial_SerialInputStream.h \
+ com_rm5248_serial_SerialOutputStream.h \
+ com_rm5248_serial_SimpleSerialInputStream.h
+
+#
+# Installation Targets
+#
+
+install:
+ /usr/bin/install /usr/bin
+
+#
+# Housekeeping
+#
+
+Archive: archive.tgz
+
+archive.tgz: $(SOURCEFILES) Makefile
+ tar cf - $(SOURCEFILES) Makefile | gzip > archive.tgz
+
+clean:
+ -/bin/rm $(OBJFILES) core 2> /dev/null
+
+realclean: clean
+ -/bin/rm -rf
Index: tags/JavaSerial0.5/NativeCode/com_rm5248_serial_SerialInputStream.h
===================================================================
--- tags/JavaSerial0.5/NativeCode/com_rm5248_serial_SerialInputStream.h (nonexistent)
+++ tags/JavaSerial0.5/NativeCode/com_rm5248_serial_SerialInputStream.h (revision 111)
@@ -0,0 +1,31 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_rm5248_serial_SerialInputStream */
+
+#ifndef _Included_com_rm5248_serial_SerialInputStream
+#define _Included_com_rm5248_serial_SerialInputStream
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_rm5248_serial_SerialInputStream_MAX_SKIP_BUFFER_SIZE
+#define com_rm5248_serial_SerialInputStream_MAX_SKIP_BUFFER_SIZE 2048L
+/*
+ * Class: com_rm5248_serial_SerialInputStream
+ * Method: readByte
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialInputStream_readByte
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_rm5248_serial_SerialInputStream
+ * Method: getAvailable
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialInputStream_getAvailable
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: tags/JavaSerial0.5/NativeCode/com_rm5248_serial_SimpleSerialInputStream.h
===================================================================
--- tags/JavaSerial0.5/NativeCode/com_rm5248_serial_SimpleSerialInputStream.h (nonexistent)
+++ tags/JavaSerial0.5/NativeCode/com_rm5248_serial_SimpleSerialInputStream.h (revision 111)
@@ -0,0 +1,31 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_rm5248_serial_SimpleSerialInputStream */
+
+#ifndef _Included_com_rm5248_serial_SimpleSerialInputStream
+#define _Included_com_rm5248_serial_SimpleSerialInputStream
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_rm5248_serial_SimpleSerialInputStream_MAX_SKIP_BUFFER_SIZE
+#define com_rm5248_serial_SimpleSerialInputStream_MAX_SKIP_BUFFER_SIZE 2048L
+/*
+ * Class: com_rm5248_serial_SimpleSerialInputStream
+ * Method: readByte
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_rm5248_serial_SimpleSerialInputStream_readByte
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_rm5248_serial_SimpleSerialInputStream
+ * Method: getAvailable
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_rm5248_serial_SimpleSerialInputStream_getAvailable
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: tags/JavaSerial0.5/NativeCode/com_rm5248_serial_SerialPort.h
===================================================================
--- tags/JavaSerial0.5/NativeCode/com_rm5248_serial_SerialPort.h (nonexistent)
+++ tags/JavaSerial0.5/NativeCode/com_rm5248_serial_SerialPort.h (revision 111)
@@ -0,0 +1,157 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_rm5248_serial_SerialPort */
+
+#ifndef _Included_com_rm5248_serial_SerialPort
+#define _Included_com_rm5248_serial_SerialPort
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_rm5248_serial_SerialPort
+ * Method: openPort
+ * Signature: (Ljava/lang/String;IIIII)I
+ */
+JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_openPort__Ljava_lang_String_2IIIII
+ (JNIEnv *, jobject, jstring, jint, jint, jint, jint, jint);
+
+/*
+ * 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 *, jobject, jstring);
+
+/*
+ * Class: com_rm5248_serial_SerialPort
+ * Method: doClose
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_rm5248_serial_SerialPort_doClose
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_rm5248_serial_SerialPort
+ * Method: setBaudRate
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setBaudRate
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_rm5248_serial_SerialPort
+ * Method: getBaudRateInternal
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getBaudRateInternal
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_rm5248_serial_SerialPort
+ * Method: setStopBits
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setStopBits
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_rm5248_serial_SerialPort
+ * Method: getStopBitsInternal
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getStopBitsInternal
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_rm5248_serial_SerialPort
+ * Method: setCharSize
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setCharSize
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_rm5248_serial_SerialPort
+ * Method: getCharSizeInternal
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getCharSizeInternal
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_rm5248_serial_SerialPort
+ * Method: setParity
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setParity
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_rm5248_serial_SerialPort
+ * Method: getParityInternal
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getParityInternal
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_rm5248_serial_SerialPort
+ * Method: setFlowControl
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setFlowControl
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_rm5248_serial_SerialPort
+ * Method: getFlowControlInternal
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getFlowControlInternal
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_rm5248_serial_SerialPort
+ * Method: getSerialLineStateInternalNonblocking
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getSerialLineStateInternalNonblocking
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_rm5248_serial_SerialPort
+ * Method: setSerialLineStateInternal
+ * Signature: (Lcom/rm5248/serial/SerialLineState;)I
+ */
+JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_setSerialLineStateInternal
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: com_rm5248_serial_SerialPort
+ * Method: getMajorNativeVersion
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getMajorNativeVersion
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_rm5248_serial_SerialPort
+ * Method: getMinorNativeVersion
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getMinorNativeVersion
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_rm5248_serial_SerialPort
+ * Method: getSerialPorts
+ * Signature: ()[Ljava/lang/String;
+ */
+JNIEXPORT jobjectArray JNICALL Java_com_rm5248_serial_SerialPort_getSerialPorts
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: tags/JavaSerial0.5/NativeCode/com_rm5248_serial_SerialOutputStream.h
===================================================================
--- tags/JavaSerial0.5/NativeCode/com_rm5248_serial_SerialOutputStream.h (nonexistent)
+++ tags/JavaSerial0.5/NativeCode/com_rm5248_serial_SerialOutputStream.h (revision 111)
@@ -0,0 +1,29 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_rm5248_serial_SerialOutputStream */
+
+#ifndef _Included_com_rm5248_serial_SerialOutputStream
+#define _Included_com_rm5248_serial_SerialOutputStream
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_rm5248_serial_SerialOutputStream
+ * Method: writeByte
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_rm5248_serial_SerialOutputStream_writeByte
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_rm5248_serial_SerialOutputStream
+ * Method: writeByteArray
+ * Signature: ([B)V
+ */
+JNIEXPORT void JNICALL Java_com_rm5248_serial_SerialOutputStream_writeByteArray
+ (JNIEnv *, jobject, jbyteArray);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: tags/JavaSerial0.5/src/com/rm5248/serial/SerialPort.java
===================================================================
--- tags/JavaSerial0.5/src/com/rm5248/serial/SerialPort.java (nonexistent)
+++ tags/JavaSerial0.5/src/com/rm5248/serial/SerialPort.java (revision 111)
@@ -0,0 +1,1236 @@
+package com.rm5248.serial;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+/**
+ * A SerialPort represents a serial port on the system.
+ *
+ * All SerialPorts must extend this class. It is unable to be instantiated, except
+ * by subclasses.
+ *
+ * See the documentation for the subclasses on how to create
+ * a specific instance of a SerialPort. The two main subclasses are IOSerialPort and
+ * NIOSerialPort.
+ *
+ * @author rm5248
+ *
+ */
+public class SerialPort {
+
+ //The first time this class is referenced, we need to load the library.
+ static{
+ loadNativeLibrary();
+ }
+
+ /**
+ * Load the native library.
+ *
+ * There are two important system properties that can be set here:
+ *
+ * com.rm5248.javaserial.lib.path - give the directory name that the JNI code is located in
+ * com.rm5248.javaserial.lib.name - explicitly give the name of the library(the default is 'javaserial')
+ *
+ * This is based largely off of SQLite-JDBC( https://github.com/xerial/sqlite-jdbc )
+ */
+ private static void loadNativeLibrary() {
+ String nativeLibraryPath = System.getProperty( "com.rm5248.javaserial.lib.path" );
+ String nativeLibraryName = System.getProperty( "com.rm5248.javaserial.lib.name" );
+
+ if( nativeLibraryName == null ){
+ nativeLibraryName = System.mapLibraryName( "javaserial" );
+ if( nativeLibraryName.endsWith( "dylib" ) ){
+ //mac uses jnilib instead of dylib for some reason
+ nativeLibraryName.replace( "dylib", "jnilib" );
+ }
+ }
+
+ if( nativeLibraryPath != null ){
+ File libToLoad = new File(nativeLibraryPath, nativeLibraryName);
+ System.load( libToLoad.getAbsolutePath() );
+ return;
+ }
+
+ //if we get here, that means that we must extract the JNI from the jar
+
+ try {
+ File extractedLib;
+ Path tempFolder;
+ String osName;
+ String arch;
+ InputStream library;
+
+ osName = System.getProperty( "os.name" );
+ if( osName.contains( "Windows" ) ){
+ osName = "Windows";
+ }else if( osName.contains( "Mac" ) || osName.contains( "Darwin" ) ){
+ osName = "Mac";
+ }else if( osName.contains( "Linux" ) ){
+ osName = "Linux";
+ }else{
+ osName = osName.replaceAll( "\\W", "" );
+ }
+
+ arch = System.getProperty( "os.arch" );
+ arch.replaceAll( "\\W", "" );
+
+ //create the temp folder to extract the library to
+ tempFolder = Files.createTempDirectory( "javaserial" );
+ tempFolder.toFile().deleteOnExit();
+
+ extractedLib = new File( tempFolder.toFile(), nativeLibraryName );
+
+ //now let's extract the proper library
+ library = SerialPort.class.getClass().getResourceAsStream( "/" + osName + "/" + arch + "/" + nativeLibraryName );
+ Files.copy( library, extractedLib.toPath() );
+ extractedLib.deleteOnExit();
+
+ System.load( extractedLib.getAbsolutePath() );
+ } catch (IOException e) {
+ throw new UnsatisfiedLinkError( "Unable to create temp directory or extract: " + e.getMessage() );
+ }
+ }
+
+ private class SerialStateListener implements Runnable{
+
+ private volatile boolean stop;
+ private SerialChangeListener listen;
+
+ SerialStateListener( SerialChangeListener listen ){
+ stop = false;
+ this.listen = listen;
+ }
+
+ @Override
+ public void run() {
+ while( !stop ){
+ synchronized( serialListenSync ){
+ try {
+ serialListenSync.wait();
+ if( stop ){
+ break;
+ }
+ listen.serialStateChanged( state );
+ } catch (Exception e) {}
+ }
+ }
+ }
+
+ void doStop(){
+ stop = true;
+ }
+ }
+
+ /**
+ * Represents the BaudRate that the SerialPort uses.
+ */
+ public enum BaudRate{
+ /** Not available in Windows */
+ B0,
+ /** Not available in Windows */
+ B50,
+ /** Not available in Windows */
+ B75,
+ B110,
+ /** Not available in Windows */
+ B134,
+ /** Not available in Windows */
+ B150,
+ B200,
+ B300,
+ B600,
+ B1200,
+ /** Not available in Windows */
+ B1800,
+ B2400,
+ B4800,
+ B9600,
+ B38400,
+ B115200
+ }
+
+ /**
+ * Represents the number of bits that the serial port uses.
+ * Typically, this is 8-bit characters.
+ */
+ public enum DataBits{
+ DATABITS_5,
+ DATABITS_6,
+ DATABITS_7,
+ DATABITS_8
+ }
+
+ /**
+ * The number of stop bits for data. Typically this is 1.
+ */
+ public enum StopBits{
+ STOPBITS_1,
+ STOPBITS_2
+ }
+
+ /**
+ * The parity bit for the data. Typically None.
+ */
+ public enum Parity{
+ NONE,
+ EVEN,
+ ODD
+ }
+
+ /**
+ * The Flow control scheme for the data, typically None.
+ */
+ public enum FlowControl{
+ NONE,
+ HARDWARE,
+ SOFTWARE
+ }
+
+ /**
+ * Flag to set if you do not want to get any control line notifications
+ */
+ public static final int NO_CONTROL_LINE_CHANGE = 0x00;
+ /**
+ * Flag to set if you want to get notifications on Data Terminal Ready line change
+ */
+ public static final int CONTROL_LINE_DTR_CHANGE = 0x01;
+ /**
+ * Flag to set if you want to get notifications on Request To Send line change
+ */
+ public static final int CONTROL_LINE_RTS_CHANGE = 0x02;
+ /**
+ * Flag to set if you want to get notifications on Carrier Detect line change
+ */
+ public static final int CONTROL_LINE_CD_CHANGE = 0x03;
+ /**
+ * Flag to set if you want to get notifications on Clear To Send line change
+ */
+ public static final int CONTROL_LINE_CTS_CHANGE = 0x04;
+ /**
+ * Flag to set if you want to get notifications on Data Set Ready line change
+ */
+ public static final int CONTROL_LINE_DSR_CHANGE = 0x05;
+ /**
+ * Flag to set if you want to get notifications on Ring Indicagor line change
+ */
+ public static final int CONTROL_LINE_RI_CHANGE = 0x06;
+ /**
+ * All CONTROL_LINE_XXX_CHANGE values OR'd together
+ */
+ public static final int ALL_CONTROL_LINES = CONTROL_LINE_DTR_CHANGE |
+ CONTROL_LINE_RTS_CHANGE | CONTROL_LINE_CD_CHANGE | CONTROL_LINE_CTS_CHANGE |
+ CONTROL_LINE_DSR_CHANGE | CONTROL_LINE_RI_CHANGE;
+
+ /* The handle to our internal data structure which keeps track of the port settings.
+ * We need a special structure, as on windows we have a HANDLE type, which is void*,
+ * yet on Linux we have a file descriptor, which is an int.
+ * This is not just a pointer to memory, because if we're running on a 64-bit
+ * system, then we might have problems putting it in 32-bits. Better safe than sorry.
+ */
+ private int handle;
+ /* Make sure we don't close ourselves twice */
+ private boolean closed;
+ /* The name of the port that's currently open */
+ private String portName;
+ /* Cache of the last gotten serial line state */
+ private volatile SerialLineState state;
+ /* The input stream that user code uses to read from the serial port. */
+ private InputStream inputStream;
+ /* The buffered serial input stream which filters out events for us. */
+ private BufferedSerialInputStream bis;
+ /* The output stream that user code uses to write to the serial port. */
+ private SerialOutputStream outputStream;
+ /* Runs in the background to check for serial port events */
+ private SerialStateListener serialListen;
+ /* Used for synchronizing serialListen */
+ private Object serialListenSync;
+ /* Depending on what control line changes we want to get back, this mask is set. */
+ private int controlLineFlags;
+
+ /**
+ * Open the specified port, 9600 baud, 8 data bits, 1 stop bit, no parity, no flow control,
+ * not ignoring control lines
+ *
+ * @param portName The name of the port to open
+ * @throws NoSuchPortException If this port does not exist
+ * @throws NotASerialPortException If the specified port is not a serial port
+ */
+ public SerialPort( String portName ) throws NoSuchPortException, NotASerialPortException {
+ this( portName, ALL_CONTROL_LINES );
+ }
+
+ /**
+ * Open the specified port, 9600 baud, 8 data bits, 1 stop bit, no parity, no flow control,
+ * looking for the specified control lines
+ *
+ * @param portName The name of the port to open
+ * @param controlLineFlags The control lines to get a notification for when they change.
+ * @throws NoSuchPortException If this port does not exist
+ * @throws NotASerialPortException If the specified port is not a serial port
+ */
+ public SerialPort( String portName, int controlLineFlags ) throws NoSuchPortException, NotASerialPortException {
+ this( portName, BaudRate.B9600, controlLineFlags );
+ }
+
+ /**
+ * Open up a serial port, but allow the user to keep the current settings of the serial port.
+ * Will notify on all control line changes.
+ *
+ * @param portName The port to open
+ * @param keepSettings If true, will simply open the serial port without setting anything. If false, this method
+ * acts the same as {@link #SerialPort(String) SerialPort( String portName ) }
+ * @throws NoSuchPortException If the port does not exist
+ * @throws NotASerialPortException If the port is not in fact a serial port
+ */
+ public SerialPort( String portName, boolean keepSettings ) throws NoSuchPortException, NotASerialPortException {
+ this( portName, keepSettings, ALL_CONTROL_LINES );
+ }
+
+ /**
+ * Open up a serial port, but allow the user to keep the current settings of the serial port.
+ *
+ * @param portName The port to open
+ * @param keepSettings If true, will simply open the serial port without setting anything. If false, this method
+ * acts the same as {@link #SerialPort(String) SerialPort( String portName ) }
+ * @param controlFlags The control flags to listen for changes for. This is a bitwise-OR of CONTROL_LINE_XXX_CHANGE, or
+ * NO_CONTROL_LINE_CHANGE if you don't care about getting notified about the control line changes.
+ * @throws NoSuchPortException If the port does not exist
+ * @throws NotASerialPortException If the port is not in fact a serial port
+ */
+ public SerialPort( String portName, boolean keepSettings, int controlFlags ) throws NoSuchPortException, NotASerialPortException{
+ if( portName == null ){
+ throw new IllegalArgumentException( "portName must not be null" );
+ }
+
+ if( keepSettings ){
+ this.handle = -1;
+ this.handle = openPort( portName );
+ this.portName = portName;
+ if( controlLineFlags == NO_CONTROL_LINE_CHANGE ){
+ inputStream = new SimpleSerialInputStream( handle );
+ }else{
+ SerialInputStream sis = new SerialInputStream( handle );
+ inputStream = sis;
+ bis = new BufferedSerialInputStream( sis, this );
+ }
+ outputStream = new SerialOutputStream( handle );
+ closed = false;
+ this.controlLineFlags = controlFlags;
+
+ SerialLineState s = new SerialLineState();
+ int state = getSerialLineStateInternalNonblocking();
+ // do some sort of bitwise operations here....
+ if( ( state & 0x01 ) > 0 ){
+ s.carrierDetect = true;
+ }
+ if( ( state & (0x01 << 1 ) ) > 0 ){
+ s.clearToSend = true;
+ }
+ if( ( state & (0x01 << 2 ) ) > 0 ){
+ s.dataSetReady = true;
+ }
+ if( ( state & (0x01 << 3 ) ) > 0 ){
+ s.dataTerminalReady = true;
+ }
+ if( ( state & (0x01 << 4 ) ) > 0 ){
+ s.requestToSend = true;
+ }
+ if( ( state & (0x01 << 5 ) ) > 0 ){
+ s.ringIndicator = true;
+ }
+
+ this.state = s;
+
+ if( controlLineFlags != NO_CONTROL_LINE_CHANGE ){
+ serialListenSync = new Object();
+ new Thread( bis, "BufferedSerialReader-" + portName ).start();
+ }
+ }else{
+ doOpenSerialPort( portName, BaudRate.B9600, DataBits.DATABITS_8,
+ StopBits.STOPBITS_1, Parity.NONE, FlowControl.NONE, controlFlags );
+ }
+
+
+ }
+
+ /**
+ * Open the specified port, no flow control, 8 data bits
+ *
+ * @param portName The name of the port to open
+ * @param rate The Baud Rate to open this port at
+ * @throws NoSuchPortException If this port does not exist
+ * @throws NotASerialPortException If the specified port is not a serial port
+ */
+ public SerialPort( String portName, BaudRate rate )
+ throws NoSuchPortException, NotASerialPortException {
+ this( portName, rate, ALL_CONTROL_LINES );
+ }
+
+ /**
+ * Open the specified port, no flow control
+ *
+ * @param portName The name of the port to open
+ * @param rate The Baud Rate to open this port at
+ * @param controlLines The control lines to be notifie don a change in.
+ * @throws NoSuchPortException If this port does not exist
+ * @throws NotASerialPortException If the specified port is not a serial port
+ */
+ public SerialPort( String portName, BaudRate rate, int controlLines )
+ throws NoSuchPortException, NotASerialPortException {
+ this( portName, rate, DataBits.DATABITS_8, controlLines );
+ }
+
+ /**
+ * Open the specified port, no flow control
+ *
+ * @param portName The name of the port to open
+ * @param rate The Baud Rate to open this port at
+ * @param data The number of data bits
+ * @throws NoSuchPortException If this port does not exist
+ * @throws NotASerialPortException If the specified port is not a serial port
+ */
+ public SerialPort( String portName, BaudRate rate, DataBits data )
+ throws NoSuchPortException, NotASerialPortException {
+ this( portName, rate, data, StopBits.STOPBITS_1, ALL_CONTROL_LINES );
+ }
+
+ /**
+ * Open the specified port, no flow control
+ *
+ * @param portName The name of the port to open
+ * @param rate The Baud Rate to open this port at
+ * @param data The number of data bits
+ * @throws NoSuchPortException If this port does not exist
+ * @throws NotASerialPortException If the specified port is not a serial port
+ */
+ public SerialPort( String portName, BaudRate rate, DataBits data, int controlLineFlags )
+ throws NoSuchPortException, NotASerialPortException {
+ doOpenSerialPort( portName, rate, data,
+ StopBits.STOPBITS_1, Parity.NONE, FlowControl.NONE, controlLineFlags );
+ }
+
+ /**
+ * Open the specified port, no parity or flow control
+ *
+ * @param portName The name of the port to open
+ * @param rate The Baud Rate to open this port at
+ * @param data The number of data bits
+ * @param stop The number of stop bits
+ * @throws NoSuchPortException If this port does not exist
+ * @throws NotASerialPortException If the specified port is not a serial port
+ */
+ public SerialPort( String portName, BaudRate rate, DataBits data, StopBits stop )
+ throws NoSuchPortException, NotASerialPortException {
+ doOpenSerialPort( portName, rate, data,
+ stop, Parity.NONE, FlowControl.NONE, ALL_CONTROL_LINES );
+ }
+
+ /**
+ * Open the specified port, no parity or flow control
+ *
+ * @param portName The name of the port to open
+ * @param rate The Baud Rate to open this port at
+ * @param data The number of data bits
+ * @param stop The number of stop bits
+ * @throws NoSuchPortException If this port does not exist
+ * @throws NotASerialPortException If the specified port is not a serial port
+ */
+ public SerialPort( String portName, BaudRate rate, DataBits data, StopBits stop, int controlFlags )
+ throws NoSuchPortException, NotASerialPortException {
+ doOpenSerialPort( portName, rate, data,
+ stop, Parity.NONE, FlowControl.NONE, controlFlags );
+ }
+
+ /**
+ * Open the specified port, no flow control, with all control line flags
+ *
+ * @param portName The name of the port to open
+ * @param rate The Baud Rate to open this port at
+ * @param data The number of data bits
+ * @param stop The number of stop bits
+ * @param parity The parity of the line
+ * @throws NoSuchPortException If this port does not exist
+ * @throws NotASerialPortException If the specified port is not a serial port
+ */
+ public SerialPort( String portName, BaudRate rate, DataBits data, StopBits stop, Parity parity )
+ throws NoSuchPortException, NotASerialPortException {
+ doOpenSerialPort( portName, rate, data, stop, parity, FlowControl.NONE, ALL_CONTROL_LINES );
+ }
+
+ /**
+ * Open the specified port, no flow control, with the specified control line flags
+ *
+ * @param portName The name of the port to open
+ * @param rate The Baud Rate to open this port at
+ * @param data The number of data bits
+ * @param stop The number of stop bits
+ * @param parity The parity of the line
+ * @param controlLineFlags A bitwise OR of any the CONTORL_LINE_XXX_CHANGE flags, or NO_CONTROL_LINE_CHANGE
+ * @throws NoSuchPortException If this port does not exist
+ * @throws NotASerialPortException If the specified port is not a serial port
+ */
+ public SerialPort( String portName, BaudRate rate, DataBits data, StopBits stop, Parity parity, int controlLineFlags )
+ throws NoSuchPortException, NotASerialPortException {
+ this( portName, rate, data, stop, parity, FlowControl.NONE, controlLineFlags );
+ }
+
+ /**
+ * Open the specified port, defining all options
+ *
+ * @param portName The name of the port to open
+ * @param rate The Baud Rate to open this port at
+ * @param data The number of data bits
+ * @param stop The number of stop bits
+ * @param parity The parity of the line
+ * @param flow The flow control of the line
+ * @throws NoSuchPortException If this port does not exist
+ * @throws NotASerialPortException If the specified port is not a serial port
+ */
+ public SerialPort( String portName, BaudRate rate, DataBits data, StopBits stop, Parity parity, FlowControl flow )
+ throws NoSuchPortException, NotASerialPortException {
+ this( portName, rate, data, stop, parity, flow, ALL_CONTROL_LINES );
+ }
+
+ /**
+ * Open the specified port, defining all options
+ *
+ * @param portName The name of the port to open
+ * @param rate The Baud Rate to open this port at
+ * @param data The number of data bits
+ * @param stop The number of stop bits
+ * @param parity The parity of the line
+ * @param flow The flow control of the line
+ * @param controlFlags The control flags to listen for changes for. This is a bitwise-OR of CONTROL_LINE_XXX_CHANGE, or
+ * NO_CONTROL_LINE_CHANGE if you don't care about getting notified about the control line changes.
+ * @throws NoSuchPortException If this port does not exist
+ * @throws NotASerialPortException If the specified port is not a serial port
+ */
+ public SerialPort( String portName, BaudRate rate, DataBits data, StopBits stop, Parity parity, FlowControl flow, int controlFlags )
+ throws NoSuchPortException, NotASerialPortException {
+ doOpenSerialPort( portName, rate, data, stop, parity, flow, controlFlags );
+ }
+
+ /**
+ * The actual method that opens up the serial port, unless we are keeping our settings.
+ */
+ private void doOpenSerialPort( String portName, BaudRate rate, DataBits data, StopBits stop, Parity parity, FlowControl flow, int controlFlags )
+ throws NoSuchPortException, NotASerialPortException {
+ int myRate = 0;
+ int myData = 0;
+ int myStop = 0;
+ int myParity = 0;
+ int myFlow = 0;
+ SerialLineState s;
+ int state;
+ SerialInputStream sis;
+
+ this.handle = -1;
+
+ //Check for null values in our arguments
+ if( portName == null ){
+ throw new IllegalArgumentException( "portName must not be null" );
+ }
+
+ if( rate == null ){
+ throw new IllegalArgumentException( "rate must not be null" );
+ }
+
+ if( data == null ){
+ throw new IllegalArgumentException( "data must not be null" );
+ }
+
+ if( stop == null ){
+ throw new IllegalArgumentException( "stop must not be null" );
+ }
+
+ if( parity == null ){
+ throw new IllegalArgumentException( "parity must not be null" );
+ }
+
+ if( flow == null ){
+ throw new IllegalArgumentException( "flow must not be null" );
+ }
+
+ //Okay, looks like we're good!
+ this.portName = portName;
+ closed = false;
+ this.controlLineFlags = controlFlags;
+
+ switch( rate ){
+ case B0 : myRate = 0; break;
+ case B50 : myRate = 50; break;
+ case B75 : myRate = 75; break;
+ case B110 : myRate = 110; break;
+ case B134 : myRate = 134; break;
+ case B150 : myRate = 150; break;
+ case B200 : myRate = 200; break;
+ case B300 : myRate = 300; break;
+ case B600 : myRate = 600; break;
+ case B1200 : myRate = 1200; break;
+ case B1800 : myRate = 1800; break;
+ case B2400 : myRate = 2400; break;
+ case B4800 : myRate = 4800; break;
+ case B9600 : myRate = 9600; break;
+ case B38400 : myRate = 38400; break;
+ case B115200: myRate = 115200; break;
+ }
+
+ switch( data ){
+ case DATABITS_5: myData = 5; break;
+ case DATABITS_6: myData = 6; break;
+ case DATABITS_7: myData = 7; break;
+ case DATABITS_8: myData = 8; break;
+ }
+
+ switch( stop ){
+ case STOPBITS_1: myStop = 1; break;
+ case STOPBITS_2: myStop = 2; break;
+ }
+
+ switch( parity ){
+ case NONE: myParity = 0; break;
+ case ODD: myParity = 1; break;
+ case EVEN: myParity = 2; break;
+ }
+
+ switch( flow ){
+ case NONE: myFlow = 0; break;
+ case HARDWARE: myFlow = 1; break;
+ case SOFTWARE: myFlow = 2; break;
+ }
+
+ handle = openPort(portName, myRate, myData, myStop, myParity, myFlow);
+ if( controlLineFlags == NO_CONTROL_LINE_CHANGE ){
+ inputStream = new SimpleSerialInputStream( handle );
+ }else{
+ sis = new SerialInputStream( handle );
+ inputStream = sis;
+ bis = new BufferedSerialInputStream( sis, this );
+ }
+ outputStream = new SerialOutputStream( handle );
+
+ s = new SerialLineState();
+ state = getSerialLineStateInternalNonblocking();
+ if( ( state & 0x01 ) > 0 ){
+ s.carrierDetect = true;
+ }
+ if( ( state & (0x01 << 1 ) ) > 0 ){
+ s.clearToSend = true;
+ }
+ if( ( state & (0x01 << 2 ) ) > 0 ){
+ s.dataSetReady = true;
+ }
+ if( ( state & (0x01 << 3 ) ) > 0 ){
+ s.dataTerminalReady = true;
+ }
+ if( ( state & (0x01 << 4 ) ) > 0 ){
+ s.requestToSend = true;
+ }
+ if( ( state & (0x01 << 5 ) ) > 0 ){
+ s.ringIndicator = true;
+ }
+
+ this.state = s;
+
+ if( controlLineFlags != NO_CONTROL_LINE_CHANGE ){
+ serialListenSync = new Object();
+ new Thread( bis, "BufferedSerialReader-" + portName ).start();
+ }
+ }
+
+
+ /**
+ * Set the Baud Rate for this port.
+ *
+ * @param rate
+ */
+ public void setBaudRate( BaudRate rate ){
+ int myRate = 0;
+
+ if( closed ){
+ throw new IllegalStateException( "Cannot set the BaudRate once the port has been closed." );
+ }
+
+ if( rate == null ){
+ throw new IllegalArgumentException( "rate must not be null" );
+ }
+
+ switch( rate ){
+ case B0 : myRate = 0; break;
+ case B50 : myRate = 50; break;
+ case B75 : myRate = 75; break;
+ case B110 : myRate = 110; break;
+ case B134 : myRate = 134; break;
+ case B150 : myRate = 150; break;
+ case B200 : myRate = 200; break;
+ case B300 : myRate = 300; break;
+ case B600 : myRate = 600; break;
+ case B1200 : myRate = 1200; break;
+ case B1800 : myRate = 1800; break;
+ case B2400 : myRate = 2400; break;
+ case B4800 : myRate = 4800; break;
+ case B9600 : myRate = 9600; break;
+ case B38400 : myRate = 38400; break;
+ case B115200: myRate = 115200; break;
+ }
+
+ setBaudRate( myRate );
+ }
+
+ public boolean isClosed(){
+ return closed;
+ }
+
+ public void finalize(){
+ close();
+ }
+
+ public void close(){
+ if( closed ) return;
+ closed = true;
+ doClose();
+ if( serialListen != null ){
+ serialListen.doStop();
+ }
+
+ if( serialListenSync != null ){
+ synchronized( serialListenSync ){
+ serialListenSync.notify();
+ }
+ }
+ }
+
+ /**
+ * Get the input stream used to talk to this device.
+ */
+ public InputStream getInputStream(){
+ if( isClosed() ){
+ throw new IllegalStateException( "Cannot get the input stream once the port has been closed." );
+ }
+
+ if( controlLineFlags == NO_CONTROL_LINE_CHANGE ){
+ return inputStream;
+ }
+
+ return bis;
+ }
+
+ /**
+ * Get the OutputStream used to talk to this device.
+ */
+ public OutputStream getOutputStream(){
+ if( isClosed() ){
+ throw new IllegalStateException( "Cannot get the output stream once the port has been closed." );
+ }
+
+ return outputStream;
+ }
+
+
+ /**
+ * Set the stop bits of the serial port, after the port has been opened.
+ *
+ * @param stop
+ */
+ public void setStopBits( StopBits stop ){
+ int myStop = 0;
+
+ if( closed ){
+ throw new IllegalStateException( "Cannot set the StopBits once the port has been closed." );
+ }
+
+ if( stop == null ){
+ throw new IllegalArgumentException( "stop must not be null" );
+ }
+
+ switch( stop ){
+ case STOPBITS_1: myStop = 1; break;
+ case STOPBITS_2: myStop = 2; break;
+ }
+
+ setStopBits( myStop );
+ }
+
+ /**
+ * Set the data bits size, after the port has been opened.
+ *
+ * @param data
+ */
+ public void setDataSize( DataBits data ){
+ int myData = 0;
+
+ if( closed ){
+ throw new IllegalStateException( "Cannot set the DataBits once the port has been closed." );
+ }
+
+ if( data == null ){
+ throw new IllegalArgumentException( "data must not be null" );
+ }
+
+ switch( data ){
+ case DATABITS_5: myData = 5; break;
+ case DATABITS_6: myData = 6; break;
+ case DATABITS_7: myData = 7; break;
+ case DATABITS_8: myData = 8; break;
+ }
+
+ setCharSize( myData );
+ }
+
+ /**
+ * Set the parity of the serial port, after the port has been opened.
+ *
+ * @param parity
+ */
+ public void setParity( Parity parity ){
+ int myParity = 0;
+
+ if( closed ){
+ throw new IllegalStateException( "Cannot set the parity once the port has been closed." );
+ }
+
+ if( parity == null ){
+ throw new IllegalArgumentException( "parity must not be null" );
+ }
+
+ switch( parity ){
+ case NONE: myParity = 0; break;
+ case ODD: myParity = 1; break;
+ case EVEN: myParity = 2; break;
+ }
+
+ setParity( myParity );
+ }
+
+ /**
+ * Get the serial line state for the specified serial port.
+ *
+ * @return
+ */
+ public SerialLineState getSerialLineState() throws IOException{
+ if( closed ){
+ throw new IllegalStateException( "Cannot get the serial line state once the port has been closed." );
+ }
+
+ int gotState = getSerialLineStateInternalNonblocking();
+
+ SerialLineState s = new SerialLineState();
+ // do some sort of bitwise operations here....
+ if( ( gotState & 0x01 ) > 0 ){
+ s.carrierDetect = true;
+ }
+ if( ( gotState & (0x01 << 1 ) ) > 0 ){
+ s.clearToSend = true;
+ }
+ if( ( gotState & (0x01 << 2 ) ) > 0 ){
+ s.dataSetReady = true;
+ }
+ if( ( gotState & (0x01 << 3 ) ) > 0 ){
+ s.dataTerminalReady = true;
+ }
+ if( ( gotState & (0x01 << 4 ) ) > 0 ){
+ s.requestToSend = true;
+ }
+ if( ( gotState & (0x01 << 5 ) ) > 0 ){
+ s.ringIndicator = true;
+ }
+
+ return s;
+ }
+
+ /**
+ * Set the serial line state to the parameters given.
+ *
+ * @param state
+ */
+ public void setSerialLineState( SerialLineState state ){
+ if( closed ){
+ throw new IllegalStateException( "Cannot set the serial line state once the port has been closed." );
+ }
+
+ setSerialLineStateInternal( state );
+
+ //Now, because Windows is weird, we need to post a serial changed event here.
+ //however, since we can only set DTR and RTS, only post an event if those are
+ //the things that changed
+// if( this.state.dataTerminalReady != state.dataTerminalReady ||
+// this.state.requestToSend != state.requestToSend ){
+// this.postSerialChangedEvent( state );
+// }
+ }
+
+
+
+ /**
+ * Get the baud rate of the serial port.
+ *
+ * @return
+ */
+ public BaudRate getBaudRate(){
+ int baudRate;
+ BaudRate toReturn;
+
+ if( closed ){
+ throw new IllegalStateException( "Cannot get the baud rate once the port has been closed." );
+ }
+
+ baudRate = getBaudRateInternal();
+ toReturn = BaudRate.B0;
+
+ switch( baudRate ){
+ case 0 : toReturn = BaudRate.B0 ; break;
+ case 50 : toReturn = BaudRate.B50 ; break;
+ case 75 : toReturn = BaudRate.B75 ; break;
+ case 110 : toReturn = BaudRate.B110 ; break;
+ case 134 : toReturn = BaudRate.B134 ; break;
+ case 150 : toReturn = BaudRate.B150 ; break;
+ case 200 : toReturn = BaudRate.B200 ; break;
+ case 300 : toReturn = BaudRate.B300 ; break;
+ case 600 : toReturn = BaudRate.B600 ; break;
+ case 1200 : toReturn = BaudRate.B1200 ; break;
+ case 1800 : toReturn = BaudRate.B1800 ; break;
+ case 2400 : toReturn = BaudRate.B2400 ; break;
+ case 4800 : toReturn = BaudRate.B4800 ; break;
+ case 9600 : toReturn = BaudRate.B9600 ; break;
+ case 38400 : toReturn = BaudRate.B38400 ; break;
+ case 115200: toReturn = BaudRate.B115200; break;
+ }
+
+ return toReturn;
+ }
+
+ /**
+ * Get the number of data bits.
+ *
+ * @return
+ */
+ public DataBits getDataBits(){
+ int dataBits;
+ DataBits bits;
+
+ if( closed ){
+ throw new IllegalStateException( "Cannot get the data bits once the port has been closed." );
+ }
+
+ dataBits = getCharSizeInternal();
+ bits = DataBits.DATABITS_8;
+
+ switch( dataBits ){
+ case 8: bits = DataBits.DATABITS_8; break;
+ case 7: bits = DataBits.DATABITS_7; break;
+ case 6: bits = DataBits.DATABITS_6; break;
+ case 5: bits = DataBits.DATABITS_5; break;
+ }
+
+ return bits;
+ }
+
+ /**
+ * Get the number of stop bits.
+ *
+ * @return
+ */
+ public StopBits getStopBits(){
+ int stopBits;
+ StopBits bits;
+
+ if( closed ){
+ throw new IllegalStateException( "Cannot get stop bits once the port has been closed." );
+ }
+
+ stopBits = getStopBitsInternal();
+ bits = StopBits.STOPBITS_1;
+
+ switch( stopBits ){
+ case 1: bits = StopBits.STOPBITS_1; break;
+ case 2: bits = StopBits.STOPBITS_2; break;
+ }
+
+ return bits;
+ }
+
+ /**
+ * Get the parity of the serial port.
+ *
+ * @return
+ */
+ public Parity getParity(){
+ int parity;
+ Parity par;
+
+ if( closed ){
+ throw new IllegalStateException( "Cannot get the parity once the port has been closed." );
+ }
+
+ parity = getParityInternal();
+ par = Parity.NONE;
+
+ switch( parity ){
+ case 0: par = Parity.NONE; break;
+ case 1: par = Parity.ODD; break;
+ case 2: par = Parity.EVEN; break;
+ }
+
+ return par;
+ }
+
+ /**
+ * Get the flow control for the serial port.
+ *
+ * @return
+ */
+ public FlowControl getFlowControl(){
+ int flowControl;
+ FlowControl cont;
+
+ if( closed ){
+ throw new IllegalStateException( "Cannot get the flow once the port has been closed." );
+ }
+
+ flowControl = getFlowControlInternal();
+ cont = FlowControl.NONE;
+
+ switch( flowControl ){
+ case 0: cont = FlowControl.NONE; break;
+ case 1: cont = FlowControl.HARDWARE; break;
+ case 2: cont = FlowControl.SOFTWARE; break;
+ }
+
+ return cont;
+ }
+
+ /**
+ * Set the flow control for the serial port
+ *
+ * @param flow
+ */
+ public void setFlowControl( FlowControl flow ){
+ if( closed ){
+ throw new IllegalStateException( "Cannot set flow once the port has been closed." );
+ }
+
+ switch( flow ){
+ case HARDWARE: setFlowControl( 1 ); break;
+ case NONE: setFlowControl( 0 ); break;
+ case SOFTWARE: setFlowControl( 2 ); break;
+ }
+ }
+
+ /**
+ * Set the listener which will get events when there is activity on the serial port.
+ * Note that this activity does NOT include receive and transmit events - this is
+ * changes on the lines of the serial port, such as RI, DSR, and DTR.
+ *
+ * If listen is null, will remove the listener.
+ *
+ * @param listen The listener which gets events
+ */
+ public void setSerialChangeListener( SerialChangeListener listen ){
+ if( serialListen != null ){
+ serialListen.doStop();
+ }
+
+ if( listen != null && !(controlLineFlags == NO_CONTROL_LINE_CHANGE) ){
+ serialListen = new SerialStateListener( listen );
+ new Thread( serialListen, "SerialListen-" + portName ).start();
+ }
+
+ }
+
+ /**
+ * Get the name of the serial port that this object represents.
+ * @return
+ */
+ public String getPortName(){
+ return portName;
+ }
+
+ /**
+ * This method is called when the state of the serial lines is changed.
+ *
+ * @param newState
+ */
+ void postSerialChangedEvent( SerialLineState newState ){
+ if( !state.equals( newState ) ){
+ SerialLineState oldState = state;
+ boolean update = false;
+ state = newState;
+
+ //At this point, we know what has changed, but we must check our bitmask to see if we should
+ //propogate this change back up to the interested class.
+ if( oldState.carrierDetect != newState.carrierDetect &&
+ (controlLineFlags & CONTROL_LINE_CD_CHANGE) != 0 ){
+ update = true;
+ }
+ if( oldState.clearToSend != newState.clearToSend &&
+ (controlLineFlags & CONTROL_LINE_CTS_CHANGE) != 0){
+ update = true;
+ }
+ if( oldState.dataSetReady != newState.dataSetReady &&
+ (controlLineFlags & CONTROL_LINE_DSR_CHANGE) != 0 ){
+ update = true;
+ }
+ if( oldState.dataTerminalReady != newState.dataTerminalReady &&
+ (controlLineFlags & CONTROL_LINE_DTR_CHANGE) != 0 ){
+ update = true;
+ }
+ if( oldState.requestToSend != newState.requestToSend &&
+ (controlLineFlags & CONTROL_LINE_RTS_CHANGE) != 0 ){
+ update = true;
+ }
+ if( oldState.ringIndicator != newState.ringIndicator &&
+ (controlLineFlags & CONTROL_LINE_RI_CHANGE) != 0 ){
+ update = true;
+ }
+
+ if( update ){
+ synchronized( serialListenSync ){
+ serialListenSync.notify();
+ }
+ }
+ }
+ }
+
+ /**
+ * Open the specified port, return an internal handle to the data structure for this port.
+ *
+ * @param portName
+ * @return
+ */
+ private native int openPort( String portName, int baudRate, int dataBits, int stopBits, int parity, int flowControl ) throws NoSuchPortException, NotASerialPortException;
+
+ /**
+ * Open the specified port, return an internal handle for the data of this port.
+ * This method DOES NOT set any of the serial port settings
+ *
+ * @param portName The port to open
+ * @return
+ */
+ private native int openPort( String portName ) throws NoSuchPortException, NotASerialPortException;
+
+ /**
+ * Close this port, release all native resources
+ */
+ private native void doClose();
+
+ /**
+ * Set the baud rate in the native code.
+ *
+ * @param baudRate
+ * @return
+ */
+ private native boolean setBaudRate( int baudRate );
+
+ private native int getBaudRateInternal();
+
+ /**
+ * Set the number of stop bits, once the port has been opened.
+ *
+ * @param stopBits
+ * @return
+ */
+ private native boolean setStopBits( int stopBits );
+
+ private native int getStopBitsInternal();
+
+ /**
+ * Set the character size, once the port has been opened.
+ * This should probably be called 'setDataBits'
+ *
+ * @param charSize
+ * @return
+ */
+ private native boolean setCharSize( int charSize );
+
+ private native int getCharSizeInternal();
+
+ /** Set the parity once the port has been opened.
+ *
+ * @param parity 0 = None, 1 = Odd, 2 = Even
+ * @return
+ */
+ private native boolean setParity( int parity );
+
+ private native int getParityInternal();
+
+ /** Set the flow control once the port has been opened.
+ *
+ *
+ * @param flowControl 0 = None, 1 = hardware, 2 = software
+ * @return
+ */
+ private native boolean setFlowControl( int flowControl );
+
+ private native int getFlowControlInternal();
+
+ /** Get the serial line state, but don't block when getting it
+ *
+ * @return
+ */
+ protected native int getSerialLineStateInternalNonblocking();
+
+ /**
+ * Set the state of the serial line.
+ * @return
+ */
+ private native int setSerialLineStateInternal( SerialLineState s );
+
+
+
+ //
+ // Static Methods
+ //
+
+ /**
+ * Get the major version of this library. For example, if this is version
+ * 0.2, this returns 0
+ */
+ public static int getMajorVersion(){
+ return 0;
+ }
+
+ /**
+ * Get the minor version of this library. For example, if this is version
+ * 0.2, this returns 2.
+ */
+ public static int getMinorVersion(){
+ return 5;
+ }
+
+ /**
+ * Get the major version of the native code. This should match up with
+ * {@link #getMajorVersion() getMajorVersion()}, although this is not
+ * guaranteed. For example, if this is version 0.2, this returns 0
+ */
+ public static native int getMajorNativeVersion();
+
+ /**
+ * Get the minor version of the native code. This should match up with
+ * {@link #getMinorVersion() getMinorVersion()}, although this is not
+ * guaranteed. For example, if this is version 0.2, this returns 2.
+ */
+ public static native int getMinorNativeVersion();
+
+ /**
+ * <p>
+ * Get an array of all the serial ports on the system. For example, on
+ * Windows this will return {@code { "COM1", "COM3", .... } } depending on how
+ * many serial devices you have plugged in. On Linux, this returns
+ * {@code { "/dev/ttyS0", "/dev/ttyUSB0", "/dev/symlink", ... } }
+ * It will not resolve symlinks, such that if there is a symlink
+ * from {@code /dev/symlink } to {@code /dev/ttyUSB0 }, they will both show up.
+ * </p>
+ * <p>
+ * <b>NOTE:</b> this will only return ports that you have permissions to
+ * open.
+ * </p>
+ *
+ * @return
+ */
+ public static native String[] getSerialPorts();
+
+}
Index: tags/JavaSerial0.5/src/com/rm5248/serial/BufferedSerialInputStream.java
===================================================================
--- tags/JavaSerial0.5/src/com/rm5248/serial/BufferedSerialInputStream.java (nonexistent)
+++ tags/JavaSerial0.5/src/com/rm5248/serial/BufferedSerialInputStream.java (revision 111)
@@ -0,0 +1,157 @@
+package com.rm5248.serial;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Okay, so the problem here is that we need to be continually reading from the serial port,
+ * because on Windows we can't simultaneously listen for events and listen for changes on
+ * the serial port. We can only do that in one place. So, to get around that problem,
+ * this BufferedSerialInputStream simply wraps the normal SerialInputStream and only
+ * returns actual data. SerialInputStream gives us back data on the status of the serial line,
+ * as well as if the byte it gave us is real or not.
+ *
+ * @author rm5248
+ *
+ */
+class BufferedSerialInputStream extends InputStream implements Runnable {
+
+ private SerialInputStream stream;
+ private byte[] buffer;
+ private int bufferBegin;
+ private int bufferEnd;
+ private SerialPort callback;
+ private IOException exceptionToThrow;
+
+ BufferedSerialInputStream( SerialInputStream s, SerialPort serialPort ){
+ stream = s;
+ buffer = new byte[ 500 ];
+ bufferBegin = 0;
+ bufferEnd = 0;
+ this.callback = serialPort;
+ exceptionToThrow = null;
+ }
+
+ @Override
+ public int read() throws IOException {
+ int byteToReturn;
+
+ if( bufferBegin != bufferEnd ){
+ //we already have a character
+ byteToReturn = buffer[ bufferBegin++ ];
+ if( bufferBegin >= buffer.length ){
+ //wrap around to the start of the array
+ bufferBegin = 0;
+ }
+ }else{
+ synchronized( buffer ){
+ try {
+ buffer.wait();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ if( exceptionToThrow != null ){
+ throw exceptionToThrow;
+ }
+ }
+
+ byteToReturn = buffer[ bufferBegin++ ];
+ if( bufferBegin >= buffer.length ){
+ //wrap around to the start of the array
+ bufferBegin = 0;
+ }
+ }
+
+ return byteToReturn;
+ }
+
+ @Override
+ public void run() {
+ while( true ){
+ int byteRead = 0;
+ try {
+ byteRead = stream.read();
+ } catch (IOException e) {
+ synchronized( buffer ){
+ exceptionToThrow = e;
+ buffer.notify();
+ }
+ break;
+ }
+ SerialLineState s = new SerialLineState();
+
+ if( ( byteRead & ( 0x01 << 9) ) > 0 ){
+ s.carrierDetect = true;
+ }
+ if( ( byteRead & (0x01 << 10 ) ) > 0 ){
+ s.clearToSend = true;
+ }
+ if( ( byteRead & (0x01 << 11 ) ) > 0 ){
+ s.dataSetReady = true;
+ }
+ if( ( byteRead & (0x01 << 12 ) ) > 0 ){
+ s.dataTerminalReady = true;
+ }
+ if( ( byteRead & (0x01 << 13 ) ) > 0 ){
+ s.requestToSend = true;
+ }
+ if( ( byteRead & (0x01 << 14 ) ) > 0 ){
+ s.ringIndicator = true;
+ }
+
+ if( ( byteRead & ( 0x01 << 15 ) ) > 0 ){
+ //this is a valid byte
+ synchronized( buffer ){
+ if( bufferEnd + 1 >= buffer.length ){
+ //loop back around to the beginning
+ bufferEnd = 0;
+ }
+ buffer[ bufferEnd++ ] = (byte)( byteRead & 0xFF );
+ if( bufferEnd == bufferBegin ){
+ //the end has wrapped around, increment the beginning
+ bufferBegin++;
+
+ if( bufferBegin >= buffer.length ){
+ bufferBegin = 0;
+ }
+ }
+
+ buffer.notify();
+ }
+ }
+
+ callback.postSerialChangedEvent( s );
+ }
+ }
+
+ @Override
+ public int available(){
+ if( bufferEnd < bufferBegin ){
+ //special case - we have looped around
+ return ( buffer.length - bufferBegin ) + bufferEnd;
+ }else{
+ return bufferEnd - bufferBegin;
+ }
+ }
+
+ @Override
+ public int read( byte[] b, int off, int len ) throws IOException{
+ int readSoFar = 0;
+
+ if( len == 0 ){
+ return 0;
+ }
+
+ for( int x = off; x < len; x++ ){
+ b[x] = (byte)read();
+ readSoFar++;
+ if( readSoFar > 0 && available() == 0 ){
+ break;
+ }
+ }
+
+ return readSoFar;
+ }
+
+}
Index: tags/JavaSerial0.5/src/com/rm5248/serial/SerialInputStream.java
===================================================================
--- tags/JavaSerial0.5/src/com/rm5248/serial/SerialInputStream.java (nonexistent)
+++ tags/JavaSerial0.5/src/com/rm5248/serial/SerialInputStream.java (revision 111)
@@ -0,0 +1,63 @@
+package com.rm5248.serial;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Input stream for the serial port. This implementation passes back the
+ * status of the control lines in the upper bits of {@code read()}, and
+ * thus must be parsed properly.
+ */
+class SerialInputStream extends InputStream{
+ /* The handle to read from. Needed for native implementation */
+ @SuppressWarnings("unused")
+ private int handle;
+
+
+ SerialInputStream( int handle ){
+ this.handle = handle;
+ }
+
+ @Override
+ public int read() throws IOException{
+ return readByte();
+ }
+
+ @Override
+ public int available() throws IOException{
+ return getAvailable();
+ }
+
+ private native int readByte() throws IOException;
+
+ private native int getAvailable() throws IOException;
+}
+
+/**
+ * A SimpleSerialInputStream does not pass back the status of the control
+ * lines on the serial port - just the raw bytes.
+ */
+class SimpleSerialInputStream extends InputStream {
+ /* The handle to read from. Needed for native implementation */
+ @SuppressWarnings("unused")
+ private int handle;
+
+
+ SimpleSerialInputStream( int handle ){
+ this.handle = handle;
+ }
+
+ @Override
+ public int read() throws IOException{
+ return readByte();
+ }
+
+ @Override
+ public int available() throws IOException{
+ return getAvailable();
+ }
+
+ private native int readByte() throws IOException;
+
+ private native int getAvailable() throws IOException;
+}
\ No newline at end of file
Index: tags/JavaSerial0.5/src/com/rm5248/serial/NoSuchPortException.java
===================================================================
--- tags/JavaSerial0.5/src/com/rm5248/serial/NoSuchPortException.java (nonexistent)
+++ tags/JavaSerial0.5/src/com/rm5248/serial/NoSuchPortException.java (revision 111)
@@ -0,0 +1,24 @@
+package com.rm5248.serial;
+
+/**
+ * This exception is thrown when you attempt to open up a port that does not exist.
+ *
+ * @author rm5248
+ *
+ */
+public class NoSuchPortException extends Exception {
+
+ /**
+ * Generated by Eclipse
+ */
+ private static final long serialVersionUID = -5218448691940726352L;
+
+ /**
+ * Create a new exception with the specified error.
+ *
+ * @param status
+ */
+ public NoSuchPortException( String status ){
+ super( status );
+ }
+}
Index: tags/JavaSerial0.5/src/com/rm5248/serial/NotASerialPortException.java
===================================================================
--- tags/JavaSerial0.5/src/com/rm5248/serial/NotASerialPortException.java (nonexistent)
+++ tags/JavaSerial0.5/src/com/rm5248/serial/NotASerialPortException.java (revision 111)
@@ -0,0 +1,23 @@
+package com.rm5248.serial;
+
+/**
+ * This exception is thrown when the device that you have opened is not a serial port.
+ *
+ * @author rm5248
+ *
+ */
+public class NotASerialPortException extends Exception {
+
+ /**
+ * Generated by Eclipse
+ */
+ private static final long serialVersionUID = 5606767768689212862L;
+
+ /** Create a new exception if this is not a serial port
+ *
+ * @param message
+ */
+ public NotASerialPortException( String message ){
+ super( message );
+ }
+}
Index: tags/JavaSerial0.5/src/com/rm5248/serial/SerialLineState.java
===================================================================
--- tags/JavaSerial0.5/src/com/rm5248/serial/SerialLineState.java (nonexistent)
+++ tags/JavaSerial0.5/src/com/rm5248/serial/SerialLineState.java (revision 111)
@@ -0,0 +1,56 @@
+package com.rm5248.serial;
+
+/**
+ * This class represents the current state of the lines on the serial port.
+ * You can also use this class to set the state of the serial port.
+ *
+ * Note that all of these options may not be available depending on the
+ * serial port that is in use, and/or the platform that you are running on.
+ *
+ */
+public class SerialLineState {
+
+ public boolean carrierDetect;
+ public boolean clearToSend;
+ public boolean dataSetReady;
+ public boolean dataTerminalReady;
+ public boolean ringIndicator;
+ public boolean requestToSend;
+
+ public SerialLineState(){
+ carrierDetect = false;
+ clearToSend = false;
+ dataSetReady = false;
+ dataTerminalReady = false;
+ ringIndicator = false;
+ requestToSend = false;
+ }
+
+ @Override
+ public boolean equals( Object o ){
+ if( o instanceof SerialLineState ){
+ SerialLineState s = (SerialLineState)o;
+
+ return ( s.carrierDetect == carrierDetect ) &&
+ ( s.clearToSend == clearToSend ) &&
+ ( s.dataSetReady == dataSetReady ) &&
+ ( s.dataTerminalReady == dataTerminalReady ) &&
+ ( s.ringIndicator == ringIndicator ) &&
+ ( s.requestToSend == requestToSend );
+ }
+
+ return false;
+ }
+
+ @Override
+ public String toString(){
+ return "[SerialLineState: " +
+ "CD: " + carrierDetect +
+ " CTS: " + clearToSend +
+ " DSR: " + dataSetReady +
+ " DTR: " + dataTerminalReady +
+ " RI: " + ringIndicator +
+ " RTS: " + requestToSend + "]";
+ }
+
+}
Index: tags/JavaSerial0.5/src/com/rm5248/serial/SerialOutputStream.java
===================================================================
--- tags/JavaSerial0.5/src/com/rm5248/serial/SerialOutputStream.java (nonexistent)
+++ tags/JavaSerial0.5/src/com/rm5248/serial/SerialOutputStream.java (revision 111)
@@ -0,0 +1,28 @@
+package com.rm5248.serial;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+class SerialOutputStream extends OutputStream{
+ /* The handle to write to */
+ @SuppressWarnings("unused")
+ private int handle;
+
+ SerialOutputStream( int handle ){
+ this.handle = handle;
+ }
+
+ @Override
+ public void write(int b) throws IOException {
+ writeByte( b );
+ }
+
+ @Override
+ public void write( byte[] arr ) throws IOException{
+ writeByteArray( arr );
+ }
+
+ private native void writeByte( int toWrite ) throws IOException;
+
+ private native void writeByteArray( byte[] array ) throws IOException;
+}
Index: tags/JavaSerial0.5/src/com/rm5248/serial/SerialChangeListener.java
===================================================================
--- tags/JavaSerial0.5/src/com/rm5248/serial/SerialChangeListener.java (nonexistent)
+++ tags/JavaSerial0.5/src/com/rm5248/serial/SerialChangeListener.java (revision 111)
@@ -0,0 +1,16 @@
+package com.rm5248.serial;
+
+/**
+ * This interface lets the user do something when the serial line state changes.
+ * The state is defined by how the lines are currently set.
+ *
+ */
+public interface SerialChangeListener {
+
+ /**
+ * Fired when the state on the serial line changes.
+ *
+ * @param state
+ */
+ public void serialStateChanged( SerialLineState state );
+}
Index: tags/JavaSerial0.5/LICENSE
===================================================================
--- tags/JavaSerial0.5/LICENSE (nonexistent)
+++ tags/JavaSerial0.5/LICENSE (revision 111)
@@ -0,0 +1,7 @@
+Copyright (c) 2013-2015 rm5248
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Index: tags/JavaSerial0.5/README
===================================================================
--- tags/JavaSerial0.5/README (nonexistent)
+++ tags/JavaSerial0.5/README (revision 111)
@@ -0,0 +1,8 @@
+Java Serial
+=========================================
+
+This software is open-source software.
+
+The home of Java Serial is at http://svn.rm5248.com/RMProgrammingUtilities/?page_id=19
+
+Use of this code is subject to license terms as laid out in LICENSE
\ No newline at end of file