diff --git a/INSTALL b/INSTALL
index b6c95c8..75c0cb0 100644
--- a/INSTALL
+++ b/INSTALL
@@ -123,29 +123,29 @@ Maven:
com.fazecast
jSerialComm
- 1.3.8
+ 1.3.9
Ivy:
-
+
Groovy:
-@Grab(group='com.fazecast', module='jSerialComm', version='1.3.8')
+@Grab(group='com.fazecast', module='jSerialComm', version='1.3.9')
Gradle:
-compile 'com.fazecast:jSerialComm:1.3.8'
+compile 'com.fazecast:jSerialComm:1.3.9'
Buildr:
-compile.with 'com.fazecast:jSerialComm:jar:1.3.8'
+compile.with 'com.fazecast:jSerialComm:jar:1.3.9'
Scala/SBT:
-libraryDependencies += "com.fazecast" % "jSerialComm" % "1.3.8"
+libraryDependencies += "com.fazecast" % "jSerialComm" % "1.3.9"
Leiningen:
-[com.fazecast/jSerialComm "1.3.8"]
+[com.fazecast/jSerialComm "1.3.9"]
diff --git a/build.gradle b/build.gradle
index 3daeeb3..3997663 100644
--- a/build.gradle
+++ b/build.gradle
@@ -4,7 +4,7 @@ apply plugin: 'maven'
group = 'com.fazecast'
archivesBaseName = 'jSerialComm'
-version = '1.3.8'
+version = '1.3.9'
sourceCompatibility = 1.6
targetCompatibility = 1.6
diff --git a/src/main/c/Android/jni/Android.mk b/src/main/c/Android/jni/Android.mk
index 0379d18..afc3114 100644
--- a/src/main/c/Android/jni/Android.mk
+++ b/src/main/c/Android/jni/Android.mk
@@ -4,9 +4,10 @@ include $(CLEAR_VARS)
LOCAL_MODULE := jSerialComm
LOCAL_SRC_FILES := SerialPort_Android.c AndroidHelperFunctions.c
+LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
all:
cp -rf libs/* ../../resources/Android
- rm -rf libs obj/* obj
+ rm -rf libs/* libs obj
diff --git a/src/main/c/Android/jni/AndroidHelperFunctions.c b/src/main/c/Android/jni/AndroidHelperFunctions.c
index 75f527c..a0bceae 100644
--- a/src/main/c/Android/jni/AndroidHelperFunctions.c
+++ b/src/main/c/Android/jni/AndroidHelperFunctions.c
@@ -32,6 +32,8 @@
#include
#include
#include
+#include
+#include
#ifndef BOTHER
#include
#endif
@@ -245,18 +247,23 @@ void setBaudRate(int portFD, int baudRate)
{
#ifdef BOTHER
struct termios2 options = { 0 };
- ioctl(portFD, TCGETS2, &options);
+
+ if (isatty(portFD))
+ ioctl(portFD, TCGETS2, &options);
options.c_cflag &= ~CBAUD;
options.c_cflag |= BOTHER;
options.c_ispeed = baudRate;
options.c_ospeed = baudRate;
- ioctl(portFD, TCSETS2, &options);
+ if (isatty(portFD))
+ ioctl(portFD, TCSETS2, &options);
#else
struct termios options = { 0 };
- tcgetattr(portFD, &options);
+ if (isatty(portFD))
+ ioctl(portFD, TCGETS, &options);
cfsetispeed(&options, B38400);
cfsetospeed(&options, B38400);
- tcsetattr(portFD, TCSANOW, &options);
+ if (isatty(portFD))
+ ioctl(portFD, TCSETS, &options);
#endif
}
diff --git a/src/main/c/Android/jni/SerialPort_Android.c b/src/main/c/Android/jni/SerialPort_Android.c
index 5341179..9e17c18 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: May 19, 2015
+ * Last Updated on: Oct 09, 2015
* Author: Will Hedgecock
*
* Copyright (C) 2012-2015 Fazecast, Inc.
@@ -27,7 +27,9 @@
#ifndef CMSPAR
#define CMSPAR 010000000000
#endif
+#include
#include
+#include
#include
#include
#include
@@ -35,9 +37,15 @@
#include
#include
#include
+#include
+#include
#include "com_fazecast_jSerialComm_SerialPort.h"
#include "AndroidHelperFunctions.h"
+// Logging defines
+#define LOG_TAG "com.fazecast.jSerialComm"
+#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
+
// Cached class, method, and field IDs
jclass serialCommClass;
jmethodID serialCommConstructor;
@@ -104,7 +112,7 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrar
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_uninitializeLibrary(JNIEnv *env, jclass serialComm)
{
- // Delete the cache global reference
+ // Delete the cached global reference
(*env)->DeleteGlobalRef(env, serialCommClass);
}
@@ -124,7 +132,7 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(
else
{
// Close the port if there was a problem setting the parameters
- close(serialPortFD);
+ while ((close(serialPortFD) == -1) && (errno != EBADF));
serialPortFD = -1;
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
}
@@ -150,10 +158,12 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J
tcflag_t parity = (parityInt == com_fazecast_jSerialComm_SerialPort_NO_PARITY) ? 0 : (parityInt == com_fazecast_jSerialComm_SerialPort_ODD_PARITY) ? (PARENB | PARODD) : (parityInt == com_fazecast_jSerialComm_SerialPort_EVEN_PARITY) ? PARENB : (parityInt == com_fazecast_jSerialComm_SerialPort_MARK_PARITY) ? (PARENB | CMSPAR | PARODD) : (PARENB | CMSPAR);
// Clear any serial port flags
- fcntl(serialPortFD, F_SETFL, 0);
+ if (isatty(serialPortFD))
+ fcntl(serialPortFD, F_SETFL, 0);
- // Set raw-mode to allow the use of tcsetattr() and ioctl()
- tcgetattr(serialPortFD, &options);
+ // Set raw-mode to allow the use of ioctl()
+ if (isatty(serialPortFD))
+ ioctl(serialPortFD, TCGETS, &options);
cfmakeraw(&options);
// Set updated port parameters
@@ -175,8 +185,9 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J
}
// Apply changes
- int retVal = tcsetattr(serialPortFD, TCSANOW, &options);
- ioctl(serialPortFD, TIOCEXCL); // Block non-root users from using this port
+ int retVal = -1;
+ if (isatty(serialPortFD))
+ retVal = ioctl(serialPortFD, TCSETS, &options);
if (baudRateCode == 0) // Set custom baud rate
setBaudRate(serialPortFD, baudRate);
return ((retVal == 0) ? JNI_TRUE : JNI_FALSE);
@@ -198,14 +209,17 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowCo
tcflag_t XonXoffOutEnabled = ((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_XONXOFF_OUT_ENABLED) > 0) ? IXON : 0;
// Retrieve existing port configuration
- tcgetattr(serialPortFD, &options);
+ if (isatty(serialPortFD))
+ ioctl(serialPortFD, TCGETS, &options);
// Set updated port parameters
options.c_cflag |= CTSRTSEnabled;
options.c_iflag |= XonXoffInEnabled | XonXoffOutEnabled;
// Apply changes
- int retVal = tcsetattr(serialPortFD, TCSANOW, &options);
+ int retVal = -1;
+ if (isatty(serialPortFD))
+ retVal = ioctl(serialPortFD, TCSETS, &options);
if (baudRateCode == 0) // Set custom baud rate
setBaudRate(serialPortFD, baudRate);
return ((retVal == 0) ? JNI_TRUE : JNI_FALSE);
@@ -223,8 +237,11 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeou
// Retrieve existing port configuration
struct termios options = { 0 };
- tcgetattr(serialPortFD, &options);
+ if (isatty(serialPortFD))
+ ioctl(serialPortFD, TCGETS, &options);
int flags = fcntl(serialPortFD, F_GETFL);
+ if (flags == -1)
+ return JNI_FALSE;
// Set updated port timeouts
if (((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_SEMI_BLOCKING) > 0) && (readTimeout > 0)) // Read Semi-blocking with timeout
@@ -265,8 +282,9 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeou
}
// Apply changes
- fcntl(serialPortFD, F_SETFL, flags);
- int retVal = tcsetattr(serialPortFD, TCSANOW, &options);
+ int retVal = fcntl(serialPortFD, F_SETFL, flags);
+ if ((retVal != -1) && isatty(serialPortFD))
+ retVal = ioctl(serialPortFD, TCSETS, &options);
if (baudRateCode == 0) // Set custom baud rate
setBaudRate(serialPortFD, baudRate);
return ((retVal == 0) ? JNI_TRUE : JNI_FALSE);
@@ -283,24 +301,27 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventF
int eventsToMonitor = (*env)->GetIntField(env, obj, eventFlagsField);
// Change read timeouts if we are monitoring data received
+ jboolean retVal;
if ((eventsToMonitor & com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_RECEIVED) > 0)
{
struct termios options = { 0 };
- tcgetattr(serialPortFD, &options);
+ ioctl(serialPortFD, TCGETS, &options);
int flags = fcntl(serialPortFD, F_GETFL);
+ if (flags == -1)
+ return JNI_FALSE;
flags &= ~O_NONBLOCK;
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = 10;
- fcntl(serialPortFD, F_SETFL, flags);
- tcsetattr(serialPortFD, TCSANOW, &options);
+ retVal = ((fcntl(serialPortFD, F_SETFL, flags) == -1) || (ioctl(serialPortFD, TCSETS, &options) == -1)) ?
+ JNI_FALSE : JNI_TRUE;
if (baudRateCode == 0) // Set custom baud rate
setBaudRate(serialPortFD, baudRate);
}
else
- Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(env, obj, serialPortFD);
+ retVal = Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(env, obj, serialPortFD);
// Apply changes
- return JNI_TRUE;
+ return retVal;
}
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNIEnv *env, jobject obj, jlong serialPortFD)
@@ -315,7 +336,8 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNI
FD_SET(serialPortFD, &waitingSet);
// Wait for a serial port event
- int retVal = select(serialPortFD + 1, &waitingSet, NULL, NULL, &timeout);
+ int retVal;
+ do { retVal = select(serialPortFD + 1, &waitingSet, NULL, NULL, &timeout); } while ((retVal < 0) && (errno == EINTR));
if (retVal <= 0)
return 0;
return (FD_ISSET(serialPortFD, &waitingSet)) ? com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_AVAILABLE : 0;
@@ -326,7 +348,7 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNat
// Close port
if (serialPortFD <= 0)
return JNI_TRUE;
- close(serialPortFD);
+ while ((close(serialPortFD) == -1) && (errno != EBADF));
serialPortFD = -1;
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
@@ -359,10 +381,11 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
// While there are more bytes we are supposed to read
while (bytesRemaining > 0)
{
- if ((numBytesRead = read(serialPortFD, readBuffer+numBytesReadTotal, bytesRemaining)) == -1)
+ do { numBytesRead = read(serialPortFD, readBuffer+numBytesReadTotal, bytesRemaining); } while ((numBytesRead < 0) && (errno == EINTR));
+ if (numBytesRead == -1)
{
// Problem reading, close port
- close(serialPortFD);
+ while ((close(serialPortFD) == -1) && (errno != EBADF));
serialPortFD = -1;
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
@@ -389,10 +412,11 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
// While there are more bytes we are supposed to read and the timeout has not elapsed
do
{
- if ((numBytesRead = read(serialPortFD, readBuffer+numBytesReadTotal, bytesRemaining)) == -1)
+ do { numBytesRead = read(serialPortFD, readBuffer+numBytesReadTotal, bytesRemaining); } while ((numBytesRead < 0) && (errno == EINTR));
+ if (numBytesRead == -1)
{
// Problem reading, close port
- close(serialPortFD);
+ while ((close(serialPortFD) == -1) && (errno != EBADF));
serialPortFD = -1;
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
@@ -411,10 +435,11 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
else // Semi- or non-blocking specified
{
// Read from port
- if ((numBytesRead = read(serialPortFD, readBuffer, bytesToRead)) == -1)
+ do { numBytesRead = read(serialPortFD, readBuffer, bytesToRead); } while ((numBytesRead < 0) && (errno == EINTR));
+ if (numBytesRead == -1)
{
// Problem reading, close port
- close(serialPortFD);
+ while ((close(serialPortFD) == -1) && (errno != EBADF));
serialPortFD = -1;
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
@@ -437,10 +462,11 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn
int numBytesWritten;
// Write to port
- if ((numBytesWritten = write(serialPortFD, writeBuffer, bytesToWrite)) == -1)
+ do { numBytesWritten = write(serialPortFD, writeBuffer, bytesToWrite); } while ((numBytesWritten < 0) && (errno == EINTR));
+ if (numBytesWritten == -1)
{
// Problem writing, close port
- close(serialPortFD);
+ while ((close(serialPortFD) == -1) && (errno != EBADF));
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 17f91d2..333a0c2 100644
--- a/src/main/c/Android/jni/com_fazecast_jSerialComm_SerialPort.h
+++ b/src/main/c/Android/jni/com_fazecast_jSerialComm_SerialPort.h
@@ -87,6 +87,14 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_uninitializeLibr
JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative
(JNIEnv *, jobject);
+/*
+ * Class: com_fazecast_jSerialComm_SerialPort
+ * Method: associateNativeHandle
+ * Signature: (J)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_associateNativeHandle
+ (JNIEnv *, jobject, jlong);
+
/*
* Class: com_fazecast_jSerialComm_SerialPort
* Method: closePortNative
diff --git a/src/main/c/Linux/SerialPort_Linux.c b/src/main/c/Linux/SerialPort_Linux.c
index f55675a..8bbeb15 100644
--- a/src/main/c/Linux/SerialPort_Linux.c
+++ b/src/main/c/Linux/SerialPort_Linux.c
@@ -2,7 +2,7 @@
* SerialPort_Linux.c
*
* Created on: Feb 25, 2012
- * Last Updated on: May 04, 2015
+ * Last Updated on: Oct 09, 2015
* Author: Will Hedgecock
*
* Copyright (C) 2012-2015 Fazecast, Inc.
@@ -126,7 +126,9 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(
else
{
// Close the port if there was a problem setting the parameters
- close(serialPortFD);
+ ioctl(serialPortFD, TIOCNXCL);
+ tcdrain(serialPortFD);
+ while ((close(serialPortFD) == -1) && (errno != EBADF));
serialPortFD = -1;
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
}
@@ -179,7 +181,7 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J
// Apply changes
int retVal = tcsetattr(serialPortFD, TCSANOW, &options);
- ioctl(serialPortFD, TIOCEXCL); // Block non-root users from using this port
+ ioctl(serialPortFD, TIOCEXCL); // Block non-root users from opening this port
if (baudRateCode == 0) // Set custom baud rate
setBaudRate(serialPortFD, baudRate);
return ((retVal == 0) ? JNI_TRUE : JNI_FALSE);
@@ -228,6 +230,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeou
struct termios options = { 0 };
tcgetattr(serialPortFD, &options);
int flags = fcntl(serialPortFD, F_GETFL);
+ if (flags == -1)
+ return JNI_FALSE;
// Set updated port timeouts
if (((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_SEMI_BLOCKING) > 0) && (readTimeout > 0)) // Read Semi-blocking with timeout
@@ -268,8 +272,9 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeou
}
// Apply changes
- fcntl(serialPortFD, F_SETFL, flags);
- int retVal = tcsetattr(serialPortFD, TCSANOW, &options);
+ int retVal = fcntl(serialPortFD, F_SETFL, flags);
+ if (retVal != -1)
+ retVal = tcsetattr(serialPortFD, TCSANOW, &options);
if (baudRateCode == 0) // Set custom baud rate
setBaudRate(serialPortFD, baudRate);
return ((retVal == 0) ? JNI_TRUE : JNI_FALSE);
@@ -286,24 +291,27 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventF
int eventsToMonitor = (*env)->GetIntField(env, obj, eventFlagsField);
// Change read timeouts if we are monitoring data received
+ jboolean retVal;
if ((eventsToMonitor & com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_RECEIVED) > 0)
{
struct termios options = { 0 };
tcgetattr(serialPortFD, &options);
int flags = fcntl(serialPortFD, F_GETFL);
+ if (flags == -1)
+ return JNI_FALSE;
flags &= ~O_NONBLOCK;
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = 10;
- fcntl(serialPortFD, F_SETFL, flags);
- tcsetattr(serialPortFD, TCSANOW, &options);
+ retVal = ((fcntl(serialPortFD, F_SETFL, flags) == -1) || (tcsetattr(serialPortFD, TCSANOW, &options) == -1)) ?
+ JNI_FALSE : JNI_TRUE;
if (baudRateCode == 0) // Set custom baud rate
setBaudRate(serialPortFD, baudRate);
}
else
- Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(env, obj, serialPortFD);
+ retVal = Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(env, obj, serialPortFD);
// Apply changes
- return JNI_TRUE;
+ return retVal;
}
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNIEnv *env, jobject obj, jlong serialPortFD)
@@ -330,7 +338,11 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNat
// Close port
if (serialPortFD <= 0)
return JNI_TRUE;
- close(serialPortFD);
+
+ // Allow others to open this port
+ ioctl(serialPortFD, TIOCNXCL);
+ tcdrain(serialPortFD);
+ while ((close(serialPortFD) == -1) && (errno != EBADF));
serialPortFD = -1;
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
@@ -366,8 +378,10 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
do { numBytesRead = read(serialPortFD, readBuffer+numBytesReadTotal, bytesRemaining); } while ((numBytesRead < 0) && (errno == EINTR));
if (numBytesRead == -1)
{
- // Problem reading, close port
- close(serialPortFD);
+ // Problem reading, allow others to open the port and close it ourselves
+ ioctl(serialPortFD, TIOCNXCL);
+ tcdrain(serialPortFD);
+ while ((close(serialPortFD) == -1) && (errno != EBADF));
serialPortFD = -1;
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
@@ -397,8 +411,10 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
do { numBytesRead = read(serialPortFD, readBuffer+numBytesReadTotal, bytesRemaining); } while ((numBytesRead < 0) && (errno == EINTR));
if (numBytesRead == -1)
{
- // Problem reading, close port
- close(serialPortFD);
+ // Problem reading, allow others to open the port and close it ourselves
+ ioctl(serialPortFD, TIOCNXCL);
+ tcdrain(serialPortFD);
+ while ((close(serialPortFD) == -1) && (errno != EBADF));
serialPortFD = -1;
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
@@ -420,8 +436,10 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
do { numBytesRead = read(serialPortFD, readBuffer, bytesToRead); } while ((numBytesRead < 0) && (errno == EINTR));
if (numBytesRead == -1)
{
- // Problem reading, close port
- close(serialPortFD);
+ // Problem reading, allow others to open the port and close it ourselves
+ ioctl(serialPortFD, TIOCNXCL);
+ tcdrain(serialPortFD);
+ while ((close(serialPortFD) == -1) && (errno != EBADF));
serialPortFD = -1;
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
@@ -447,8 +465,10 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn
do { numBytesWritten = write(serialPortFD, writeBuffer, bytesToWrite); } while ((numBytesWritten < 0) && (errno == EINTR));
if (numBytesWritten == -1)
{
- // Problem writing, close port
- close(serialPortFD);
+ // Problem writing, allow others to open the port and close it ourselves
+ ioctl(serialPortFD, TIOCNXCL);
+ tcdrain(serialPortFD);
+ while ((close(serialPortFD) == -1) && (errno != EBADF));
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 10d5c8b..2bcacb1 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: July 1, 2015
+ * Last Updated on: Oct 09, 2015
* Author: Will Hedgecock
*
* Copyright (C) 2012-2015 Fazecast, Inc.
@@ -177,7 +177,9 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(
else
{
// Close the port if there was a problem setting the parameters
- close(serialPortFD);
+ ioctl(serialPortFD, TIOCNXCL);
+ tcdrain(serialPortFD);
+ while ((close(serialPortFD) == -1) && (errno != EBADF));
serialPortFD = -1;
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
}
@@ -273,6 +275,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeou
struct termios options;
tcgetattr(serialPortFD, &options);
int flags = fcntl(serialPortFD, F_GETFL);
+ if (flags == -1)
+ return JNI_FALSE;
// Set updated port timeouts
if (((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_SEMI_BLOCKING) > 0) && (readTimeout > 0)) // Read Semi-blocking with timeout
@@ -313,8 +317,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeou
}
// Apply changes
- fcntl(serialPortFD, F_SETFL, flags);
- return (tcsetattr(serialPortFD, TCSANOW, &options) == 0) ? JNI_TRUE : JNI_FALSE;
+ int retVal = fcntl(serialPortFD, F_SETFL, flags);
+ return ((retVal != -1) && (tcsetattr(serialPortFD, TCSANOW, &options) == 0)) ? JNI_TRUE : JNI_FALSE;
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(JNIEnv *env, jobject obj, jlong serialPortFD)
@@ -332,11 +336,13 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventF
struct termios options;
tcgetattr(serialPortFD, &options);
int flags = fcntl(serialPortFD, F_GETFL);
+ if (flags == -1)
+ return JNI_FALSE;
flags &= ~O_NONBLOCK;
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = 10;
- fcntl(serialPortFD, F_SETFL, flags);
- retVal = (tcsetattr(serialPortFD, TCSANOW, &options) == 0) ? JNI_TRUE : JNI_FALSE;
+ retVal = ((fcntl(serialPortFD, F_SETFL, flags) != -1) && (tcsetattr(serialPortFD, TCSANOW, &options) != -1)) ?
+ JNI_TRUE : JNI_FALSE;
}
else
retVal = Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(env, obj, serialPortFD);
@@ -368,8 +374,11 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNat
// Close port
if (serialPortFD <= 0)
return JNI_TRUE;
+
+ // Allow others to open the port and close it ourselves
+ ioctl(serialPortFD, TIOCNXCL);
tcdrain(serialPortFD);
- close(serialPortFD);
+ while ((close(serialPortFD) == -1) && (errno != EBADF));
serialPortFD = -1;
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
@@ -405,8 +414,10 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
do { numBytesRead = read(serialPortFD, readBuffer+numBytesReadTotal, bytesRemaining); } while ((numBytesRead < 0) && (errno == EINTR));
if (numBytesRead == -1)
{
- // Problem reading, close port
- close(serialPortFD);
+ // Problem reading, allow others to open the port and close it ourselves
+ ioctl(serialPortFD, TIOCNXCL);
+ tcdrain(serialPortFD);
+ while ((close(serialPortFD) == -1) && (errno != EBADF));
serialPortFD = -1;
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
@@ -436,8 +447,10 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
do { numBytesRead = read(serialPortFD, readBuffer+numBytesReadTotal, bytesRemaining); } while ((numBytesRead < 0) && (errno == EINTR));
if (numBytesRead == -1)
{
- // Problem reading, close port
- close(serialPortFD);
+ // Problem reading, allow others to open the port and close it ourselves
+ ioctl(serialPortFD, TIOCNXCL);
+ tcdrain(serialPortFD);
+ while ((close(serialPortFD) == -1) && (errno != EBADF));
serialPortFD = -1;
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
@@ -459,8 +472,10 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
do { numBytesRead = read(serialPortFD, readBuffer, bytesToRead); } while ((numBytesRead < 0) && (errno == EINTR));
if (numBytesRead == -1)
{
- // Problem reading, close port
- close(serialPortFD);
+ // Problem reading, allow others to open the port and close it ourselves
+ ioctl(serialPortFD, TIOCNXCL);
+ tcdrain(serialPortFD);
+ while ((close(serialPortFD) == -1) && (errno != EBADF));
serialPortFD = -1;
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
@@ -486,8 +501,10 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn
do { numBytesWritten = write(serialPortFD, writeBuffer, bytesToWrite); } while ((numBytesWritten < 0) && (errno == EINTR));
if (numBytesWritten == -1)
{
- // Problem writing, close port
- close(serialPortFD);
+ // Problem writing, allow others to open the port and close it ourselves
+ ioctl(serialPortFD, TIOCNXCL);
+ tcdrain(serialPortFD);
+ while ((close(serialPortFD) == -1) && (errno != EBADF));
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 046cfa7..5e851ea 100644
--- a/src/main/c/Windows/SerialPort_Windows.c
+++ b/src/main/c/Windows/SerialPort_Windows.c
@@ -263,7 +263,8 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(
else
{
// Close the port if there was a problem setting the parameters
- CloseHandle(serialPortHandle);
+ PurgeComm(serialPortHandle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
+ while (!CloseHandle(serialPortHandle));
serialPortHandle = INVALID_HANDLE_VALUE;
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
}
@@ -474,7 +475,8 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNI
if (GetLastError() != ERROR_IO_PENDING) // Problem occurred
{
// Problem reading, close port
- CloseHandle(serialPortHandle);
+ PurgeComm(serialPortHandle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
+ while (!CloseHandle(serialPortHandle));
serialPortHandle = INVALID_HANDLE_VALUE;
env->SetLongField(obj, serialPortHandleField, -1l);
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
@@ -498,12 +500,12 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNat
PurgeComm(serialPortHandle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
// Close port
- BOOL retVal = CloseHandle(serialPortHandle);
+ while (!CloseHandle(serialPortHandle));
serialPortHandle = INVALID_HANDLE_VALUE;
env->SetLongField(obj, serialPortHandleField, -1l);
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
- return (retVal == 0) ? JNI_FALSE : JNI_TRUE;
+ return JNI_TRUE;
}
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(JNIEnv *env, jobject obj, jlong serialPortFD)
@@ -542,7 +544,8 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
if (GetLastError() != ERROR_IO_PENDING) // Problem occurred
{
// Problem reading, close port
- CloseHandle(serialPortHandle);
+ PurgeComm(serialPortHandle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
+ while (!CloseHandle(serialPortHandle));
serialPortHandle = INVALID_HANDLE_VALUE;
env->SetLongField(obj, serialPortHandleField, -1l);
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
@@ -550,7 +553,8 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
else if ((result = GetOverlappedResult(serialPortHandle, &overlappedStruct, &numBytesRead, TRUE)) == FALSE)
{
// Problem reading, close port
- CloseHandle(serialPortHandle);
+ PurgeComm(serialPortHandle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
+ while (!CloseHandle(serialPortHandle));
serialPortHandle = INVALID_HANDLE_VALUE;
env->SetLongField(obj, serialPortHandleField, -1l);
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
@@ -586,7 +590,8 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn
if (GetLastError() != ERROR_IO_PENDING)
{
// Problem writing, close port
- CloseHandle(serialPortHandle);
+ PurgeComm(serialPortHandle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
+ while (!CloseHandle(serialPortHandle));
serialPortHandle = INVALID_HANDLE_VALUE;
env->SetLongField(obj, serialPortHandleField, -1l);
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
@@ -594,7 +599,8 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn
else if ((result = GetOverlappedResult(serialPortHandle, &overlappedStruct, &numBytesWritten, TRUE)) == FALSE)
{
// Problem reading, close port
- CloseHandle(serialPortHandle);
+ PurgeComm(serialPortHandle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
+ while (!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/SerialPortDataListener.java b/src/main/java/com/fazecast/jSerialComm/SerialPortDataListener.java
index f195e44..29d9789 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.8
+ * @version 1.3.9
* @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 1a48e84..b78c32b 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.8
+ * @version 1.3.9
* @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 2d34e0f..fa6e8fe 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.8
+ * @version 1.3.9
* @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 69ca98e..796fdae 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 d1fbbfe..76df292 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 2f3ef77..00b5906 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 f91e7bd..764c7ff 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 d456d62..a503d4c 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 a5075b8..d218b02 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 289932f..26e27d6 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 e2e97ea..d6a4900 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 dc42eb8..88e2861 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 b1f4c2a..fd7bd06 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 3669a83..cf1163b 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 21d8430..9990bfc 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 a1d864c..e91fe41 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 fd57cde..c5010c3 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/test/java/com/fazecast/jSerialComm/SerialPortTest.java b/src/test/java/com/fazecast/jSerialComm/SerialPortTest.java
index 54ac6b1..044826b 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.8
+ * @version 1.3.9
* @see java.io.InputStream
* @see java.io.OutputStream
*/