Retrieve port details/description when calling getCommPort(String)

This commit is contained in:
Will Hedgecock 2022-01-25 14:34:25 -06:00
parent df6969e0be
commit 7ba248b535
35 changed files with 131 additions and 32 deletions

View File

@ -79,6 +79,7 @@ jfieldID writeTimeoutField;
jfieldID eventFlagsField;
// List of available serial ports
char portsEnumerated = 0;
serialPortVector serialPorts = { NULL, 0, 0 };
// JNI exception handler
@ -98,6 +99,37 @@ static inline jboolean checkJniError(JNIEnv *env, int lineNumber)
return JNI_FALSE;
}
// Generalized port enumeration function
static void enumeratePorts(void)
{
// Reset the enumerated flag on all non-open serial ports
for (int i = 0; i < serialPorts.length; ++i)
serialPorts.ports[i]->enumerated = (serialPorts.ports[i]->handle > 0);
// Enumerate serial ports on this machine
#if defined(__linux__)
recursiveSearchForComPorts(&serialPorts, "/sys/devices/");
driverBasedSearchForComPorts(&serialPorts, "/proc/tty/driver/serial", "/dev/ttyS");
driverBasedSearchForComPorts(&serialPorts, "/proc/tty/driver/mvebu_serial", "/dev/ttyMV");
lastDitchSearchForComPorts(&serialPorts);
#elif defined(__sun__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
searchForComPorts(&serialPorts);
#endif
// Remove all non-enumerated ports from the serial port listing
for (int i = 0; i < serialPorts.length; ++i)
if (!serialPorts.ports[i]->enumerated)
{
removePort(&serialPorts, serialPorts.ports[i]);
i--;
}
portsEnumerated = 1;
}
#if defined(__linux__) && !defined(__ANDROID__)
// Event listening threads
@ -207,31 +239,8 @@ void* eventReadingThread2(void *serialPortPointer)
JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommPorts(JNIEnv *env, jclass serialComm)
{
// Reset the enumerated flag on all non-open serial ports
for (int i = 0; i < serialPorts.length; ++i)
serialPorts.ports[i]->enumerated = (serialPorts.ports[i]->handle > 0);
// Enumerate serial ports on this machine
#if defined(__linux__)
recursiveSearchForComPorts(&serialPorts, "/sys/devices/");
driverBasedSearchForComPorts(&serialPorts, "/proc/tty/driver/serial", "/dev/ttyS");
driverBasedSearchForComPorts(&serialPorts, "/proc/tty/driver/mvebu_serial", "/dev/ttyMV");
lastDitchSearchForComPorts(&serialPorts);
#elif defined(__sun__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
searchForComPorts(&serialPorts);
#endif
// Remove all non-enumerated ports from the serial port listing
for (int i = 0; i < serialPorts.length; ++i)
if (!serialPorts.ports[i]->enumerated)
{
removePort(&serialPorts, serialPorts.ports[i]);
i--;
}
// Enumerate all ports on the current system
enumeratePorts();
// Create a Java-based port listing
jobjectArray arrayObject = (*env)->NewObjectArray(env, serialPorts.length, serialCommClass, 0);
@ -356,6 +365,38 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_uninitializeLibr
checkJniError(env, __LINE__ - 1);
}
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_retrievePortDetails(JNIEnv *env, jobject obj)
{
// Retrieve the serial port parameter fields
jstring portNameJString = (jstring)(*env)->GetObjectField(env, obj, comPortField);
if (checkJniError(env, __LINE__ - 1)) return;
const char *portName = (*env)->GetStringUTFChars(env, portNameJString, NULL);
if (checkJniError(env, __LINE__ - 1)) return;
// Ensure that the serial port exists
if (!portsEnumerated)
enumeratePorts();
serialPort *port = fetchPort(&serialPorts, portName);
if (!port)
{
(*env)->ReleaseStringUTFChars(env, portNameJString, portName);
checkJniError(env, __LINE__ - 1);
return;
}
// 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;
// Release all JNI structures
(*env)->ReleaseStringUTFChars(env, portNameJString, portName);
checkJniError(env, __LINE__ - 1);
}
JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(JNIEnv *env, jobject obj)
{
// Retrieve the serial port parameter fields

View File

@ -99,6 +99,14 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrar
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_uninitializeLibrary
(JNIEnv *, jclass);
/*
* Class: com_fazecast_jSerialComm_SerialPort
* Method: retrievePortDetails
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_retrievePortDetails
(JNIEnv *, jobject);
/*
* Class: com_fazecast_jSerialComm_SerialPort
* Method: openPortNative

View File

@ -2,7 +2,7 @@
* SerialPort_Windows.c
*
* Created on: Feb 25, 2012
* Last Updated on: Jan 21, 2022
* Last Updated on: Jan 25, 2022
* Author: Will Hedgecock
*
* Copyright (C) 2012-2022 Fazecast, Inc.
@ -78,6 +78,7 @@ typedef int (__stdcall *FT_CreateDeviceInfoListFunction)(LPDWORD);
typedef int (__stdcall *FT_GetDeviceInfoListFunction)(FT_DEVICE_LIST_INFO_NODE*, LPDWORD);
// List of available serial ports
char portsEnumerated = 0;
serialPortVector serialPorts = { NULL, 0, 0 };
// JNI exception handler
@ -97,7 +98,8 @@ static inline jboolean checkJniError(JNIEnv *env, int lineNumber)
return JNI_FALSE;
}
JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommPorts(JNIEnv *env, jclass serialComm)
// Generalized port enumeration function
static void enumeratePorts(void)
{
// Reset the enumerated flag on all non-open serial ports
for (int i = 0; i < serialPorts.length; ++i)
@ -312,8 +314,16 @@ JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommP
removePort(&serialPorts, serialPorts.ports[i]);
i--;
}
portsEnumerated = 1;
}
JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommPorts(JNIEnv *env, jclass serialComm)
{
// 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)
@ -415,6 +425,38 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_uninitializeLibr
checkJniError(env, __LINE__ - 1);
}
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_retrievePortDetails(JNIEnv *env, jobject obj)
{
// Retrieve the serial port parameter fields
jstring portNameJString = (jstring)(*env)->GetObjectField(env, obj, comPortField);
if (checkJniError(env, __LINE__ - 1)) return;
const wchar_t *portName = (wchar_t*)(*env)->GetStringChars(env, portNameJString, NULL);
if (checkJniError(env, __LINE__ - 1)) return;
// Ensure that the serial port exists
if (!portsEnumerated)
enumeratePorts();
serialPort *port = fetchPort(&serialPorts, portName);
if (!port)
{
(*env)->ReleaseStringChars(env, portNameJString, (const jchar*)portName);
checkJniError(env, __LINE__ - 1);
return;
}
// 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;
// Release all JNI structures
(*env)->ReleaseStringChars(env, portNameJString, (const jchar*)portName);
checkJniError(env, __LINE__ - 1);
}
JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(JNIEnv *env, jobject obj)
{
// Retrieve the serial port parameter fields

View File

@ -2,7 +2,7 @@
* WindowsHelperFunctions.c
*
* Created on: May 05, 2015
* Last Updated on: Jan 22, 2022
* Last Updated on: Jan 25, 2022
* Author: Will Hedgecock
*
* Copyright (C) 2012-2022 Fazecast, Inc.
@ -77,6 +77,11 @@ serialPort* pushBack(serialPortVector* vector, const wchar_t* key, const wchar_t
serialPort* fetchPort(serialPortVector* vector, const wchar_t* key)
{
// Move past any opening slashes
if ((key[0] == L'\\') && (key[1] == L'\\') && (key[2] == L'.') && (key[3] == L'\\'))
key += 4;
// Retrieve the serial port specified by the passed-in key
for (int i = 0; i < vector->length; ++i)
if (wcscmp(key, vector->ports[i]->portPath) == 0)
return vector->ports[i];

View File

@ -2,7 +2,7 @@
* SerialPort.java
*
* Created on: Feb 25, 2012
* Last Updated on: Jan 20, 2022
* Last Updated on: Jan 25, 2022
* Author: Will Hedgecock
*
* Copyright (C) 2012-2022 Fazecast, Inc.
@ -460,7 +460,7 @@ public final class SerialPort
* @return A {@link SerialPort} object.
* @throws SerialPortInvalidPortException If a {@link SerialPort} object cannot be created due to a logical or formatting error in the portDescriptor parameter.
*/
static public final SerialPort getCommPort(String portDescriptor) throws SerialPortInvalidPortException
static public final synchronized SerialPort getCommPort(String portDescriptor) throws SerialPortInvalidPortException
{
// Correct port descriptor, if needed
try
@ -493,6 +493,8 @@ public final class SerialPort
serialPort.comPort = portDescriptor;
serialPort.friendlyName = "User-Specified Port";
serialPort.portDescription = "User-Specified Port";
serialPort.portLocation = "0-0";
serialPort.retrievePortDetails();
return serialPort;
}
@ -552,7 +554,7 @@ public final class SerialPort
private volatile String comPort, friendlyName, portDescription, portLocation;
private volatile boolean eventListenerRunning = false, disableConfig = false, disableExclusiveLock = false;
private volatile boolean rs485Mode = false, rs485ActiveHigh = true, rs485RxDuringTx = false, rs485EnableTermination = false;
private volatile boolean isRtsEnabled = true, isDtrEnabled = true, autoFlushIOBuffers = false;
private volatile boolean isRtsEnabled = true, isDtrEnabled = true, autoFlushIOBuffers = false, requestElevatedPermissions = false;
private SerialPortInputStream inputStream = null;
private SerialPortOutputStream outputStream = null;
@ -709,7 +711,7 @@ public final class SerialPort
* exclusive locks on system resources.
*/
public final synchronized void disableExclusiveLock() { disableExclusiveLock = true; }
/**
* Returns the source code line location of the latest error encountered during execution of
* the native code for this port.
@ -734,6 +736,7 @@ public final class SerialPort
// Serial Port Setup Methods
private static native void initializeLibrary(); // Initializes the JNI code
private static native void uninitializeLibrary(); // Un-initializes the JNI code
private final native void retrievePortDetails(); // Retrieves port descriptions, names, and details
private final native long openPortNative(); // Opens serial port
private final native long closePortNative(long portHandle); // Closes serial port
private final native boolean configPort(long portHandle); // Changes/sets serial port parameters as defined by this class