diff --git a/src/main/c/Windows/SerialPort_Windows.c b/src/main/c/Windows/SerialPort_Windows.c index c5e061a..2f5fdd5 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: Oct 29, 2019 + * Last Updated on: Nov 07, 2019 * Author: Will Hedgecock * * Copyright (C) 2012-2019 Fazecast, Inc. @@ -638,7 +638,16 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(J COMSTAT commInfo; if (!ClearCommError(serialPortHandle, NULL, &commInfo)) + { + // 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; + } DWORD numBytesAvailable = commInfo.cbInQue; return (jint)numBytesAvailable; @@ -660,9 +669,26 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAwaitingWri JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToRead, jlong offset) { + // Retrieve the serial port handle HANDLE serialPortHandle = (HANDLE)serialPortFD; if (serialPortHandle == INVALID_HANDLE_VALUE) return -1; + + // Check for a disconnected serial port + COMSTAT commInfo; + if (!ClearCommError(serialPortHandle, NULL, &commInfo)) + { + // 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; + } + + // Create an asynchronous result structure OVERLAPPED overlappedStruct = {0}; overlappedStruct.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (overlappedStruct.hEvent == NULL) @@ -672,32 +698,29 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv } char *readBuffer = (char*)malloc(bytesToRead); DWORD numBytesRead = 0; - BOOL result; // Read from serial port - if ((result = ReadFile(serialPortHandle, readBuffer, bytesToRead, &numBytesRead, &overlappedStruct)) == FALSE) - { - if (GetLastError() != ERROR_IO_PENDING) // Problem occurred - { - // 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) - { - // 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); - } - } + BOOL result; + if (((result = ReadFile(serialPortHandle, readBuffer, bytesToRead, NULL, &overlappedStruct)) == FALSE) && (GetLastError() != ERROR_IO_PENDING)) + { + // 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) + { + // 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 CloseHandle(overlappedStruct.hEvent); @@ -708,9 +731,26 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToWrite, jlong offset) { + // Retrieve the serial port handle HANDLE serialPortHandle = (HANDLE)serialPortFD; if (serialPortHandle == INVALID_HANDLE_VALUE) return -1; + + // Check for a disconnected serial port + COMSTAT commInfo; + if (!ClearCommError(serialPortHandle, NULL, &commInfo)) + { + // 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; + } + + // Create an asynchronous result structure OVERLAPPED overlappedStruct = {0}; overlappedStruct.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (overlappedStruct.hEvent == NULL) @@ -726,28 +766,25 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn //EscapeCommFunction(serialPortHandle, SETDTR); // Write to serial port - if ((result = WriteFile(serialPortHandle, writeBuffer+offset, bytesToWrite, &numBytesWritten, &overlappedStruct)) == FALSE) + if (((result = WriteFile(serialPortHandle, writeBuffer+offset, bytesToWrite, NULL, &overlappedStruct)) == FALSE) && (GetLastError() != ERROR_IO_PENDING)) { - if (GetLastError() != ERROR_IO_PENDING) - { - // 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) - { - // 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); - } + // 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) + { + // 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 diff --git a/src/main/c/Windows/WindowsHelperFunctions.c b/src/main/c/Windows/WindowsHelperFunctions.c index 9524cde..348e8ad 100644 --- a/src/main/c/Windows/WindowsHelperFunctions.c +++ b/src/main/c/Windows/WindowsHelperFunctions.c @@ -5,7 +5,7 @@ * Last Updated on: Mar 25, 2016 * Author: Will Hedgecock * - * Copyright (C) 2012-2018 Fazecast, Inc. + * Copyright (C) 2012-2016 Fazecast, Inc. * * This file is part of jSerialComm. * @@ -53,6 +53,7 @@ void push_back(struct charTupleVector* vector, const wchar_t* firstString, const char keyExists(struct charTupleVector* vector, const wchar_t* key) { + // Search for a vector item with a matching key size_t i; for (i = 0; i < vector->length; ++i) if (wcscmp(key, vector->first[i]) == 0) diff --git a/src/main/resources/Windows/x86/jSerialComm.dll b/src/main/resources/Windows/x86/jSerialComm.dll index 7c3af35..e97cf47 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 d559b96..bbc1074 100644 Binary files a/src/main/resources/Windows/x86_64/jSerialComm.dll and b/src/main/resources/Windows/x86_64/jSerialComm.dll differ