Move all global/class sync to native code
This commit is contained in:
parent
60ed45bb5d
commit
7330e76913
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
|||
* <p>
|
||||
* The serial ports can be accessed by iterating through each of the SerialPort objects in this array.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
|
@ -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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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.
|
||||
*/
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue