diff --git a/INSTALL b/INSTALL index f5a9783..9c17b7a 100644 --- a/INSTALL +++ b/INSTALL @@ -123,31 +123,31 @@ Maven: com.fazecast jSerialComm - 1.3.3 + 1.3.4 Ivy: - + Grape: @Grapes( - @Grab(group='com.fazecast', module='jSerialComm', version='1.3.3') + @Grab(group='com.fazecast', module='jSerialComm', version='1.3.4') ) Gradle: -'com.fazecast:jSerialComm:1.3.3' +'com.fazecast:jSerialComm:1.3.4' Buildr: -'com.fazecast:jSerialComm:jar:1.3.3' +'com.fazecast:jSerialComm:jar:1.3.4' SBT: -libraryDependencies += "com.fazecast" % "jSerialComm" % "1.3.3" +libraryDependencies += "com.fazecast" % "jSerialComm" % "1.3.4" Leiningen: -[com.fazecast/jSerialComm "1.3.3"] +[com.fazecast/jSerialComm "1.3.4"] diff --git a/build.gradle b/build.gradle index 410ee6e..7543acc 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ apply plugin: 'maven' group = 'com.fazecast' archivesBaseName = 'jSerialComm' -version = '1.3.3' +version = '1.3.4' sourceCompatibility = 1.6 targetCompatibility = 1.6 diff --git a/src/main/c/Android/jni/SerialPort_Android.c b/src/main/c/Android/jni/SerialPort_Android.c index f99e4b4..5341179 100644 --- a/src/main/c/Android/jni/SerialPort_Android.c +++ b/src/main/c/Android/jni/SerialPort_Android.c @@ -2,7 +2,7 @@ * SerialPort_Android.c * * Created on: Mar 13, 2015 - * Last Updated on: Apr 30, 2015 + * Last Updated on: May 19, 2015 * Author: Will Hedgecock * * Copyright (C) 2012-2015 Fazecast, Inc. @@ -39,9 +39,9 @@ #include "AndroidHelperFunctions.h" // Cached class, method, and field IDs -int serialPortFD = -1; jclass serialCommClass; jmethodID serialCommConstructor; +jfieldID serialPortFdField; jfieldID comPortField; jfieldID portStringField; jfieldID isOpenedField; @@ -87,6 +87,7 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrar serialCommConstructor = (*env)->GetMethodID(env, serialCommClass, "", "()V"); // Cache + serialPortFdField = (*env)->GetFieldID(env, serialCommClass, "portHandle", "J"); comPortField = (*env)->GetFieldID(env, serialCommClass, "comPort", "Ljava/lang/String;"); portStringField = (*env)->GetFieldID(env, serialCommClass, "portString", "Ljava/lang/String;"); isOpenedField = (*env)->GetFieldID(env, serialCommClass, "isOpened", "Z"); @@ -107,17 +108,18 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_uninitializeLibr (*env)->DeleteGlobalRef(env, serialCommClass); } -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(JNIEnv *env, jobject obj) +JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(JNIEnv *env, jobject obj) { jstring portNameJString = (jstring)(*env)->GetObjectField(env, obj, comPortField); const char *portName = (*env)->GetStringUTFChars(env, portNameJString, NULL); // Try to open existing serial port with read/write access + int serialPortFD = -1; if ((serialPortFD = open(portName, O_RDWR | O_NOCTTY | O_NONBLOCK)) > 0) { // Configure the port parameters and timeouts - if (Java_com_fazecast_jSerialComm_SerialPort_configPort(env, obj) && Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(env, obj) && - Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(env, obj)) + if (Java_com_fazecast_jSerialComm_SerialPort_configPort(env, obj, serialPortFD) && Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(env, obj, serialPortFD) && + Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(env, obj, serialPortFD)) (*env)->SetBooleanField(env, obj, isOpenedField, JNI_TRUE); else { @@ -129,10 +131,10 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNati } (*env)->ReleaseStringUTFChars(env, portNameJString, portName); - return (serialPortFD == -1) ? JNI_FALSE : JNI_TRUE; + return serialPortFD; } -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(JNIEnv *env, jobject obj) +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(JNIEnv *env, jobject obj, jlong serialPortFD) { if (serialPortFD <= 0) return JNI_FALSE; @@ -180,7 +182,7 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J return ((retVal == 0) ? JNI_TRUE : JNI_FALSE); } -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(JNIEnv *env, jobject obj) +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(JNIEnv *env, jobject obj, jlong serialPortFD) { if (serialPortFD <= 0) return JNI_FALSE; @@ -209,7 +211,7 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowCo return ((retVal == 0) ? JNI_TRUE : JNI_FALSE); } -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(JNIEnv *env, jobject obj) +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(JNIEnv *env, jobject obj, jlong serialPortFD) { // Get port timeouts from Java class if (serialPortFD <= 0) @@ -270,7 +272,7 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeou return ((retVal == 0) ? JNI_TRUE : JNI_FALSE); } -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(JNIEnv *env, jobject obj) +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(JNIEnv *env, jobject obj, jlong serialPortFD) { if (serialPortFD <= 0) return JNI_FALSE; @@ -295,13 +297,13 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventF setBaudRate(serialPortFD, baudRate); } else - Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(env, obj); + Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(env, obj, serialPortFD); // Apply changes return JNI_TRUE; } -JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNIEnv *env, jobject obj) +JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNIEnv *env, jobject obj, jlong serialPortFD) { if (serialPortFD <= 0) return 0; @@ -319,19 +321,20 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNI return (FD_ISSET(serialPortFD, &waitingSet)) ? com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_AVAILABLE : 0; } -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNative(JNIEnv *env, jobject obj) +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNative(JNIEnv *env, jobject obj, jlong serialPortFD) { // Close port if (serialPortFD <= 0) return JNI_TRUE; close(serialPortFD); serialPortFD = -1; + (*env)->SetLongField(env, obj, serialPortFdField, -1l); (*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE); return JNI_TRUE; } -JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(JNIEnv *env, jobject obj) +JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(JNIEnv *env, jobject obj, jlong serialPortFD) { int numBytesAvailable = -1; if (serialPortFD > 0) @@ -340,7 +343,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(J return numBytesAvailable; } -JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv *env, jobject obj, jbyteArray buffer, jlong bytesToRead) +JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToRead) { // Get port handle and read timeout from Java class if (serialPortFD <= 0) @@ -361,6 +364,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv // Problem reading, close port close(serialPortFD); serialPortFD = -1; + (*env)->SetLongField(env, obj, serialPortFdField, -1l); (*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE); break; } @@ -390,6 +394,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv // Problem reading, close port close(serialPortFD); serialPortFD = -1; + (*env)->SetLongField(env, obj, serialPortFdField, -1l); (*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE); break; } @@ -411,6 +416,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv // Problem reading, close port close(serialPortFD); serialPortFD = -1; + (*env)->SetLongField(env, obj, serialPortFdField, -1l); (*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE); } else @@ -423,7 +429,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv return (numBytesRead == -1) ? -1 : numBytesReadTotal; } -JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jbyteArray buffer, jlong bytesToWrite) +JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToWrite) { if (serialPortFD <= 0) return -1; @@ -436,6 +442,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn // Problem writing, close port close(serialPortFD); serialPortFD = -1; + (*env)->SetLongField(env, obj, serialPortFdField, -1l); (*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE); } diff --git a/src/main/c/Android/jni/com_fazecast_jSerialComm_SerialPort.h b/src/main/c/Android/jni/com_fazecast_jSerialComm_SerialPort.h index 31cb20c..17f91d2 100644 --- a/src/main/c/Android/jni/com_fazecast_jSerialComm_SerialPort.h +++ b/src/main/c/Android/jni/com_fazecast_jSerialComm_SerialPort.h @@ -82,82 +82,82 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_uninitializeLibr /* * Class: com_fazecast_jSerialComm_SerialPort * Method: openPortNative - * Signature: ()Z + * Signature: ()J */ -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative +JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative (JNIEnv *, jobject); /* * Class: com_fazecast_jSerialComm_SerialPort * Method: closePortNative - * Signature: ()Z + * Signature: (J)Z */ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNative - (JNIEnv *, jobject); + (JNIEnv *, jobject, jlong); /* * Class: com_fazecast_jSerialComm_SerialPort * Method: configPort - * Signature: ()Z + * Signature: (J)Z */ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort - (JNIEnv *, jobject); + (JNIEnv *, jobject, jlong); /* * Class: com_fazecast_jSerialComm_SerialPort * Method: configFlowControl - * Signature: ()Z + * Signature: (J)Z */ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowControl - (JNIEnv *, jobject); + (JNIEnv *, jobject, jlong); /* * Class: com_fazecast_jSerialComm_SerialPort * Method: configTimeouts - * Signature: ()Z + * Signature: (J)Z */ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeouts - (JNIEnv *, jobject); + (JNIEnv *, jobject, jlong); /* * Class: com_fazecast_jSerialComm_SerialPort * Method: configEventFlags - * Signature: ()Z + * Signature: (J)Z */ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventFlags - (JNIEnv *, jobject); + (JNIEnv *, jobject, jlong); /* * Class: com_fazecast_jSerialComm_SerialPort * Method: waitForEvent - * Signature: ()I + * Signature: (J)I */ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent - (JNIEnv *, jobject); + (JNIEnv *, jobject, jlong); /* * Class: com_fazecast_jSerialComm_SerialPort * Method: bytesAvailable - * Signature: ()I + * Signature: (J)I */ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable - (JNIEnv *, jobject); + (JNIEnv *, jobject, jlong); /* * Class: com_fazecast_jSerialComm_SerialPort * Method: readBytes - * Signature: ([BJ)I + * Signature: (J[BJ)I */ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes - (JNIEnv *, jobject, jbyteArray, jlong); + (JNIEnv *, jobject, jlong, jbyteArray, jlong); /* * Class: com_fazecast_jSerialComm_SerialPort * Method: writeBytes - * Signature: ([BJ)I + * Signature: (J[BJ)I */ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes - (JNIEnv *, jobject, jbyteArray, jlong); + (JNIEnv *, jobject, jlong, jbyteArray, jlong); #ifdef __cplusplus } diff --git a/src/main/c/Linux/SerialPort_Linux.c b/src/main/c/Linux/SerialPort_Linux.c index bc78888..338f6a6 100644 --- a/src/main/c/Linux/SerialPort_Linux.c +++ b/src/main/c/Linux/SerialPort_Linux.c @@ -40,9 +40,9 @@ #include "LinuxHelperFunctions.h" // Cached class, method, and field IDs -int serialPortFD = -1; jclass serialCommClass; jmethodID serialCommConstructor; +jfieldID serialPortFdField; jfieldID comPortField; jfieldID portStringField; jfieldID isOpenedField; @@ -88,6 +88,7 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrar serialCommConstructor = (*env)->GetMethodID(env, serialCommClass, "", "()V"); // Cache + serialPortFdField = (*env)->GetFieldID(env, serialCommClass, "portHandle", "J"); comPortField = (*env)->GetFieldID(env, serialCommClass, "comPort", "Ljava/lang/String;"); portStringField = (*env)->GetFieldID(env, serialCommClass, "portString", "Ljava/lang/String;"); isOpenedField = (*env)->GetFieldID(env, serialCommClass, "isOpened", "Z"); @@ -108,17 +109,18 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_uninitializeLibr (*env)->DeleteGlobalRef(env, serialCommClass); } -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(JNIEnv *env, jobject obj) +JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(JNIEnv *env, jobject obj) { jstring portNameJString = (jstring)(*env)->GetObjectField(env, obj, comPortField); const char *portName = (*env)->GetStringUTFChars(env, portNameJString, NULL); // Try to open existing serial port with read/write access + int serialPortFD = -1; if ((serialPortFD = open(portName, O_RDWR | O_NOCTTY | O_NONBLOCK)) > 0) { // Configure the port parameters and timeouts - if (Java_com_fazecast_jSerialComm_SerialPort_configPort(env, obj) && Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(env, obj) && - Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(env, obj)) + if (Java_com_fazecast_jSerialComm_SerialPort_configPort(env, obj, serialPortFD) && Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(env, obj, serialPortFD) && + Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(env, obj, serialPortFD)) (*env)->SetBooleanField(env, obj, isOpenedField, JNI_TRUE); else { @@ -130,10 +132,10 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNati } (*env)->ReleaseStringUTFChars(env, portNameJString, portName); - return (serialPortFD == -1) ? JNI_FALSE : JNI_TRUE; + return serialPortFD; } -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(JNIEnv *env, jobject obj) +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(JNIEnv *env, jobject obj, jlong serialPortFD) { if (serialPortFD <= 0) return JNI_FALSE; @@ -182,7 +184,7 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J return ((retVal == 0) ? JNI_TRUE : JNI_FALSE); } -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(JNIEnv *env, jobject obj) +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(JNIEnv *env, jobject obj, jlong serialPortFD) { if (serialPortFD <= 0) return JNI_FALSE; @@ -211,7 +213,7 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowCo return ((retVal == 0) ? JNI_TRUE : JNI_FALSE); } -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(JNIEnv *env, jobject obj) +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(JNIEnv *env, jobject obj, jlong serialPortFD) { // Get port timeouts from Java class if (serialPortFD <= 0) @@ -272,7 +274,7 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeou return ((retVal == 0) ? JNI_TRUE : JNI_FALSE); } -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(JNIEnv *env, jobject obj) +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(JNIEnv *env, jobject obj, jlong serialPortFD) { if (serialPortFD <= 0) return JNI_FALSE; @@ -297,13 +299,13 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventF setBaudRate(serialPortFD, baudRate); } else - Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(env, obj); + Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(env, obj, serialPortFD); // Apply changes return JNI_TRUE; } -JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNIEnv *env, jobject obj) +JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNIEnv *env, jobject obj, jlong serialPortFD) { if (serialPortFD <= 0) return 0; @@ -321,19 +323,20 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNI return (FD_ISSET(serialPortFD, &waitingSet)) ? com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_AVAILABLE : 0; } -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNative(JNIEnv *env, jobject obj) +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNative(JNIEnv *env, jobject obj, jlong serialPortFD) { // Close port if (serialPortFD <= 0) return JNI_TRUE; close(serialPortFD); serialPortFD = -1; + (*env)->SetLongField(env, obj, serialPortFdField, -1l); (*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE); return JNI_TRUE; } -JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(JNIEnv *env, jobject obj) +JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(JNIEnv *env, jobject obj, jlong serialPortFD) { int numBytesAvailable = -1; if (serialPortFD > 0) @@ -342,7 +345,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(J return numBytesAvailable; } -JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv *env, jobject obj, jbyteArray buffer, jlong bytesToRead) +JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToRead) { // Get port handle and read timeout from Java class if (serialPortFD <= 0) @@ -363,6 +366,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv // Problem reading, close port close(serialPortFD); serialPortFD = -1; + (*env)->SetLongField(env, obj, serialPortFdField, -1l); (*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE); break; } @@ -392,6 +396,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv // Problem reading, close port close(serialPortFD); serialPortFD = -1; + (*env)->SetLongField(env, obj, serialPortFdField, -1l); (*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE); break; } @@ -413,6 +418,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv // Problem reading, close port close(serialPortFD); serialPortFD = -1; + (*env)->SetLongField(env, obj, serialPortFdField, -1l); (*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE); } else @@ -425,7 +431,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv return (numBytesRead == -1) ? -1 : numBytesReadTotal; } -JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jbyteArray buffer, jlong bytesToWrite) +JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToWrite) { if (serialPortFD <= 0) return -1; @@ -438,6 +444,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn // Problem writing, close port close(serialPortFD); serialPortFD = -1; + (*env)->SetLongField(env, obj, serialPortFdField, -1l); (*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE); } diff --git a/src/main/c/OSX/SerialPort_OSX.c b/src/main/c/OSX/SerialPort_OSX.c index 96f253e..fc53333 100644 --- a/src/main/c/OSX/SerialPort_OSX.c +++ b/src/main/c/OSX/SerialPort_OSX.c @@ -2,7 +2,7 @@ * SerialPort_OSX.c * * Created on: Feb 25, 2012 - * Last Updated on: Apr 30, 2015 + * Last Updated on: May 19, 2015 * Author: Will Hedgecock * * Copyright (C) 2012-2015 Fazecast, Inc. @@ -41,9 +41,9 @@ #include "../com_fazecast_jSerialComm_SerialPort.h" // Cached class, method, and field IDs -int serialPortFD = -1; jclass serialCommClass; jmethodID serialCommConstructor; +jfieldID serialPortFdField; jfieldID comPortField; jfieldID portStringField; jfieldID isOpenedField; @@ -139,6 +139,7 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrar serialCommConstructor = (*env)->GetMethodID(env, serialCommClass, "", "()V"); // Cache + serialPortFdField = (*env)->GetFieldID(env, serialCommClass, "portHandle", "J"); comPortField = (*env)->GetFieldID(env, serialCommClass, "comPort", "Ljava/lang/String;"); portStringField = (*env)->GetFieldID(env, serialCommClass, "portString", "Ljava/lang/String;"); isOpenedField = (*env)->GetFieldID(env, serialCommClass, "isOpened", "Z"); @@ -159,17 +160,18 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_uninitializeLibr (*env)->DeleteGlobalRef(env, serialCommClass); } -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(JNIEnv *env, jobject obj) +JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(JNIEnv *env, jobject obj) { jstring portNameJString = (jstring)(*env)->GetObjectField(env, obj, comPortField); const char *portName = (*env)->GetStringUTFChars(env, portNameJString, NULL); // Try to open existing serial port with read/write access + int serialPortFD = -1; if ((serialPortFD = open(portName, O_RDWR | O_NOCTTY | O_NONBLOCK)) > 0) { // Configure the port parameters and timeouts - if (Java_com_fazecast_jSerialComm_SerialPort_configPort(env, obj) && Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(env, obj) && - Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(env, obj)) + if (Java_com_fazecast_jSerialComm_SerialPort_configPort(env, obj, serialPortFD) && Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(env, obj, serialPortFD) && + Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(env, obj, serialPortFD)) (*env)->SetBooleanField(env, obj, isOpenedField, JNI_TRUE); else { @@ -181,10 +183,10 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNati } (*env)->ReleaseStringUTFChars(env, portNameJString, portName); - return (serialPortFD == -1) ? JNI_FALSE : JNI_TRUE; + return serialPortFD; } -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(JNIEnv *env, jobject obj) +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(JNIEnv *env, jobject obj, jlong serialPortFD) { if (serialPortFD <= 0) return JNI_FALSE; @@ -227,7 +229,7 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J return (ioctl(serialPortFD, IOSSIOSPEED, &baudRate) == -1) ? JNI_FALSE : JNI_TRUE; } -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(JNIEnv *env, jobject obj) +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(JNIEnv *env, jobject obj, jlong serialPortFD) { if (serialPortFD <= 0) return JNI_FALSE; @@ -251,7 +253,7 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowCo return (tcsetattr(serialPortFD, TCSANOW, &options) == -1) ? JNI_FALSE : JNI_TRUE; } -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(JNIEnv *env, jobject obj) +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(JNIEnv *env, jobject obj, jlong serialPortFD) { // Get port timeouts from Java class if (serialPortFD <= 0) @@ -307,7 +309,7 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeou return (tcsetattr(serialPortFD, TCSANOW, &options) == 0) ? JNI_TRUE : JNI_FALSE; } -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(JNIEnv *env, jobject obj) +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(JNIEnv *env, jobject obj, jlong serialPortFD) { if (serialPortFD <= 0) return JNI_FALSE; @@ -329,12 +331,12 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventF retVal = (tcsetattr(serialPortFD, TCSANOW, &options) == 0) ? JNI_TRUE : JNI_FALSE; } else - retVal = Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(env, obj); + retVal = Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(env, obj, serialPortFD); return retVal; } -JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNIEnv *env, jobject obj) +JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNIEnv *env, jobject obj, jlong serialPortFD) { if (serialPortFD <= 0) return 0; @@ -352,7 +354,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNI return (FD_ISSET(serialPortFD, &waitingSet)) ? com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_AVAILABLE : 0; } -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNative(JNIEnv *env, jobject obj) +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNative(JNIEnv *env, jobject obj, jlong serialPortFD) { // Close port if (serialPortFD <= 0) @@ -360,12 +362,13 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNat tcdrain(serialPortFD); close(serialPortFD); serialPortFD = -1; + (*env)->SetLongField(env, obj, serialPortFdField, -1l); (*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE); return JNI_TRUE; } -JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(JNIEnv *env, jobject obj) +JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(JNIEnv *env, jobject obj, jlong serialPortFD) { int numBytesAvailable = -1; if (serialPortFD > 0) @@ -374,7 +377,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(J return numBytesAvailable; } -JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv *env, jobject obj, jbyteArray buffer, jlong bytesToRead) +JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToRead) { // Get port handle and read timeout from Java class if (serialPortFD <= 0) @@ -395,6 +398,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv // Problem reading, close port close(serialPortFD); serialPortFD = -1; + (*env)->SetLongField(env, obj, serialPortFdField, -1l); (*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE); break; } @@ -424,6 +428,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv // Problem reading, close port close(serialPortFD); serialPortFD = -1; + (*env)->SetLongField(env, obj, serialPortFdField, -1l); (*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE); break; } @@ -445,6 +450,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv // Problem reading, close port close(serialPortFD); serialPortFD = -1; + (*env)->SetLongField(env, obj, serialPortFdField, -1l); (*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE); } else @@ -457,7 +463,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv return (numBytesRead == -1) ? -1 : numBytesReadTotal; } -JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jbyteArray buffer, jlong bytesToWrite) +JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToWrite) { if (serialPortFD <= 0) return -1; @@ -470,6 +476,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn // Problem writing, close port close(serialPortFD); serialPortFD = -1; + (*env)->SetLongField(env, obj, serialPortFdField, -1l); (*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE); } diff --git a/src/main/c/Windows/SerialPort_Windows.c b/src/main/c/Windows/SerialPort_Windows.c index aa6d6fe..046cfa7 100644 --- a/src/main/c/Windows/SerialPort_Windows.c +++ b/src/main/c/Windows/SerialPort_Windows.c @@ -2,7 +2,7 @@ * SerialPort_Windows.c * * Created on: Feb 25, 2012 - * Last Updated on: May 04, 2015 + * Last Updated on: May 19, 2015 * Author: Will Hedgecock * * Copyright (C) 2012-2015 Fazecast, Inc. @@ -35,9 +35,9 @@ #include "WindowsHelperFunctions.h" // Cached class, method, and field IDs -HANDLE serialPortHandle = INVALID_HANDLE_VALUE; jclass serialCommClass; jmethodID serialCommConstructor; +jfieldID serialPortHandleField; jfieldID comPortField; jfieldID portStringField; jfieldID isOpenedField; @@ -226,6 +226,7 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrar serialCommConstructor = env->GetMethodID(serialCommClass, "", "()V"); // Cache + serialPortHandleField = env->GetFieldID(serialCommClass, "portHandle", "J"); comPortField = env->GetFieldID(serialCommClass, "comPort", "Ljava/lang/String;"); portStringField = env->GetFieldID(serialCommClass, "portString", "Ljava/lang/String;"); isOpenedField = env->GetFieldID(serialCommClass, "isOpened", "Z"); @@ -246,17 +247,18 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_uninitializeLibr env->DeleteGlobalRef(serialCommClass); } -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(JNIEnv *env, jobject obj) +JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(JNIEnv *env, jobject obj) { jstring portNameJString = (jstring)env->GetObjectField(obj, comPortField); const char *portName = env->GetStringUTFChars(portNameJString, NULL); // Try to open existing serial port with read/write access + HANDLE serialPortHandle = INVALID_HANDLE_VALUE; if ((serialPortHandle = CreateFile(portName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_OVERLAPPED, NULL)) != INVALID_HANDLE_VALUE) { // Configure the port parameters and timeouts - if (Java_com_fazecast_jSerialComm_SerialPort_configPort(env, obj) && Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(env, obj) && - Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(env, obj)) + if (Java_com_fazecast_jSerialComm_SerialPort_configPort(env, obj, (jlong)serialPortHandle) && Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(env, obj, (jlong)serialPortHandle) && + Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(env, obj, (jlong)serialPortHandle)) env->SetBooleanField(obj, isOpenedField, JNI_TRUE); else { @@ -268,11 +270,12 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNati } env->ReleaseStringUTFChars(portNameJString, portName); - return (serialPortHandle == INVALID_HANDLE_VALUE) ? JNI_FALSE : JNI_TRUE; + return (jlong)serialPortHandle; } -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(JNIEnv *env, jobject obj) +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(JNIEnv *env, jobject obj, jlong serialPortFD) { + HANDLE serialPortHandle = (HANDLE)serialPortFD; if (serialPortHandle == INVALID_HANDLE_VALUE) return JNI_FALSE; DCB dcbSerialParams = {0}; @@ -304,8 +307,9 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J return SetCommState(serialPortHandle, &dcbSerialParams); } -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(JNIEnv *env, jobject obj) +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(JNIEnv *env, jobject obj, jlong serialPortFD) { + HANDLE serialPortHandle = (HANDLE)serialPortFD; if (serialPortHandle == INVALID_HANDLE_VALUE) return JNI_FALSE; DCB dcbSerialParams = {0}; @@ -347,9 +351,10 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowCo return SetCommState(serialPortHandle, &dcbSerialParams); } -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(JNIEnv *env, jobject obj) +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(JNIEnv *env, jobject obj, jlong serialPortFD) { // Get port timeouts from Java class + HANDLE serialPortHandle = (HANDLE)serialPortFD; if (serialPortHandle == INVALID_HANDLE_VALUE) return JNI_FALSE; COMMTIMEOUTS timeouts = {0}; @@ -416,8 +421,9 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeou return SetCommTimeouts(serialPortHandle, &timeouts); } -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(JNIEnv *env, jobject obj) +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(JNIEnv *env, jobject obj, jlong serialPortFD) { + HANDLE serialPortHandle = (HANDLE)serialPortFD; if (serialPortHandle == INVALID_HANDLE_VALUE) return JNI_FALSE; @@ -442,14 +448,15 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventF SetCommTimeouts(serialPortHandle, &timeouts); } else - Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(env, obj); + Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(env, obj, serialPortFD); // Apply changes return SetCommMask(serialPortHandle, eventFlags); } -JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNIEnv *env, jobject obj) +JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNIEnv *env, jobject obj, jlong serialPortFD) { + HANDLE serialPortHandle = (HANDLE)serialPortFD; if (serialPortHandle == INVALID_HANDLE_VALUE) return 0; OVERLAPPED overlappedStruct = {0}; @@ -469,6 +476,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNI // Problem reading, close port CloseHandle(serialPortHandle); serialPortHandle = INVALID_HANDLE_VALUE; + env->SetLongField(obj, serialPortHandleField, -1l); env->SetBooleanField(obj, isOpenedField, JNI_FALSE); } else if (GetOverlappedResult(serialPortHandle, &overlappedStruct, &numBytesRead, TRUE) == FALSE) @@ -481,9 +489,10 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNI (((eventMask & EV_TXEMPTY) > 0) ? com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_WRITTEN : 0); } -JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNative(JNIEnv *env, jobject obj) +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNative(JNIEnv *env, jobject obj, jlong serialPortFD) { // Purge any outstanding port operations + HANDLE serialPortHandle = (HANDLE)serialPortFD; if (serialPortHandle == INVALID_HANDLE_VALUE) return JNI_TRUE; PurgeComm(serialPortHandle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR); @@ -491,13 +500,15 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNat // Close port BOOL retVal = CloseHandle(serialPortHandle); serialPortHandle = INVALID_HANDLE_VALUE; + env->SetLongField(obj, serialPortHandleField, -1l); env->SetBooleanField(obj, isOpenedField, JNI_FALSE); return (retVal == 0) ? JNI_FALSE : JNI_TRUE; } -JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(JNIEnv *env, jobject obj) +JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(JNIEnv *env, jobject obj, jlong serialPortFD) { + HANDLE serialPortHandle = (HANDLE)serialPortFD; if (serialPortHandle == INVALID_HANDLE_VALUE) return -1; @@ -509,8 +520,9 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(J return (jint)numBytesAvailable; } -JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv *env, jobject obj, jbyteArray buffer, jlong bytesToRead) +JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToRead) { + HANDLE serialPortHandle = (HANDLE)serialPortFD; if (serialPortHandle == INVALID_HANDLE_VALUE) return -1; OVERLAPPED overlappedStruct = {0}; @@ -532,6 +544,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv // Problem reading, close port CloseHandle(serialPortHandle); serialPortHandle = INVALID_HANDLE_VALUE; + env->SetLongField(obj, serialPortHandleField, -1l); env->SetBooleanField(obj, isOpenedField, JNI_FALSE); } else if ((result = GetOverlappedResult(serialPortHandle, &overlappedStruct, &numBytesRead, TRUE)) == FALSE) @@ -539,6 +552,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv // Problem reading, close port CloseHandle(serialPortHandle); serialPortHandle = INVALID_HANDLE_VALUE; + env->SetLongField(obj, serialPortHandleField, -1l); env->SetBooleanField(obj, isOpenedField, JNI_FALSE); } } @@ -550,8 +564,9 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv return (result == TRUE) ? numBytesRead : -1; } -JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jbyteArray buffer, jlong bytesToWrite) +JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToWrite) { + HANDLE serialPortHandle = (HANDLE)serialPortFD; if (serialPortHandle == INVALID_HANDLE_VALUE) return -1; OVERLAPPED overlappedStruct = {0}; @@ -573,6 +588,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn // Problem writing, close port CloseHandle(serialPortHandle); serialPortHandle = INVALID_HANDLE_VALUE; + env->SetLongField(obj, serialPortHandleField, -1l); env->SetBooleanField(obj, isOpenedField, JNI_FALSE); } else if ((result = GetOverlappedResult(serialPortHandle, &overlappedStruct, &numBytesWritten, TRUE)) == FALSE) @@ -580,6 +596,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn // Problem reading, close port CloseHandle(serialPortHandle); serialPortHandle = INVALID_HANDLE_VALUE; + env->SetLongField(obj, serialPortHandleField, -1l); env->SetBooleanField(obj, isOpenedField, JNI_FALSE); } } diff --git a/src/main/java/com/fazecast/jSerialComm/SerialPort.java b/src/main/java/com/fazecast/jSerialComm/SerialPort.java index 87081fb..8188037 100644 --- a/src/main/java/com/fazecast/jSerialComm/SerialPort.java +++ b/src/main/java/com/fazecast/jSerialComm/SerialPort.java @@ -38,7 +38,7 @@ import java.util.Date; * This class provides native access to serial ports and devices without requiring external libraries or tools. * * @author Will Hedgecock <will.hedgecock@fazecast.com> - * @version 1.3.3 + * @version 1.3.4 * @see java.io.InputStream * @see java.io.OutputStream */ @@ -243,6 +243,7 @@ public final class SerialPort static final public int LISTENING_EVENT_DATA_WRITTEN = 0x00000100; // Serial Port Parameters + private volatile long portHandle = -1; private volatile int baudRate = 9600, dataBits = 8, stopBits = ONE_STOP_BIT, parity = NO_PARITY, eventFlags = 0; private volatile int timeoutMode = TIMEOUT_NONBLOCKING, readTimeout = 0, writeTimeout = 0, flowControl = 0; private volatile SerialPortInputStream inputStream = null; @@ -276,7 +277,7 @@ public final class SerialPort } try { Thread.sleep(500); } catch (Exception e) {} - if (!isOpened && openPortNative()) + if (!isOpened && (portHandle = openPortNative()) > 0) { inputStream = new SerialPortInputStream(); outputStream = new SerialPortOutputStream(); @@ -295,24 +296,28 @@ public final class SerialPort { if (serialEventListener != null) serialEventListener.stopListening(); - if (isOpened && closePortNative()) + if (isOpened && closePortNative(portHandle)) { inputStream = null; outputStream = null; + portHandle = -1; } return !isOpened; } // Serial Port Setup Methods - private static native void initializeLibrary(); // Initializes the JNI code - private static native void uninitializeLibrary(); // Un-initializes the JNI code - private final native boolean openPortNative(); // Opens serial port - private final native boolean closePortNative(); // Closes serial port - private final native boolean configPort(); // Changes/sets serial port parameters as defined by this class - private final native boolean configFlowControl(); // Changes/sets flow control parameters as defined by this class - private final native boolean configTimeouts(); // Changes/sets serial port timeouts as defined by this class - private final native boolean configEventFlags(); // Changes/sets which serial events to listen for as defined by this class - private final native int waitForEvent(); // Waits for serial event to occur as specified in eventFlags + private static native void initializeLibrary(); // Initializes the JNI code + private static native void uninitializeLibrary(); // Un-initializes the JNI code + private final native long openPortNative(); // Opens serial port + private final native boolean closePortNative(long portHandle); // Closes serial port + private final native boolean configPort(long portHandle); // Changes/sets serial port parameters as defined by this class + private final native boolean configFlowControl(long portHandle); // Changes/sets flow control parameters as defined by this class + private final native boolean configTimeouts(long portHandle); // Changes/sets serial port timeouts as defined by this class + private final native boolean configEventFlags(long portHandle); // Changes/sets which serial events to listen for as defined by this class + private final native int waitForEvent(long portHandle); // Waits for serial event to occur as specified in eventFlags + private final native int bytesAvailable(long portHandle); // Returns number of bytes available for reading + private final native int readBytes(long portHandle, byte[] buffer, long bytesToRead); // Reads bytes from serial port + private final native int writeBytes(long portHandle, byte[] buffer, long bytesToWrite); // Write bytes to serial port /** * Returns the number of bytes available without blocking if {@link #readBytes} were to be called immediately @@ -320,7 +325,7 @@ public final class SerialPort * * @return The number of bytes currently available to be read, or -1 if the port is not open. */ - public final native int bytesAvailable(); + public final int bytesAvailable() { return bytesAvailable(portHandle); } /** * Reads up to bytesToRead raw data bytes from the serial port and stores them in the buffer. @@ -335,7 +340,7 @@ public final class SerialPort * @param bytesToRead The number of bytes to read from the serial port. * @return The number of bytes successfully read, or -1 if there was an error reading from the port. */ - public final native int readBytes(byte[] buffer, long bytesToRead); + public final int readBytes(byte[] buffer, long bytesToRead) { return readBytes(portHandle, buffer, bytesToRead); } /** * Writes up to bytesToWrite raw data bytes from the buffer parameter to the serial port. @@ -350,7 +355,7 @@ public final class SerialPort * @param bytesToWrite The number of bytes to write to the serial port. * @return The number of bytes successfully written, or -1 if there was an error writing to the port. */ - public final native int writeBytes(byte[] buffer, long bytesToWrite); + public final int writeBytes(byte[] buffer, long bytesToWrite) { return writeBytes(portHandle, buffer, bytesToWrite); } // Default Constructor private SerialPort() {} @@ -390,7 +395,7 @@ public final class SerialPort if (isOpened) { - configEventFlags(); + configEventFlags(portHandle); serialEventListener.startListening(); } return true; @@ -410,7 +415,7 @@ public final class SerialPort eventFlags = 0; if (isOpened) - configEventFlags(); + configEventFlags(portHandle); } /** @@ -474,7 +479,7 @@ public final class SerialPort if (isOpened) { try { Thread.sleep(200); } catch (Exception e) {} - configPort(); + configPort(portHandle); } } @@ -525,7 +530,7 @@ public final class SerialPort if (isOpened) { try { Thread.sleep(200); } catch (Exception e) {} - configTimeouts(); + configTimeouts(portHandle); } } @@ -543,7 +548,7 @@ public final class SerialPort if (isOpened) { try { Thread.sleep(200); } catch (Exception e) {} - configPort(); + configPort(portHandle); } } @@ -561,7 +566,7 @@ public final class SerialPort if (isOpened) { try { Thread.sleep(200); } catch (Exception e) {} - configPort(); + configPort(portHandle); } } @@ -585,7 +590,7 @@ public final class SerialPort if (isOpened) { try { Thread.sleep(200); } catch (Exception e) {} - configPort(); + configPort(portHandle); } } @@ -624,7 +629,7 @@ public final class SerialPort if (isOpened) { try { Thread.sleep(200); } catch (Exception e) {} - configFlowControl(); + configFlowControl(portHandle); } } @@ -648,7 +653,7 @@ public final class SerialPort if (isOpened) { try { Thread.sleep(200); } catch (Exception e) {} - configPort(); + configPort(portHandle); } } @@ -797,7 +802,7 @@ public final class SerialPort int oldEventFlags = eventFlags; eventFlags = 0; - configEventFlags(); + configEventFlags(portHandle); try { serialEventThread.join(); } catch (InterruptedException e) {} serialEventThread = null; eventFlags = oldEventFlags; @@ -805,7 +810,7 @@ public final class SerialPort public final void waitForSerialEvent() throws NullPointerException { - switch (waitForEvent()) + switch (waitForEvent(portHandle)) { case LISTENING_EVENT_DATA_AVAILABLE: { diff --git a/src/main/java/com/fazecast/jSerialComm/SerialPortDataListener.java b/src/main/java/com/fazecast/jSerialComm/SerialPortDataListener.java index 4067a6c..3acfccb 100644 --- a/src/main/java/com/fazecast/jSerialComm/SerialPortDataListener.java +++ b/src/main/java/com/fazecast/jSerialComm/SerialPortDataListener.java @@ -31,7 +31,7 @@ import java.util.EventListener; * This interface must be implemented to enable simple event-based serial port I/O. * * @author Will Hedgecock <will.hedgecock@fazecast.com> - * @version 1.3.3 + * @version 1.3.4 * @see java.util.EventListener */ public interface SerialPortDataListener extends EventListener diff --git a/src/main/java/com/fazecast/jSerialComm/SerialPortEvent.java b/src/main/java/com/fazecast/jSerialComm/SerialPortEvent.java index ec05f58..6a51ff4 100644 --- a/src/main/java/com/fazecast/jSerialComm/SerialPortEvent.java +++ b/src/main/java/com/fazecast/jSerialComm/SerialPortEvent.java @@ -31,7 +31,7 @@ import java.util.EventObject; * This class describes an asynchronous serial port event. * * @author Will Hedgecock <will.hedgecock@fazecast.com> - * @version 1.3.3 + * @version 1.3.4 * @see java.util.EventObject */ public final class SerialPortEvent extends EventObject diff --git a/src/main/java/com/fazecast/jSerialComm/SerialPortPacketListener.java b/src/main/java/com/fazecast/jSerialComm/SerialPortPacketListener.java index c603113..3827b1e 100644 --- a/src/main/java/com/fazecast/jSerialComm/SerialPortPacketListener.java +++ b/src/main/java/com/fazecast/jSerialComm/SerialPortPacketListener.java @@ -31,7 +31,7 @@ package com.fazecast.jSerialComm; * Note: Using this interface will negate any serial port read timeout settings since they make no sense in an asynchronous context. * * @author Will Hedgecock <will.hedgecock@fazecast.com> - * @version 1.3.3 + * @version 1.3.4 * @see com.fazecast.jSerialComm.SerialPortDataListener * @see java.util.EventListener */ diff --git a/src/main/resources/Android/arm64-v8a/libjSerialComm.so b/src/main/resources/Android/arm64-v8a/libjSerialComm.so index c238c42..69ca98e 100644 Binary files a/src/main/resources/Android/arm64-v8a/libjSerialComm.so and b/src/main/resources/Android/arm64-v8a/libjSerialComm.so differ diff --git a/src/main/resources/Android/armeabi-v7a/libjSerialComm.so b/src/main/resources/Android/armeabi-v7a/libjSerialComm.so index ace723f..d1fbbfe 100644 Binary files a/src/main/resources/Android/armeabi-v7a/libjSerialComm.so and b/src/main/resources/Android/armeabi-v7a/libjSerialComm.so differ diff --git a/src/main/resources/Android/armeabi/libjSerialComm.so b/src/main/resources/Android/armeabi/libjSerialComm.so index 719056c..2f3ef77 100644 Binary files a/src/main/resources/Android/armeabi/libjSerialComm.so and b/src/main/resources/Android/armeabi/libjSerialComm.so differ diff --git a/src/main/resources/Android/mips/libjSerialComm.so b/src/main/resources/Android/mips/libjSerialComm.so index 7c38bdf..f91e7bd 100644 Binary files a/src/main/resources/Android/mips/libjSerialComm.so and b/src/main/resources/Android/mips/libjSerialComm.so differ diff --git a/src/main/resources/Android/mips64/libjSerialComm.so b/src/main/resources/Android/mips64/libjSerialComm.so index bc71bb3..d456d62 100644 Binary files a/src/main/resources/Android/mips64/libjSerialComm.so and b/src/main/resources/Android/mips64/libjSerialComm.so differ diff --git a/src/main/resources/Android/x86/libjSerialComm.so b/src/main/resources/Android/x86/libjSerialComm.so index 8c7b74e..a5075b8 100644 Binary files a/src/main/resources/Android/x86/libjSerialComm.so and b/src/main/resources/Android/x86/libjSerialComm.so differ diff --git a/src/main/resources/Android/x86_64/libjSerialComm.so b/src/main/resources/Android/x86_64/libjSerialComm.so index d929ef7..289932f 100644 Binary files a/src/main/resources/Android/x86_64/libjSerialComm.so and b/src/main/resources/Android/x86_64/libjSerialComm.so differ diff --git a/src/main/resources/Linux/armv5/libjSerialComm.so b/src/main/resources/Linux/armv5/libjSerialComm.so index 9feed05..78df79e 100644 Binary files a/src/main/resources/Linux/armv5/libjSerialComm.so and b/src/main/resources/Linux/armv5/libjSerialComm.so differ diff --git a/src/main/resources/Linux/armv6-hf/libjSerialComm.so b/src/main/resources/Linux/armv6-hf/libjSerialComm.so index e161200..c87f9c5 100644 Binary files a/src/main/resources/Linux/armv6-hf/libjSerialComm.so and b/src/main/resources/Linux/armv6-hf/libjSerialComm.so differ diff --git a/src/main/resources/Linux/armv6/libjSerialComm.so b/src/main/resources/Linux/armv6/libjSerialComm.so index 09800ec..7c43a44 100644 Binary files a/src/main/resources/Linux/armv6/libjSerialComm.so and b/src/main/resources/Linux/armv6/libjSerialComm.so differ diff --git a/src/main/resources/Linux/armv7-hf/libjSerialComm.so b/src/main/resources/Linux/armv7-hf/libjSerialComm.so index fbd3ba7..fefd343 100644 Binary files a/src/main/resources/Linux/armv7-hf/libjSerialComm.so and b/src/main/resources/Linux/armv7-hf/libjSerialComm.so differ diff --git a/src/main/resources/Linux/armv7/libjSerialComm.so b/src/main/resources/Linux/armv7/libjSerialComm.so index 2a5e6d9..744b5ac 100644 Binary files a/src/main/resources/Linux/armv7/libjSerialComm.so and b/src/main/resources/Linux/armv7/libjSerialComm.so differ diff --git a/src/main/resources/Linux/x86/libjSerialComm.so b/src/main/resources/Linux/x86/libjSerialComm.so index 52e90f5..313404c 100644 Binary files a/src/main/resources/Linux/x86/libjSerialComm.so and b/src/main/resources/Linux/x86/libjSerialComm.so differ diff --git a/src/main/resources/Linux/x86_64/libjSerialComm.so b/src/main/resources/Linux/x86_64/libjSerialComm.so index ba539d2..49b150e 100644 Binary files a/src/main/resources/Linux/x86_64/libjSerialComm.so and b/src/main/resources/Linux/x86_64/libjSerialComm.so differ diff --git a/src/main/resources/OSX/x86/libjSerialComm.jnilib b/src/main/resources/OSX/x86/libjSerialComm.jnilib deleted file mode 100644 index 0efd3d6..0000000 Binary files a/src/main/resources/OSX/x86/libjSerialComm.jnilib and /dev/null differ diff --git a/src/main/resources/OSX/x86_64/libjSerialComm.jnilib b/src/main/resources/OSX/x86_64/libjSerialComm.jnilib deleted file mode 100644 index 0ee9a23..0000000 Binary files a/src/main/resources/OSX/x86_64/libjSerialComm.jnilib and /dev/null differ diff --git a/src/main/resources/Windows/x86/jSerialComm.dll b/src/main/resources/Windows/x86/jSerialComm.dll index f3f07fd..3f4247e 100644 Binary files a/src/main/resources/Windows/x86/jSerialComm.dll and b/src/main/resources/Windows/x86/jSerialComm.dll differ diff --git a/src/main/resources/Windows/x86/jSerialComm.exp b/src/main/resources/Windows/x86/jSerialComm.exp index a7c6a48..b1083ef 100644 Binary files a/src/main/resources/Windows/x86/jSerialComm.exp and b/src/main/resources/Windows/x86/jSerialComm.exp differ diff --git a/src/main/resources/Windows/x86/jSerialComm.lib b/src/main/resources/Windows/x86/jSerialComm.lib index d1f0c29..44c8d63 100644 Binary files a/src/main/resources/Windows/x86/jSerialComm.lib and b/src/main/resources/Windows/x86/jSerialComm.lib differ diff --git a/src/main/resources/Windows/x86_64/jSerialComm.dll b/src/main/resources/Windows/x86_64/jSerialComm.dll index 6e9e33c..9911153 100644 Binary files a/src/main/resources/Windows/x86_64/jSerialComm.dll and b/src/main/resources/Windows/x86_64/jSerialComm.dll differ diff --git a/src/main/resources/Windows/x86_64/jSerialComm.exp b/src/main/resources/Windows/x86_64/jSerialComm.exp index c70bfb2..fc978d9 100644 Binary files a/src/main/resources/Windows/x86_64/jSerialComm.exp and b/src/main/resources/Windows/x86_64/jSerialComm.exp differ diff --git a/src/main/resources/Windows/x86_64/jSerialComm.lib b/src/main/resources/Windows/x86_64/jSerialComm.lib index c3d304d..84c7ee9 100644 Binary files a/src/main/resources/Windows/x86_64/jSerialComm.lib and b/src/main/resources/Windows/x86_64/jSerialComm.lib differ diff --git a/src/test/java/com/fazecast/jSerialComm/SerialPortTest.java b/src/test/java/com/fazecast/jSerialComm/SerialPortTest.java index 7c6c13a..4af234b 100644 --- a/src/test/java/com/fazecast/jSerialComm/SerialPortTest.java +++ b/src/test/java/com/fazecast/jSerialComm/SerialPortTest.java @@ -32,7 +32,7 @@ import java.util.Scanner; * This class provides a test case for the jSerialComm library. * * @author Will Hedgecock <will.hedgecock@gmail.com> - * @version 1.3.2 + * @version 1.3.4 * @see java.io.InputStream * @see java.io.OutputStream */ @@ -173,6 +173,35 @@ public class SerialPortTest System.out.print((char)in.read()); in.close(); } catch (Exception e) { e.printStackTrace(); } + System.out.println("\n\nAttempting to read from two serial ports simultaneously\n"); + System.out.println("\nAvailable Ports:\n"); + for (int i = 0; i < ports.length; ++i) + System.out.println(" [" + i + "] " + ports[i].getSystemPortName() + ": " + ports[i].getDescriptivePortName()); + SerialPort ubxPort2; + System.out.print("\nChoose your second desired serial port, or enter -1 to skip this test: "); + serialPortChoice = 0; + try { serialPortChoice = (new Scanner(System.in)).nextInt(); } catch (Exception e) {} + if (serialPortChoice != -1) + { + ubxPort2 = ports[serialPortChoice]; + ubxPort2.openPort(); + try + { + System.out.print("\nReading from first serial port...\n\n"); + in = ubxPort.getInputStream(); + InputStream in2 = ubxPort2.getInputStream(); + for (int j = 0; j < 1000; ++j) + System.out.print((char)in.read()); + System.out.print("\nReading from second serial port...\n\n"); + for (int j = 0; j < 100; ++j) + System.out.print((char)in2.read()); + System.out.print("\nReading from first serial port again...\n\n"); + for (int j = 0; j < 1000; ++j) + System.out.print((char)in.read()); + in.close(); + in2.close(); + } catch (Exception e) { e.printStackTrace(); } + } System.out.println("\n\nEntering Java-based InputStream in Scanner mode and reading 200 lines\n"); ubxPort.setComPortTimeouts(SerialPort.TIMEOUT_SCANNER, 0, 0); Scanner scanner = new Scanner(ubxPort.getInputStream());