Fixed a problem whereby serial baud rates were not updated correctly on some Linux distros.

This commit is contained in:
hedgecrw85 2015-04-21 12:18:20 -05:00
parent c41af75283
commit 8561097d18
16 changed files with 120 additions and 42 deletions

14
INSTALL
View File

@ -106,31 +106,31 @@ Maven:
<dependency> <dependency>
<groupId>com.fazecast</groupId> <groupId>com.fazecast</groupId>
<artifactId>jSerialComm</artifactId> <artifactId>jSerialComm</artifactId>
<version>1.1.0</version> <version>1.1.1</version>
</dependency> </dependency>
Ivy: Ivy:
<dependency org="com.fazecast" name="jSerialComm" rev="1.1.0"/> <dependency org="com.fazecast" name="jSerialComm" rev="1.1.1"/>
Grape: Grape:
@Grapes( @Grapes(
@Grab(group='com.fazecast', module='jSerialComm', version='1.1.0') @Grab(group='com.fazecast', module='jSerialComm', version='1.1.1')
) )
Gradle: Gradle:
'com.fazecast:jSerialComm:1.1.0' 'com.fazecast:jSerialComm:1.1.1'
Buildr: Buildr:
'com.fazecast:jSerialComm:jar:1.1.0' 'com.fazecast:jSerialComm:jar:1.1.1'
SBT: SBT:
libraryDependencies += "com.fazecast" % "jSerialComm" % "1.1.0" libraryDependencies += "com.fazecast" % "jSerialComm" % "1.1.1"
Leiningen: Leiningen:
[com.fazecast/jSerialComm "1.1.0"] [com.fazecast/jSerialComm "1.1.1"]

View File

@ -4,7 +4,7 @@ apply plugin: 'maven'
group = 'com.fazecast' group = 'com.fazecast'
archivesBaseName = 'jSerialComm' archivesBaseName = 'jSerialComm'
version = '1.1.0' version = '1.1.1'
sourceCompatibility = 1.6 sourceCompatibility = 1.6
targetCompatibility = 1.6 targetCompatibility = 1.6

View File

@ -28,12 +28,11 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/ioctl.h> #include <fcntl.h>
#include <sys/stat.h>
#include <linux/serial.h> #include <linux/serial.h>
#include <dirent.h> #include <dirent.h>
#include <fcntl.h> #include <asm/termios.h>
#include <unistd.h> #include <asm/ioctls.h>
#include "LinuxHelperFunctions.h" #include "LinuxHelperFunctions.h"
void push_back(struct charPairVector* vector, const char* firstString, const char* secondString) void push_back(struct charPairVector* vector, const char* firstString, const char* secondString)
@ -158,4 +157,70 @@ void recursiveSearchForComPorts(charPairVector* comPorts, const char* fullPathTo
closedir(directoryIterator); closedir(directoryIterator);
} }
unsigned int getBaudRateCode(int baudRate)
{
switch (baudRate)
{
case 50:
return B50;
case 75:
return B75;
case 110:
return B110;
case 134:
return B134;
case 150:
return B150;
case 200:
return B200;
case 300:
return B300;
case 600:
return B600;
case 1200:
return B1200;
case 1800:
return B1800;
case 2400:
return B2400;
case 4800:
return B4800;
case 9600:
return B9600;
case 19200:
return B19200;
case 38400:
return B38400;
case 57600:
return B57600;
case 115200:
return B115200;
case 230400:
return B230400;
case 460800:
return B460800;
case 500000:
return B500000;
case 576000:
return B576000;
case 921600:
return B921600;
default:
return 0;
}
return 0;
}
void setBaudRate(int portFD, int baudRate)
{
struct termios2 options = { 0 };
ioctl(portFD, TCGETS2, &options);
options.c_cflag &= ~CBAUD;
options.c_cflag |= BOTHER;
options.c_ispeed = baudRate;
options.c_ospeed = baudRate;
ioctl(portFD, TCSETS2, &options);
}
#endif #endif

View File

