Retry POSIX calls if EINTR value is returned and try a last-ditch brute force enumeration of any ports that aren't properly listed in sysfs on Linux.

This commit is contained in:
hedgecrw85 2015-08-13 16:45:05 -05:00
parent 7e7ac77796
commit ec0acd7ac4
11 changed files with 74 additions and 11 deletions

View File

@ -53,6 +53,15 @@ void push_back(struct charPairVector* vector, const char* firstString, const cha
strcpy(vector->second[vector->length-1], secondString);
}
char keyExists(struct charPairVector* vector, const char* key)
{
size_t i;
for (i = 0; i < vector->length; ++i)
if (strcmp(key, vector->first[i]) == 0)
return 1;
return 0;
}
void getFriendlyName(const char* productFile, char* friendlyName)
{
int friendlyNameLength = 0;
@ -201,6 +210,47 @@ void recursiveSearchForComPorts(charPairVector* comPorts, const char* fullPathTo
closedir(directoryIterator);
}
void lastDitchSearchForComPorts(charPairVector* comPorts)
{
// Open the linux dev directory
DIR *directoryIterator = opendir("/dev/");
if (!directoryIterator)
return;
// Read all files in the current directory
struct dirent *directoryEntry = readdir(directoryIterator);
while (directoryEntry)
{
// See if the file names a potential serial port
if ((strlen(directoryEntry->d_name) >= 6) && (directoryEntry->d_name[0] == 't') && (directoryEntry->d_name[1] == 't') && (directoryEntry->d_name[2] == 'y') &&
(((directoryEntry->d_name[3] == 'A') && (directoryEntry->d_name[4] == 'M') && (directoryEntry->d_name[5] == 'A')) ||
((directoryEntry->d_name[3] == 'A') && (directoryEntry->d_name[4] == 'C') && (directoryEntry->d_name[5] == 'M')) ||
((directoryEntry->d_name[3] == 'U') && (directoryEntry->d_name[4] == 'S') && (directoryEntry->d_name[5] == 'B'))))
{
// Determine system name of port
char* systemName = (char*)malloc(256);
strcpy(systemName, "/dev/");
strcat(systemName, directoryEntry->d_name);
// Set static friendly name
char* friendlyName = (char*)malloc(256);
strcpy(friendlyName, "USB-Based Serial Port");
// Determine if port is already in the list, and add it if not
if (!keyExists(comPorts, systemName))
push_back(comPorts, systemName, friendlyName);
// Clean up memory
free(systemName);
free(friendlyName);
}
directoryEntry = readdir(directoryIterator);
}
// Close the directory
closedir(directoryIterator);
}
unsigned int getBaudRateCode(int baudRate)
{
switch (baudRate)

View File

@ -32,9 +32,11 @@ typedef struct charPairVector
size_t length;
} charPairVector;
void push_back(struct charPairVector* vector, const char* firstString, const char* secondString);
char keyExists(struct charPairVector* vector, const char* key);
void getDriverName(const char* directoryToSearch, char* friendlyName);
void recursiveSearchForComPorts(charPairVector* comPorts, const char* fullPathToSearch);
void lastDitchSearchForComPorts(charPairVector* comPorts);
void getFriendlyName(const char* productFile, char* friendlyName);
unsigned int getBaudRateCode(int baudRate);
void setBaudRate(int portFD, int baudRate);

View File

@ -61,6 +61,7 @@ JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommP
// Enumerate serial ports on machine
charPairVector serialPorts = { (char**)malloc(1), (char**)malloc(1), 0 };
recursiveSearchForComPorts(&serialPorts, "/sys/devices/");
lastDitchSearchForComPorts(&serialPorts);
jobjectArray arrayObject = (*env)->NewObjectArray(env, serialPorts.length, serialCommClass, 0);
int i;
for (i = 0; i < serialPorts.length; ++i)
@ -317,7 +318,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;
@ -361,7 +363,8 @@ 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);
@ -391,7 +394,8 @@ 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);
@ -413,7 +417,8 @@ 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);
@ -436,10 +441,11 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn
if (serialPortFD <= 0)
return -1;
jbyte *writeBuffer = (*env)->GetByteArrayElements(env, buffer, 0);
int numBytesWritten;
int numBytesWritten, result = 0;
// 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);

View File

@ -356,7 +356,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;
@ -401,7 +402,8 @@ 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);
@ -431,7 +433,8 @@ 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);
@ -453,7 +456,8 @@ 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);
@ -479,7 +483,8 @@ 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);