in src/main/c/Windows/SerialPort_Windows.c [938:1119]
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(JNIEnv *env, jobject obj, jlong serialPortPointer)
{
// Retrieve port parameters from the Java class
serialPort *port = (serialPort*)(intptr_t)serialPortPointer;
unsigned char disableConfig = (*env)->GetBooleanField(env, obj, disableConfigField);
if (checkJniError(env, __LINE__ - 1)) return JNI_FALSE;
DWORD baudRate = (DWORD)(*env)->GetIntField(env, obj, baudRateField);
if (checkJniError(env, __LINE__ - 1)) return JNI_FALSE;
BYTE byteSize = (BYTE)(*env)->GetIntField(env, obj, dataBitsField);
if (checkJniError(env, __LINE__ - 1)) return JNI_FALSE;
int stopBitsInt = (*env)->GetIntField(env, obj, stopBitsField);
if (checkJniError(env, __LINE__ - 1)) return JNI_FALSE;
int parityInt = (*env)->GetIntField(env, obj, parityField);
if (checkJniError(env, __LINE__ - 1)) return JNI_FALSE;
int flowControl = (*env)->GetIntField(env, obj, flowControlField);
if (checkJniError(env, __LINE__ - 1)) return JNI_FALSE;
int timeoutMode = (*env)->GetIntField(env, obj, timeoutModeField);
if (checkJniError(env, __LINE__ - 1)) return JNI_FALSE;
int readTimeout = (*env)->GetIntField(env, obj, readTimeoutField);
if (checkJniError(env, __LINE__ - 1)) return JNI_FALSE;
int writeTimeout = (*env)->GetIntField(env, obj, writeTimeoutField);
if (checkJniError(env, __LINE__ - 1)) return JNI_FALSE;
int eventsToMonitor = (*env)->GetIntField(env, obj, eventFlagsField);
if (checkJniError(env, __LINE__ - 1)) return JNI_FALSE;
char xonStartChar = (*env)->GetByteField(env, obj, xonStartCharField);
if (checkJniError(env, __LINE__ - 1)) return JNI_FALSE;
char xoffStopChar = (*env)->GetByteField(env, obj, xoffStopCharField);
if (checkJniError(env, __LINE__ - 1)) return JNI_FALSE;
DWORD sendDeviceQueueSize = (DWORD)(*env)->GetIntField(env, obj, sendDeviceQueueSizeField);
if (checkJniError(env, __LINE__ - 1)) return JNI_FALSE;
DWORD receiveDeviceQueueSize = (DWORD)(*env)->GetIntField(env, obj, receiveDeviceQueueSizeField);
if (checkJniError(env, __LINE__ - 1)) return JNI_FALSE;
BYTE rs485ModeEnabled = (BYTE)(*env)->GetBooleanField(env, obj, rs485ModeField);
if (checkJniError(env, __LINE__ - 1)) return JNI_FALSE;
BYTE isDtrEnabled = (*env)->GetBooleanField(env, obj, isDtrEnabledField);
if (checkJniError(env, __LINE__ - 1)) return JNI_FALSE;
BYTE isRtsEnabled = (*env)->GetBooleanField(env, obj, isRtsEnabledField);
if (checkJniError(env, __LINE__ - 1)) return JNI_FALSE;
BYTE stopBits = (stopBitsInt == com_fazecast_jSerialComm_SerialPort_ONE_STOP_BIT) ? ONESTOPBIT : ((stopBitsInt == com_fazecast_jSerialComm_SerialPort_ONE_POINT_FIVE_STOP_BITS) ? ONE5STOPBITS : TWOSTOPBITS);
BYTE parity = (parityInt == com_fazecast_jSerialComm_SerialPort_NO_PARITY) ? NOPARITY : ((parityInt == com_fazecast_jSerialComm_SerialPort_ODD_PARITY) ? ODDPARITY : ((parityInt == com_fazecast_jSerialComm_SerialPort_EVEN_PARITY) ? EVENPARITY : ((parityInt == com_fazecast_jSerialComm_SerialPort_MARK_PARITY) ? MARKPARITY : SPACEPARITY)));
BOOL isParity = (parityInt == com_fazecast_jSerialComm_SerialPort_NO_PARITY) ? FALSE : TRUE;
BOOL CTSEnabled = (((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_CTS_ENABLED) > 0) ||
((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_RTS_ENABLED) > 0));
BOOL DSREnabled = (((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_DSR_ENABLED) > 0) ||
((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_DTR_ENABLED) > 0));
BYTE DTRValue = ((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_DTR_ENABLED) > 0) ? DTR_CONTROL_HANDSHAKE : (isDtrEnabled ? DTR_CONTROL_ENABLE : DTR_CONTROL_DISABLE);
BYTE RTSValue = (rs485ModeEnabled ? RTS_CONTROL_TOGGLE :
(((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_RTS_ENABLED) > 0) ? RTS_CONTROL_HANDSHAKE : (isRtsEnabled ? RTS_CONTROL_ENABLE : RTS_CONTROL_DISABLE)));
BOOL XonXoffInEnabled = ((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_XONXOFF_IN_ENABLED) > 0);
BOOL XonXoffOutEnabled = ((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_XONXOFF_OUT_ENABLED) > 0);
// Retrieve existing port configuration
DCB dcbSerialParams;
memset(&dcbSerialParams, 0, sizeof(DCB));
dcbSerialParams.DCBlength = sizeof(DCB);
SetupComm(port->handle, receiveDeviceQueueSize, sendDeviceQueueSize);
if (!GetCommState(port->handle, &dcbSerialParams))
{
port->errorLineNumber = lastErrorLineNumber = __LINE__ - 2;
port->errorNumber = lastErrorNumber = GetLastError();
return JNI_FALSE;
}
// Configure port parameters if not explicitly disabled
if (!disableConfig)
{
// Set updated port parameters
dcbSerialParams.BaudRate = baudRate;
dcbSerialParams.ByteSize = byteSize;
dcbSerialParams.StopBits = stopBits;
dcbSerialParams.Parity = parity;
dcbSerialParams.fParity = isParity;
dcbSerialParams.fBinary = TRUE;
dcbSerialParams.fAbortOnError = FALSE;
dcbSerialParams.fRtsControl = RTSValue;
dcbSerialParams.fOutxCtsFlow = CTSEnabled;
dcbSerialParams.fOutxDsrFlow = DSREnabled;
dcbSerialParams.fDtrControl = DTRValue;
dcbSerialParams.fDsrSensitivity = DSREnabled;
dcbSerialParams.fOutX = XonXoffOutEnabled;
dcbSerialParams.fInX = XonXoffInEnabled;
dcbSerialParams.fTXContinueOnXoff = TRUE;
dcbSerialParams.fErrorChar = FALSE;
dcbSerialParams.fNull = FALSE;
dcbSerialParams.XonLim = 2048;
dcbSerialParams.XoffLim = 512;
dcbSerialParams.XonChar = xonStartChar;
dcbSerialParams.XoffChar = xoffStopChar;
// Apply changes
if (!SetCommState(port->handle, &dcbSerialParams))
{
port->errorLineNumber = lastErrorLineNumber = __LINE__ - 2;
port->errorNumber = lastErrorNumber = GetLastError();
return JNI_FALSE;
}
}
else
{
// Update the Java-side port configuration values
(*env)->SetIntField(env, obj, baudRateField, (int)dcbSerialParams.BaudRate);
(*env)->SetIntField(env, obj, dataBitsField, (int)dcbSerialParams.ByteSize);
(*env)->SetIntField(env, obj, stopBitsField, (dcbSerialParams.StopBits == ONESTOPBIT) ? com_fazecast_jSerialComm_SerialPort_ONE_STOP_BIT : ((dcbSerialParams.StopBits == ONE5STOPBITS) ? com_fazecast_jSerialComm_SerialPort_ONE_POINT_FIVE_STOP_BITS : com_fazecast_jSerialComm_SerialPort_TWO_STOP_BITS));
if (dcbSerialParams.fParity)
(*env)->SetIntField(env, obj, parityField, (dcbSerialParams.Parity == NOPARITY) ? com_fazecast_jSerialComm_SerialPort_NO_PARITY : ((dcbSerialParams.Parity == ODDPARITY) ? com_fazecast_jSerialComm_SerialPort_ODD_PARITY : ((dcbSerialParams.Parity == EVENPARITY) ? com_fazecast_jSerialComm_SerialPort_EVEN_PARITY : ((dcbSerialParams.Parity == MARKPARITY) ? com_fazecast_jSerialComm_SerialPort_MARK_PARITY : com_fazecast_jSerialComm_SerialPort_SPACE_PARITY))));
else
(*env)->SetIntField(env, obj, parityField, com_fazecast_jSerialComm_SerialPort_NO_PARITY);
(*env)->SetByteField(env, obj, xonStartCharField, dcbSerialParams.XonChar);
(*env)->SetByteField(env, obj, xoffStopCharField, dcbSerialParams.XoffChar);
int flowControl = (dcbSerialParams.fInX ? com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_XONXOFF_IN_ENABLED : 0) | (dcbSerialParams.fOutX ? com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_XONXOFF_OUT_ENABLED : 0) |
(dcbSerialParams.fOutxCtsFlow ? com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_CTS_ENABLED : 0) | (dcbSerialParams.fOutxDsrFlow ? com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_DSR_ENABLED : 0) |
((dcbSerialParams.fDtrControl == DTR_CONTROL_HANDSHAKE) ? com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_DTR_ENABLED : 0) |
((dcbSerialParams.fRtsControl == RTS_CONTROL_HANDSHAKE) ? com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_RTS_ENABLED : 0);
(*env)->SetIntField(env, obj, flowControlField, flowControl);
(*env)->SetBooleanField(env, obj, isDtrEnabledField, dcbSerialParams.fDtrControl == DTR_CONTROL_ENABLE);
(*env)->SetBooleanField(env, obj, isRtsEnabledField, dcbSerialParams.fRtsControl == RTS_CONTROL_ENABLE);
(*env)->SetBooleanField(env, obj, rs485ModeField, dcbSerialParams.fRtsControl == RTS_CONTROL_TOGGLE);
}
// Get event flags from the Java class
int eventFlags = EV_ERR;
if ((eventsToMonitor & com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_AVAILABLE) || (eventsToMonitor & com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_RECEIVED))
eventFlags |= EV_RXCHAR;
if (eventsToMonitor & com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_WRITTEN)
eventFlags |= EV_TXEMPTY;
if (eventsToMonitor & com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_BREAK_INTERRUPT)
eventFlags |= EV_BREAK;
if (eventsToMonitor & com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_CTS)
eventFlags |= EV_CTS;
if (eventsToMonitor & com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DSR)
eventFlags |= EV_DSR;
if (eventsToMonitor & com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_RING_INDICATOR)
eventFlags |= EV_RING;
if (eventsToMonitor & com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_CARRIER_DETECT)
eventFlags |= EV_RLSD;
// Set updated port timeouts
COMMTIMEOUTS timeouts;
memset(&timeouts, 0, sizeof(COMMTIMEOUTS));
timeouts.WriteTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = (timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_WRITE_BLOCKING) ? writeTimeout : 0;
if (eventsToMonitor & com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_RECEIVED)
{
// Force specific read timeouts if we are monitoring data received
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
timeouts.ReadTotalTimeoutConstant = 1000;
}
else if (timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_SCANNER)
{
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
timeouts.ReadTotalTimeoutConstant = 0x0FFFFFFF;
}
else if (timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_SEMI_BLOCKING)
{
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
timeouts.ReadTotalTimeoutConstant = readTimeout ? readTimeout : 0x0FFFFFFF;
}
else if (timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_BLOCKING)
{
timeouts.ReadIntervalTimeout = 0;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.ReadTotalTimeoutConstant = readTimeout;
}
else // Non-blocking
{
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.ReadTotalTimeoutConstant = 0;
}
// Apply changes
if (!SetCommTimeouts(port->handle, &timeouts) || !SetCommMask(port->handle, eventFlags))
{
port->errorLineNumber = lastErrorLineNumber = __LINE__ - 2;
port->errorNumber = lastErrorNumber = GetLastError();
return JNI_FALSE;
}
return JNI_TRUE;
}