Complete overhaul of Posix native implementation
This commit is contained in:
parent
bc39570ff1
commit
28efbd1a51
|
@ -2,7 +2,7 @@
|
||||||
* SerialPort_Posix.c
|
* SerialPort_Posix.c
|
||||||
*
|
*
|
||||||
* Created on: Feb 25, 2012
|
* Created on: Feb 25, 2012
|
||||||
* Last Updated on: Nov 03, 2021
|
* Last Updated on: Nov 14, 2021
|
||||||
* Author: Will Hedgecock
|
* Author: Will Hedgecock
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012-2021 Fazecast, Inc.
|
* Copyright (C) 2012-2021 Fazecast, Inc.
|
||||||
|
@ -38,18 +38,8 @@
|
||||||
#include <linux/serial.h>
|
#include <linux/serial.h>
|
||||||
#elif defined(__sun__)
|
#elif defined(__sun__)
|
||||||
#include <sys/filio.h>
|
#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
|
#endif
|
||||||
#include "PosixHelperFunctions.h"
|
#include "PosixHelperFunctions.h"
|
||||||
#include "../com_fazecast_jSerialComm_SerialPort.h"
|
|
||||||
|
|
||||||
// Cached class, method, and field IDs
|
// Cached class, method, and field IDs
|
||||||
jclass serialCommClass;
|
jclass serialCommClass;
|
||||||
|
@ -81,139 +71,52 @@ jfieldID readTimeoutField;
|
||||||
jfieldID writeTimeoutField;
|
jfieldID writeTimeoutField;
|
||||||
jfieldID eventFlagsField;
|
jfieldID eventFlagsField;
|
||||||
|
|
||||||
|
// List of available serial ports
|
||||||
|
serialPortVector serialPorts = { NULL, 0 };
|
||||||
|
|
||||||
JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommPorts(JNIEnv *env, jclass serialComm)
|
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__)
|
#if defined(__linux__)
|
||||||
{
|
|
||||||
// Enumerate serial ports on machine
|
|
||||||
charTupleVector serialPorts = { (char**)malloc(1), (char**)malloc(1), (char**)malloc(1), 0 };
|
|
||||||
recursiveSearchForComPorts(&serialPorts, "/sys/devices/");
|
recursiveSearchForComPorts(&serialPorts, "/sys/devices/");
|
||||||
|
driverBasedSearchForComPorts(&serialPorts, "/proc/tty/driver/serial", "/dev/ttyS");
|
||||||
|
driverBasedSearchForComPorts(&serialPorts, "/proc/tty/driver/mvebu_serial", "/dev/ttyMV");
|
||||||
lastDitchSearchForComPorts(&serialPorts);
|
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
|
#elif defined(__sun__) || defined(__APPLE__)
|
||||||
(*env)->SetObjectArrayElement(env, arrayObject, i, serialCommObject);
|
|
||||||
}
|
|
||||||
free(serialPorts.first);
|
|
||||||
free(serialPorts.second);
|
|
||||||
free(serialPorts.third);
|
|
||||||
|
|
||||||
return arrayObject;
|
|
||||||
}
|
|
||||||
#elif defined(__sun__)
|
|
||||||
{
|
|
||||||
// Enumerate serial ports on machine
|
|
||||||
charTupleVector serialPorts = { (char**)malloc(1), (char**)malloc(1), (char**)malloc(1), 0 };
|
|
||||||
searchForComPorts(&serialPorts);
|
searchForComPorts(&serialPorts);
|
||||||
jobjectArray arrayObject = (*env)->NewObjectArray(env, serialPorts.length, serialCommClass, 0);
|
|
||||||
int i;
|
#endif
|
||||||
for (i = 0; i < serialPorts.length; ++i)
|
|
||||||
|
// Remove all non-enumerated ports from the serial port listing
|
||||||
|
for (int i = 0; i < serialPorts.length; ++i)
|
||||||
|
if (!serialPorts.ports[i]->enumerated)
|
||||||
{
|
{
|
||||||
// Create new SerialComm object containing the enumerated values
|
removePort(&serialPorts, serialPorts.ports[i]);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a Java-based port listing
|
||||||
|
jobjectArray arrayObject = (*env)->NewObjectArray(env, serialPorts.length, serialCommClass, 0);
|
||||||
|
for (int i = 0; i < serialPorts.length; ++i)
|
||||||
|
{
|
||||||
|
// Create a new SerialComm object containing the enumerated values
|
||||||
jobject serialCommObject = (*env)->NewObject(env, serialCommClass, serialCommConstructor);
|
jobject serialCommObject = (*env)->NewObject(env, serialCommClass, serialCommConstructor);
|
||||||
(*env)->SetObjectField(env, serialCommObject, portDescriptionField, (*env)->NewStringUTF(env, serialPorts.third[i]));
|
(*env)->SetObjectField(env, serialCommObject, portDescriptionField, (*env)->NewStringUTF(env, serialPorts.ports[i]->portDescription));
|
||||||
(*env)->SetObjectField(env, serialCommObject, friendlyNameField, (*env)->NewStringUTF(env, serialPorts.second[i]));
|
(*env)->SetObjectField(env, serialCommObject, friendlyNameField, (*env)->NewStringUTF(env, serialPorts.ports[i]->friendlyName));
|
||||||
(*env)->SetObjectField(env, serialCommObject, comPortField, (*env)->NewStringUTF(env, serialPorts.first[i]));
|
(*env)->SetObjectField(env, serialCommObject, comPortField, (*env)->NewStringUTF(env, serialPorts.ports[i]->portPath));
|
||||||
free(serialPorts.first[i]);
|
|
||||||
free(serialPorts.second[i]);
|
|
||||||
free(serialPorts.third[i]);
|
|
||||||
|
|
||||||
// Add new SerialComm object to array
|
// Add new SerialComm object to array
|
||||||
(*env)->SetObjectArrayElement(env, arrayObject, i, serialCommObject);
|
(*env)->SetObjectArrayElement(env, arrayObject, i, serialCommObject);
|
||||||
}
|
}
|
||||||
free(serialPorts.first);
|
|
||||||
free(serialPorts.second);
|
|
||||||
free(serialPorts.third);
|
|
||||||
|
|
||||||
return arrayObject;
|
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)
|
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");
|
writeTimeoutField = (*env)->GetFieldID(env, serialCommClass, "writeTimeout", "I");
|
||||||
eventFlagsField = (*env)->GetFieldID(env, serialCommClass, "eventFlags", "I");
|
eventFlagsField = (*env)->GetFieldID(env, serialCommClass, "eventFlags", "I");
|
||||||
|
|
||||||
// Disable handling of SIGIO POSIX signals
|
// Disable handling of various POSIX signals
|
||||||
sigset_t blockMask;
|
sigset_t blockMask;
|
||||||
sigemptyset(&blockMask);
|
sigemptyset(&blockMask);
|
||||||
struct sigaction ignoreAction = { 0 };
|
struct sigaction ignoreAction = { 0 };
|
||||||
ignoreAction.sa_handler = SIG_IGN;
|
ignoreAction.sa_handler = SIG_IGN;
|
||||||
ignoreAction.sa_mask = blockMask;
|
ignoreAction.sa_mask = blockMask;
|
||||||
sigaction(SIGIO, &ignoreAction, NULL);
|
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)
|
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);
|
(*env)->DeleteGlobalRef(env, serialCommClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(JNIEnv *env, jobject obj)
|
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);
|
jstring portNameJString = (jstring)(*env)->GetObjectField(env, obj, comPortField);
|
||||||
const char *portName = (*env)->GetStringUTFChars(env, portNameJString, NULL);
|
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 disableExclusiveLock = (*env)->GetBooleanField(env, obj, disableExclusiveLockField);
|
||||||
|
unsigned char disableAutoConfig = (*env)->GetBooleanField(env, obj, disableConfigField);
|
||||||
|
|
||||||
// Try to open existing serial port with read/write access
|
// Ensure that the serial port still exists and is not already open
|
||||||
int serialPortFD = -1;
|
serialPort *port = fetchPort(&serialPorts, portName);
|
||||||
if ((serialPortFD = open(portName, O_RDWR | O_NOCTTY | O_NONBLOCK)) > 0)
|
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
|
// 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;
|
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
|
// Close the port if there was a problem setting the parameters
|
||||||
while ((close(serialPortFD) == -1) && (errno == EINTR))
|
fcntl(port->handle, F_SETFL, O_NONBLOCK);
|
||||||
|
while (close(port->handle) && (errno == EINTR))
|
||||||
errno = 0;
|
errno = 0;
|
||||||
serialPortFD = -1;
|
port->handle = -1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
port->errorNumber = errno;
|
||||||
|
|
||||||
|
// Return a pointer to the serial port data structure
|
||||||
(*env)->ReleaseStringUTFChars(env, portNameJString, portName);
|
(*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)
|
// Retrieve port parameters from the Java class
|
||||||
return JNI_FALSE;
|
serialPort *port = (serialPort*)(intptr_t)serialPortPointer;
|
||||||
struct termios options = {0};
|
|
||||||
|
|
||||||
// Get port parameters from Java class
|
|
||||||
baud_rate baudRate = (*env)->GetIntField(env, obj, baudRateField);
|
baud_rate baudRate = (*env)->GetIntField(env, obj, baudRateField);
|
||||||
int byteSizeInt = (*env)->GetIntField(env, obj, dataBitsField);
|
int byteSizeInt = (*env)->GetIntField(env, obj, dataBitsField);
|
||||||
int stopBitsInt = (*env)->GetIntField(env, obj, stopBitsField);
|
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 receiveDeviceQueueSize = (*env)->GetIntField(env, obj, receiveDeviceQueueSizeField);
|
||||||
int rs485DelayBefore = (*env)->GetIntField(env, obj, rs485DelayBeforeField);
|
int rs485DelayBefore = (*env)->GetIntField(env, obj, rs485DelayBeforeField);
|
||||||
int rs485DelayAfter = (*env)->GetIntField(env, obj, rs485DelayAfterField);
|
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 rs485ModeEnabled = (*env)->GetBooleanField(env, obj, rs485ModeField);
|
||||||
unsigned char rs485ActiveHigh = (*env)->GetBooleanField(env, obj, rs485ActiveHighField);
|
unsigned char rs485ActiveHigh = (*env)->GetBooleanField(env, obj, rs485ActiveHighField);
|
||||||
unsigned char rs485EnableTermination = (*env)->GetBooleanField(env, obj, rs485EnableTerminationField);
|
unsigned char rs485EnableTermination = (*env)->GetBooleanField(env, obj, rs485EnableTerminationField);
|
||||||
unsigned char rs485RxDuringTx = (*env)->GetBooleanField(env, obj, rs485RxDuringTxField);
|
unsigned char rs485RxDuringTx = (*env)->GetBooleanField(env, obj, rs485RxDuringTxField);
|
||||||
unsigned char isDtrEnabled = (*env)->GetBooleanField(env, obj, isDtrEnabledField);
|
unsigned char isDtrEnabled = (*env)->GetBooleanField(env, obj, isDtrEnabledField);
|
||||||
unsigned char isRtsEnabled = (*env)->GetBooleanField(env, obj, isRtsEnabledField);
|
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 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);
|
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);
|
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)
|
if (!isDtrEnabled || !isRtsEnabled)
|
||||||
options.c_cflag &= ~HUPCL;
|
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)
|
if (byteSizeInt < 8)
|
||||||
options.c_iflag |= ISTRIP;
|
options.c_iflag |= ISTRIP;
|
||||||
if (parityInt != 0)
|
if (parityInt != 0)
|
||||||
options.c_iflag |= (INPCK | IGNPAR);
|
options.c_iflag |= (INPCK | IGNPAR);
|
||||||
if (XonXoffInEnabled)
|
if ((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_XONXOFF_IN_ENABLED) > 0)
|
||||||
options.c_iflag |= IXOFF;
|
options.c_iflag |= IXOFF;
|
||||||
else
|
if ((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_XONXOFF_OUT_ENABLED) > 0)
|
||||||
options.c_cflag &= ~(IXOFF);
|
|
||||||
if (XonXoffOutEnabled)
|
|
||||||
options.c_iflag |= IXON;
|
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);
|
baud_rate baudRateCode = getBaudRateCode(baudRate);
|
||||||
unsigned char nonStandardBaudRate = (baudRateCode == 0);
|
if (!baudRateCode)
|
||||||
if (nonStandardBaudRate)
|
|
||||||
baudRateCode = B38400;
|
baudRateCode = B38400;
|
||||||
cfsetispeed(&options, baudRateCode);
|
cfsetispeed(&options, baudRateCode);
|
||||||
cfsetospeed(&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__)
|
#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.xmit_fifo_size = sendDeviceQueueSize;
|
||||||
serInfo.flags |= ASYNC_LOW_LATENCY;
|
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
|
// Attempt to set the requested RS-485 mode
|
||||||
#if defined(__linux__)
|
struct serial_rs485 rs485Conf = { 0 };
|
||||||
struct serial_rs485 rs485Conf = {0};
|
if (!ioctl(port->handle, TIOCGRS485, &rs485Conf))
|
||||||
if (ioctl(serialPortFD, TIOCGRS485, &rs485Conf) == 0)
|
|
||||||
{
|
{
|
||||||
if (rs485ModeEnabled)
|
if (rs485ModeEnabled)
|
||||||
rs485Conf.flags |= SER_RS485_ENABLED;
|
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.flags &= ~(SER_RS485_TERMINATE_BUS);
|
||||||
rs485Conf.delay_rts_before_send = rs485DelayBefore / 1000;
|
rs485Conf.delay_rts_before_send = rs485DelayBefore / 1000;
|
||||||
rs485Conf.delay_rts_after_send = rs485DelayAfter / 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
|
#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
|
// Retrieve the existing port configuration
|
||||||
if (serialPortFD <= 0)
|
int flags = 0;
|
||||||
return JNI_FALSE;
|
struct termios options = { 0 };
|
||||||
|
serialPort *port = (serialPort*)(intptr_t)serialPortPointer;
|
||||||
baud_rate baudRate = (*env)->GetIntField(env, obj, baudRateField);
|
baud_rate baudRate = (*env)->GetIntField(env, obj, baudRateField);
|
||||||
baud_rate baudRateCode = getBaudRateCode(baudRate);
|
tcgetattr(port->handle, &options);
|
||||||
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;
|
|
||||||
|
|
||||||
// Set updated port timeouts
|
// 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[VMIN] = 0;
|
||||||
options.c_cc[VTIME] = readTimeout / 100;
|
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[VMIN] = 1;
|
||||||
options.c_cc[VTIME] = 0;
|
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[VMIN] = 0;
|
||||||
options.c_cc[VTIME] = readTimeout / 100;
|
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[VMIN] = 1;
|
||||||
options.c_cc[VTIME] = 0;
|
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[VMIN] = 1;
|
||||||
options.c_cc[VTIME] = 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[VMIN] = 0;
|
||||||
options.c_cc[VTIME] = 0;
|
options.c_cc[VTIME] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply changes
|
// Apply changes
|
||||||
int retVal = fcntl(serialPortFD, F_SETFL, flags);
|
if (fcntl(port->handle, 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)
|
|
||||||
{
|
{
|
||||||
struct termios options = {0};
|
port->errorLineNumber = __LINE__ - 2;
|
||||||
tcgetattr(serialPortFD, &options);
|
port->errorNumber = errno;
|
||||||
int flags = fcntl(serialPortFD, F_GETFL);
|
|
||||||
if (flags == -1)
|
|
||||||
return JNI_FALSE;
|
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);
|
|
||||||
}
|
}
|
||||||
else
|
if (tcsetattr(port->handle, TCSANOW, &options) || tcsetattr(port->handle, TCSANOW, &options))
|
||||||
retVal = Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(env, obj, serialPortFD);
|
{
|
||||||
|
port->errorLineNumber = __LINE__ - 2;
|
||||||
// Apply changes
|
port->errorNumber = errno;
|
||||||
return retVal;
|
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
|
// Initialize the waiting set
|
||||||
if (serialPortFD <= 0)
|
serialPort *port = (serialPort*)(intptr_t)serialPortPointer;
|
||||||
return 0;
|
struct pollfd waitingSet = { port->handle, POLLIN, 0 };
|
||||||
struct pollfd waitingSet = { serialPortFD, 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
|
// Wait for a serial port event
|
||||||
if (poll(&waitingSet, 1, 500) <= 0)
|
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;
|
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
|
// Unblock, unlock, and close the port
|
||||||
if (serialPortFD <= 0)
|
serialPort *port = (serialPort*)(intptr_t)serialPortPointer;
|
||||||
return JNI_TRUE;
|
fsync(port->handle);
|
||||||
|
tcdrain(port->handle);
|
||||||
// Force the port to enter non-blocking mode to ensure that any current reads return
|
tcflush(port->handle, TCIOFLUSH);
|
||||||
struct termios options = {0};
|
fcntl(port->handle, F_SETFL, O_NONBLOCK);
|
||||||
tcgetattr(serialPortFD, &options);
|
flock(port->handle, LOCK_UN | LOCK_NB);
|
||||||
int flags = fcntl(serialPortFD, F_GETFL);
|
while (close(port->handle) && (errno == EINTR))
|
||||||
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))
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
|
port->handle = -1;
|
||||||
return JNI_TRUE;
|
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;
|
int numBytesAvailable = -1;
|
||||||
if ((serialPortFD > 0) && (ioctl(serialPortFD, FIONREAD, &numBytesAvailable) == -1))
|
ioctl(((serialPort*)(intptr_t)serialPortPointer)->handle, FIONREAD, &numBytesAvailable);
|
||||||
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
|
|
||||||
return 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;
|
int numBytesToWrite = -1;
|
||||||
if ((serialPortFD > 0) && (ioctl(serialPortFD, TIOCOUTQ, &numBytesToWrite) == -1))
|
ioctl(((serialPort*)(intptr_t)serialPortPointer)->handle, TIOCOUTQ, &numBytesToWrite);
|
||||||
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
|
|
||||||
return 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
|
// Ensure that the allocated read buffer is large enough
|
||||||
if (serialPortFD <= 0)
|
serialPort *port = (serialPort*)(intptr_t)serialPortPointer;
|
||||||
return -1;
|
|
||||||
int timeoutMode = (*env)->GetIntField(env, obj, timeoutModeField);
|
|
||||||
int readTimeout = (*env)->GetIntField(env, obj, readTimeoutField);
|
|
||||||
int numBytesRead, numBytesReadTotal = 0, bytesRemaining = bytesToRead, ioctlResult = 0;
|
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
|
// 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))
|
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 there are more bytes we are supposed to read
|
||||||
while (bytesRemaining > 0)
|
while (bytesRemaining > 0)
|
||||||
{
|
{
|
||||||
do { numBytesRead = read(serialPortFD, readBuffer+numBytesReadTotal, bytesRemaining); } while ((numBytesRead < 0) && (errno == EINTR));
|
// Attempt to read some number of bytes from the serial port
|
||||||
if ((numBytesRead == -1) || ((numBytesRead == 0) && (ioctl(serialPortFD, FIONREAD, &ioctlResult) == -1)))
|
port->errorLineNumber = __LINE__ + 1;
|
||||||
{
|
do { errno = 0; numBytesRead = read(port->handle, port->readBuffer + numBytesReadTotal, bytesRemaining); port->errorNumber = errno; } while ((numBytesRead < 0) && (errno == EINTR));
|
||||||
// Problem reading, close the port
|
if ((numBytesRead == -1) || ((numBytesRead == 0) && (ioctl(port->handle, FIONREAD, &ioctlResult) == -1)))
|
||||||
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
|
|
||||||
serialPortFD = -1;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
// Fix index variables
|
// Fix index variables
|
||||||
numBytesReadTotal += numBytesRead;
|
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
|
else if ((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_BLOCKING) > 0) // Blocking mode, but not indefinitely
|
||||||
{
|
{
|
||||||
// Get current system time
|
// Get current system time
|
||||||
struct timeval expireTime = {0}, currTime = {0};
|
struct timeval expireTime = { 0 }, currTime = { 0 };
|
||||||
gettimeofday(&expireTime, NULL);
|
gettimeofday(&expireTime, NULL);
|
||||||
expireTime.tv_usec += (readTimeout * 1000);
|
expireTime.tv_usec += (readTimeout * 1000);
|
||||||
if (expireTime.tv_usec > 1000000)
|
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
|
// While there are more bytes we are supposed to read and the timeout has not elapsed
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
do { numBytesRead = read(serialPortFD, readBuffer+numBytesReadTotal, bytesRemaining); } while ((numBytesRead < 0) && (errno == EINTR));
|
port->errorLineNumber = __LINE__ + 1;
|
||||||
if ((numBytesRead == -1) || ((numBytesRead == 0) && (ioctl(serialPortFD, FIONREAD, &ioctlResult) == -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)))
|
||||||
// Problem reading, close the port
|
|
||||||
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
|
|
||||||
serialPortFD = -1;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
// Fix index variables
|
// Fix index variables
|
||||||
numBytesReadTotal += numBytesRead;
|
numBytesReadTotal += numBytesRead;
|
||||||
|
@ -655,78 +523,62 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
|
||||||
}
|
}
|
||||||
else // Semi- or non-blocking specified
|
else // Semi- or non-blocking specified
|
||||||
{
|
{
|
||||||
// Read from port
|
// Read from the port
|
||||||
do { numBytesRead = read(serialPortFD, readBuffer, bytesToRead); } while ((numBytesRead < 0) && (errno == EINTR));
|
port->errorLineNumber = __LINE__ + 1;
|
||||||
if ((numBytesRead == -1) || ((numBytesRead == 0) && (ioctl(serialPortFD, FIONREAD, &ioctlResult) == -1)))
|
do { errno = 0; numBytesRead = read(port->handle, port->readBuffer, bytesToRead); port->errorNumber = errno; } while ((numBytesRead < 0) && (errno == EINTR));
|
||||||
{
|
if (numBytesRead > 0)
|
||||||
// Problem reading, close the port
|
|
||||||
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
|
|
||||||
serialPortFD = -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
numBytesReadTotal = numBytesRead;
|
numBytesReadTotal = numBytesRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return number of bytes read if successful
|
// Return number of bytes read if successful
|
||||||
(*env)->SetByteArrayRegion(env, buffer, offset, numBytesReadTotal, (jbyte*)readBuffer);
|
(*env)->SetByteArrayRegion(env, buffer, offset, numBytesReadTotal, (jbyte*)port->readBuffer);
|
||||||
free(readBuffer);
|
return (numBytesRead == -1) ? -1 : numBytesReadTotal;
|
||||||
return ((numBytesRead == -1) || (serialPortFD == -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)
|
// Retrieve port parameters from the Java class
|
||||||
return -1;
|
serialPort *port = (serialPort*)(intptr_t)serialPortPointer;
|
||||||
int timeoutMode = (*env)->GetIntField(env, obj, timeoutModeField);
|
|
||||||
jbyte *writeBuffer = (*env)->GetByteArrayElements(env, buffer, 0);
|
jbyte *writeBuffer = (*env)->GetByteArrayElements(env, buffer, 0);
|
||||||
int numBytesWritten, result = 0, ioctlResult = 0;
|
int numBytesWritten, result = 0, ioctlResult = 0;
|
||||||
|
|
||||||
// Write to port
|
// Write to the port
|
||||||
do { numBytesWritten = write(serialPortFD, writeBuffer+offset, bytesToWrite); } while ((numBytesWritten < 0) && (errno == EINTR));
|
do {
|
||||||
if ((numBytesWritten == -1) || ((numBytesWritten == 0) && (ioctl(serialPortFD, FIONREAD, &ioctlResult) == -1)))
|
errno = 0;
|
||||||
{
|
port->errorLineNumber = __LINE__ + 1;
|
||||||
// Problem writing, close the port
|
numBytesWritten = write(port->handle, writeBuffer + offset, bytesToWrite);
|
||||||
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
|
port->errorNumber = errno;
|
||||||
serialPortFD = -1;
|
} while ((numBytesWritten < 0) && (errno == EINTR));
|
||||||
}
|
|
||||||
|
|
||||||
// Wait until all bytes were written in write-blocking mode
|
// Wait until all bytes were written in write-blocking mode
|
||||||
if (((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_WRITE_BLOCKING) > 0) && (serialPortFD > 0))
|
if (((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_WRITE_BLOCKING) > 0) && (numBytesWritten > 0))
|
||||||
tcdrain(serialPortFD);
|
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);
|
(*env)->ReleaseByteArrayElements(env, buffer, writeBuffer, JNI_ABORT);
|
||||||
return numBytesWritten;
|
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 (ioctl(((serialPort*)(intptr_t)serialPortPointer)->handle, TIOCSBRK) == 0);
|
||||||
return JNI_FALSE;
|
|
||||||
return (ioctl(serialPortFD, 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 (ioctl(((serialPort*)(intptr_t)serialPortPointer)->handle, TIOCCBRK) == 0);
|
||||||
return JNI_FALSE;
|
|
||||||
return (ioctl(serialPortFD, 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)
|
const int modemBits = TIOCM_RTS;
|
||||||
return JNI_FALSE;
|
return (ioctl(((serialPort*)(intptr_t)serialPortPointer)->handle, TIOCMBIS, &modemBits) == 0);
|
||||||
int modemBits = TIOCM_RTS;
|
|
||||||
return (ioctl(serialPortFD, 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)
|
const int modemBits = TIOCM_RTS;
|
||||||
return JNI_FALSE;
|
return (ioctl(((serialPort*)(intptr_t)serialPortPointer)->handle, TIOCMBIC, &modemBits) == 0);
|
||||||
int modemBits = TIOCM_RTS;
|
|
||||||
return (ioctl(serialPortFD, TIOCMBIC, &modemBits) == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_presetRTS(JNIEnv *env, jobject obj)
|
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);
|
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)
|
const int modemBits = TIOCM_DTR;
|
||||||
return JNI_FALSE;
|
return (ioctl(((serialPort*)(intptr_t)serialPortPointer)->handle, TIOCMBIS, &modemBits) == 0);
|
||||||
int modemBits = TIOCM_DTR;
|
|
||||||
return (ioctl(serialPortFD, 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)
|
const int modemBits = TIOCM_DTR;
|
||||||
return JNI_FALSE;
|
return (ioctl(((serialPort*)(intptr_t)serialPortPointer)->handle, TIOCMBIC, &modemBits) == 0);
|
||||||
int modemBits = TIOCM_DTR;
|
|
||||||
return (ioctl(serialPortFD, TIOCMBIC, &modemBits) == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_presetDTR(JNIEnv *env, jobject obj)
|
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);
|
jstring portNameJString = (jstring)(*env)->GetObjectField(env, obj, comPortField);
|
||||||
const char *portName = (*env)->GetStringUTFChars(env, portNameJString, NULL);
|
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];
|
char commandString[128];
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
sprintf(commandString, "stty -F %s -hupcl >>/dev/null 2>&1", portName);
|
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);
|
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;
|
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;
|
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;
|
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;
|
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;
|
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;
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,9 +88,9 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative
|
||||||
/*
|
/*
|
||||||
* Class: com_fazecast_jSerialComm_SerialPort
|
* Class: com_fazecast_jSerialComm_SerialPort
|
||||||
* Method: closePortNative
|
* 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);
|
(JNIEnv *, jobject, jlong);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -104,18 +104,10 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort
|
||||||
/*
|
/*
|
||||||
* Class: com_fazecast_jSerialComm_SerialPort
|
* Class: com_fazecast_jSerialComm_SerialPort
|
||||||
* Method: configTimeouts
|
* Method: configTimeouts
|
||||||
* Signature: (J)Z
|
* Signature: (JIIII)Z
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeouts
|
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeouts
|
||||||
(JNIEnv *, jobject, jlong);
|
(JNIEnv *, jobject, jlong, jint, jint, jint, jint);
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: com_fazecast_jSerialComm_SerialPort
|
|
||||||
* Method: configEventFlags
|
|
||||||
* Signature: (J)Z
|
|
||||||
*/
|
|
||||||
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventFlags
|
|
||||||
(JNIEnv *, jobject, jlong);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: com_fazecast_jSerialComm_SerialPort
|
* Class: com_fazecast_jSerialComm_SerialPort
|
||||||
|
@ -144,18 +136,18 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAwaitingWri
|
||||||
/*
|
/*
|
||||||
* Class: com_fazecast_jSerialComm_SerialPort
|
* Class: com_fazecast_jSerialComm_SerialPort
|
||||||
* Method: readBytes
|
* Method: readBytes
|
||||||
* Signature: (J[BJJ)I
|
* Signature: (J[BJJII)I
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes
|
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
|
* Class: com_fazecast_jSerialComm_SerialPort
|
||||||
* Method: writeBytes
|
* Method: writeBytes
|
||||||
* Signature: (J[BJJ)I
|
* Signature: (J[BJJI)I
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes
|
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
|
* 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
|
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_getRI
|
||||||
(JNIEnv *, jobject, jlong);
|
(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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue