Perform full port close routine upon native error

This commit is contained in:
hedgecrw85 2020-02-18 16:45:10 -06:00
parent 349f0adffb
commit 4bdd0bf331
1 changed files with 26 additions and 92 deletions

View File

@ -2,7 +2,7 @@
* SerialPort_Windows.c * SerialPort_Windows.c
* *
* Created on: Feb 25, 2012 * Created on: Feb 25, 2012
* Last Updated on: Jan 03, 2020 * Last Updated on: Feb 18, 2020
* Author: Will Hedgecock * Author: Will Hedgecock
* *
* Copyright (C) 2012-2020 Fazecast, Inc. * Copyright (C) 2012-2020 Fazecast, Inc.
@ -572,12 +572,8 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNI
if (GetLastError() != ERROR_IO_PENDING) // Problem occurred if (GetLastError() != ERROR_IO_PENDING) // Problem occurred
{ {
// Problem reading, close port // Problem reading, close port
int numRetries = 10; Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
PurgeComm(serialPortHandle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
while (env->GetBooleanField(obj, isOpenedField) && !CloseHandle(serialPortHandle) && (numRetries-- > 0));
serialPortHandle = INVALID_HANDLE_VALUE; serialPortHandle = INVALID_HANDLE_VALUE;
env->SetLongField(obj, serialPortHandleField, -1l);
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
} }
else else
{ {
@ -594,17 +590,8 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNI
// Ensure that new data actually was received // Ensure that new data actually was received
COMSTAT commInfo; COMSTAT commInfo;
if (!ClearCommError(serialPortHandle, &errorsMask, &commInfo)) if ((serialPortHandle != INVALID_HANDLE_VALUE) && !ClearCommError(serialPortHandle, &errorsMask, &commInfo))
{ Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
// Problem detected, close port
int numRetries = 10;
PurgeComm(serialPortHandle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
while (env->GetBooleanField(obj, isOpenedField) && !CloseHandle(serialPortHandle) && (numRetries-- > 0));
serialPortHandle = INVALID_HANDLE_VALUE;
env->SetLongField(obj, serialPortHandleField, -1l);
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
return -1;
}
numBytesRead = commInfo.cbInQue; numBytesRead = commInfo.cbInQue;
// Return type of event if successful // Return type of event if successful
@ -632,16 +619,16 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNat
// Close the port // Close the port
int numRetries = 10; int numRetries = 10;
env->SetBooleanField(obj, isOpenedField, JNI_FALSE); while (env->GetBooleanField(obj, isOpenedField) && !CloseHandle(serialPortHandle) && (GetLastError() != ERROR_INVALID_HANDLE) && (numRetries-- > 0));
while (!CloseHandle(serialPortHandle) && (numRetries-- > 0));
if (numRetries > 0) if (numRetries > 0)
{ {
env->SetLongField(obj, serialPortHandleField, -1l); env->SetLongField(obj, serialPortHandleField, -1l);
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
return JNI_TRUE; return JNI_TRUE;
} }
else
env->SetBooleanField(obj, isOpenedField, JNI_TRUE);
// Error closing port, reconfigure port settings
Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(env, obj, serialPortFD);
return JNI_FALSE; return JNI_FALSE;
} }
@ -651,22 +638,16 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(J
if (serialPortHandle == INVALID_HANDLE_VALUE) if (serialPortHandle == INVALID_HANDLE_VALUE)
return -1; return -1;
// Retrieve bytes available to read
COMSTAT commInfo; COMSTAT commInfo;
DWORD errorsMask; DWORD errorsMask;
if (!ClearCommError(serialPortHandle, &errorsMask, &commInfo)) if (!ClearCommError(serialPortHandle, &errorsMask, &commInfo))
{ {
// Problem detected, close port // Problem detected, close port
int numRetries = 10; Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
PurgeComm(serialPortHandle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
while (env->GetBooleanField(obj, isOpenedField) && !CloseHandle(serialPortHandle) && (numRetries-- > 0));
serialPortHandle = INVALID_HANDLE_VALUE; serialPortHandle = INVALID_HANDLE_VALUE;
env->SetLongField(obj, serialPortHandleField, -1l);
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
return -1;
} }
DWORD numBytesAvailable = commInfo.cbInQue; return (serialPortHandle == INVALID_HANDLE_VALUE) ? -1 : commInfo.cbInQue;
return (jint)numBytesAvailable;
} }
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAwaitingWrite(JNIEnv *env, jobject obj, jlong serialPortFD) JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAwaitingWrite(JNIEnv *env, jobject obj, jlong serialPortFD)
@ -675,13 +656,16 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAwaitingWri
if (serialPortHandle == INVALID_HANDLE_VALUE) if (serialPortHandle == INVALID_HANDLE_VALUE)
return -1; return -1;
// Retrieve bytes awaiting write
COMSTAT commInfo; COMSTAT commInfo;
DWORD errorsMask; DWORD errorsMask;
if (!ClearCommError(serialPortHandle, &errorsMask, &commInfo)) if (!ClearCommError(serialPortHandle, &errorsMask, &commInfo))
return -1; {
DWORD numBytesToWrite = commInfo.cbOutQue; // Problem detected, close port
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
return (jint)numBytesToWrite; serialPortHandle = INVALID_HANDLE_VALUE;
}
return (serialPortHandle == INVALID_HANDLE_VALUE) ? -1 : commInfo.cbOutQue;
} }
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToRead, jlong offset) JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToRead, jlong offset)
@ -697,12 +681,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
if (!ClearCommError(serialPortHandle, &errorsMask, &commInfo)) if (!ClearCommError(serialPortHandle, &errorsMask, &commInfo))
{ {
// Problem detected, close port // Problem detected, close port
int numRetries = 10; Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
PurgeComm(serialPortHandle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
while (env->GetBooleanField(obj, isOpenedField) && !CloseHandle(serialPortHandle) && (numRetries-- > 0));
serialPortHandle = INVALID_HANDLE_VALUE;
env->SetLongField(obj, serialPortHandleField, -1l);
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
return -1; return -1;
} }
@ -717,28 +696,12 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
char *readBuffer = (char*)malloc(bytesToRead); char *readBuffer = (char*)malloc(bytesToRead);
DWORD numBytesRead = 0; DWORD numBytesRead = 0;
// Read from serial port // Read from serial port and close upon error
BOOL result; BOOL result;
if (((result = ReadFile(serialPortHandle, readBuffer, bytesToRead, NULL, &overlappedStruct)) == FALSE) && (GetLastError() != ERROR_IO_PENDING)) if (((result = ReadFile(serialPortHandle, readBuffer, bytesToRead, NULL, &overlappedStruct)) == FALSE) && (GetLastError() != ERROR_IO_PENDING))
{ Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
// Problem reading, close port
int numRetries = 10;
PurgeComm(serialPortHandle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
while (env->GetBooleanField(obj, isOpenedField) && !CloseHandle(serialPortHandle) && (numRetries-- > 0));
serialPortHandle = INVALID_HANDLE_VALUE;
env->SetLongField(obj, serialPortHandleField, -1l);
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
}
else if ((result = GetOverlappedResult(serialPortHandle, &overlappedStruct, &numBytesRead, TRUE)) == FALSE) else if ((result = GetOverlappedResult(serialPortHandle, &overlappedStruct, &numBytesRead, TRUE)) == FALSE)
{ Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
// Problem reading, close port
int numRetries = 10;
PurgeComm(serialPortHandle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
while (env->GetBooleanField(obj, isOpenedField) && !CloseHandle(serialPortHandle) && (numRetries-- > 0));
serialPortHandle = INVALID_HANDLE_VALUE;
env->SetLongField(obj, serialPortHandleField, -1l);
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
}
// Return number of bytes read if successful // Return number of bytes read if successful
CloseHandle(overlappedStruct.hEvent); CloseHandle(overlappedStruct.hEvent);
@ -760,12 +723,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn
if (!ClearCommError(serialPortHandle, &errorsMask, &commInfo)) if (!ClearCommError(serialPortHandle, &errorsMask, &commInfo))
{ {
// Problem detected, close port // Problem detected, close port
int numRetries = 10; Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
PurgeComm(serialPortHandle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
while (env->GetBooleanField(obj, isOpenedField) && !CloseHandle(serialPortHandle) && (numRetries-- > 0));
serialPortHandle = INVALID_HANDLE_VALUE;
env->SetLongField(obj, serialPortHandleField, -1l);
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
return -1; return -1;
} }
@ -781,35 +739,11 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn
DWORD numBytesWritten = 0; DWORD numBytesWritten = 0;
BOOL result; BOOL result;
// Set the DTR line to high if using RS-422 // Write to serial port and close upon error
//EscapeCommFunction(serialPortHandle, SETDTR);
// Write to serial port
if (((result = WriteFile(serialPortHandle, writeBuffer+offset, bytesToWrite, NULL, &overlappedStruct)) == FALSE) && (GetLastError() != ERROR_IO_PENDING)) if (((result = WriteFile(serialPortHandle, writeBuffer+offset, bytesToWrite, NULL, &overlappedStruct)) == FALSE) && (GetLastError() != ERROR_IO_PENDING))
{ Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
// Problem writing, close port
int numRetries = 10;
PurgeComm(serialPortHandle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
while (env->GetBooleanField(obj, isOpenedField) && !CloseHandle(serialPortHandle) && (numRetries-- > 0));
serialPortHandle = INVALID_HANDLE_VALUE;
env->SetLongField(obj, serialPortHandleField, -1l);
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
}
else if ((result = GetOverlappedResult(serialPortHandle, &overlappedStruct, &numBytesWritten, TRUE)) == FALSE) else if ((result = GetOverlappedResult(serialPortHandle, &overlappedStruct, &numBytesWritten, TRUE)) == FALSE)
{ Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
// Problem writing, close port
int numRetries = 10;
PurgeComm(serialPortHandle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
while (env->GetBooleanField(obj, isOpenedField) && !CloseHandle(serialPortHandle) && (numRetries-- > 0));
serialPortHandle = INVALID_HANDLE_VALUE;
env->SetLongField(obj, serialPortHandleField, -1l);
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
}
// Clear the DTR line if using RS-422
//COMSTAT commInfo;
//do { ClearCommError(serialPortHandle, NULL, &commInfo); } while (commInfo.cbOutQue > 0);
//EscapeCommFunction(serialPortHandle, CLRDTR);
// Return number of bytes written if successful // Return number of bytes written if successful
CloseHandle(overlappedStruct.hEvent); CloseHandle(overlappedStruct.hEvent);