Read/write directly to buffers, and force non-blocking mode before close()
This commit is contained in:
parent
283784e4b9
commit
b8b93d7b73
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue