Add new functionality to set custom XON/XOFF characters

This commit is contained in:
Will Hedgecock 2021-11-19 18:16:16 -06:00
parent b52271c48c
commit bd89ff1438
27 changed files with 77 additions and 4 deletions

View File

@ -2,7 +2,7 @@
* SerialPort_Posix.c
*
* Created on: Feb 25, 2012
* Last Updated on: Nov 14, 2021
* Last Updated on: Nov 19, 2021
* Author: Will Hedgecock
*
* Copyright (C) 2012-2021 Fazecast, Inc.
@ -66,6 +66,8 @@ jfieldID rs485EnableTerminationField;
jfieldID rs485RxDuringTxField;
jfieldID rs485DelayBeforeField;
jfieldID rs485DelayAfterField;
jfieldID xonStartCharField;
jfieldID xoffStopCharField;
jfieldID timeoutModeField;
jfieldID readTimeoutField;
jfieldID writeTimeoutField;
@ -147,6 +149,8 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrar
rs485RxDuringTxField = (*env)->GetFieldID(env, serialCommClass, "rs485RxDuringTx", "Z");
rs485DelayBeforeField = (*env)->GetFieldID(env, serialCommClass, "rs485DelayBefore", "I");
rs485DelayAfterField = (*env)->GetFieldID(env, serialCommClass, "rs485DelayAfter", "I");
xonStartCharField = (*env)->GetFieldID(env, serialCommClass, "xonStartChar", "B");
xoffStopCharField = (*env)->GetFieldID(env, serialCommClass, "xoffStopChar", "B");
timeoutModeField = (*env)->GetFieldID(env, serialCommClass, "timeoutMode", "I");
readTimeoutField = (*env)->GetFieldID(env, serialCommClass, "readTimeout", "I");
writeTimeoutField = (*env)->GetFieldID(env, serialCommClass, "writeTimeout", "I");
@ -248,10 +252,14 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J
unsigned char rs485RxDuringTx = (*env)->GetBooleanField(env, obj, rs485RxDuringTxField);
unsigned char isDtrEnabled = (*env)->GetBooleanField(env, obj, isDtrEnabledField);
unsigned char isRtsEnabled = (*env)->GetBooleanField(env, obj, isRtsEnabledField);
char xonStartChar = (*env)->GetByteField(env, obj, xonStartCharField);
char xoffStopChar = (*env)->GetByteField(env, obj, xoffStopCharField);
// Clear any serial port flags and set up raw non-canonical port parameters
struct termios options = { 0 };
tcgetattr(port->handle, &options);
options.c_cc[VSTART] = (unsigned char)xonStartChar;
options.c_cc[VSTOP] = (unsigned char)xoffStopChar;
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);
@ -423,6 +431,18 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNI
// 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
/*
ioctl: TIOCMIWAIT
ioctl: TIOCGICOUNT
static final public int LISTENING_EVENT_BREAK_INTERRUPT = 0x00010000;
static final public int LISTENING_EVENT_CARRIER_DETECT = 0x00020000;
static final public int LISTENING_EVENT_CTS = 0x00040000;
static final public int LISTENING_EVENT_DSR = 0x00080000;
static final public int LISTENING_EVENT_RING_INDICATOR = 0x00100000;
static final public int LISTENING_EVENT_FRAMING_ERROR = 0x00200000;
static final public int LISTENING_EVENT_OVERRUN_ERROR = 0x00400000;
static final public int LISTENING_EVENT_PARITY_ERROR = 0x00800000;
static final public int LISTENING_EVENT_OUTPUT_EMPTY = 0x01000000;*/
// Wait for a serial port event
if (poll(&waitingSet, 1, 500) <= 0)

View File