@ -35,5 +35,7 @@ void push_back(struct charPairVector* vector, const char* firstString, const cha
void recursiveSearchForComPorts(charPairVector* comPorts, const char* fullPathToSearch); void recursiveSearchForComPorts(charPairVector* comPorts, const char* fullPathToSearch);
void getFriendlyName(const char* productFile, char* friendlyName); void getFriendlyName(const char* productFile, char* friendlyName);
unsigned int getBaudRateCode(int baudRate);
void setBaudRate(int portFD, int baudRate);
#endif // #ifndef __LINUX_HELPER_FUNCTIONS_HEADER_H__ #endif // #ifndef __LINUX_HELPER_FUNCTIONS_HEADER_H__

View File

@ -108,10 +108,6 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J
if (portFD <= 0) if (portFD <= 0)
return JNI_FALSE; return JNI_FALSE;
// Set raw-mode to allow the use of tcsetattr() and ioctl()
fcntl(portFD, F_SETFL, 0);
cfmakeraw(&options);
// Get port parameters from Java class // Get port parameters from Java class
int baudRate = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "baudRate", "I")); int baudRate = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "baudRate", "I"));
int byteSizeInt = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "dataBits", "I")); int byteSizeInt = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "dataBits", "I"));
@ -120,31 +116,35 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J
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 stopBits = ((stopBitsInt == com_fazecast_jSerialComm_SerialPort_ONE_STOP_BIT) || (stopBitsInt == com_fazecast_jSerialComm_SerialPort_ONE_POINT_FIVE_STOP_BITS)) ? 0 : CSTOPB; 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); 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);
int flowControl = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "flowControl", "I"));
tcflag_t XonXoffInEnabled = ((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_XONXOFF_IN_ENABLED) > 0) ? IXOFF : 0;
tcflag_t XonXoffOutEnabled = ((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_XONXOFF_OUT_ENABLED) > 0) ? IXON : 0;
// Retrieve existing port configuration // Clear any serial port flags
fcntl(portFD, F_SETFL, 0);
// Set raw-mode to allow the use of tcsetattr() and ioctl()
tcgetattr(portFD, &options); tcgetattr(portFD, &options);
cfmakeraw(&options);
// Set updated port parameters // Set updated port parameters
options.c_cflag = (B38400 | byteSize | stopBits | parity | CLOCAL | CREAD); options.c_cflag = (byteSize | stopBits | parity | CLOCAL | CREAD);
if (parityInt == com_fazecast_jSerialComm_SerialPort_SPACE_PARITY) if (parityInt == com_fazecast_jSerialComm_SerialPort_SPACE_PARITY)
options.c_cflag &= ~PARODD; options.c_cflag &= ~PARODD;
options.c_iflag = ((parityInt > 0) ? (INPCK | ISTRIP) : IGNPAR); options.c_iflag &= ~(INPCK | IGNPAR);
options.c_oflag = 0; options.c_iflag |= ((parityInt > 0) ? (INPCK | ISTRIP) : IGNPAR);
options.c_lflag = 0;
// Set baud rate
unsigned int baudRateCode = getBaudRateCode(baudRate);
if (baudRateCode != 0)
{
cfsetispeed(&options, baudRateCode);
cfsetospeed(&options, baudRateCode);
}
// Apply changes // Apply changes
tcsetattr(portFD, TCSANOW, &options); int retVal = tcsetattr(portFD, TCSANOW, &options);
ioctl(portFD, TIOCEXCL); // Block non-root users from using this port ioctl(portFD, TIOCEXCL); // Block non-root users from using this port
if (baudRateCode == 0) // Set custom baud rate
// Allow custom baud rate (only for true serial ports) setBaudRate(portFD, baudRate);
ioctl(portFD, TIOCGSERIAL, &serialInfo); return ((retVal == 0) ? JNI_TRUE : JNI_FALSE);
serialInfo.flags = ASYNC_SPD_CUST | ASYNC_LOW_LATENCY;
serialInfo.custom_divisor = serialInfo.baud_base / baudRate;
ioctl(portFD, TIOCSSERIAL, &serialInfo);
return JNI_TRUE;
} }
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(JNIEnv *env, jobject obj) JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(JNIEnv *env, jobject obj)
@ -156,6 +156,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowCo
return JNI_FALSE; return JNI_FALSE;
// Get port parameters from Java class // Get port parameters from Java class
int baudRate = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "baudRate", "I"));
unsigned int baudRateCode = getBaudRateCode(baudRate);
int flowControl = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "flowControl", "I")); int flowControl = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "flowControl", "I"));
tcflag_t CTSRTSEnabled = (((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_CTS_ENABLED) > 0) || tcflag_t CTSRTSEnabled = (((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_CTS_ENABLED) > 0) ||
((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_RTS_ENABLED) > 0)) ? CRTSCTS : 0; ((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_RTS_ENABLED) > 0)) ? CRTSCTS : 0;
@ -167,13 +169,13 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowCo
// Set updated port parameters // Set updated port parameters
options.c_cflag |= CTSRTSEnabled; options.c_cflag |= CTSRTSEnabled;
options.c_iflag |= XonXoffInEnabled | XonXoffOutEnabled; options.c_iflag |= (XonXoffInEnabled | XonXoffOutEnabled);
options.c_oflag = 0;
options.c_lflag = 0;
// Apply changes // Apply changes
tcsetattr(portFD, TCSANOW, &options); int retVal = tcsetattr(portFD, TCSANOW, &options);
return JNI_TRUE; if (baudRateCode == 0) // Set custom baud rate
setBaudRate(portFD, baudRate);
return ((retVal == 0) ? JNI_TRUE : JNI_FALSE);
} }
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(JNIEnv *env, jobject obj) JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(JNIEnv *env, jobject obj)
@ -181,6 +183,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeou
// Get port timeouts from Java class // Get port timeouts from Java class
jclass serialCommClass = (*env)->GetObjectClass(env, obj); jclass serialCommClass = (*env)->GetObjectClass(env, obj);
int serialFD = (int)(*env)->GetLongField(env, obj, (*env)->GetFieldID(env, serialCommClass, "portHandle", "J")); int serialFD = (int)(*env)->GetLongField(env, obj, (*env)->GetFieldID(env, serialCommClass, "portHandle", "J"));
int baudRate = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "baudRate", "I"));
unsigned int baudRateCode = getBaudRateCode(baudRate);
int timeoutMode = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "timeoutMode", "I")); int timeoutMode = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "timeoutMode", "I"));
int readTimeout = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "readTimeout", "I")); int readTimeout = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "readTimeout", "I"));
if (serialFD <= 0) if (serialFD <= 0)
@ -225,7 +229,10 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeou
// Apply changes // Apply changes
fcntl(serialFD, F_SETFL, flags); fcntl(serialFD, F_SETFL, flags);
return (tcsetattr(serialFD, TCSANOW, &options) == 0) ? JNI_TRUE : JNI_FALSE; int retVal = tcsetattr(serialFD, TCSANOW, &options);
if (baudRateCode == 0) // Set custom baud rate
setBaudRate(serialFD, baudRate);
return ((retVal == 0) ? JNI_TRUE : JNI_FALSE);
} }
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(JNIEnv *env, jobject obj) JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(JNIEnv *env, jobject obj)
@ -236,6 +243,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventF
return JNI_FALSE; return JNI_FALSE;
// Get event flags from Java class // Get event flags from Java class
int baudRate = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "baudRate", "I"));
unsigned int baudRateCode = getBaudRateCode(baudRate);
int eventsToMonitor = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "eventFlags", "I")); int eventsToMonitor = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "eventFlags", "I"));
// Change read timeouts if we are monitoring data received // Change read timeouts if we are monitoring data received
@ -249,6 +258,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventF
options.c_cc[VTIME] = 10; options.c_cc[VTIME] = 10;
fcntl(serialFD, F_SETFL, flags); fcntl(serialFD, F_SETFL, flags);
tcsetattr(serialFD, TCSANOW, &options); tcsetattr(serialFD, TCSANOW, &options);
if (baudRateCode == 0) // Set custom baud rate
setBaudRate(serialFD, baudRate);
} }
else else
Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(env, obj); Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(env, obj);

