Read/write directly to buffers, and force non-blocking mode before close()

This commit is contained in:
hedgecrw85 2018-07-27 15:06:32 -05:00
parent 283784e4b9
commit b8b93d7b73
5 changed files with 85 additions and 45 deletions

View File

@ -2,7 +2,7 @@
* SerialPort_Android.c
*
* Created on: Mar 13, 2015
* Last Updated on: Apr 01, 2018
* Last Updated on: Jul 27, 2018
* Author: Will Hedgecock
*
* Copyright (C) 2012-2018 Fazecast, Inc.
@ -393,14 +393,24 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNI
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNative(JNIEnv *env, jobject obj, jlong serialPortFD)
{
// Close port
// Ensure that the port is open
if (serialPortFD <= 0)
return JNI_TRUE;
while ((close(serialPortFD) == -1) && (errno != EBADF));
serialPortFD = -1;
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
// Force the port to enter non-blocking mode to ensure that any current reads return
struct termios options;
tcgetattr(serialPortFD, &options);
int flags = fcntl(serialPortFD, F_GETFL);
flags |= O_NONBLOCK;
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = 0;
int retVal = fcntl(serialPortFD, F_SETFL, flags);
tcsetattr(serialPortFD, TCSANOW, &options);
// Close the port
while ((close(serialPortFD) == -1) && (errno != EBADF));
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
return JNI_TRUE;
}
@ -422,7 +432,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAwaitingWri
return numBytesToWrite;
}
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToRead)
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToRead, jlong offset)
{
// Get port handle and read timeout from Java class
if (serialPortFD <= 0)
@ -506,12 +516,12 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
}
// Return number of bytes read if successful
(*env)->SetByteArrayRegion(env, buffer, 0, numBytesReadTotal, (jbyte*)readBuffer);
(*env)->SetByteArrayRegion(env, buffer, offset, numBytesReadTotal, (jbyte*)readBuffer);
free(readBuffer);
return (numBytesRead == -1) ? -1 : numBytesReadTotal;
return (numBytesRead == -1) || !((*env)->GetBooleanField(env, obj, isOpenedField)) ? -1 : numBytesReadTotal;
}
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToWrite)
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToWrite, jlong offset)
{
if (serialPortFD <= 0)
return -1;
@ -519,7 +529,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn
int numBytesWritten;
// Write to port
do { numBytesWritten = write(serialPortFD, writeBuffer, bytesToWrite); } while ((numBytesWritten < 0) && (errno == EINTR));
do { numBytesWritten = write(serialPortFD, writeBuffer+offset, bytesToWrite); } while ((numBytesWritten < 0) && (errno == EINTR));
if (numBytesWritten == -1)
{
// Problem writing, close port

View File

@ -146,18 +146,18 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAwaitingWri
/*
* Class: com_fazecast_jSerialComm_SerialPort
* Method: readBytes
* Signature: (J[BJ)I
* Signature: (J[BJJ)I
*/
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes
(JNIEnv *, jobject, jlong, jbyteArray, jlong);
(JNIEnv *, jobject, jlong, jbyteArray, jlong, jlong);
/*
* Class: com_fazecast_jSerialComm_SerialPort
* Method: writeBytes
* Signature: (J[BJ)I
* Signature: (J[BJJ)I
*/
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes
(JNIEnv *, jobject, jlong, jbyteArray, jlong);
(JNIEnv *, jobject, jlong, jbyteArray, jlong, jlong);
/*
* Class: com_fazecast_jSerialComm_SerialPort

View File

@ -2,7 +2,7 @@
* SerialPort_Linux.c
*
* Created on: Feb 25, 2012
* Last Updated on: Apr 23, 2018
* Last Updated on: Jul 27, 2018
* Author: Will Hedgecock
*
* Copyright (C) 2012-2018 Fazecast, Inc.
@ -322,18 +322,28 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNI
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNative(JNIEnv *env, jobject obj, jlong serialPortFD)
{
// Close port
// Ensure that the port is open
if (serialPortFD <= 0)
return JNI_TRUE;
// Allow others to open this port
// Allow others to open the port
ioctl(serialPortFD, TIOCNXCL);
tcdrain(serialPortFD);
while ((close(serialPortFD) == -1) && (errno != EBADF));
serialPortFD = -1;
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
// Force the port to enter non-blocking mode to ensure that any current reads return
struct termios options;
tcgetattr(serialPortFD, &options);
int flags = fcntl(serialPortFD, F_GETFL);
flags |= O_NONBLOCK;
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = 0;
int retVal = fcntl(serialPortFD, F_SETFL, flags);
tcsetattr(serialPortFD, TCSANOW, &options);
// Close the port
while ((close(serialPortFD) == -1) && (errno != EBADF));
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
return JNI_TRUE;
}
@ -355,7 +365,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAwaitingWri
return numBytesToWrite;
}
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToRead)
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToRead, jlong offset)
{
// Get port handle and read timeout from Java class
if (serialPortFD <= 0)
@ -445,12 +455,12 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
}
// Return number of bytes read if successful
(*env)->SetByteArrayRegion(env, buffer, 0, numBytesReadTotal, (jbyte*)readBuffer);
(*env)->SetByteArrayRegion(env, buffer, offset, numBytesReadTotal, (jbyte*)readBuffer);
free(readBuffer);
return (numBytesRead == -1) ? -1 : numBytesReadTotal;
return (numBytesRead == -1) || !((*env)->GetBooleanField(env, obj, isOpenedField)) ? -1 : numBytesReadTotal;
}
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToWrite)
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToWrite, jlong offset)
{
if (serialPortFD <= 0)
return -1;
@ -463,7 +473,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn
//ioctl(serialPortFD, TIOCMSET, &result);
// Write to port
do { numBytesWritten = write(serialPortFD, writeBuffer, bytesToWrite); } while ((numBytesWritten < 0) && (errno == EINTR));
do { numBytesWritten = write(serialPortFD, writeBuffer+offset, bytesToWrite); } while ((numBytesWritten < 0) && (errno == EINTR));
if (numBytesWritten == -1)
{
// Problem writing, allow others to open the port and close it ourselves

View File

@ -2,7 +2,7 @@
* SerialPort_OSX.c
*
* Created on: Feb 25, 2012
* Last Updated on: Apr 01, 2018
* Last Updated on: Jul 27, 2018
* Author: Will Hedgecock
*
* Copyright (C) 2012-2018 Fazecast, Inc.
@ -358,18 +358,28 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNI
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNative(JNIEnv *env, jobject obj, jlong serialPortFD)
{
// Close port
// Ensure that the port is open
if (serialPortFD <= 0)
return JNI_TRUE;
// Allow others to open the port and close it ourselves
// Allow others to open the port
ioctl(serialPortFD, TIOCNXCL);
tcdrain(serialPortFD);
while ((close(serialPortFD) == -1) && (errno != EBADF));
serialPortFD = -1;
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
// Force the port to enter non-blocking mode to ensure that any current reads return
struct termios options;
tcgetattr(serialPortFD, &options);
int flags = fcntl(serialPortFD, F_GETFL);
flags |= O_NONBLOCK;
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = 0;
int retVal = fcntl(serialPortFD, F_SETFL, flags);
tcsetattr(serialPortFD, TCSANOW, &options);
// Close the port
while ((close(serialPortFD) == -1) && (errno != EBADF));
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
return JNI_TRUE;
}
@ -391,7 +401,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAwaitingWri
return numBytesToWrite;
}
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToRead)
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToRead, jlong offset)
{
// Get port handle and read timeout from Java class
if (serialPortFD <= 0)
@ -481,12 +491,12 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
}
// Return number of bytes read if successful
(*env)->SetByteArrayRegion(env, buffer, 0, numBytesReadTotal, (jbyte*)readBuffer);
(*env)->SetByteArrayRegion(env, buffer, offset, numBytesReadTotal, (jbyte*)readBuffer);
free(readBuffer);
return (numBytesRead == -1) ? -1 : numBytesReadTotal;
return (numBytesRead == -1) || !((*env)->GetBooleanField(env, obj, isOpenedField)) ? -1 : numBytesReadTotal;
}
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToWrite)
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToWrite, jlong offset)
{
if (serialPortFD <= 0)
return -1;
@ -494,7 +504,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn
int numBytesWritten;
// Write to port
do { numBytesWritten = write(serialPortFD, writeBuffer, bytesToWrite); } while ((numBytesWritten < 0) && (errno == EINTR));
do { numBytesWritten = write(serialPortFD, writeBuffer+offset, bytesToWrite); } while ((numBytesWritten < 0) && (errno == EINTR));
if (numBytesWritten == -1)
{
// Problem writing, allow others to open the port and close it ourselves

View File

@ -2,7 +2,7 @@
* SerialPort_Windows.c
*
* Created on: Feb 25, 2012
* Last Updated on: Apr 03, 2018
* Last Updated on: Jul 27, 2018
* Author: Will Hedgecock
*
* Copyright (C) 2012-2018 Fazecast, Inc.
@ -596,16 +596,26 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNat
return JNI_TRUE;
PurgeComm(serialPortHandle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
// Close port
// Force the port to enter non-blocking mode to ensure that any current reads return
COMMTIMEOUTS timeouts = {0};
timeouts.WriteTotalTimeoutMultiplier = 0;
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(serialPortHandle, &timeouts);
// Close the port
int numRetries = 10;
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
while (!CloseHandle(serialPortHandle) && (numRetries-- > 0));
if (numRetries > 0)
{
serialPortHandle = INVALID_HANDLE_VALUE;
env->SetLongField(obj, serialPortHandleField, -1l);
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
return JNI_TRUE;
}
else
env->SetBooleanField(obj, isOpenedField, JNI_TRUE);
return JNI_FALSE;
}
@ -638,7 +648,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAwaitingWri
return (jint)numBytesToWrite;
}
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToRead)
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToRead, jlong offset)
{
HANDLE serialPortHandle = (HANDLE)serialPortFD;
if (serialPortHandle == INVALID_HANDLE_VALUE)
@ -681,12 +691,12 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
// Return number of bytes read if successful
CloseHandle(overlappedStruct.hEvent);
env->SetByteArrayRegion(buffer, 0, numBytesRead, (jbyte*)readBuffer);
env->SetByteArrayRegion(buffer, offset, numBytesRead, (jbyte*)readBuffer);
free(readBuffer);
return (result == TRUE) ? numBytesRead : -1;
return (result == TRUE) && (env->GetBooleanField(obj, isOpenedField)) ? numBytesRead : -1;
}
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToWrite)
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToWrite, jlong offset)
{
HANDLE serialPortHandle = (HANDLE)serialPortFD;
if (serialPortHandle == INVALID_HANDLE_VALUE)
@ -706,7 +716,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn
//EscapeCommFunction(serialPortHandle, SETDTR);
// Write to serial port
if ((result = WriteFile(serialPortHandle, writeBuffer, bytesToWrite, &numBytesWritten, &overlappedStruct)) == FALSE)
if ((result = WriteFile(serialPortHandle, writeBuffer+offset, bytesToWrite, &numBytesWritten, &overlappedStruct)) == FALSE)
{
if (GetLastError() != ERROR_IO_PENDING)
{