diff --git a/src/main/c/Android/jni/SerialPort_Android.c b/src/main/c/Android/jni/SerialPort_Android.c index a407396..820632f 100644 --- a/src/main/c/Android/jni/SerialPort_Android.c +++ b/src/main/c/Android/jni/SerialPort_Android.c @@ -2,7 +2,7 @@ * SerialPort_Android.c * * Created on: Mar 13, 2015 - * Last Updated on: Jul 27, 2018 + * Last Updated on: Oct 07, 2018 * Author: Will Hedgecock * * Copyright (C) 2012-2018 Fazecast, Inc. @@ -54,6 +54,9 @@ jfieldID comPortField; jfieldID friendlyNameField; jfieldID portDescriptionField; jfieldID isOpenedField; +jfieldID disableConfigField; +jfieldID isDtrEnabledField; +jfieldID isRtsEnabledField; jfieldID baudRateField; jfieldID dataBitsField; jfieldID stopBitsField; @@ -104,6 +107,9 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrar friendlyNameField = (*env)->GetFieldID(env, serialCommClass, "friendlyName", "Ljava/lang/String;"); portDescriptionField = (*env)->GetFieldID(env, serialCommClass, "portDescription", "Ljava/lang/String;"); isOpenedField = (*env)->GetFieldID(env, serialCommClass, "isOpened", "Z"); + disableConfigField = (*env)->GetFieldID(env, serialCommClass, "disableConfig", "Z"); + isDtrEnabledField = (*env)->GetFieldID(env, serialCommClass, "isDtrEnabled", "Z"); + isRtsEnabledField = (*env)->GetFieldID(env, serialCommClass, "isRtsEnabled", "Z"); baudRateField = (*env)->GetFieldID(env, serialCommClass, "baudRate", "I"); dataBitsField = (*env)->GetFieldID(env, serialCommClass, "dataBits", "I"); stopBitsField = (*env)->GetFieldID(env, serialCommClass, "stopBits", "I"); @@ -126,6 +132,8 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative( // TODO: SET A FLAG SAYING THAT WE ARE NOT USING USBFS 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); // Try to open existing serial port with read/write access int serialPortFD = -1; @@ -138,6 +146,9 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative( fcntl(serialPortFD, F_SETFL, 0); ioctl(serialPortFD, TCGETS, &options); cfmakeraw(&options); + if (!isDtrEnabled || !isRtsEnabled) + options.c_cflag &= ~HUPCL; + options.c_iflag |= BRKINT; ioctl(serialPortFD, TCSETS, &options); } @@ -192,6 +203,9 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J int stopBitsInt = (*env)->GetIntField(env, obj, stopBitsField); int parityInt = (*env)->GetIntField(env, obj, parityField); int flowControl = (*env)->GetIntField(env, obj, flowControlField); + unsigned char configDisabled = (*env)->GetBooleanField(env, obj, disableConfigField); + unsigned char isDtrEnabled = (*env)->GetBooleanField(env, obj, isDtrEnabledField); + unsigned char isRtsEnabled = (*env)->GetBooleanField(env, obj, isRtsEnabledField); tcflag_t byteSize = (byteSizeInt == 5) ? CS5 : (byteSizeInt == 6) ? CS6 : (byteSizeInt == 7) ? CS7 : CS8; tcflag_t stopBits = ((stopBitsInt == com_fazecast_jSerialComm_SerialPort_ONE_STOP_BIT) || (stopBitsInt == com_fazecast_jSerialComm_SerialPort_ONE_POINT_FIVE_STOP_BITS)) ? 0 : CSTOPB; 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); @@ -207,6 +221,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J options.c_cflag = (byteSize | stopBits | parity | CLOCAL | CREAD | CTSRTSEnabled); if (parityInt == com_fazecast_jSerialComm_SerialPort_SPACE_PARITY) options.c_cflag &= ~PARODD; + if (!isDtrEnabled || !isRtsEnabled) + options.c_cflag &= ~HUPCL; options.c_iflag &= ~(INPCK | IGNPAR | PARMRK | ISTRIP); if (byteSizeInt < 8) options.c_iflag |= ISTRIP; @@ -235,7 +251,7 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J // Apply changes int retVal = -1; if (isatty(serialPortFD)) - retVal = ioctl(serialPortFD, TCSETS, &options); + retVal = configDisabled ? 0 : ioctl(serialPortFD, TCSETS, &options); else return JNI_FALSE;/* { @@ -577,6 +593,34 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_clearRTS(JNI return (ioctl(serialPortFD, TIOCMBIC, &modemBits) == 0); } +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_presetRTS(JNIEnv *env, jobject obj) +{ + jstring portNameJString = (jstring)(*env)->GetObjectField(env, obj, comPortField); + const char *portName = (*env)->GetStringUTFChars(env, portNameJString, NULL); + + // Send a system command to preset the RTS mode of the serial port + char commandString[64]; + sprintf(commandString, "stty -f %s hupcl", portName); + int result = system(commandString); + + (*env)->ReleaseStringUTFChars(env, portNameJString, portName); + return (result == 0); +} + +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_preclearRTS(JNIEnv *env, jobject obj) +{ + jstring portNameJString = (jstring)(*env)->GetObjectField(env, obj, comPortField); + const char *portName = (*env)->GetStringUTFChars(env, portNameJString, NULL); + + // Send a system command to preset the RTS mode of the serial port + char commandString[64]; + sprintf(commandString, "stty -f %s -hupcl", portName); + int result = system(commandString); + + (*env)->ReleaseStringUTFChars(env, portNameJString, portName); + return (result == 0); +} + JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_setDTR(JNIEnv *env, jobject obj, jlong serialPortFD) { if (serialPortFD <= 0) @@ -593,6 +637,34 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_clearDTR(JNI return (ioctl(serialPortFD, TIOCMBIC, &modemBits) == 0); } +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_presetDTR(JNIEnv *env, jobject obj) +{ + 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 + char commandString[64]; + sprintf(commandString, "stty -f %s hupcl", portName); + int result = system(commandString); + + (*env)->ReleaseStringUTFChars(env, portNameJString, portName); + return (result == 0); +} + +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_preclearDTR(JNIEnv *env, jobject obj) +{ + 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 + char commandString[64]; + sprintf(commandString, "stty -f %s -hupcl", portName); + int result = system(commandString); + + (*env)->ReleaseStringUTFChars(env, portNameJString, portName); + return (result == 0); +} + JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCTS(JNIEnv *env, jobject obj, jlong serialPortFD) { if (serialPortFD <= 0) diff --git a/src/main/c/Android/jni/com_fazecast_jSerialComm_SerialPort.h b/src/main/c/Android/jni/com_fazecast_jSerialComm_SerialPort.h index 8ed2846..aab06db 100644 --- a/src/main/c/Android/jni/com_fazecast_jSerialComm_SerialPort.h +++ b/src/main/c/Android/jni/com_fazecast_jSerialComm_SerialPort.h @@ -191,6 +191,22 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_setRTS JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_clearRTS (JNIEnv *, jobject, jlong); +/* + * Class: com_fazecast_jSerialComm_SerialPort + * Method: presetRTS + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_presetRTS + (JNIEnv *, jobject); + +/* + * Class: com_fazecast_jSerialComm_SerialPort + * Method: preclearRTS + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_preclearRTS + (JNIEnv *, jobject); + /* * Class: com_fazecast_jSerialComm_SerialPort * Method: setDTR @@ -207,6 +223,22 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_setDTR JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_clearDTR (JNIEnv *, jobject, jlong); +/* + * Class: com_fazecast_jSerialComm_SerialPort + * Method: presetDTR + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_presetDTR + (JNIEnv *, jobject); + +/* + * Class: com_fazecast_jSerialComm_SerialPort + * Method: preclearDTR + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_preclearDTR + (JNIEnv *, jobject); + /* * Class: com_fazecast_jSerialComm_SerialPort * Method: getCTS diff --git a/src/main/c/Linux/SerialPort_Linux.c b/src/main/c/Linux/SerialPort_Linux.c index 8c4034f..6178f95 100644 --- a/src/main/c/Linux/SerialPort_Linux.c +++ b/src/main/c/Linux/SerialPort_Linux.c @@ -2,7 +2,7 @@ * SerialPort_Linux.c * * Created on: Feb 25, 2012 - * Last Updated on: Jul 27, 2018 + * Last Updated on: Oct 07, 2018 * Author: Will Hedgecock * * Copyright (C) 2012-2018 Fazecast, Inc. @@ -47,6 +47,9 @@ jfieldID comPortField; jfieldID friendlyNameField; jfieldID portDescriptionField; jfieldID isOpenedField; +jfieldID disableConfigField; +jfieldID isDtrEnabledField; +jfieldID isRtsEnabledField; jfieldID baudRateField; jfieldID dataBitsField; jfieldID stopBitsField; @@ -98,6 +101,9 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrar friendlyNameField = (*env)->GetFieldID(env, serialCommClass, "friendlyName", "Ljava/lang/String;"); portDescriptionField = (*env)->GetFieldID(env, serialCommClass, "portDescription", "Ljava/lang/String;"); isOpenedField = (*env)->GetFieldID(env, serialCommClass, "isOpened", "Z"); + disableConfigField = (*env)->GetFieldID(env, serialCommClass, "disableConfig", "Z"); + isDtrEnabledField = (*env)->GetFieldID(env, serialCommClass, "isDtrEnabled", "Z"); + isRtsEnabledField = (*env)->GetFieldID(env, serialCommClass, "isRtsEnabled", "Z"); baudRateField = (*env)->GetFieldID(env, serialCommClass, "baudRate", "I"); dataBitsField = (*env)->GetFieldID(env, serialCommClass, "dataBits", "I"); stopBitsField = (*env)->GetFieldID(env, serialCommClass, "stopBits", "I"); @@ -119,6 +125,8 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative( { 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); // Try to open existing serial port with read/write access int serialPortFD = -1; @@ -129,6 +137,8 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative( fcntl(serialPortFD, F_SETFL, 0); tcgetattr(serialPortFD, &options); cfmakeraw(&options); + if (!isDtrEnabled || !isRtsEnabled) + options.c_cflag &= ~HUPCL; options.c_iflag |= BRKINT; tcsetattr(serialPortFD, TCSANOW, &options); @@ -150,11 +160,6 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative( return serialPortFD; } -//JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_associateNativeHandle(JNIEnv *env, jobject obj, jlong serialPortFD) -//{ -// ; -//} - JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(JNIEnv *env, jobject obj, jlong serialPortFD) { if (serialPortFD <= 0) @@ -167,6 +172,9 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J int stopBitsInt = (*env)->GetIntField(env, obj, stopBitsField); int parityInt = (*env)->GetIntField(env, obj, parityField); int flowControl = (*env)->GetIntField(env, obj, flowControlField); + unsigned char configDisabled = (*env)->GetBooleanField(env, obj, disableConfigField); + unsigned char isDtrEnabled = (*env)->GetBooleanField(env, obj, isDtrEnabledField); + unsigned char isRtsEnabled = (*env)->GetBooleanField(env, obj, isRtsEnabledField); tcflag_t byteSize = (byteSizeInt == 5) ? CS5 : (byteSizeInt == 6) ? CS6 : (byteSizeInt == 7) ? CS7 : CS8; tcflag_t stopBits = ((stopBitsInt == com_fazecast_jSerialComm_SerialPort_ONE_STOP_BIT) || (stopBitsInt == com_fazecast_jSerialComm_SerialPort_ONE_POINT_FIVE_STOP_BITS)) ? 0 : CSTOPB; 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); @@ -180,6 +188,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J options.c_cflag = (byteSize | stopBits | parity | CLOCAL | CREAD | CTSRTSEnabled); if (parityInt == com_fazecast_jSerialComm_SerialPort_SPACE_PARITY) options.c_cflag &= ~PARODD; + if (!isDtrEnabled || !isRtsEnabled) + options.c_cflag &= ~HUPCL; options.c_iflag &= ~(INPCK | IGNPAR | PARMRK | ISTRIP); if (byteSizeInt < 8) options.c_iflag |= ISTRIP; @@ -196,7 +206,7 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J } // Apply changes - int retVal = tcsetattr(serialPortFD, TCSANOW, &options); + int retVal = configDisabled ? 0 : tcsetattr(serialPortFD, TCSANOW, &options); ioctl(serialPortFD, TIOCEXCL); // Block non-root users from opening this port if (baudRateCode == 0) // Set custom baud rate setBaudRate(serialPortFD, baudRate); @@ -537,6 +547,34 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_clearRTS(JNI return (ioctl(serialPortFD, TIOCMBIC, &modemBits) == 0); } +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_presetRTS(JNIEnv *env, jobject obj) +{ + jstring portNameJString = (jstring)(*env)->GetObjectField(env, obj, comPortField); + const char *portName = (*env)->GetStringUTFChars(env, portNameJString, NULL); + + // Send a system command to preset the RTS mode of the serial port + char commandString[64]; + sprintf(commandString, "stty -f %s hupcl", portName); + int result = system(commandString); + + (*env)->ReleaseStringUTFChars(env, portNameJString, portName); + return (result == 0); +} + +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_preclearRTS(JNIEnv *env, jobject obj) +{ + jstring portNameJString = (jstring)(*env)->GetObjectField(env, obj, comPortField); + const char *portName = (*env)->GetStringUTFChars(env, portNameJString, NULL); + + // Send a system command to preset the RTS mode of the serial port + char commandString[64]; + sprintf(commandString, "stty -f %s -hupcl", portName); + int result = system(commandString); + + (*env)->ReleaseStringUTFChars(env, portNameJString, portName); + return (result == 0); +} + JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_setDTR(JNIEnv *env, jobject obj, jlong serialPortFD) { if (serialPortFD <= 0) @@ -553,6 +591,34 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_clearDTR(JNI return (ioctl(serialPortFD, TIOCMBIC, &modemBits) == 0); } +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_presetDTR(JNIEnv *env, jobject obj) +{ + 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 + char commandString[64]; + sprintf(commandString, "stty -f %s hupcl", portName); + int result = system(commandString); + + (*env)->ReleaseStringUTFChars(env, portNameJString, portName); + return (result == 0); +} + +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_preclearDTR(JNIEnv *env, jobject obj) +{ + 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 + char commandString[64]; + sprintf(commandString, "stty -f %s -hupcl", portName); + int result = system(commandString); + + (*env)->ReleaseStringUTFChars(env, portNameJString, portName); + return (result == 0); +} + JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCTS(JNIEnv *env, jobject obj, jlong serialPortFD) { if (serialPortFD <= 0) diff --git a/src/main/c/OSX/SerialPort_OSX.c b/src/main/c/OSX/SerialPort_OSX.c index 5aa3858..748022b 100644 --- a/src/main/c/OSX/SerialPort_OSX.c +++ b/src/main/c/OSX/SerialPort_OSX.c @@ -2,7 +2,7 @@ * SerialPort_OSX.c * * Created on: Feb 25, 2012 - * Last Updated on: Jul 27, 2018 + * Last Updated on: Oct 07, 2018 * Author: Will Hedgecock * * Copyright (C) 2012-2018 Fazecast, Inc. @@ -46,9 +46,12 @@ jclass serialCommClass; jmethodID serialCommConstructor; jfieldID serialPortFdField; jfieldID comPortField; +jfieldID disableConfigField; jfieldID friendlyNameField; jfieldID portDescriptionField; jfieldID isOpenedField; +jfieldID isDtrEnabledField; +jfieldID isRtsEnabledField; jfieldID baudRateField; jfieldID dataBitsField; jfieldID stopBitsField; @@ -148,6 +151,9 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrar friendlyNameField = (*env)->GetFieldID(env, serialCommClass, "friendlyName", "Ljava/lang/String;"); portDescriptionField = (*env)->GetFieldID(env, serialCommClass, "portDescription", "Ljava/lang/String;"); isOpenedField = (*env)->GetFieldID(env, serialCommClass, "isOpened", "Z"); + disableConfigField = (*env)->GetFieldID(env, serialCommClass, "disableConfig", "Z"); + isDtrEnabledField = (*env)->GetFieldID(env, serialCommClass, "isDtrEnabled", "Z"); + isRtsEnabledField = (*env)->GetFieldID(env, serialCommClass, "isRtsEnabled", "Z"); baudRateField = (*env)->GetFieldID(env, serialCommClass, "baudRate", "I"); dataBitsField = (*env)->GetFieldID(env, serialCommClass, "dataBits", "I"); stopBitsField = (*env)->GetFieldID(env, serialCommClass, "stopBits", "I"); @@ -169,6 +175,8 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative( { 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); // Try to open existing serial port with read/write access int serialPortFD = -1; @@ -179,6 +187,9 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative( fcntl(serialPortFD, F_SETFL, 0); tcgetattr(serialPortFD, &options); cfmakeraw(&options); + if (!isDtrEnabled || !isRtsEnabled) + options.c_cflag &= ~HUPCL; + options.c_iflag |= BRKINT; tcsetattr(serialPortFD, TCSANOW, &options); // Configure the port parameters and timeouts @@ -211,6 +222,9 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J int stopBitsInt = (*env)->GetIntField(env, obj, stopBitsField); int parityInt = (*env)->GetIntField(env, obj, parityField); int flowControl = (*env)->GetIntField(env, obj, flowControlField); + unsigned char configDisabled = (*env)->GetBooleanField(env, obj, disableConfigField); + unsigned char isDtrEnabled = (*env)->GetBooleanField(env, obj, isDtrEnabledField); + unsigned char isRtsEnabled = (*env)->GetBooleanField(env, obj, isRtsEnabledField); tcflag_t byteSize = (byteSizeInt == 5) ? CS5 : (byteSizeInt == 6) ? CS6 : (byteSizeInt == 7) ? CS7 : CS8; tcflag_t stopBits = ((stopBitsInt == com_fazecast_jSerialComm_SerialPort_ONE_STOP_BIT) || (stopBitsInt == com_fazecast_jSerialComm_SerialPort_ONE_POINT_FIVE_STOP_BITS)) ? 0 : CSTOPB; 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); @@ -224,6 +238,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J options.c_cflag = (byteSize | stopBits | parity | CLOCAL | CREAD | CTSRTSEnabled); if (parityInt == com_fazecast_jSerialComm_SerialPort_SPACE_PARITY) options.c_cflag &= ~PARODD; + if (!isDtrEnabled || !isRtsEnabled) + options.c_cflag &= ~HUPCL; options.c_iflag &= ~(INPCK | IGNPAR | PARMRK | ISTRIP); if (byteSizeInt < 8) options.c_iflag |= ISTRIP; @@ -240,7 +256,7 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J } // Apply changes - int retVal = tcsetattr(serialPortFD, TCSANOW, &options); + int retVal = configDisabled ? 0 : tcsetattr(serialPortFD, TCSANOW, &options); ioctl(serialPortFD, TIOCEXCL); // Block non-root users from opening this port if (baudRateCode == 0) // Set custom baud rate { @@ -554,6 +570,34 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_clearRTS(JNI return (ioctl(serialPortFD, TIOCMBIC, &modemBits) == 0); } +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_presetRTS(JNIEnv *env, jobject obj) +{ + jstring portNameJString = (jstring)(*env)->GetObjectField(env, obj, comPortField); + const char *portName = (*env)->GetStringUTFChars(env, portNameJString, NULL); + + // Send a system command to preset the RTS mode of the serial port + char commandString[64]; + sprintf(commandString, "stty -f %s hupcl", portName); + int result = system(commandString); + + (*env)->ReleaseStringUTFChars(env, portNameJString, portName); + return (result == 0); +} + +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_preclearRTS(JNIEnv *env, jobject obj) +{ + jstring portNameJString = (jstring)(*env)->GetObjectField(env, obj, comPortField); + const char *portName = (*env)->GetStringUTFChars(env, portNameJString, NULL); + + // Send a system command to preset the RTS mode of the serial port + char commandString[64]; + sprintf(commandString, "stty -f %s -hupcl", portName); + int result = system(commandString); + + (*env)->ReleaseStringUTFChars(env, portNameJString, portName); + return (result == 0); +} + JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_setDTR(JNIEnv *env, jobject obj, jlong serialPortFD) { if (serialPortFD <= 0) @@ -570,6 +614,34 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_clearDTR(JNI return (ioctl(serialPortFD, TIOCMBIC, &modemBits) == 0); } +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_presetDTR(JNIEnv *env, jobject obj) +{ + 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 + char commandString[64]; + sprintf(commandString, "stty -f %s hupcl", portName); + int result = system(commandString); + + (*env)->ReleaseStringUTFChars(env, portNameJString, portName); + return (result == 0); +} + +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_preclearDTR(JNIEnv *env, jobject obj) +{ + 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 + char commandString[64]; + sprintf(commandString, "stty -f %s -hupcl", portName); + int result = system(commandString); + + (*env)->ReleaseStringUTFChars(env, portNameJString, portName); + return (result == 0); +} + JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCTS(JNIEnv *env, jobject obj, jlong serialPortFD) { if (serialPortFD <= 0) diff --git a/src/main/c/Windows/Makefile b/src/main/c/Windows/Makefile index 470dcc5..89eae9d 100644 --- a/src/main/c/Windows/Makefile +++ b/src/main/c/Windows/Makefile @@ -2,9 +2,9 @@ COMPILE = cl LINK = link CFLAGS = /c /O2 /GF /GL /MT /EHsc /fp:precise /J /nologo /TP -LDFLAGS = /DLL /LTCG /NOASSEMBLY /NOLOGO /DELAYLOAD:ftd2xx.dll +LDFLAGS = /DLL /LTCG /NOASSEMBLY /NOLOGO INCLUDES = /I"$(JDK_HOME)/include" /I"$(JDK_HOME)/include/win32" -LIBRARIES = Advapi32.lib SetupAPI.lib DelayImp.lib +LIBRARIES = Advapi32.lib SetupAPI.lib DELETE = @del /q /f RMDIR = @rd /q /s MKDIR = @md @@ -44,23 +44,18 @@ all : $(PRINT). # Builds 32-bit Windows libraries -win32 : checkdirs $(BUILD_DIR)\x86\$(LIBRARY_NAME) - $(DELETE) $(BUILD_DIR)\x86\*.obj - $(COPY) $(BUILD_DIR)\x86\*.* $(RESOURCE_DIR)\x86 - $(COPY) ftdi\ftd2xx32.dll $(RESOURCE_DIR)\x86\ftd2xx.dll +win32 : $(BUILD_DIR)\x86 $(BUILD_DIR)\x86\$(LIBRARY_NAME) + $(COPY) $(BUILD_DIR)\x86\*.dll $(RESOURCE_DIR)\x86 $(DELETE) ..\*.h $(RMDIR) $(BUILD_DIR)\.. # Builds 64-bit Windows libraries -win64 : checkdirs $(BUILD_DIR)\x86_64\$(LIBRARY_NAME) - $(DELETE) $(BUILD_DIR)\x86_64\*.obj - $(COPY) $(BUILD_DIR)\x86_64\*.* $(RESOURCE_DIR)\x86_64 - $(COPY) ftdi\ftd2xx64.dll $(RESOURCE_DIR)\x86_64\ftd2xx.dll +win64 : $(BUILD_DIR)\x86_64 $(BUILD_DIR)\x86_64\$(LIBRARY_NAME) + $(COPY) $(BUILD_DIR)\x86_64\*.dll $(RESOURCE_DIR)\x86_64 $(DELETE) ..\*.h $(RMDIR) $(BUILD_DIR)\.. # Rule to create build directories -checkdirs : $(BUILD_DIR)\x86 $(BUILD_DIR)\x86_64 $(BUILD_DIR)\x86 : $(MKDIR) "$@" $(BUILD_DIR)\x86_64 : @@ -68,11 +63,11 @@ $(BUILD_DIR)\x86_64 : # Rule to build 32-bit library $(BUILD_DIR)\x86\$(LIBRARY_NAME) : $(JNI_HEADER) $(OBJECTSx86) - $(LINK) $(LDFLAGS) /MACHINE:X86 /OUT:$@ $(OBJECTSx86) $(LIBRARIES) ftdi/ftd2xx32.lib + $(LINK) $(LDFLAGS) /MACHINE:X86 /OUT:$@ $(OBJECTSx86) $(LIBRARIES) # Rule to build 64-bit library $(BUILD_DIR)\x86_64\$(LIBRARY_NAME) : $(JNI_HEADER) $(OBJECTSx86_64) - $(LINK) $(LDFLAGS) /MACHINE:X64 /OUT:$@ $(OBJECTSx86_64) $(LIBRARIES) ftdi/ftd2xx64.lib + $(LINK) $(LDFLAGS) /MACHINE:X64 /OUT:$@ $(OBJECTSx86_64) $(LIBRARIES) # Suffix rules to get from *.c -> *.obj $(OBJECTSx86_64) : diff --git a/src/main/c/Windows/SerialPort_Windows.c b/src/main/c/Windows/SerialPort_Windows.c index 83cf125..f1e90d8 100644 --- a/src/main/c/Windows/SerialPort_Windows.c +++ b/src/main/c/Windows/SerialPort_Windows.c @@ -2,7 +2,7 @@ * SerialPort_Windows.c * * Created on: Feb 25, 2012 - * Last Updated on: Sep 25, 2018 + * Last Updated on: Oct 07, 2018 * Author: Will Hedgecock * * Copyright (C) 2012-2018 Fazecast, Inc. @@ -47,47 +47,27 @@ jfieldID comPortField; jfieldID friendlyNameField; jfieldID portDescriptionField; jfieldID isOpenedField; +jfieldID disableConfigField; +jfieldID isDtrEnabledField; +jfieldID isRtsEnabledField; jfieldID baudRateField; jfieldID dataBitsField; jfieldID stopBitsField; jfieldID parityField; jfieldID flowControlField; +jfieldID sendDeviceQueueSizeField; +jfieldID receiveDeviceQueueSizeField; jfieldID timeoutModeField; jfieldID readTimeoutField; jfieldID writeTimeoutField; jfieldID eventFlagsField; -// FTDI DLL library loader -EXTERN_C IMAGE_DOS_HEADER __ImageBase; -HINSTANCE hDllInstance = (HINSTANCE)&__ImageBase; -HMODULE LocalLoadLibrary(LPCSTR pszModuleName) -{ - CHAR szPath[MAX_PATH] = ""; - DWORD cchPath = GetModuleFileNameA(hDllInstance, szPath, MAX_PATH); - while (cchPath > 0) - { - switch(szPath[cchPath - 1]) - { - case '\\': - case '/': - case ':': - break; - default: - --cchPath; - continue; - } - break; - } - lstrcpynA(szPath + cchPath, pszModuleName, MAX_PATH - cchPath); - return LoadLibraryA(szPath); -} -FARPROC WINAPI DllLoadNotifyHook(unsigned dliNotify, PDelayLoadInfo pdli) -{ - if (dliNotify == dliNotePreLoadLibrary) - return (FARPROC)LocalLoadLibrary(pdli->szDll); - return NULL; -} -extern "C" const PfnDliHook __pfnDliNotifyHook2 = DllLoadNotifyHook; +// Run-time loadable DLL function +typedef int (__cdecl *FT_CreateDeviceInfoListFunction)(LPDWORD); +typedef int (__cdecl *FT_GetDeviceInfoListFunction)(FT_DEVICE_LIST_INFO_NODE*, LPDWORD); +typedef int (__cdecl *FT_GetComPortNumberFunction)(FT_HANDLE, LPLONG); +typedef int (__cdecl *FT_OpenFunction)(int, FT_HANDLE*); +typedef int (__cdecl *FT_CloseFunction)(FT_HANDLE); JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommPorts(JNIEnv *env, jclass serialComm) { @@ -286,35 +266,48 @@ JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommP } // Attempt to locate any FTDI-specified port descriptions - DWORD numDevs; - if ((FT_CreateDeviceInfoList(&numDevs) == FT_OK) && (numDevs > 0)) + HINSTANCE ftdiLibInstance = LoadLibrary(TEXT("ftd2xx.dll")); + if (ftdiLibInstance != NULL) { - FT_DEVICE_LIST_INFO_NODE *devInfo = (FT_DEVICE_LIST_INFO_NODE*)malloc(sizeof(FT_DEVICE_LIST_INFO_NODE)*numDevs); - if (FT_GetDeviceInfoList(devInfo, &numDevs) == FT_OK) + FT_CreateDeviceInfoListFunction FT_CreateDeviceInfoList = (FT_CreateDeviceInfoListFunction)GetProcAddress(ftdiLibInstance, "FT_CreateDeviceInfoList"); + FT_GetDeviceInfoListFunction FT_GetDeviceInfoList = (FT_GetDeviceInfoListFunction)GetProcAddress(ftdiLibInstance, "FT_GetDeviceInfoList"); + FT_GetComPortNumberFunction FT_GetComPortNumber = (FT_GetComPortNumberFunction)GetProcAddress(ftdiLibInstance, "FT_GetComPortNumber"); + FT_OpenFunction FT_Open = (FT_OpenFunction)GetProcAddress(ftdiLibInstance, "FT_Open"); + FT_CloseFunction FT_Close = (FT_CloseFunction)GetProcAddress(ftdiLibInstance, "FT_Close"); + if ((FT_CreateDeviceInfoList != NULL) && (FT_GetDeviceInfoList != NULL) && (FT_GetComPortNumber != NULL) && (FT_Open != NULL) && (FT_Close != NULL)) { - int i, j; - wchar_t comPortString[128]; - for (i = 0; i < numDevs; ++i) + DWORD numDevs; + if ((FT_CreateDeviceInfoList(&numDevs) == FT_OK) && (numDevs > 0)) { - LONG comPortNumber = 0; - if ((FT_Open(i, &devInfo[i].ftHandle) == FT_OK) && (FT_GetComPortNumber(devInfo[i].ftHandle, &comPortNumber) == FT_OK)) + FT_DEVICE_LIST_INFO_NODE *devInfo = (FT_DEVICE_LIST_INFO_NODE*)malloc(sizeof(FT_DEVICE_LIST_INFO_NODE)*numDevs); + if (FT_GetDeviceInfoList(devInfo, &numDevs) == FT_OK) { - // Update port description if COM port is actually connected and present in the port list - FT_Close(devInfo[i].ftHandle); - swprintf(comPortString, sizeof(comPortString) / sizeof(wchar_t), L"COM%ld", comPortNumber); - for (j = 0; j < serialCommPorts.length; ++j) - if (wcscmp(serialCommPorts.first[j], comPortString) == 0) + int i, j; + wchar_t comPortString[128]; + for (i = 0; i < numDevs; ++i) + { + LONG comPortNumber = 0; + if ((FT_Open(i, &devInfo[i].ftHandle) == FT_OK) && (FT_GetComPortNumber(devInfo[i].ftHandle, &comPortNumber) == FT_OK)) { - size_t descLength = 8+strlen(devInfo[i].Description); - free(serialCommPorts.third[j]); - serialCommPorts.third[j] = (wchar_t*)malloc(descLength*sizeof(wchar_t)); - MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, devInfo[i].Description, -1, serialCommPorts.third[j], descLength); - break; + // Update port description if COM port is actually connected and present in the port list + FT_Close(devInfo[i].ftHandle); + swprintf(comPortString, sizeof(comPortString) / sizeof(wchar_t), L"COM%ld", comPortNumber); + for (j = 0; j < serialCommPorts.length; ++j) + if (wcscmp(serialCommPorts.first[j], comPortString) == 0) + { + size_t descLength = 8+strlen(devInfo[i].Description); + free(serialCommPorts.third[j]); + serialCommPorts.third[j] = (wchar_t*)malloc(descLength*sizeof(wchar_t)); + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, devInfo[i].Description, -1, serialCommPorts.third[j], descLength); + break; + } } + } } + free(devInfo); } } - free(devInfo); + FreeLibrary(ftdiLibInstance); } // Get relevant SerialComm methods and fill in com port array @@ -355,11 +348,16 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrar friendlyNameField = env->GetFieldID(serialCommClass, "friendlyName", "Ljava/lang/String;"); portDescriptionField = env->GetFieldID(serialCommClass, "portDescription", "Ljava/lang/String;"); isOpenedField = env->GetFieldID(serialCommClass, "isOpened", "Z"); + disableConfigField = env->GetFieldID(serialCommClass, "disableConfig", "Z"); + isDtrEnabledField = env->GetFieldID(serialCommClass, "isDtrEnabled", "Z"); + isRtsEnabledField = env->GetFieldID(serialCommClass, "isRtsEnabled", "Z"); baudRateField = env->GetFieldID(serialCommClass, "baudRate", "I"); dataBitsField = env->GetFieldID(serialCommClass, "dataBits", "I"); stopBitsField = env->GetFieldID(serialCommClass, "stopBits", "I"); parityField = env->GetFieldID(serialCommClass, "parity", "I"); flowControlField = env->GetFieldID(serialCommClass, "flowControl", "I"); + sendDeviceQueueSizeField = env->GetFieldID(serialCommClass, "sendDeviceQueueSize", "I"); + receiveDeviceQueueSizeField = env->GetFieldID(serialCommClass, "receiveDeviceQueueSize", "I"); timeoutModeField = env->GetFieldID(serialCommClass, "timeoutMode", "I"); readTimeoutField = env->GetFieldID(serialCommClass, "readTimeout", "I"); writeTimeoutField = env->GetFieldID(serialCommClass, "writeTimeout", "I"); @@ -413,6 +411,11 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J int stopBitsInt = env->GetIntField(obj, stopBitsField); int parityInt = env->GetIntField(obj, parityField); int flowControl = env->GetIntField(obj, flowControlField); + DWORD sendDeviceQueueSize = (DWORD)env->GetIntField(obj, sendDeviceQueueSizeField); + DWORD receiveDeviceQueueSize = (DWORD)env->GetIntField(obj, receiveDeviceQueueSizeField); + BYTE configDisabled = (BYTE)env->GetBooleanField(obj, disableConfigField); + BYTE isDtrEnabled = env->GetBooleanField(obj, isDtrEnabledField); + BYTE isRtsEnabled = env->GetBooleanField(obj, isRtsEnabledField); 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; @@ -420,13 +423,14 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J ((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 : DTR_CONTROL_ENABLE; - BYTE RTSValue = ((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_RTS_ENABLED) > 0) ? RTS_CONTROL_HANDSHAKE : RTS_CONTROL_ENABLE; + BYTE DTRValue = ((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_DTR_ENABLED) > 0) ? DTR_CONTROL_HANDSHAKE : (isDtrEnabled ? DTR_CONTROL_ENABLE : DTR_CONTROL_DISABLE); + BYTE RTSValue = ((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 - if (!GetCommState(serialPortHandle, &dcbSerialParams)) + SetupComm(serialPortHandle, receiveDeviceQueueSize, sendDeviceQueueSize); + if (!configDisabled && !GetCommState(serialPortHandle, &dcbSerialParams)) return JNI_FALSE; // Set updated port parameters @@ -454,7 +458,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J dcbSerialParams.XoffChar = (char)19; // Apply changes - return SetCommState(serialPortHandle, &dcbSerialParams) && Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(env, obj, serialPortFD); + return (configDisabled ? Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(env, obj, serialPortFD) : + (SetCommState(serialPortHandle, &dcbSerialParams) && Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(env, obj, serialPortFD))); } JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(JNIEnv *env, jobject obj, jlong serialPortFD) @@ -783,6 +788,44 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_clearRTS(JNI return EscapeCommFunction(serialPortHandle, CLRRTS); } +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_presetRTS(JNIEnv *env, jobject obj) +{ + jstring portNameJString = (jstring)env->GetObjectField(obj, comPortField); + const char *portName = env->GetStringUTFChars(portNameJString, NULL); + const char* comPort = strrchr(portName, '\\'); + + // Try to preset the RTS mode of the COM port using a Windows command + int result = -1; + if (comPort != NULL) + { + char commandString[32]; + sprintf(commandString, "MODE %s rts=on", comPort + 1); + result = system(commandString); + } + + env->ReleaseStringUTFChars(portNameJString, portName); + return (result == 0); +} + +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_preclearRTS(JNIEnv *env, jobject obj) +{ + jstring portNameJString = (jstring)env->GetObjectField(obj, comPortField); + const char *portName = env->GetStringUTFChars(portNameJString, NULL); + const char* comPort = strrchr(portName, '\\'); + + // Try to preset the RTS mode of the COM port using a Windows command + int result = -1; + if (comPort != NULL) + { + char commandString[32]; + sprintf(commandString, "MODE %s rts=off", comPort + 1); + result = system(commandString); + } + + env->ReleaseStringUTFChars(portNameJString, portName); + return (result == 0); +} + JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_setDTR(JNIEnv *env, jobject obj, jlong serialPortFD) { HANDLE serialPortHandle = (HANDLE)serialPortFD; @@ -799,6 +842,44 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_clearDTR(JNI return EscapeCommFunction(serialPortHandle, CLRDTR); } +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_presetDTR(JNIEnv *env, jobject obj) +{ + jstring portNameJString = (jstring)env->GetObjectField(obj, comPortField); + const char *portName = env->GetStringUTFChars(portNameJString, NULL); + const char* comPort = strrchr(portName, '\\'); + + // Try to preset the DTR mode of the COM port using a Windows command + int result = -1; + if (comPort != NULL) + { + char commandString[32]; + sprintf(commandString, "MODE %s dtr=on", comPort + 1); + result = system(commandString); + } + + env->ReleaseStringUTFChars(portNameJString, portName); + return (result == 0); +} + +JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_preclearDTR(JNIEnv *env, jobject obj) +{ + jstring portNameJString = (jstring)env->GetObjectField(obj, comPortField); + const char *portName = env->GetStringUTFChars(portNameJString, NULL); + const char* comPort = strrchr(portName, '\\'); + + // Try to preset the DTR mode of the COM port using a Windows command + int result = -1; + if (comPort != NULL) + { + char commandString[32]; + sprintf(commandString, "MODE %s dtr=off", comPort + 1); + result = system(commandString); + } + + env->ReleaseStringUTFChars(portNameJString, portName); + return (result == 0); +} + JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCTS(JNIEnv *env, jobject obj, jlong serialPortFD) { HANDLE serialPortHandle = (HANDLE)serialPortFD; diff --git a/src/main/c/Windows/ftdi/ftd2xx32.dll b/src/main/c/Windows/ftdi/ftd2xx32.dll deleted file mode 100644 index ecafeb7..0000000 Binary files a/src/main/c/Windows/ftdi/ftd2xx32.dll and /dev/null differ diff --git a/src/main/c/Windows/ftdi/ftd2xx32.lib b/src/main/c/Windows/ftdi/ftd2xx32.lib deleted file mode 100644 index b2e0a53..0000000 Binary files a/src/main/c/Windows/ftdi/ftd2xx32.lib and /dev/null differ diff --git a/src/main/c/Windows/ftdi/ftd2xx64.dll b/src/main/c/Windows/ftdi/ftd2xx64.dll deleted file mode 100644 index 4c8ab6c..0000000 Binary files a/src/main/c/Windows/ftdi/ftd2xx64.dll and /dev/null differ diff --git a/src/main/c/Windows/ftdi/ftd2xx64.lib b/src/main/c/Windows/ftdi/ftd2xx64.lib deleted file mode 100644 index 8a04fec..0000000 Binary files a/src/main/c/Windows/ftdi/ftd2xx64.lib and /dev/null differ diff --git a/src/main/java/com/fazecast/jSerialComm/SerialPort.java b/src/main/java/com/fazecast/jSerialComm/SerialPort.java index e0a9d1b..9b22da8 100644 --- a/src/main/java/com/fazecast/jSerialComm/SerialPort.java +++ b/src/main/java/com/fazecast/jSerialComm/SerialPort.java @@ -2,7 +2,7 @@ * SerialPort.java * * Created on: Feb 25, 2012 - * Last Updated on: Aug 20, 2018 + * Last Updated on: Oct 07, 2018 * Author: Will Hedgecock * * Copyright (C) 2012-2018 Fazecast, Inc. @@ -42,7 +42,7 @@ import java.util.Date; * This class provides native access to serial ports and devices without requiring external libraries or tools. * * @author Will Hedgecock <will.hedgecock@fazecast.com> - * @version 2.2.3 + * @version 2.3.0 * @see java.io.InputStream * @see java.io.OutputStream */ @@ -203,29 +203,6 @@ public final class SerialPort tempNativeLibrary.deleteOnExit(); try { - // Copy the FTDI driver library to the system temp directory if on Windows - if (isWindows) - { - String ftdiFileName = tempFileDirectory + "ftd2xx.dll"; - File tempFtdiLibrary = new File(ftdiFileName); - InputStream ftdiContents = SerialPort.class.getResourceAsStream("/" + libraryPath + "/ftd2xx.dll"); - if (ftdiContents != null) - { - try - { - FileOutputStream destinationFileContents = new FileOutputStream(tempFtdiLibrary); - byte transferBuffer[] = new byte[4096]; - int numBytesRead; - - while ((numBytesRead = ftdiContents.read(transferBuffer)) > 0) - destinationFileContents.write(transferBuffer, 0, numBytesRead); - destinationFileContents.close(); - } - catch (FileNotFoundException e) {}; - ftdiContents.close(); - } - } - // Load the native jSerialComm library InputStream fileContents = SerialPort.class.getResourceAsStream("/" + libraryPath + "/" + fileName); if (fileContents == null) @@ -270,10 +247,7 @@ public final class SerialPort * @return The port description as reported by the device itself. */ @Override - public String toString() - { - return getPortDescription(); - } + public String toString() { return getPortDescription(); } /** * Returns a list of all available serial ports on this machine. @@ -334,40 +308,6 @@ public final class SerialPort return serialPort; } -// /** -// * Allocates a {@link SerialPort} object corresponding to a previously opened serial port file descriptor. -// *
-// * Using this method to create a {@link SerialPort} object may not allow you to change some port characteristics -// * like baud rate, flow control, or parity, depending on the methodology that was used to initially open the native -// * file descriptor. -// *
-// * Use of this constructor is not recommended except for use with Android-specific applications. In this -// * case, you can use the Android USB Host APIs to allow the user to grant permission to use the port, and then -// * return the native file descriptor to this library via the Android UsbDeviceConnection.getFileDescriptor() method. -// *
-// * For non-Android applications, any of the other constructors are recommended; however, this method may still be -// * used if you have a specific need for it in your application. -// * -// * @param nativeFileDescriptor A pre-opened file descriptor corresponding to the serial port you would like to use with this library. -// * @return A SerialPort object. -// */ -/* static public SerialPort getCommPort(long nativeFileDescriptor) - { - // Create SerialPort object and associate it with the native file descriptor - SerialPort serialPort = new SerialPort(); - if (!serialPort.associateNativeHandle(nativeFileDescriptor)) - serialPort.comPort = "UNKNOWN"; - serialPort.portString = "User-Specified Port"; - serialPort.portHandle = nativeFileDescriptor; - serialPort.isOpened = true; - - // Create the Input/OutputStream interfaces - serialPort.inputStream = serialPort.new SerialPortInputStream(); - serialPort.outputStream = serialPort.new SerialPortOutputStream(); - - return serialPort; - }*/ - // Parity Values static final public int NO_PARITY = 0; static final public int ODD_PARITY = 1; @@ -406,28 +346,33 @@ public final class SerialPort private volatile long portHandle = -1; private volatile int baudRate = 9600, dataBits = 8, stopBits = ONE_STOP_BIT, parity = NO_PARITY, eventFlags = 0; private volatile int timeoutMode = TIMEOUT_NONBLOCKING, readTimeout = 0, writeTimeout = 0, flowControl = 0; + private volatile int sendDeviceQueueSize = 4096, receiveDeviceQueueSize = 4096; private volatile SerialPortInputStream inputStream = null; private volatile SerialPortOutputStream outputStream = null; private volatile SerialPortDataListener userDataListener = null; private volatile SerialPortEventListener serialEventListener = null; private volatile String comPort, friendlyName, portDescription; - private volatile boolean isOpened = false; + private volatile boolean isOpened = false, disableConfig = false, isRtsEnabled = true, isDtrEnabled = true; /** * Opens this serial port for reading and writing with an optional delay time. *
* All serial port parameters or timeouts can be changed at any time before or after the port has been opened. *
- * Note that calling this method on an already opened port will simply return a value of true. + * Note that calling this method on an already opened port will simply reconfigure the port parameters. * * @param safetySleepTime The number of milliseconds to sleep before opening the port in case of frequent closing/openings. + * @param deviceSendQueueSize The requested size in bytes of the internal device driver's output queue (only has an effect on Windows) + * @param deviceReceiveQueueSize The requested size in bytes of the internal device driver's input queue (only has an effect on Windows) * @return Whether the port was successfully opened. */ - public final boolean openPort(int safetySleepTime) + public final boolean openPort(int safetySleepTime, int deviceSendQueueSize, int deviceReceiveQueueSize) { - // Return true if already opened + // Set the send/receive internal buffer sizes, and return true if already opened + sendDeviceQueueSize = deviceSendQueueSize; + receiveDeviceQueueSize = deviceReceiveQueueSize; if (isOpened) - return true; + return configPort(portHandle); // Force a sleep to ensure that the port does not become unusable due to rapid closing/opening on the part of the user if (safetySleepTime > 0) @@ -474,6 +419,18 @@ public final class SerialPort return isOpened; } + /** + * Opens this serial port for reading and writing with an optional delay time. + *
+ * All serial port parameters or timeouts can be changed at any time before or after the port has been opened. + *
+ * Note that calling this method on an already opened port will simply reconfigure the port parameters. + * + * @param safetySleepTime The number of milliseconds to sleep before opening the port in case of frequent closing/openings. + * @return Whether the port was successfully opened. + */ + public final boolean openPort(int safetySleepTime) { return openPort(safetySleepTime, sendDeviceQueueSize, receiveDeviceQueueSize); } + /** * Opens this serial port for reading and writing. *
@@ -481,7 +438,7 @@ public final class SerialPort *
* All serial port parameters or timeouts can be changed at any time before or after the port has been opened. *
- * Note that calling this method on an already opened port will simply return a value of true. + * Note that calling this method on an already opened port will simply reconfigure the port parameters. * * @return Whether the port was successfully opened. */ @@ -514,6 +471,15 @@ public final class SerialPort */ public final boolean isOpen() { return isOpened; } + /** + * Disable the library from calling any of the underlying device driver configuration methods. + *
+ * This function should never be called except in very specific cases involving USB-to-Serial converters + * with buggy device drivers. In that case, this function must be called before attempting to + * open the port. + */ + public final void disablePortConfiguration() { disableConfig = true; } + // Serial Port Setup Methods private static native void initializeLibrary(); // Initializes the JNI code private static native void uninitializeLibrary(); // Un-initializes the JNI code @@ -531,8 +497,12 @@ public final class SerialPort private final native boolean clearBreak(long portHandle); // Clear BREAK status on serial line private final native boolean setRTS(long portHandle); // Set RTS line to 1 private final native boolean clearRTS(long portHandle); // Clear RTS line to 0 + private final native boolean presetRTS(); // Set RTS line to 1 prior to opening + private final native boolean preclearRTS(); // Clear RTS line to 0 prior to opening private final native boolean setDTR(long portHandle); // Set DTR line to 1 private final native boolean clearDTR(long portHandle); // Clear DTR line to 0 + private final native boolean presetDTR(); // Set DTR line to 1 prior to opening + private final native boolean preclearDTR(); // Clear DTR line to 0 prior to opening private final native boolean getCTS(long portHandle); // Returns whether the CTS signal is 1 private final native boolean getDSR(long portHandle); // Returns whether the DSR signal is 1 @@ -631,25 +601,41 @@ public final class SerialPort * Sets the state of the RTS line to 1. * @return true if successful, false if not. */ - public final boolean setRTS() { return setRTS(portHandle); } + public final boolean setRTS() + { + isRtsEnabled = true; + return (isOpened ? setRTS(portHandle) : presetRTS()); + } /** * Clears the state of the RTS line to 0. * @return true if successful, false if not. */ - public final boolean clearRTS() { return clearRTS(portHandle); } + public final boolean clearRTS() + { + isRtsEnabled = false; + return (isOpened ? clearRTS(portHandle) : preclearRTS()); + } /** * Sets the state of the DTR line to 1. * @return true if successful, false if not. */ - public final boolean setDTR() { return setDTR(portHandle); } + public final boolean setDTR() + { + isDtrEnabled = true; + return (isOpened ? setDTR(portHandle) : presetDTR()); + } /** * Clears the state of the DTR line to 0. * @return true if successful, false if not. */ - public final boolean clearDTR() { return clearDTR(portHandle); } + public final boolean clearDTR() + { + isDtrEnabled = false; + return (isOpened ? clearDTR(portHandle) : preclearDTR()); + } /** * Returns whether the CTS line is currently asserted. diff --git a/src/main/java/com/fazecast/jSerialComm/SerialPortDataListener.java b/src/main/java/com/fazecast/jSerialComm/SerialPortDataListener.java index 36d2e30..8131e95 100644 --- a/src/main/java/com/fazecast/jSerialComm/SerialPortDataListener.java +++ b/src/main/java/com/fazecast/jSerialComm/SerialPortDataListener.java @@ -31,7 +31,7 @@ import java.util.EventListener; * This interface must be implemented to enable simple event-based serial port I/O. * * @author Will Hedgecock <will.hedgecock@fazecast.com> - * @version 2.2.3 + * @version 2.3.0 * @see java.util.EventListener */ public interface SerialPortDataListener extends EventListener diff --git a/src/main/java/com/fazecast/jSerialComm/SerialPortEvent.java b/src/main/java/com/fazecast/jSerialComm/SerialPortEvent.java index 05f439a..801db19 100644 --- a/src/main/java/com/fazecast/jSerialComm/SerialPortEvent.java +++ b/src/main/java/com/fazecast/jSerialComm/SerialPortEvent.java @@ -31,7 +31,7 @@ import java.util.EventObject; * This class describes an asynchronous serial port event. * * @author Will Hedgecock <will.hedgecock@fazecast.com> - * @version 2.2.3 + * @version 2.3.0 * @see java.util.EventObject */ public final class SerialPortEvent extends EventObject diff --git a/src/main/java/com/fazecast/jSerialComm/SerialPortIOException.java b/src/main/java/com/fazecast/jSerialComm/SerialPortIOException.java index 039eef2..ee88de8 100644 --- a/src/main/java/com/fazecast/jSerialComm/SerialPortIOException.java +++ b/src/main/java/com/fazecast/jSerialComm/SerialPortIOException.java @@ -31,7 +31,7 @@ import java.io.IOException; * This class describes a serial port IO exception. * * @author Will Hedgecock <will.hedgecock@fazecast.com> - * @version 2.2.3 + * @version 2.3.0 * @see java.io.IOException */ public final class SerialPortIOException extends IOException diff --git a/src/main/java/com/fazecast/jSerialComm/SerialPortPacketListener.java b/src/main/java/com/fazecast/jSerialComm/SerialPortPacketListener.java index db42e45..3215f49 100644 --- a/src/main/java/com/fazecast/jSerialComm/SerialPortPacketListener.java +++ b/src/main/java/com/fazecast/jSerialComm/SerialPortPacketListener.java @@ -31,7 +31,7 @@ package com.fazecast.jSerialComm; * Note: Using this interface will negate any serial port read timeout settings since they make no sense in an asynchronous context. * * @author Will Hedgecock <will.hedgecock@fazecast.com> - * @version 2.2.3 + * @version 2.3.0 * @see com.fazecast.jSerialComm.SerialPortDataListener * @see java.util.EventListener */ diff --git a/src/main/java/com/fazecast/jSerialComm/SerialPortTimeoutException.java b/src/main/java/com/fazecast/jSerialComm/SerialPortTimeoutException.java index 875641e..a9cd3b4 100644 --- a/src/main/java/com/fazecast/jSerialComm/SerialPortTimeoutException.java +++ b/src/main/java/com/fazecast/jSerialComm/SerialPortTimeoutException.java @@ -31,7 +31,7 @@ import java.io.InterruptedIOException; * This class describes a serial port timeout exception. * * @author Will Hedgecock <will.hedgecock@fazecast.com> - * @version 2.2.3 + * @version 2.3.0 * @see java.io.InterruptedIOException */ public final class SerialPortTimeoutException extends InterruptedIOException diff --git a/src/main/resources/Android/arm64-v8a/libjSerialComm.so b/src/main/resources/Android/arm64-v8a/libjSerialComm.so index fd0695a..4420606 100644 Binary files a/src/main/resources/Android/arm64-v8a/libjSerialComm.so and b/src/main/resources/Android/arm64-v8a/libjSerialComm.so differ diff --git a/src/main/resources/Android/armeabi-v7a/libjSerialComm.so b/src/main/resources/Android/armeabi-v7a/libjSerialComm.so index 239b998..ac1188d 100644 Binary files a/src/main/resources/Android/armeabi-v7a/libjSerialComm.so and b/src/main/resources/Android/armeabi-v7a/libjSerialComm.so differ diff --git a/src/main/resources/Android/armeabi/libjSerialComm.so b/src/main/resources/Android/armeabi/libjSerialComm.so index 6373aae..dddcf31 100644 Binary files a/src/main/resources/Android/armeabi/libjSerialComm.so and b/src/main/resources/Android/armeabi/libjSerialComm.so differ diff --git a/src/main/resources/Android/mips/libjSerialComm.so b/src/main/resources/Android/mips/libjSerialComm.so index 62c6ed6..029b025 100644 Binary files a/src/main/resources/Android/mips/libjSerialComm.so and b/src/main/resources/Android/mips/libjSerialComm.so differ diff --git a/src/main/resources/Android/mips64/libjSerialComm.so b/src/main/resources/Android/mips64/libjSerialComm.so index e7341ac..9cde1ed 100644 Binary files a/src/main/resources/Android/mips64/libjSerialComm.so and b/src/main/resources/Android/mips64/libjSerialComm.so differ diff --git a/src/main/resources/Android/x86/libjSerialComm.so b/src/main/resources/Android/x86/libjSerialComm.so index f10ef22..877e959 100644 Binary files a/src/main/resources/Android/x86/libjSerialComm.so and b/src/main/resources/Android/x86/libjSerialComm.so differ diff --git a/src/main/resources/Android/x86_64/libjSerialComm.so b/src/main/resources/Android/x86_64/libjSerialComm.so index caf85f0..96417fb 100644 Binary files a/src/main/resources/Android/x86_64/libjSerialComm.so and b/src/main/resources/Android/x86_64/libjSerialComm.so differ diff --git a/src/main/resources/OSX/x86/libjSerialComm.jnilib b/src/main/resources/OSX/x86/libjSerialComm.jnilib index 03b24c4..75ad188 100755 Binary files a/src/main/resources/OSX/x86/libjSerialComm.jnilib and b/src/main/resources/OSX/x86/libjSerialComm.jnilib differ diff --git a/src/main/resources/OSX/x86_64/libjSerialComm.jnilib b/src/main/resources/OSX/x86_64/libjSerialComm.jnilib index cdc58b3..35b7d9a 100755 Binary files a/src/main/resources/OSX/x86_64/libjSerialComm.jnilib and b/src/main/resources/OSX/x86_64/libjSerialComm.jnilib differ diff --git a/src/main/resources/Windows/x86/ftd2xx.dll b/src/main/resources/Windows/x86/ftd2xx.dll deleted file mode 100644 index ecafeb7..0000000 Binary files a/src/main/resources/Windows/x86/ftd2xx.dll and /dev/null differ diff --git a/src/main/resources/Windows/x86/jSerialComm.dll b/src/main/resources/Windows/x86/jSerialComm.dll index 6da66a7..133a732 100644 Binary files a/src/main/resources/Windows/x86/jSerialComm.dll and b/src/main/resources/Windows/x86/jSerialComm.dll differ diff --git a/src/main/resources/Windows/x86/jSerialComm.exp b/src/main/resources/Windows/x86/jSerialComm.exp deleted file mode 100644 index 93e111a..0000000 Binary files a/src/main/resources/Windows/x86/jSerialComm.exp and /dev/null differ diff --git a/src/main/resources/Windows/x86/jSerialComm.lib b/src/main/resources/Windows/x86/jSerialComm.lib deleted file mode 100644 index 46cf6ba..0000000 Binary files a/src/main/resources/Windows/x86/jSerialComm.lib and /dev/null differ diff --git a/src/main/resources/Windows/x86_64/ftd2xx.dll b/src/main/resources/Windows/x86_64/ftd2xx.dll deleted file mode 100644 index 4c8ab6c..0000000 Binary files a/src/main/resources/Windows/x86_64/ftd2xx.dll and /dev/null differ diff --git a/src/main/resources/Windows/x86_64/jSerialComm.dll b/src/main/resources/Windows/x86_64/jSerialComm.dll index 84be263..d89ab55 100644 Binary files a/src/main/resources/Windows/x86_64/jSerialComm.dll and b/src/main/resources/Windows/x86_64/jSerialComm.dll differ diff --git a/src/main/resources/Windows/x86_64/jSerialComm.exp b/src/main/resources/Windows/x86_64/jSerialComm.exp deleted file mode 100644 index 4b99f12..0000000 Binary files a/src/main/resources/Windows/x86_64/jSerialComm.exp and /dev/null differ diff --git a/src/main/resources/Windows/x86_64/jSerialComm.lib b/src/main/resources/Windows/x86_64/jSerialComm.lib deleted file mode 100644 index d7e3f2c..0000000 Binary files a/src/main/resources/Windows/x86_64/jSerialComm.lib and /dev/null differ diff --git a/src/test/java/com/fazecast/jSerialComm/SerialPortTest.java b/src/test/java/com/fazecast/jSerialComm/SerialPortTest.java index fb081d1..ef28be1 100644 --- a/src/test/java/com/fazecast/jSerialComm/SerialPortTest.java +++ b/src/test/java/com/fazecast/jSerialComm/SerialPortTest.java @@ -32,7 +32,7 @@ import java.util.Scanner; * This class provides a test case for the jSerialComm library. * * @author Will Hedgecock <will.hedgecock@gmail.com> - * @version 2.2.3 + * @version 2.3.0 * @see java.io.InputStream * @see java.io.OutputStream */