View File

@ -38,7 +38,7 @@ import java.util.Date;
* This class provides native access to serial ports and devices without requiring external libraries or tools. * This class provides native access to serial ports and devices without requiring external libraries or tools.
* *
* @author Will Hedgecock &lt;will.hedgecock@fazecast.com&gt; * @author Will Hedgecock &lt;will.hedgecock@fazecast.com&gt;
* @version 1.1.0 * @version 1.1.1
* @see java.io.InputStream * @see java.io.InputStream
* @see java.io.OutputStream * @see java.io.OutputStream
*/ */

View File

@ -31,7 +31,7 @@ import java.util.EventListener;
* This interface must be implemented to enable simple event-based serial port I/O. * This interface must be implemented to enable simple event-based serial port I/O.
* *
* @author Will Hedgecock &lt;will.hedgecock@fazecast.com&gt; * @author Will Hedgecock &lt;will.hedgecock@fazecast.com&gt;
* @version 1.1.0 * @version 1.1.1
* @see java.util.EventListener * @see java.util.EventListener
*/ */
public interface SerialPortDataListener extends EventListener public interface SerialPortDataListener extends EventListener

View File

@ -31,7 +31,7 @@ import java.util.EventObject;
* This class describes an asynchronous serial port event. * This class describes an asynchronous serial port event.
* *
* @author Will Hedgecock &lt;will.hedgecock@fazecast.com&gt; * @author Will Hedgecock &lt;will.hedgecock@fazecast.com&gt;
* @version 1.1.0 * @version 1.1.1
* @see java.util.EventObject * @see java.util.EventObject
*/ */
public final class SerialPortEvent extends EventObject public final class SerialPortEvent extends EventObject

View File

@ -31,7 +31,7 @@ package com.fazecast.jSerialComm;
* <i>Note</i>: Using this interface will negate any serial port read timeout settings since they make no sense in an asynchronous context. * <i>Note</i>: Using this interface will negate any serial port read timeout settings since they make no sense in an asynchronous context.
* *
* @author Will Hedgecock &lt;will.hedgecock@fazecast.com&gt; * @author Will Hedgecock &lt;will.hedgecock@fazecast.com&gt;
* @version 1.1.0 * @version 1.1.1
* @see com.fazecast.jSerialComm.SerialPortDataListener * @see com.fazecast.jSerialComm.SerialPortDataListener
* @see java.util.EventListener * @see java.util.EventListener
*/ */