@ -47,12 +47,32 @@ extern "C" {
#define com_fazecast_jSerialComm_SerialPort_TIMEOUT_WRITE_BLOCKING 256L
#undef com_fazecast_jSerialComm_SerialPort_TIMEOUT_SCANNER
#define com_fazecast_jSerialComm_SerialPort_TIMEOUT_SCANNER 4096L
#undef com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_TIMED_OUT
#define com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_TIMED_OUT 0L
#undef com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_AVAILABLE
#define com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_AVAILABLE 1L
#undef com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_RECEIVED
#define com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_RECEIVED 16L
#undef com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_WRITTEN
#define com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_WRITTEN 256L
#undef com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_BREAK_INTERRUPT
#define com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_BREAK_INTERRUPT 65536L
#undef com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_CARRIER_DETECT
#define com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_CARRIER_DETECT 131072L
#undef com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_CTS
#define com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_CTS 262144L
#undef com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DSR
#define com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DSR 524288L
#undef com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_RING_INDICATOR
#define com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_RING_INDICATOR 1048576L
#undef com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_FRAMING_ERROR
#define com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_FRAMING_ERROR 2097152L
#undef com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_OVERRUN_ERROR
#define com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_OVERRUN_ERROR 4194304L
#undef com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_PARITY_ERROR
#define com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_PARITY_ERROR 8388608L
#undef com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_OUTPUT_EMPTY
#define com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_OUTPUT_EMPTY 16777216L
/*
* Class: com_fazecast_jSerialComm_SerialPort
* Method: getCommPorts

View File

@ -2,7 +2,7 @@
* SerialPort_Windows.c
*
* Created on: Feb 25, 2012
* Last Updated on: Nov 12, 2021
* Last Updated on: Nov 19, 2021
* Author: Will Hedgecock
*
* Copyright (C) 2012-2021 Fazecast, Inc.
@ -59,6 +59,8 @@ jfieldID receiveDeviceQueueSizeField;
jfieldID rs485ModeField;
jfieldID rs485DelayBeforeField;
jfieldID rs485DelayAfterField;
jfieldID xonStartCharField;
jfieldID xoffStopCharField;
jfieldID timeoutModeField;
jfieldID readTimeoutField;
jfieldID writeTimeoutField;
@ -374,6 +376,8 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrar
rs485ModeField = env->GetFieldID(serialCommClass, "rs485Mode", "Z");
rs485DelayBeforeField = env->GetFieldID(serialCommClass, "rs485DelayBefore", "I");
rs485DelayAfterField = env->GetFieldID(serialCommClass, "rs485DelayAfter", "I");
xonStartCharField = env->GetFieldID(serialCommClass, "xonStartChar", "B");
xoffStopCharField = env->GetFieldID(serialCommClass, "xoffStopChar", "B");
timeoutModeField = env->GetFieldID(serialCommClass, "timeoutMode", "I");
readTimeoutField = env->GetFieldID(serialCommClass, "readTimeout", "I");
writeTimeoutField = env->GetFieldID(serialCommClass, "writeTimeout", "I");
@ -443,6 +447,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J
int readTimeout = env->GetIntField(obj, readTimeoutField);
int writeTimeout = env->GetIntField(obj, writeTimeoutField);
int eventsToMonitor = env->GetIntField(obj, eventFlagsField);
char xonStartChar = env->GetByteField(obj, xonStartCharField);
char xoffStopChar = env->GetByteField(obj, xoffStopCharField);
DWORD sendDeviceQueueSize = (DWORD)env->GetIntField(obj, sendDeviceQueueSizeField);
DWORD receiveDeviceQueueSize = (DWORD)env->GetIntField(obj, receiveDeviceQueueSizeField);
BYTE rs485ModeEnabled = (BYTE)env->GetBooleanField(obj, rs485ModeField);
@ -487,8 +493,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J
dcbSerialParams.fNull = FALSE;
dcbSerialParams.XonLim = 2048;
dcbSerialParams.XoffLim = 512;
dcbSerialParams.XonChar = (char)17;
dcbSerialParams.XoffChar = (char)19;
dcbSerialParams.XonChar = xonStartChar;
dcbSerialParams.XoffChar = xoffStopChar;
// Apply changes
return (SetCommState(port->handle, &dcbSerialParams) && Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(env, obj, serialPortPointer, timeoutMode, readTimeout, writeTimeout, eventsToMonitor));

View File

@ -385,6 +385,7 @@ public final class SerialPort
static final public int TIMEOUT_SCANNER = 0x00001000;
// Serial Port Listening Events
static final public int LISTENING_EVENT_TIMED_OUT = 0x00000000;
static final public int LISTENING_EVENT_DATA_AVAILABLE = 0x00000001;
static final public int LISTENING_EVENT_DATA_RECEIVED = 0x00000010;
static final public int LISTENING_EVENT_DATA_WRITTEN = 0x00000100;
@ -395,6 +396,7 @@ public final class SerialPort
private volatile int timeoutMode = TIMEOUT_NONBLOCKING, readTimeout = 0, writeTimeout = 0, flowControl = 0;
private volatile int sendDeviceQueueSize = 4096, receiveDeviceQueueSize = 4096;
private volatile int safetySleepTimeMS = 200, rs485DelayBefore = 0, rs485DelayAfter = 0;
private volatile byte xonStartChar = 17, xoffStopChar = 19;
private volatile SerialPortDataListener userDataListener = null;
private volatile SerialPortEventListener serialEventListener = null;
private volatile String comPort, friendlyName, portDescription;
@ -1299,6 +1301,31 @@ public final class SerialPort
return true;
}
/**
* Sets custom XON/XOFF flow control characters for the device.
* <p>
* Custom characters should almost never be used, as most devices expect the XON/START character to be 17 and the
* XOFF/STOP character to be 13. If your device expects different flow control characters, they may be changed using
* this function.
*
* @param xonStartCharacter The decimal-based character to use as an XON signal.
* @param xoffStopCharacter The decimal-based character to use as an XOFF signal.
* @return Whether the port configuration is valid or disallowed on this system (only meaningful after the port is already opened).
*/
public final synchronized boolean setXonXoffCharacters(byte xonStartCharacter, byte xoffStopCharacter)
{
xonStartChar = xonStartCharacter;
xoffStopChar = xoffStopCharacter;
if (portHandle > 0)
{
if (safetySleepTimeMS > 0)
try { Thread.sleep(safetySleepTimeMS); } catch (Exception e) { Thread.currentThread().interrupt(); }
return configPort(portHandle);
}
return true;
}
/**
* Gets a descriptive string representing this serial port or the device connected to it.
* <p>