diff --git a/src/main/c/Posix/SerialPort_Posix.c b/src/main/c/Posix/SerialPort_Posix.c index bab110d..9e48765 100644 --- a/src/main/c/Posix/SerialPort_Posix.c +++ b/src/main/c/Posix/SerialPort_Posix.c @@ -2,7 +2,7 @@ * SerialPort_Posix.c * * Created on: Feb 25, 2012 - * Last Updated on: Feb 14, 2022 + * Last Updated on: Feb 15, 2022 * Author: Will Hedgecock * * Copyright (C) 2012-2022 Fazecast, Inc. @@ -79,8 +79,9 @@ jfieldID readTimeoutField; jfieldID writeTimeoutField; jfieldID eventFlagsField; -// List of available serial ports +// Global list of available serial ports char portsEnumerated = 0; +pthread_mutex_t criticalSection; serialPortVector serialPorts = { NULL, 0, 0 }; // JNI exception handler @@ -240,30 +241,36 @@ void* eventReadingThread2(void *serialPortPointer) JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommPorts(JNIEnv *env, jclass serialComm) { + // Mark this entire function as a critical section + pthread_mutex_lock(&criticalSection); + // Enumerate all ports on the current system enumeratePorts(); // Create a Java-based port listing jobjectArray arrayObject = (*env)->NewObjectArray(env, serialPorts.length, serialCommClass, 0); - if (checkJniError(env, __LINE__ - 1)) return arrayObject; - for (int i = 0; i < serialPorts.length; ++i) + char stopLooping = checkJniError(env, __LINE__ - 1) ? 1 : 0; + for (int i = 0; !stopLooping && (i < serialPorts.length); ++i) { // Create a new SerialComm object containing the enumerated values jobject serialCommObject = (*env)->NewObject(env, serialCommClass, serialCommConstructor); - if (checkJniError(env, __LINE__ - 1)) return arrayObject; + if (checkJniError(env, __LINE__ - 1)) stopLooping = 1; (*env)->SetObjectField(env, serialCommObject, portDescriptionField, (*env)->NewStringUTF(env, serialPorts.ports[i]->portDescription)); - if (checkJniError(env, __LINE__ - 1)) return arrayObject; + if (checkJniError(env, __LINE__ - 1)) stopLooping = 1; (*env)->SetObjectField(env, serialCommObject, friendlyNameField, (*env)->NewStringUTF(env, serialPorts.ports[i]->friendlyName)); - if (checkJniError(env, __LINE__ - 1)) return arrayObject; + if (checkJniError(env, __LINE__ - 1)) stopLooping = 1; (*env)->SetObjectField(env, serialCommObject, comPortField, (*env)->NewStringUTF(env, serialPorts.ports[i]->portPath)); - if (checkJniError(env, __LINE__ - 1)) return arrayObject; + if (checkJniError(env, __LINE__ - 1)) stopLooping = 1; (*env)->SetObjectField(env, serialCommObject, portLocationField, (*env)->NewStringUTF(env, serialPorts.ports[i]->portLocation)); - if (checkJniError(env, __LINE__ - 1)) return arrayObject; + if (checkJniError(env, __LINE__ - 1)) stopLooping = 1; // Add new SerialComm object to array (*env)->SetObjectArrayElement(env, arrayObject, i, serialCommObject); - if (checkJniError(env, __LINE__ - 1)) return arrayObject; + if (checkJniError(env, __LINE__ - 1)) stopLooping = 1; } + + // Exit critical section and return the com port array + pthread_mutex_unlock(&criticalSection); return arrayObject; } @@ -354,6 +361,9 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrar sigaction(SIGUSR2, &ignoreAction, NULL); sigaction(SIGTTOU, &ignoreAction, NULL); sigaction(SIGTTIN, &ignoreAction, NULL); + + // Initialize the critical section lock + pthread_mutex_init(&criticalSection, NULL); } JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_uninitializeLibrary(JNIEnv *env, jclass serialComm) @@ -366,6 +376,9 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_uninitializeLibr // Delete the cached global reference (*env)->DeleteGlobalRef(env, serialCommClass); checkJniError(env, __LINE__ - 1); + + // Delete the critical section lock + pthread_mutex_destroy(&criticalSection); } JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_retrievePortDetails(JNIEnv *env, jobject obj) @@ -377,25 +390,33 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_retrievePortDeta if (checkJniError(env, __LINE__ - 1)) return; // Ensure that the serial port exists + char continueRetrieval = 1; + pthread_mutex_lock(&criticalSection); if (!portsEnumerated) enumeratePorts(); serialPort *port = fetchPort(&serialPorts, portName); if (!port) - { - (*env)->ReleaseStringUTFChars(env, portNameJString, portName); - checkJniError(env, __LINE__ - 1); - return; - } + continueRetrieval = 0; // Fill in the Java-side port details - (*env)->SetObjectField(env, obj, portDescriptionField, (*env)->NewStringUTF(env, port->portDescription)); - if (checkJniError(env, __LINE__ - 1)) return; - (*env)->SetObjectField(env, obj, friendlyNameField, (*env)->NewStringUTF(env, port->friendlyName)); - if (checkJniError(env, __LINE__ - 1)) return; - (*env)->SetObjectField(env, obj, portLocationField, (*env)->NewStringUTF(env, port->portLocation)); - if (checkJniError(env, __LINE__ - 1)) return; + if (continueRetrieval) + { + (*env)->SetObjectField(env, obj, portDescriptionField, (*env)->NewStringUTF(env, port->portDescription)); + if (checkJniError(env, __LINE__ - 1)) continueRetrieval = 0; + } + if (continueRetrieval) + { + (*env)->SetObjectField(env, obj, friendlyNameField, (*env)->NewStringUTF(env, port->friendlyName)); + if (checkJniError(env, __LINE__ - 1)) continueRetrieval = 0; + } + if (continueRetrieval) + { + (*env)->SetObjectField(env, obj, portLocationField, (*env)->NewStringUTF(env, port->portLocation)); + if (checkJniError(env, __LINE__ - 1)) continueRetrieval = 0; + } // Release all JNI structures + pthread_mutex_unlock(&criticalSection); (*env)->ReleaseStringUTFChars(env, portNameJString, portName); checkJniError(env, __LINE__ - 1); } @@ -405,8 +426,6 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative( // Retrieve the serial port parameter fields jstring portNameJString = (jstring)(*env)->GetObjectField(env, obj, comPortField); if (checkJniError(env, __LINE__ - 1)) return 0; - const char *portName = (*env)->GetStringUTFChars(env, portNameJString, NULL); - if (checkJniError(env, __LINE__ - 1)) return 0; unsigned char disableExclusiveLock = (*env)->GetBooleanField(env, obj, disableExclusiveLockField); if (checkJniError(env, __LINE__ - 1)) return 0; unsigned char requestElevatedPermissions = (*env)->GetBooleanField(env, obj, requestElevatedPermissionsField); @@ -415,14 +434,18 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative( if (checkJniError(env, __LINE__ - 1)) return 0; unsigned char autoFlushIOBuffers = (*env)->GetBooleanField(env, obj, autoFlushIOBuffersField); if (checkJniError(env, __LINE__ - 1)) return 0; + const char *portName = (*env)->GetStringUTFChars(env, portNameJString, NULL); + if (checkJniError(env, __LINE__ - 1)) return 0; // Ensure that the serial port still exists and is not already open + pthread_mutex_lock(&criticalSection); serialPort *port = fetchPort(&serialPorts, portName); if (!port) { // Create port representation and add to serial port listing port = pushBack(&serialPorts, portName, "User-Specified Port", "User-Specified Port", "0-0"); } + pthread_mutex_unlock(&criticalSection); if (!port || (port->handle > 0)) { (*env)->ReleaseStringUTFChars(env, portNameJString, portName); @@ -437,17 +460,21 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative( verifyAndSetUserPortGroup(portName); // Try to open the serial port with read/write access + pthread_mutex_lock(&criticalSection); port->errorLineNumber = lastErrorLineNumber = __LINE__ + 1; if ((port->handle = open(portName, O_RDWR | O_NOCTTY | O_NONBLOCK | O_CLOEXEC)) > 0) { // Ensure that multiple root users cannot access the device simultaneously + pthread_mutex_unlock(&criticalSection); if (!disableExclusiveLock && flock(port->handle, LOCK_EX | LOCK_NB)) { port->errorLineNumber = lastErrorLineNumber = __LINE__ - 2; port->errorNumber = lastErrorNumber = errno; while (close(port->handle) && (errno == EINTR)) errno = 0; + pthread_mutex_lock(&criticalSection); port->handle = -1; + pthread_mutex_unlock(&criticalSection); } else if (!disableAutoConfig && !Java_com_fazecast_jSerialComm_SerialPort_configPort(env, obj, (jlong)(intptr_t)port)) { @@ -455,7 +482,9 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative( fcntl(port->handle, F_SETFL, O_NONBLOCK); while (close(port->handle) && (errno == EINTR)) errno = 0; + pthread_mutex_lock(&criticalSection); port->handle = -1; + pthread_mutex_unlock(&criticalSection); } else if (autoFlushIOBuffers) { @@ -466,7 +495,10 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative( } } else + { port->errorNumber = lastErrorNumber = errno; + pthread_mutex_unlock(&criticalSection); + } // Return a pointer to the serial port data structure (*env)->ReleaseStringUTFChars(env, portNameJString, portName); @@ -808,7 +840,9 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNative flock(port->handle, LOCK_UN | LOCK_NB); while (close(port->handle) && (errno == EINTR)) errno = 0; + pthread_mutex_lock(&criticalSection); port->handle = -1; + pthread_mutex_unlock(&criticalSection); return 0; } diff --git a/src/main/c/Windows/SerialPort_Windows.c b/src/main/c/Windows/SerialPort_Windows.c index 3ec5ae1..a95c0be 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: Jan 28, 2022 + * Last Updated on: Feb 15, 2022 * Author: Will Hedgecock * * Copyright (C) 2012-2022 Fazecast, Inc. @@ -78,8 +78,9 @@ jfieldID eventFlagsField; typedef int (__stdcall *FT_CreateDeviceInfoListFunction)(LPDWORD); typedef int (__stdcall *FT_GetDeviceInfoListFunction)(FT_DEVICE_LIST_INFO_NODE*, LPDWORD); -// List of available serial ports +// Global list of available serial ports char portsEnumerated = 0; +CRITICAL_SECTION criticalSection; serialPortVector serialPorts = { NULL, 0, 0 }; // JNI exception handler @@ -320,31 +321,37 @@ static void enumeratePorts(void) JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommPorts(JNIEnv *env, jclass serialComm) { + // Mark this entire function as a critical section + EnterCriticalSection(&criticalSection); + // Enumerate all ports on the current system enumeratePorts(); // Get relevant SerialComm methods and fill in com port array wchar_t comPort[128]; jobjectArray arrayObject = (*env)->NewObjectArray(env, serialPorts.length, serialCommClass, 0); - if (checkJniError(env, __LINE__ - 1)) return arrayObject; - for (int i = 0; i < serialPorts.length; ++i) + char stopLooping = checkJniError(env, __LINE__ - 1) ? 1 : 0; + for (int i = 0; !stopLooping && (i < serialPorts.length); ++i) { // Create new SerialComm object containing the enumerated values jobject serialCommObject = (*env)->NewObject(env, serialCommClass, serialCommConstructor); - if (checkJniError(env, __LINE__ - 1)) return arrayObject; + if (checkJniError(env, __LINE__ - 1)) stopLooping = 1; (*env)->SetObjectField(env, serialCommObject, comPortField, (*env)->NewString(env, (jchar*)serialPorts.ports[i]->portPath, wcslen(serialPorts.ports[i]->portPath))); - if (checkJniError(env, __LINE__ - 1)) return arrayObject; + if (checkJniError(env, __LINE__ - 1)) stopLooping = 1; (*env)->SetObjectField(env, serialCommObject, friendlyNameField, (*env)->NewString(env, (jchar*)serialPorts.ports[i]->friendlyName, wcslen(serialPorts.ports[i]->friendlyName))); - if (checkJniError(env, __LINE__ - 1)) return arrayObject; + if (checkJniError(env, __LINE__ - 1)) stopLooping = 1; (*env)->SetObjectField(env, serialCommObject, portDescriptionField, (*env)->NewString(env, (jchar*)serialPorts.ports[i]->portDescription, wcslen(serialPorts.ports[i]->portDescription))); - if (checkJniError(env, __LINE__ - 1)) return arrayObject; + if (checkJniError(env, __LINE__ - 1)) stopLooping = 1; (*env)->SetObjectField(env, serialCommObject, portLocationField, (*env)->NewString(env, (jchar*)serialPorts.ports[i]->portLocation, wcslen(serialPorts.ports[i]->portLocation))); - if (checkJniError(env, __LINE__ - 1)) return arrayObject; + if (checkJniError(env, __LINE__ - 1)) stopLooping = 1; // Add new SerialComm object to array (*env)->SetObjectArrayElement(env, arrayObject, i, serialCommObject); - if (checkJniError(env, __LINE__ - 1)) return arrayObject; + if (checkJniError(env, __LINE__ - 1)) stopLooping = 1; } + + // Exit critical section and return the com port array + LeaveCriticalSection(&criticalSection); return arrayObject; } @@ -412,6 +419,9 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrar if (checkJniError(env, __LINE__ - 1)) return; eventFlagsField = (*env)->GetFieldID(env, serialCommClass, "eventFlags", "I"); if (checkJniError(env, __LINE__ - 1)) return; + + // Initialize the critical section lock + InitializeCriticalSection(&criticalSection); } JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_uninitializeLibrary(JNIEnv *env, jclass serialComm) @@ -424,6 +434,9 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_uninitializeLibr // Delete the cached global reference (*env)->DeleteGlobalRef(env, serialCommClass); checkJniError(env, __LINE__ - 1); + + // Delete the critical section lock + DeleteCriticalSection(&criticalSection); } JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_retrievePortDetails(JNIEnv *env, jobject obj) @@ -435,25 +448,33 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_retrievePortDeta if (checkJniError(env, __LINE__ - 1)) return; // Ensure that the serial port exists + char continueRetrieval = 1; + EnterCriticalSection(&criticalSection); if (!portsEnumerated) enumeratePorts(); serialPort *port = fetchPort(&serialPorts, portName); if (!port) - { - (*env)->ReleaseStringChars(env, portNameJString, (const jchar*)portName); - checkJniError(env, __LINE__ - 1); - return; - } + continueRetrieval = 0; // Fill in the Java-side port details - (*env)->SetObjectField(env, obj, friendlyNameField, (*env)->NewString(env, (jchar*)port->friendlyName, wcslen(port->friendlyName))); - if (checkJniError(env, __LINE__ - 1)) return; - (*env)->SetObjectField(env, obj, portDescriptionField, (*env)->NewString(env, (jchar*)port->portDescription, wcslen(port->portDescription))); - if (checkJniError(env, __LINE__ - 1)) return; - (*env)->SetObjectField(env, obj, portLocationField, (*env)->NewString(env, (jchar*)port->portLocation, wcslen(port->portLocation))); - if (checkJniError(env, __LINE__ - 1)) return; + if (continueRetrieval) + { + (*env)->SetObjectField(env, obj, friendlyNameField, (*env)->NewString(env, (jchar*)port->friendlyName, wcslen(port->friendlyName))); + if (checkJniError(env, __LINE__ - 1)) continueRetrieval = 0; + } + if (continueRetrieval) + { + (*env)->SetObjectField(env, obj, portDescriptionField, (*env)->NewString(env, (jchar*)port->portDescription, wcslen(port->portDescription))); + if (checkJniError(env, __LINE__ - 1)) continueRetrieval = 0; + } + if (continueRetrieval) + { + (*env)->SetObjectField(env, obj, portLocationField, (*env)->NewString(env, (jchar*)port->portLocation, wcslen(port->portLocation))); + if (checkJniError(env, __LINE__ - 1)) continueRetrieval = 0; + } // Release all JNI structures + LeaveCriticalSection(&criticalSection); (*env)->ReleaseStringChars(env, portNameJString, (const jchar*)portName); checkJniError(env, __LINE__ - 1); } @@ -463,22 +484,24 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative( // Retrieve the serial port parameter fields jstring portNameJString = (jstring)(*env)->GetObjectField(env, obj, comPortField); if (checkJniError(env, __LINE__ - 1)) return 0; - const wchar_t *portName = (wchar_t*)(*env)->GetStringChars(env, portNameJString, NULL); - if (checkJniError(env, __LINE__ - 1)) return 0; unsigned char requestElevatedPermissions = (*env)->GetBooleanField(env, obj, requestElevatedPermissionsField); if (checkJniError(env, __LINE__ - 1)) return 0; unsigned char disableAutoConfig = (*env)->GetBooleanField(env, obj, disableConfigField); if (checkJniError(env, __LINE__ - 1)) return 0; unsigned char autoFlushIOBuffers = (*env)->GetBooleanField(env, obj, autoFlushIOBuffersField); if (checkJniError(env, __LINE__ - 1)) return 0; + const wchar_t *portName = (wchar_t*)(*env)->GetStringChars(env, portNameJString, NULL); + if (checkJniError(env, __LINE__ - 1)) return 0; // Ensure that the serial port still exists and is not already open + EnterCriticalSection(&criticalSection); serialPort *port = fetchPort(&serialPorts, portName); if (!port) { // Create port representation and add to serial port listing port = pushBack(&serialPorts, portName, L"User-Specified Port", L"User-Specified Port", L"0-0"); } + LeaveCriticalSection(&criticalSection); if (!port || (port->handle != INVALID_HANDLE_VALUE)) { (*env)->ReleaseStringChars(env, portNameJString, (const jchar*)portName); @@ -492,9 +515,12 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative( reduceLatencyToMinimum(portName + 4, requestElevatedPermissions); // Try to open the serial port with read/write access + EnterCriticalSection(&criticalSection); + port->errorLineNumber = lastErrorLineNumber = __LINE__ + 1; if ((port->handle = CreateFileW(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 + LeaveCriticalSection(&criticalSection); if (!disableAutoConfig && !Java_com_fazecast_jSerialComm_SerialPort_configPort(env, obj, (jlong)(intptr_t)port)) { // Close the port if there was a problem setting the parameters @@ -502,15 +528,17 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative( CancelIoEx(port->handle, NULL); SetCommMask(port->handle, 0); CloseHandle(port->handle); + EnterCriticalSection(&criticalSection); port->handle = INVALID_HANDLE_VALUE; + LeaveCriticalSection(&criticalSection); } else if (autoFlushIOBuffers) Java_com_fazecast_jSerialComm_SerialPort_flushRxTxBuffers(env, obj, (jlong)(intptr_t)port); } else { - port->errorLineNumber = lastErrorLineNumber = __LINE__ - 15; port->errorNumber = lastErrorNumber = GetLastError(); + LeaveCriticalSection(&criticalSection); } // Return a pointer to the serial port data structure @@ -790,14 +818,15 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNative // Purge any outstanding port operations PurgeComm(port->handle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR); CancelIoEx(port->handle, NULL); - FlushFileBuffers(port->handle); SetCommMask(port->handle, 0); // Close the port port->eventListenerRunning = 0; port->errorLineNumber = lastErrorLineNumber = __LINE__ + 1; port->errorNumber = lastErrorNumber = (!CloseHandle(port->handle) ? GetLastError() : 0); + EnterCriticalSection(&criticalSection); port->handle = INVALID_HANDLE_VALUE; + LeaveCriticalSection(&criticalSection); return 0; } diff --git a/src/main/java/com/fazecast/jSerialComm/SerialPort.java b/src/main/java/com/fazecast/jSerialComm/SerialPort.java index 0e21a05..83e8302 100644 --- a/src/main/java/com/fazecast/jSerialComm/SerialPort.java +++ b/src/main/java/com/fazecast/jSerialComm/SerialPort.java @@ -2,7 +2,7 @@ * SerialPort.java * * Created on: Feb 25, 2012 - * Last Updated on: Feb 14, 2022 + * Last Updated on: Feb 15, 2022 * Author: Will Hedgecock * * Copyright (C) 2012-2022 Fazecast, Inc. @@ -444,10 +444,16 @@ public final class SerialPort *
* The serial ports can be accessed by iterating through each of the SerialPort objects in this array. *
- * Note that the {@link #openPort()} method must be called before any attempts to read from or write to the port. + * Note that the array will also include any serial ports that your application currently has open, even if + * the devices attached to those ports become disconnected. As such, it is important that you always call + * {@link #closePort()} on a SerialPort object if it becomes disconnected, which is detectable by inspecting + * the return values from the various read calls or by registering a {@link SerialPortDataListener} for the + * {@link SerialPort#LISTENING_EVENT_PORT_DISCONNECTED} event. + *
+ * The {@link #openPort()} method must be called before any attempts to read from or write to the port. * Likewise, {@link #closePort()} should be called when you are finished accessing the port. *
- * Also note that repeated calls to this function will re-enumerate all serial ports and will return a completely + * Note that repeated calls to this function will re-enumerate all serial ports and will return a completely * unique set of array objects. As such, you should store a reference to the serial port object(s) you are * interested in in your own application code. *
@@ -501,9 +507,7 @@ public final class SerialPort serialPort.friendlyName = "User-Specified Port"; serialPort.portDescription = "User-Specified Port"; serialPort.portLocation = "0-0"; - synchronized (SerialPort.class) { - serialPort.retrievePortDetails(); - } + serialPort.retrievePortDetails(); return serialPort; } @@ -629,13 +633,8 @@ public final class SerialPort } } - // Natively open the serial port, and synchronize to the class scope since port enumeration methods are class-based, - // and this method may alter or read a global class structure in native code - synchronized (SerialPort.class) { - portHandle = openPortNative(); - } - - // Start an event-based listener if registered and the port is open + // Natively open the serial port, and start an event-based listener if registered + portHandle = openPortNative(); if ((portHandle != 0) && (serialEventListener != null)) serialEventListener.startListening(); return (portHandle != 0); @@ -689,14 +688,9 @@ public final class SerialPort if (serialEventListener != null) serialEventListener.stopListening(); - // Natively close the port, and synchronize to the class scope since port enumeration methods are class-based, - // and this method may alter or read a global class structure in native code + // Natively close the port if (portHandle != 0) - { - synchronized (SerialPort.class) { - portHandle = closePortNative(portHandle); - } - } + portHandle = closePortNative(portHandle); return (portHandle == 0); } @@ -751,8 +745,8 @@ public final class SerialPort * Returns the source code line location of the latest error encountered during execution of * the native code for this port. *
- * This function must be called while the port is still open as soon as an error is encountered, - * or it may return an incorrect source code line location. + * This function must be called as soon as an error is encountered, or it may return an incorrect source + * code line location. * * @return Source line of latest native code error. */ @@ -761,8 +755,8 @@ public final class SerialPort /** * Returns the error number returned by the most recent native source code line that failed execution. *
- * This function must be called while the port is still open as soon as an error is encountered, - * or it may return an incorrect or invalid error code. + * This function must be called as soon as an error is encountered, or it may return an incorrect or + * invalid error code. * * @return Error number of the latest native code error. */ diff --git a/src/main/resources/Android/arm64-v8a/libjSerialComm.so b/src/main/resources/Android/arm64-v8a/libjSerialComm.so index 706b549..abed6eb 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 806e621..b71460e 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/x86/libjSerialComm.so b/src/main/resources/Android/x86/libjSerialComm.so index f070d25..ef1fce4 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 5d18c18..cd1f158 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/FreeBSD/arm64/libjSerialComm.so b/src/main/resources/FreeBSD/arm64/libjSerialComm.so index 5016209..9e0c448 100644 Binary files a/src/main/resources/FreeBSD/arm64/libjSerialComm.so and b/src/main/resources/FreeBSD/arm64/libjSerialComm.so differ diff --git a/src/main/resources/FreeBSD/x86/libjSerialComm.so b/src/main/resources/FreeBSD/x86/libjSerialComm.so index 4d15458..e1b21d8 100644 Binary files a/src/main/resources/FreeBSD/x86/libjSerialComm.so and b/src/main/resources/FreeBSD/x86/libjSerialComm.so differ diff --git a/src/main/resources/FreeBSD/x86_64/libjSerialComm.so b/src/main/resources/FreeBSD/x86_64/libjSerialComm.so index 4b7e2cb..775b8c6 100644 Binary files a/src/main/resources/FreeBSD/x86_64/libjSerialComm.so and b/src/main/resources/FreeBSD/x86_64/libjSerialComm.so differ diff --git a/src/main/resources/Linux/armv5/libjSerialComm.so b/src/main/resources/Linux/armv5/libjSerialComm.so index ae540d9..e4d2e19 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/libjSerialComm.so b/src/main/resources/Linux/armv6/libjSerialComm.so index 3379f1d..e2d1b97 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/armv6hf/libjSerialComm.so b/src/main/resources/Linux/armv6hf/libjSerialComm.so index 7aa48bd..976b33b 100644 Binary files a/src/main/resources/Linux/armv6hf/libjSerialComm.so and b/src/main/resources/Linux/armv6hf/libjSerialComm.so differ diff --git a/src/main/resources/Linux/armv7/libjSerialComm.so b/src/main/resources/Linux/armv7/libjSerialComm.so index 1c4c50e..f0e9390 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/armv7hf/libjSerialComm.so b/src/main/resources/Linux/armv7hf/libjSerialComm.so index 1570ff1..ec97a34 100644 Binary files a/src/main/resources/Linux/armv7hf/libjSerialComm.so and b/src/main/resources/Linux/armv7hf/libjSerialComm.so differ diff --git a/src/main/resources/Linux/armv8_32/libjSerialComm.so b/src/main/resources/Linux/armv8_32/libjSerialComm.so index ddff21b..e12978e 100644 Binary files a/src/main/resources/Linux/armv8_32/libjSerialComm.so and b/src/main/resources/Linux/armv8_32/libjSerialComm.so differ diff --git a/src/main/resources/Linux/armv8_64/libjSerialComm.so b/src/main/resources/Linux/armv8_64/libjSerialComm.so index 2e88884..be0a22a 100644 Binary files a/src/main/resources/Linux/armv8_64/libjSerialComm.so and b/src/main/resources/Linux/armv8_64/libjSerialComm.so differ diff --git a/src/main/resources/Linux/ppc64le/libjSerialComm.so b/src/main/resources/Linux/ppc64le/libjSerialComm.so index 8a79136..ed0cbcf 100644 Binary files a/src/main/resources/Linux/ppc64le/libjSerialComm.so and b/src/main/resources/Linux/ppc64le/libjSerialComm.so differ diff --git a/src/main/resources/Linux/x86/libjSerialComm.so b/src/main/resources/Linux/x86/libjSerialComm.so index de27a84..90b5022 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 18f3d83..9528ae0 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/aarch64/libjSerialComm.jnilib b/src/main/resources/OSX/aarch64/libjSerialComm.jnilib index 9feda04..c4d9c19 100755 Binary files a/src/main/resources/OSX/aarch64/libjSerialComm.jnilib and b/src/main/resources/OSX/aarch64/libjSerialComm.jnilib differ diff --git a/src/main/resources/OSX/x86/libjSerialComm.jnilib b/src/main/resources/OSX/x86/libjSerialComm.jnilib index 04fe402..2f5430f 100644 Binary files a/src/main/resources/OSX/x86/libjSerialComm.jnilib and b/src/main/resources/OSX/x86/libjSerialComm.jnilib differ diff --git a/src/main/resources/OSX/x86_64/libjSerialComm.jnilib b/src/main/resources/OSX/x86_64/libjSerialComm.jnilib index 25c61ff..9eca7c8 100755 Binary files a/src/main/resources/OSX/x86_64/libjSerialComm.jnilib and b/src/main/resources/OSX/x86_64/libjSerialComm.jnilib differ diff --git a/src/main/resources/OpenBSD/amd64/libjSerialComm.so b/src/main/resources/OpenBSD/amd64/libjSerialComm.so index 84ae575..ad89aa5 100644 Binary files a/src/main/resources/OpenBSD/amd64/libjSerialComm.so and b/src/main/resources/OpenBSD/amd64/libjSerialComm.so differ diff --git a/src/main/resources/OpenBSD/x86/libjSerialComm.so b/src/main/resources/OpenBSD/x86/libjSerialComm.so index d6191bb..be24602 100644 Binary files a/src/main/resources/OpenBSD/x86/libjSerialComm.so and b/src/main/resources/OpenBSD/x86/libjSerialComm.so differ diff --git a/src/main/resources/Solaris/sparcv8plus_32/libjSerialComm.so b/src/main/resources/Solaris/sparcv8plus_32/libjSerialComm.so index fecb5ce..5431276 100644 Binary files a/src/main/resources/Solaris/sparcv8plus_32/libjSerialComm.so and b/src/main/resources/Solaris/sparcv8plus_32/libjSerialComm.so differ diff --git a/src/main/resources/Solaris/sparcv9_64/libjSerialComm.so b/src/main/resources/Solaris/sparcv9_64/libjSerialComm.so index 3cb9ae2..fca35fb 100644 Binary files a/src/main/resources/Solaris/sparcv9_64/libjSerialComm.so and b/src/main/resources/Solaris/sparcv9_64/libjSerialComm.so differ diff --git a/src/main/resources/Solaris/x86/libjSerialComm.so b/src/main/resources/Solaris/x86/libjSerialComm.so index a6ffbf9..e626519 100644 Binary files a/src/main/resources/Solaris/x86/libjSerialComm.so and b/src/main/resources/Solaris/x86/libjSerialComm.so differ diff --git a/src/main/resources/Solaris/x86_64/libjSerialComm.so b/src/main/resources/Solaris/x86_64/libjSerialComm.so index bd0bc86..83d1049 100644 Binary files a/src/main/resources/Solaris/x86_64/libjSerialComm.so and b/src/main/resources/Solaris/x86_64/libjSerialComm.so differ diff --git a/src/main/resources/Windows/aarch64/jSerialComm.dll b/src/main/resources/Windows/aarch64/jSerialComm.dll index 79b76f5..79c345a 100644 Binary files a/src/main/resources/Windows/aarch64/jSerialComm.dll and b/src/main/resources/Windows/aarch64/jSerialComm.dll differ diff --git a/src/main/resources/Windows/armv7/jSerialComm.dll b/src/main/resources/Windows/armv7/jSerialComm.dll index e9c7d12..29c1f92 100644 Binary files a/src/main/resources/Windows/armv7/jSerialComm.dll and b/src/main/resources/Windows/armv7/jSerialComm.dll differ diff --git a/src/main/resources/Windows/x86/jSerialComm.dll b/src/main/resources/Windows/x86/jSerialComm.dll index 4301fb9..220cfba 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_64/jSerialComm.dll b/src/main/resources/Windows/x86_64/jSerialComm.dll index 695d567..ccde335 100644 Binary files a/src/main/resources/Windows/x86_64/jSerialComm.dll and b/src/main/resources/Windows/x86_64/jSerialComm.dll differ