Complete overhaul of Posix native implementation

This commit is contained in:
Will Hedgecock 2021-11-16 21:00:43 -06:00
parent bc39570ff1
commit 28efbd1a51
2 changed files with 285 additions and 431 deletions

View File

@ -2,7 +2,7 @@
* SerialPort_Posix.c
*
* Created on: Feb 25, 2012
* Last Updated on: Nov 03, 2021
* Last Updated on: Nov 14, 2021
* Author: Will Hedgecock
*
* Copyright (C) 2012-2021 Fazecast, Inc.
@ -38,18 +38,8 @@
#include <linux/serial.h>
#elif defined(__sun__)
#include <sys/filio.h>
#elif defined(__APPLE__)
#include <AvailabilityMacros.h>
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/serial/IOSerialKeys.h>
#include <IOKit/serial/ioss.h>
#if (MAC_OS_X_VERSION_MAX_ALLOWED < 120000) // Before macOS 12 Monterey
#define kIOMainPortDefault kIOMasterPortDefault
#endif
#endif
#include "PosixHelperFunctions.h"
#include "../com_fazecast_jSerialComm_SerialPort.h"
// Cached class, method, and field IDs
jclass serialCommClass;
@ -81,139 +71,52 @@ jfieldID readTimeoutField;
jfieldID writeTimeoutField;
jfieldID eventFlagsField;
// List of available serial ports
serialPortVector serialPorts = { NULL, 0 };
JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommPorts(JNIEnv *env, jclass serialComm)
{
// Reset the enumerated flag on all non-open serial ports
for (int i = 0; i < serialPorts.length; ++i)
serialPorts.ports[i]->enumerated = (serialPorts.ports[i]->handle > 0);
// Enumerate serial ports on this machine
#if defined(__linux__)
{
// Enumerate serial ports on machine
charTupleVector serialPorts = { (char**)malloc(1), (char**)malloc(1), (char**)malloc(1), 0 };
recursiveSearchForComPorts(&serialPorts, "/sys/devices/");
driverBasedSearchForComPorts(&serialPorts, "/proc/tty/driver/serial", "/dev/ttyS");
driverBasedSearchForComPorts(&serialPorts, "/proc/tty/driver/mvebu_serial", "/dev/ttyMV");
lastDitchSearchForComPorts(&serialPorts);
jobjectArray arrayObject = (*env)->NewObjectArray(env, serialPorts.length, serialCommClass, 0);
int i;
for (i = 0; i < serialPorts.length; ++i)
{
// Create new SerialComm object containing the enumerated values
jobject serialCommObject = (*env)->NewObject(env, serialCommClass, serialCommConstructor);
(*env)->SetObjectField(env, serialCommObject, portDescriptionField, (*env)->NewStringUTF(env, serialPorts.third[i]));
(*env)->SetObjectField(env, serialCommObject, friendlyNameField, (*env)->NewStringUTF(env, serialPorts.second[i]));
(*env)->SetObjectField(env, serialCommObject, comPortField, (*env)->NewStringUTF(env, serialPorts.first[i]));
free(serialPorts.first[i]);
free(serialPorts.second[i]);
free(serialPorts.third[i]);
// Add new SerialComm object to array
(*env)->SetObjectArrayElement(env, arrayObject, i, serialCommObject);
}
free(serialPorts.first);
free(serialPorts.second);
free(serialPorts.third);
#elif defined(__sun__) || defined(__APPLE__)
return arrayObject;
}
#elif defined(__sun__)
{
// Enumerate serial ports on machine
charTupleVector serialPorts = { (char**)malloc(1), (char**)malloc(1), (char**)malloc(1), 0 };
searchForComPorts(&serialPorts);
#endif
// Remove all non-enumerated ports from the serial port listing
for (int i = 0; i < serialPorts.length; ++i)
if (!serialPorts.ports[i]->enumerated)
{
removePort(&serialPorts, serialPorts.ports[i]);
i--;
}
// Create a Java-based port listing
jobjectArray arrayObject = (*env)->NewObjectArray(env, serialPorts.length, serialCommClass, 0);
int i;
for (i = 0; i < serialPorts.length; ++i)
for (int i = 0; i < serialPorts.length; ++i)
{
// Create new SerialComm object containing the enumerated values
// Create a new SerialComm object containing the enumerated values
jobject serialCommObject = (*env)->NewObject(env, serialCommClass, serialCommConstructor);
(*env)->SetObjectField(env, serialCommObject, portDescriptionField, (*env)->NewStringUTF(env, serialPorts.third[i]));
(*env)->SetObjectField(env, serialCommObject, friendlyNameField, (*env)->NewStringUTF(env, serialPorts.second[i]));
(*env)->SetObjectField(env, serialCommObject, comPortField, (*env)->NewStringUTF(env, serialPorts.first[i]));
free(serialPorts.first[i]);
free(serialPorts.second[i]);
free(serialPorts.third[i]);
(*env)->SetObjectField(env, serialCommObject, portDescriptionField, (*env)->NewStringUTF(env, serialPorts.ports[i]->portDescription));
(*env)->SetObjectField(env, serialCommObject, friendlyNameField, (*env)->NewStringUTF(env, serialPorts.ports[i]->friendlyName));
(*env)->SetObjectField(env, serialCommObject, comPortField, (*env)->NewStringUTF(env, serialPorts.ports[i]->portPath));
// Add new SerialComm object to array
(*env)->SetObjectArrayElement(env, arrayObject, i, serialCommObject);
}
free(serialPorts.first);
free(serialPorts.second);
free(serialPorts.third);
return arrayObject;
}
#elif defined(__APPLE__)
{
io_object_t serialPort;
io_iterator_t serialPortIterator;
int numValues = 0;
char friendlyName[1024], comPortCu[1024], comPortTty[1024], portDescription[1024];
// Enumerate serial ports on machine
IOServiceGetMatchingServices(kIOMainPortDefault, IOServiceMatching(kIOSerialBSDServiceValue), &serialPortIterator);
while ((serialPort = IOIteratorNext(serialPortIterator)))
{
++numValues;
IOObjectRelease(serialPort);
}
IOIteratorReset(serialPortIterator);
jobjectArray arrayObject = (*env)->NewObjectArray(env, numValues*2, serialCommClass, 0);
for (int i = 0; i < numValues; ++i)
{
// Get serial port information
serialPort = IOIteratorNext(serialPortIterator);
friendlyName[0] = '\0';
io_registry_entry_t parent = 0;
io_registry_entry_t service = serialPort;
while (service)
{
if (IOObjectConformsTo(service, "IOUSBDevice"))
{
IORegistryEntryGetName(service, friendlyName);
break;
}
if (IORegistryEntryGetParentEntry(service, kIOServicePlane, &parent) != KERN_SUCCESS)
break;
if (service != serialPort)
IOObjectRelease(service);
service = parent;
}
if (service != serialPort)
IOObjectRelease(service);
// Get serial port name and COM value
if (friendlyName[0] == '\0')
{
CFStringRef friendlyNameRef = (CFStringRef)IORegistryEntryCreateCFProperty(serialPort, CFSTR(kIOTTYDeviceKey), kCFAllocatorDefault, 0);
CFStringGetCString(friendlyNameRef, friendlyName, sizeof(friendlyName), kCFStringEncodingUTF8);
CFRelease(friendlyNameRef);
}
CFStringRef comPortRef = (CFStringRef)IORegistryEntryCreateCFProperty(serialPort, CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
CFStringGetCString(comPortRef, comPortCu, sizeof(comPortCu), kCFStringEncodingUTF8);
CFRelease(comPortRef);
comPortRef = (CFStringRef)IORegistryEntryCreateCFProperty(serialPort, CFSTR(kIODialinDeviceKey), kCFAllocatorDefault, 0);
CFStringGetCString(comPortRef, comPortTty, sizeof(comPortTty), kCFStringEncodingUTF8);
CFRelease(comPortRef);
// Create new SerialComm callout object containing the enumerated values and add to array
jobject serialCommObject = (*env)->NewObject(env, serialCommClass, serialCommConstructor);
(*env)->SetObjectField(env, serialCommObject, portDescriptionField, (*env)->NewStringUTF(env, friendlyName));
(*env)->SetObjectField(env, serialCommObject, friendlyNameField, (*env)->NewStringUTF(env, friendlyName));
(*env)->SetObjectField(env, serialCommObject, comPortField, (*env)->NewStringUTF(env, comPortCu));
(*env)->SetObjectArrayElement(env, arrayObject, i*2, serialCommObject);
(*env)->DeleteLocalRef(env, serialCommObject);
// Create new SerialComm dialin object containing the enumerated values and add to array
strcat(friendlyName, " (Dial-In)");
serialCommObject = (*env)->NewObject(env, serialCommClass, serialCommConstructor);
(*env)->SetObjectField(env, serialCommObject, portDescriptionField, (*env)->NewStringUTF(env, friendlyName));
(*env)->SetObjectField(env, serialCommObject, friendlyNameField, (*env)->NewStringUTF(env, friendlyName));
(*env)->SetObjectField(env, serialCommObject, comPortField, (*env)->NewStringUTF(env, comPortTty));
(*env)->SetObjectArrayElement(env, arrayObject, i*2 + 1, serialCommObject);
(*env)->DeleteLocalRef(env, serialCommObject);
IOObjectRelease(serialPort);
}
IOObjectRelease(serialPortIterator);
return arrayObject;
}
#endif
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrary(JNIEnv *env, jclass serialComm)
{
@ -249,86 +152,80 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrar
writeTimeoutField = (*env)->GetFieldID(env, serialCommClass, "writeTimeout", "I");
eventFlagsField = (*env)->GetFieldID(env, serialCommClass, "eventFlags", "I");
// Disable handling of SIGIO POSIX signals
// Disable handling of various POSIX signals
sigset_t blockMask;
sigemptyset(&blockMask);
struct sigaction ignoreAction = { 0 };
ignoreAction.sa_handler = SIG_IGN;
ignoreAction.sa_mask = blockMask;
sigaction(SIGIO, &ignoreAction, NULL);
sigaction(SIGINT, &ignoreAction, NULL);
sigaction(SIGTERM, &ignoreAction, NULL);
sigaction(SIGCONT, &ignoreAction, NULL);
sigaction(SIGUSR1, &ignoreAction, NULL);
sigaction(SIGUSR2, &ignoreAction, NULL);
sigaction(SIGTTOU, &ignoreAction, NULL);
sigaction(SIGTTIN, &ignoreAction, NULL);
}
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_uninitializeLibrary(JNIEnv *env, jclass serialComm)
{
// Delete the cache global reference
// Delete the cached global reference
(*env)->DeleteGlobalRef(env, serialCommClass);
}
JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(JNIEnv *env, jobject obj)
{
// Retrieve the serial port parameter fields
jstring portNameJString = (jstring)(*env)->GetObjectField(env, obj, comPortField);
const char *portName = (*env)->GetStringUTFChars(env, portNameJString, NULL);
unsigned char isDtrEnabled = (*env)->GetBooleanField(env, obj, isDtrEnabledField);
unsigned char isRtsEnabled = (*env)->GetBooleanField(env, obj, isRtsEnabledField);
unsigned char rs485ModeEnabled = (*env)->GetBooleanField(env, obj, rs485ModeField);
unsigned char disableExclusiveLock = (*env)->GetBooleanField(env, obj, disableExclusiveLockField);
unsigned char disableAutoConfig = (*env)->GetBooleanField(env, obj, disableConfigField);
// Try to open existing serial port with read/write access
int serialPortFD = -1;
if ((serialPortFD = open(portName, O_RDWR | O_NOCTTY | O_NONBLOCK)) > 0)
// Ensure that the serial port still exists and is not already open
serialPort *port = fetchPort(&serialPorts, portName);
if (!port)
{
// Create port representation and add to serial port listing
port = pushBack(&serialPorts, portName, "User-Specified Port", "User-Specified Port");
}
if (!port || (port->handle > 0))
return 0;
// Try to open the serial port with read/write access
port->errorLineNumber = __LINE__ + 1;
if ((port->handle = open(portName, O_RDWR | O_NOCTTY | O_NONBLOCK | O_CLOEXEC)) > 0)
{
// Ensure that multiple root users cannot access the device simultaneously
if (!disableExclusiveLock && (flock(serialPortFD, LOCK_EX | LOCK_NB) == -1))
if (!disableExclusiveLock && flock(port->handle, LOCK_EX | LOCK_NB))
{
while ((close(serialPortFD) == -1) && (errno == EINTR))
port->errorLineNumber = __LINE__ - 2;
port->errorNumber = errno;
while (close(port->handle) && (errno == EINTR))
errno = 0;
serialPortFD = -1;
port->handle = -1;
}
else
else if (!disableAutoConfig && !Java_com_fazecast_jSerialComm_SerialPort_configPort(env, obj, (jlong)(intptr_t)port))
{
// Clear any serial port flags and set up raw, non-canonical port parameters
struct termios options = {0};
fcntl(serialPortFD, F_SETFL, 0);
tcgetattr(serialPortFD, &options);
#if defined(__sun__)
options.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF);
options.c_oflag &= ~OPOST;
options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
options.c_cflag &= ~(CSIZE | PARENB);
options.c_cflag |= CS8;
#else
cfmakeraw(&options);
#endif
if (!isDtrEnabled || !isRtsEnabled)
options.c_cflag &= ~HUPCL;
if (!rs485ModeEnabled)
options.c_iflag |= BRKINT;
tcsetattr(serialPortFD, TCSANOW, &options);
// Configure the port parameters and timeouts
if (Java_com_fazecast_jSerialComm_SerialPort_configPort(env, obj, serialPortFD))
(*env)->SetLongField(env, obj, serialPortFdField, serialPortFD);
else
{
// Close the port if there was a problem setting the parameters
while ((close(serialPortFD) == -1) && (errno == EINTR))
errno = 0;
serialPortFD = -1;
}
// Close the port if there was a problem setting the parameters
fcntl(port->handle, F_SETFL, O_NONBLOCK);
while (close(port->handle) && (errno == EINTR))
errno = 0;
port->handle = -1;
}
}
else
port->errorNumber = errno;
// Return a pointer to the serial port data structure
(*env)->ReleaseStringUTFChars(env, portNameJString, portName);
return serialPortFD;
return (jlong)(intptr_t)port;
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(JNIEnv *env, jobject obj, jlong serialPortFD)
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(JNIEnv *env, jobject obj, jlong serialPortPointer)
{
if (serialPortFD <= 0)
return JNI_FALSE;
struct termios options = {0};
// Get port parameters from Java class
// Retrieve port parameters from the Java class
serialPort *port = (serialPort*)(intptr_t)serialPortPointer;
baud_rate baudRate = (*env)->GetIntField(env, obj, baudRateField);
int byteSizeInt = (*env)->GetIntField(env, obj, dataBitsField);
int stopBitsInt = (*env)->GetIntField(env, obj, stopBitsField);
@ -338,75 +235,73 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J
int receiveDeviceQueueSize = (*env)->GetIntField(env, obj, receiveDeviceQueueSizeField);
int rs485DelayBefore = (*env)->GetIntField(env, obj, rs485DelayBeforeField);
int rs485DelayAfter = (*env)->GetIntField(env, obj, rs485DelayAfterField);
unsigned char configDisabled = (*env)->GetBooleanField(env, obj, disableConfigField);
int timeoutMode = (*env)->GetIntField(env, obj, timeoutModeField);
int readTimeout = (*env)->GetIntField(env, obj, readTimeoutField);
int writeTimeout = (*env)->GetIntField(env, obj, writeTimeoutField);
int eventsToMonitor = (*env)->GetIntField(env, obj, eventFlagsField);
unsigned char rs485ModeEnabled = (*env)->GetBooleanField(env, obj, rs485ModeField);
unsigned char rs485ActiveHigh = (*env)->GetBooleanField(env, obj, rs485ActiveHighField);
unsigned char rs485EnableTermination = (*env)->GetBooleanField(env, obj, rs485EnableTerminationField);
unsigned char rs485RxDuringTx = (*env)->GetBooleanField(env, obj, rs485RxDuringTxField);
unsigned char isDtrEnabled = (*env)->GetBooleanField(env, obj, isDtrEnabledField);
unsigned char isRtsEnabled = (*env)->GetBooleanField(env, obj, isRtsEnabledField);
unsigned char XonXoffInEnabled = ((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_XONXOFF_IN_ENABLED) > 0);
unsigned char XonXoffOutEnabled = ((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_XONXOFF_OUT_ENABLED) > 0);
// Clear any serial port flags and set up raw non-canonical port parameters
struct termios options = { 0 };
tcgetattr(port->handle, &options);
options.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | INPCK | IGNPAR | IGNCR | ICRNL | IXON | IXOFF);
options.c_oflag &= ~OPOST;
options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
options.c_cflag &= ~(CSIZE | PARENB | CMSPAR | PARODD | CSTOPB | CRTSCTS);
// Update the user-specified port parameters
tcflag_t byteSize = (byteSizeInt == 5) ? CS5 : (byteSizeInt == 6) ? CS6 : (byteSizeInt == 7) ? CS7 : CS8;
tcflag_t parity = (parityInt == com_fazecast_jSerialComm_SerialPort_NO_PARITY) ? 0 : (parityInt == com_fazecast_jSerialComm_SerialPort_ODD_PARITY) ? (PARENB | PARODD) : (parityInt == com_fazecast_jSerialComm_SerialPort_EVEN_PARITY) ? PARENB : (parityInt == com_fazecast_jSerialComm_SerialPort_MARK_PARITY) ? (PARENB | CMSPAR | PARODD) : (PARENB | CMSPAR);
// Set updated port parameters
tcgetattr(serialPortFD, &options);
options.c_cflag &= ~(CSIZE | PARENB | CMSPAR | PARODD);
options.c_cflag |= (byteSize | parity | CLOCAL | CREAD);
if (stopBitsInt == com_fazecast_jSerialComm_SerialPort_TWO_STOP_BITS)
options.c_cflag |= CSTOPB;
else
options.c_cflag &= ~CSTOPB;
if (((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_CTS_ENABLED) > 0) || ((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_RTS_ENABLED) > 0))
options.c_cflag |= CRTSCTS;
else
options.c_cflag &= ~CRTSCTS;
if (!isDtrEnabled || !isRtsEnabled)
options.c_cflag &= ~HUPCL;
options.c_iflag &= ~(INPCK | IGNPAR | PARMRK | ISTRIP);
if (!rs485ModeEnabled)
options.c_iflag |= BRKINT;
if (stopBitsInt == com_fazecast_jSerialComm_SerialPort_TWO_STOP_BITS)
options.c_cflag |= CSTOPB;
if (((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_CTS_ENABLED) > 0) || ((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_RTS_ENABLED) > 0))
options.c_cflag |= CRTSCTS;
if (byteSizeInt < 8)
options.c_iflag |= ISTRIP;
if (parityInt != 0)
options.c_iflag |= (INPCK | IGNPAR);
if (XonXoffInEnabled)
if ((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_XONXOFF_IN_ENABLED) > 0)
options.c_iflag |= IXOFF;
else
options.c_cflag &= ~(IXOFF);
if (XonXoffOutEnabled)
if ((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_XONXOFF_OUT_ENABLED) > 0)
options.c_iflag |= IXON;
else
options.c_cflag &= ~(IXON);
// Set baud rate and apply changes
// Set the baud rate and apply all changes
baud_rate baudRateCode = getBaudRateCode(baudRate);
unsigned char nonStandardBaudRate = (baudRateCode == 0);
if (nonStandardBaudRate)
if (!baudRateCode)
baudRateCode = B38400;
cfsetispeed(&options, baudRateCode);
cfsetospeed(&options, baudRateCode);
int retVal = configDisabled ? 0 : tcsetattr(serialPortFD, TCSANOW, &options);
if (tcsetattr(port->handle, TCSANOW, &options) || tcsetattr(port->handle, TCSANOW, &options))
{
port->errorLineNumber = __LINE__ - 2;
port->errorNumber = errno;
return JNI_FALSE;
}
// Attempt to set the transmit buffer size and any necessary custom baud rates
#if defined(__linux__)
struct serial_struct serInfo = {0};
if (ioctl(serialPortFD, TIOCGSERIAL, &serInfo) == 0)
// Attempt to set the transmit buffer size
struct serial_struct serInfo = { 0 };
if (!ioctl(port->handle, TIOCGSERIAL, &serInfo))
{
serInfo.xmit_fifo_size = sendDeviceQueueSize;
serInfo.flags |= ASYNC_LOW_LATENCY;
ioctl(serialPortFD, TIOCSSERIAL, &serInfo);
ioctl(port->handle, TIOCSSERIAL, &serInfo);
}
#else
(*env)->SetIntField(env, obj, sendDeviceQueueSizeField, sysconf(_SC_PAGESIZE));
#endif
(*env)->SetIntField(env, obj, receiveDeviceQueueSizeField, sysconf(_SC_PAGESIZE));
if (nonStandardBaudRate)
setBaudRateCustom(serialPortFD, baudRate);
// Attempt to set the requested RS-485 mode
#if defined(__linux__)
struct serial_rs485 rs485Conf = {0};
if (ioctl(serialPortFD, TIOCGRS485, &rs485Conf) == 0)
struct serial_rs485 rs485Conf = { 0 };
if (!ioctl(port->handle, TIOCGRS485, &rs485Conf))
{
if (rs485ModeEnabled)
rs485Conf.flags |= SER_RS485_ENABLED;
@ -432,115 +327,99 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J
rs485Conf.flags &= ~(SER_RS485_TERMINATE_BUS);
rs485Conf.delay_rts_before_send = rs485DelayBefore / 1000;
rs485Conf.delay_rts_after_send = rs485DelayAfter / 1000;
ioctl(serialPortFD, TIOCSRS485, &rs485Conf);
if (ioctl(port->handle, TIOCSRS485, &rs485Conf))
{
port->errorLineNumber = __LINE__ - 2;
port->errorNumber = errno;
return JNI_FALSE;
}
}
#endif
return ((retVal == 0) && Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(env, obj, serialPortFD) ? JNI_TRUE : JNI_FALSE);
// Configure the serial port read and write timeouts
return Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(env, obj, serialPortPointer, timeoutMode, readTimeout, writeTimeout, eventsToMonitor);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(JNIEnv *env, jobject obj, jlong serialPortFD)
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(JNIEnv *env, jobject obj, jlong serialPortPointer, jint timeoutMode, jint readTimeout, jint writeTimeout, jint eventsToMonitor)
{
// Get port timeouts from Java class
if (serialPortFD <= 0)
return JNI_FALSE;
// Retrieve the existing port configuration
int flags = 0;
struct termios options = { 0 };
serialPort *port = (serialPort*)(intptr_t)serialPortPointer;
baud_rate baudRate = (*env)->GetIntField(env, obj, baudRateField);
baud_rate baudRateCode = getBaudRateCode(baudRate);
int timeoutMode = (*env)->GetIntField(env, obj, timeoutModeField);
int readTimeout = (*env)->GetIntField(env, obj, readTimeoutField);
// Retrieve existing port configuration
struct termios options = {0};
tcgetattr(serialPortFD, &options);
int flags = fcntl(serialPortFD, F_GETFL);
if (flags == -1)
return JNI_FALSE;
tcgetattr(port->handle, &options);
// Set updated port timeouts
if (((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_SEMI_BLOCKING) > 0) && (readTimeout > 0)) // Read Semi-blocking with timeout
if ((eventsToMonitor & com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_RECEIVED) > 0)
{
// Force specific read timeouts if we are monitoring data received
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = 10;
}
else if (((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_SEMI_BLOCKING) > 0) && (readTimeout > 0)) // Read Semi-blocking with timeout
{
flags &= ~O_NONBLOCK;
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = readTimeout / 100;
}
else if ((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_SEMI_BLOCKING) > 0) // Read Semi-blocking without timeout
else if ((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_SEMI_BLOCKING) > 0) // Read Semi-blocking without timeout
{
flags &= ~O_NONBLOCK;
options.c_cc[VMIN] = 1;
options.c_cc[VTIME] = 0;
}
else if (((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_BLOCKING) > 0) && (readTimeout > 0)) // Read Blocking with timeout
else if (((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_BLOCKING) > 0) && (readTimeout > 0)) // Read Blocking with timeout
{
flags &= ~O_NONBLOCK;
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = readTimeout / 100;
}
else if ((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_BLOCKING) > 0) // Read Blocking without timeout
else if ((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_BLOCKING) > 0) // Read Blocking without timeout
{
flags &= ~O_NONBLOCK;
options.c_cc[VMIN] = 1;
options.c_cc[VTIME] = 0;
}
else if ((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_SCANNER) > 0) // Scanner Mode
else if ((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_SCANNER) > 0) // Scanner Mode
{
flags &= ~O_NONBLOCK;
options.c_cc[VMIN] = 1;
options.c_cc[VTIME] = 1;
}
else // Non-blocking
else // Non-blocking
{
flags |= O_NONBLOCK;
flags = O_NONBLOCK;
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = 0;
}
// Apply changes
int retVal = fcntl(serialPortFD, F_SETFL, flags);
if (retVal != -1)
retVal = tcsetattr(serialPortFD, TCSANOW, &options);
if (baudRateCode == 0)
setBaudRateCustom(serialPortFD, baudRate);
return ((retVal == 0) ? JNI_TRUE : JNI_FALSE);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(JNIEnv *env, jobject obj, jlong serialPortFD)
{
if (serialPortFD <= 0)
return JNI_FALSE;
// Get event flags from Java class
baud_rate baudRate = (*env)->GetIntField(env, obj, baudRateField);
baud_rate baudRateCode = getBaudRateCode(baudRate);
int eventsToMonitor = (*env)->GetIntField(env, obj, eventFlagsField);
// Change read timeouts if we are monitoring data received
jboolean retVal;
if ((eventsToMonitor & com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_RECEIVED) > 0)
if (fcntl(port->handle, F_SETFL, flags))
{
struct termios options = {0};
tcgetattr(serialPortFD, &options);
int flags = fcntl(serialPortFD, F_GETFL);
if (flags == -1)
return JNI_FALSE;
flags &= ~O_NONBLOCK;
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = 10;
retVal = ((fcntl(serialPortFD, F_SETFL, flags) == -1) || (tcsetattr(serialPortFD, TCSANOW, &options) == -1)) ? JNI_FALSE : JNI_TRUE;
if (baudRateCode == 0)
setBaudRateCustom(serialPortFD, baudRate);
port->errorLineNumber = __LINE__ - 2;
port->errorNumber = errno;
return JNI_FALSE;
}
else
retVal = Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(env, obj, serialPortFD);
// Apply changes
return retVal;
if (tcsetattr(port->handle, TCSANOW, &options) || tcsetattr(port->handle, TCSANOW, &options))
{
port->errorLineNumber = __LINE__ - 2;
port->errorNumber = errno;
return JNI_FALSE;
}
if (!getBaudRateCode(baudRate) && setBaudRateCustom(port->handle, baudRate))
{
port->errorLineNumber = __LINE__ - 2;
port->errorNumber = errno;
return JNI_FALSE;
}
return JNI_TRUE;
}
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNIEnv *env, jobject obj, jlong serialPortFD)
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNIEnv *env, jobject obj, jlong serialPortPointer)
{
// Initialize the waiting set
if (serialPortFD <= 0)
return 0;
struct pollfd waitingSet = { serialPortFD, POLLIN, 0 };
serialPort *port = (serialPort*)(intptr_t)serialPortPointer;
struct pollfd waitingSet = { port->handle, POLLIN, 0 };
// TODO: START THREAD TO HANDLE ALL OF THIS IN C
// TODO: LISTEN FOR ERROR EVENTS IN CASE SERIAL PORT GETS UNPLUGGED? TEST IF WORKS?
// TODO: STORE ALL AVAILABLE PORTS IN C, RECHECK AVAILABLE PORTS UPON RESCAN SO ALREADY OPEN PORTS DON'T GET MESSED UP
// Wait for a serial port event
if (poll(&waitingSet, 1, 500) <= 0)
@ -548,58 +427,54 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNI
return (waitingSet.revents & POLLIN) ? com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_AVAILABLE : 0;
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNative(JNIEnv *env, jobject obj, jlong serialPortFD)
JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNative(JNIEnv *env, jobject obj, jlong serialPortPointer)
{
// Ensure that the port is open
if (serialPortFD <= 0)
return JNI_TRUE;
// Force the port to enter non-blocking mode to ensure that any current reads return
struct termios options = {0};
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
flock(serialPortFD, LOCK_UN | LOCK_NB);
fdatasync(serialPortFD);
while ((close(serialPortFD) == -1) && (errno == EINTR))
// Unblock, unlock, and close the port
serialPort *port = (serialPort*)(intptr_t)serialPortPointer;
fsync(port->handle);
tcdrain(port->handle);
tcflush(port->handle, TCIOFLUSH);
fcntl(port->handle, F_SETFL, O_NONBLOCK);
flock(port->handle, LOCK_UN | LOCK_NB);
while (close(port->handle) && (errno == EINTR))
errno = 0;
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
return JNI_TRUE;
port->handle = -1;
return 0;
}
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(JNIEnv *env, jobject obj, jlong serialPortFD)
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(JNIEnv *env, jobject obj, jlong serialPortPointer)
{
// Retrieve bytes available to read and close port upon error
// Retrieve bytes available to read
int numBytesAvailable = -1;
if ((serialPortFD > 0) && (ioctl(serialPortFD, FIONREAD, &numBytesAvailable) == -1))
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
ioctl(((serialPort*)(intptr_t)serialPortPointer)->handle, FIONREAD, &numBytesAvailable);
return 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 serialPortPointer)
{
// Retrieve bytes awaiting write and close port upon error
// Retrieve bytes awaiting write
int numBytesToWrite = -1;
if ((serialPortFD > 0) && (ioctl(serialPortFD, TIOCOUTQ, &numBytesToWrite) == -1))
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
ioctl(((serialPort*)(intptr_t)serialPortPointer)->handle, TIOCOUTQ, &numBytesToWrite);
return numBytesToWrite;
}
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 serialPortPointer, jbyteArray buffer, jlong bytesToRead, jlong offset, jint timeoutMode, jint readTimeout)
{
// Get port handle and read timeout from Java class
if (serialPortFD <= 0)
return -1;
int timeoutMode = (*env)->GetIntField(env, obj, timeoutModeField);
int readTimeout = (*env)->GetIntField(env, obj, readTimeoutField);
// Ensure that the allocated read buffer is large enough
serialPort *port = (serialPort*)(intptr_t)serialPortPointer;
int numBytesRead, numBytesReadTotal = 0, bytesRemaining = bytesToRead, ioctlResult = 0;
char* readBuffer = (char*)malloc(bytesToRead);
if (bytesToRead > port->readBufferLength)
{
port->errorLineNumber = __LINE__ + 1;
char *newMemory = (char*)realloc(port->readBuffer, bytesToRead);
if (!newMemory)
{
port->errorNumber = errno;
return -1;
}
port->readBuffer = newMemory;
port->readBufferLength = bytesToRead;
}
// Infinite blocking mode specified, don't return until we have completely finished the read
if (((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_BLOCKING) > 0) && (readTimeout == 0))
@ -607,14 +482,11 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
// While there are more bytes we are supposed to read
while (bytesRemaining > 0)
{
do { numBytesRead = read(serialPortFD, readBuffer+numBytesReadTotal, bytesRemaining); } while ((numBytesRead < 0) && (errno == EINTR));
if ((numBytesRead == -1) || ((numBytesRead == 0) && (ioctl(serialPortFD, FIONREAD, &ioctlResult) == -1)))
{
// Problem reading, close the port
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
serialPortFD = -1;
// Attempt to read some number of bytes from the serial port
port->errorLineNumber = __LINE__ + 1;
do { errno = 0; numBytesRead = read(port->handle, port->readBuffer + numBytesReadTotal, bytesRemaining); port->errorNumber = errno; } while ((numBytesRead < 0) && (errno == EINTR));
if ((numBytesRead == -1) || ((numBytesRead == 0) && (ioctl(port->handle, FIONREAD, &ioctlResult) == -1)))
break;
}
// Fix index variables
numBytesReadTotal += numBytesRead;
@ -624,7 +496,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
else if ((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_BLOCKING) > 0) // Blocking mode, but not indefinitely
{
// Get current system time
struct timeval expireTime = {0}, currTime = {0};
struct timeval expireTime = { 0 }, currTime = { 0 };
gettimeofday(&expireTime, NULL);
expireTime.tv_usec += (readTimeout * 1000);
if (expireTime.tv_usec > 1000000)
@ -636,14 +508,10 @@ 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
{
do { numBytesRead = read(serialPortFD, readBuffer+numBytesReadTotal, bytesRemaining); } while ((numBytesRead < 0) && (errno == EINTR));
if ((numBytesRead == -1) || ((numBytesRead == 0) && (ioctl(serialPortFD, FIONREAD, &ioctlResult) == -1)))
{
// Problem reading, close the port
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
serialPortFD = -1;
port->errorLineNumber = __LINE__ + 1;
do { errno = 0; numBytesRead = read(port->handle, port->readBuffer + numBytesReadTotal, bytesRemaining); port->errorNumber = errno; } while ((numBytesRead < 0) && (errno == EINTR));
if ((numBytesRead == -1) || ((numBytesRead == 0) && (ioctl(port->handle, FIONREAD, &ioctlResult) == -1)))
break;
}
// Fix index variables
numBytesReadTotal += numBytesRead;
@ -655,78 +523,62 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
}
else // Semi- or non-blocking specified
{
// Read from port
do { numBytesRead = read(serialPortFD, readBuffer, bytesToRead); } while ((numBytesRead < 0) && (errno == EINTR));
if ((numBytesRead == -1) || ((numBytesRead == 0) && (ioctl(serialPortFD, FIONREAD, &ioctlResult) == -1)))
{
// Problem reading, close the port
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
serialPortFD = -1;
}
else
// Read from the port
port->errorLineNumber = __LINE__ + 1;
do { errno = 0; numBytesRead = read(port->handle, port->readBuffer, bytesToRead); port->errorNumber = errno; } while ((numBytesRead < 0) && (errno == EINTR));
if (numBytesRead > 0)
numBytesReadTotal = numBytesRead;
}
// Return number of bytes read if successful
(*env)->SetByteArrayRegion(env, buffer, offset, numBytesReadTotal, (jbyte*)readBuffer);
free(readBuffer);
return ((numBytesRead == -1) || (serialPortFD == -1)) ? -1 : numBytesReadTotal;
(*env)->SetByteArrayRegion(env, buffer, offset, numBytesReadTotal, (jbyte*)port->readBuffer);
return (numBytesRead == -1) ? -1 : numBytesReadTotal;
}
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToWrite, jlong offset)
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jlong serialPortPointer, jbyteArray buffer, jlong bytesToWrite, jlong offset, jint timeoutMode)
{
if (serialPortFD <= 0)
return -1;
int timeoutMode = (*env)->GetIntField(env, obj, timeoutModeField);
// Retrieve port parameters from the Java class
serialPort *port = (serialPort*)(intptr_t)serialPortPointer;
jbyte *writeBuffer = (*env)->GetByteArrayElements(env, buffer, 0);
int numBytesWritten, result = 0, ioctlResult = 0;
// Write to port
do { numBytesWritten = write(serialPortFD, writeBuffer+offset, bytesToWrite); } while ((numBytesWritten < 0) && (errno == EINTR));
if ((numBytesWritten == -1) || ((numBytesWritten == 0) && (ioctl(serialPortFD, FIONREAD, &ioctlResult) == -1)))
{
// Problem writing, close the port
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
serialPortFD = -1;
}
// Write to the port
do {
errno = 0;
port->errorLineNumber = __LINE__ + 1;
numBytesWritten = write(port->handle, writeBuffer + offset, bytesToWrite);
port->errorNumber = errno;
} while ((numBytesWritten < 0) && (errno == EINTR));
// Wait until all bytes were written in write-blocking mode
if (((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_WRITE_BLOCKING) > 0) && (serialPortFD > 0))
tcdrain(serialPortFD);
if (((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_WRITE_BLOCKING) > 0) && (numBytesWritten > 0))
tcdrain(port->handle);
// Return number of bytes written if successful
// Return the number of bytes written if successful
(*env)->ReleaseByteArrayElements(env, buffer, writeBuffer, JNI_ABORT);
return numBytesWritten;
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_setBreak(JNIEnv *env, jobject obj, jlong serialPortFD)
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_setBreak(JNIEnv *env, jobject obj, jlong serialPortPointer)
{
if (serialPortFD <= 0)
return JNI_FALSE;
return (ioctl(serialPortFD, TIOCSBRK) == 0);
return (ioctl(((serialPort*)(intptr_t)serialPortPointer)->handle, TIOCSBRK) == 0);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_clearBreak(JNIEnv *env, jobject obj, jlong serialPortFD)
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_clearBreak(JNIEnv *env, jobject obj, jlong serialPortPointer)
{
if (serialPortFD <= 0)
return JNI_FALSE;
return (ioctl(serialPortFD, TIOCCBRK) == 0);
return (ioctl(((serialPort*)(intptr_t)serialPortPointer)->handle, TIOCCBRK) == 0);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_setRTS(JNIEnv *env, jobject obj, jlong serialPortFD)
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_setRTS(JNIEnv *env, jobject obj, jlong serialPortPointer)
{
if (serialPortFD <= 0)
return JNI_FALSE;
int modemBits = TIOCM_RTS;
return (ioctl(serialPortFD, TIOCMBIS, &modemBits) == 0);
const int modemBits = TIOCM_RTS;
return (ioctl(((serialPort*)(intptr_t)serialPortPointer)->handle, TIOCMBIS, &modemBits) == 0);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_clearRTS(JNIEnv *env, jobject obj, jlong serialPortFD)
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_clearRTS(JNIEnv *env, jobject obj, jlong serialPortPointer)
{
if (serialPortFD <= 0)
return JNI_FALSE;
int modemBits = TIOCM_RTS;
return (ioctl(serialPortFD, TIOCMBIC, &modemBits) == 0);
const int modemBits = TIOCM_RTS;
return (ioctl(((serialPort*)(intptr_t)serialPortPointer)->handle, TIOCMBIC, &modemBits) == 0);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_presetRTS(JNIEnv *env, jobject obj)
@ -765,20 +617,16 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_preclearRTS(
return (result == 0);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_setDTR(JNIEnv *env, jobject obj, jlong serialPortFD)
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_setDTR(JNIEnv *env, jobject obj, jlong serialPortPointer)
{
if (serialPortFD <= 0)
return JNI_FALSE;
int modemBits = TIOCM_DTR;
return (ioctl(serialPortFD, TIOCMBIS, &modemBits) == 0);
const int modemBits = TIOCM_DTR;
return (ioctl(((serialPort*)(intptr_t)serialPortPointer)->handle, TIOCMBIS, &modemBits) == 0);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_clearDTR(JNIEnv *env, jobject obj, jlong serialPortFD)
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_clearDTR(JNIEnv *env, jobject obj, jlong serialPortPointer)
{
if (serialPortFD <= 0)
return JNI_FALSE;
int modemBits = TIOCM_DTR;
return (ioctl(serialPortFD, TIOCMBIC, &modemBits) == 0);
const int modemBits = TIOCM_DTR;
return (ioctl(((serialPort*)(intptr_t)serialPortPointer)->handle, TIOCMBIC, &modemBits) == 0);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_presetDTR(JNIEnv *env, jobject obj)
@ -804,7 +652,7 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_preclearDTR(
jstring portNameJString = (jstring)(*env)->GetObjectField(env, obj, comPortField);
const char *portName = (*env)->GetStringUTFChars(env, portNameJString, NULL);
// Send a system command to preset the DTR mode of the serial port
// Send a system command to preclear the DTR mode of the serial port
char commandString[128];
#if defined(__linux__)
sprintf(commandString, "stty -F %s -hupcl >>/dev/null 2>&1", portName);
@ -817,50 +665,48 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_preclearDTR(
return (result == 0);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCTS(JNIEnv *env, jobject obj, jlong serialPortFD)
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCTS(JNIEnv *env, jobject obj, jlong serialPortPointer)
{
if (serialPortFD <= 0)
return JNI_FALSE;
int modemBits = 0;
return (ioctl(serialPortFD, TIOCMGET, &modemBits) == 0) && (modemBits & TIOCM_CTS);
return (ioctl(((serialPort*)(intptr_t)serialPortPointer)->handle, TIOCMGET, &modemBits) == 0) && (modemBits & TIOCM_CTS);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_getDSR(JNIEnv *env, jobject obj, jlong serialPortFD)
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_getDSR(JNIEnv *env, jobject obj, jlong serialPortPointer)
{
if (serialPortFD <= 0)
return JNI_FALSE;
int modemBits = 0;
return (ioctl(serialPortFD, TIOCMGET, &modemBits) == 0) && (modemBits & TIOCM_DSR);
return (ioctl(((serialPort*)(intptr_t)serialPortPointer)->handle, TIOCMGET, &modemBits) == 0) && (modemBits & TIOCM_DSR);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_getDCD(JNIEnv *env, jobject obj, jlong serialPortFD)
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_getDCD(JNIEnv *env, jobject obj, jlong serialPortPointer)
{
if (serialPortFD <= 0)
return JNI_FALSE;
int modemBits = 0;
return (ioctl(serialPortFD, TIOCMGET, &modemBits) == 0) && (modemBits & TIOCM_CAR);
return (ioctl(((serialPort*)(intptr_t)serialPortPointer)->handle, TIOCMGET, &modemBits) == 0) && (modemBits & TIOCM_CAR);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_getDTR(JNIEnv *env, jobject obj, jlong serialPortFD)
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_getDTR(JNIEnv *env, jobject obj, jlong serialPortPointer)
{
if (serialPortFD <= 0)
return JNI_FALSE;
int modemBits = 0;
return (ioctl(serialPortFD, TIOCMGET, &modemBits) == 0) && (modemBits & TIOCM_DTR);
return (ioctl(((serialPort*)(intptr_t)serialPortPointer)->handle, TIOCMGET, &modemBits) == 0) && (modemBits & TIOCM_DTR);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_getRTS(JNIEnv *env, jobject obj, jlong serialPortFD)
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_getRTS(JNIEnv *env, jobject obj, jlong serialPortPointer)
{
if (serialPortFD <= 0)
return JNI_FALSE;
int modemBits = 0;
return (ioctl(serialPortFD, TIOCMGET, &modemBits) == 0) && (modemBits & TIOCM_RTS);
return (ioctl(((serialPort*)(intptr_t)serialPortPointer)->handle, TIOCMGET, &modemBits) == 0) && (modemBits & TIOCM_RTS);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_getRI(JNIEnv *env, jobject obj, jlong serialPortFD)
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_getRI(JNIEnv *env, jobject obj, jlong serialPortPointer)
{
if (serialPortFD <= 0)
return JNI_FALSE;
int modemBits = 0;
return (ioctl(serialPortFD, TIOCMGET, &modemBits) == 0) && (modemBits & TIOCM_RI);
return (ioctl(((serialPort*)(intptr_t)serialPortPointer)->handle, TIOCMGET, &modemBits) == 0) && (modemBits & TIOCM_RI);
}
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_getLastErrorLocation(JNIEnv *env, jobject obj, jlong serialPortPointer)
{
return ((serialPort*)(intptr_t)serialPortPointer)->errorLineNumber;
}
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_getLastErrorCode(JNIEnv *env, jobject obj, jlong serialPortPointer)
{
return ((serialPort*)(intptr_t)serialPortPointer)->errorNumber;
}

View File

@ -88,9 +88,9 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative
/*
* Class: com_fazecast_jSerialComm_SerialPort
* Method: closePortNative
* Signature: (J)Z
* Signature: (J)J
*/
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNative
JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNative
(JNIEnv *, jobject, jlong);
/*
@ -104,18 +104,10 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort
/*
* Class: com_fazecast_jSerialComm_SerialPort
* Method: configTimeouts
* Signature: (J)Z
* Signature: (JIIII)Z
*/
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeouts
(JNIEnv *, jobject, jlong);
/*
* Class: com_fazecast_jSerialComm_SerialPort
* Method: configEventFlags
* Signature: (J)Z
*/
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventFlags
(JNIEnv *, jobject, jlong);
(JNIEnv *, jobject, jlong, jint, jint, jint, jint);
/*
* Class: com_fazecast_jSerialComm_SerialPort
@ -144,18 +136,18 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAwaitingWri
/*
* Class: com_fazecast_jSerialComm_SerialPort
* Method: readBytes
* Signature: (J[BJJ)I
* Signature: (J[BJJII)I
*/
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes
(JNIEnv *, jobject, jlong, jbyteArray, jlong, jlong);
(JNIEnv *, jobject, jlong, jbyteArray, jlong, jlong, jint, jint);
/*
* Class: com_fazecast_jSerialComm_SerialPort
* Method: writeBytes
* Signature: (J[BJJ)I
* Signature: (J[BJJI)I
*/
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes
(JNIEnv *, jobject, jlong, jbyteArray, jlong, jlong);
(JNIEnv *, jobject, jlong, jbyteArray, jlong, jlong, jint);
/*
* Class: com_fazecast_jSerialComm_SerialPort
@ -285,6 +277,22 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_getRTS
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_getRI
(JNIEnv *, jobject, jlong);
/*
* Class: com_fazecast_jSerialComm_SerialPort
* Method: getLastErrorLocation
* Signature: (J)I
*/
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_getLastErrorLocation
(JNIEnv *, jobject, jlong);
/*
* Class: com_fazecast_jSerialComm_SerialPort
* Method: getLastErrorCode
* Signature: (J)I
*/
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_getLastErrorCode
(JNIEnv *, jobject, jlong);
#ifdef __cplusplus
}
#endif