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>
<groupId>com.fazecast</groupId>
<artifactId>jSerialComm</artifactId>
<version>1.1.0</version>
<version>1.1.1</version>
</dependency>
Ivy:
<dependency org="com.fazecast" name="jSerialComm" rev="1.1.0"/>
<dependency org="com.fazecast" name="jSerialComm" rev="1.1.1"/>
Grape:
@Grapes(
@Grab(group='com.fazecast', module='jSerialComm', version='1.1.0')
@Grab(group='com.fazecast', module='jSerialComm', version='1.1.1')
)
Gradle:
'com.fazecast:jSerialComm:1.1.0'
'com.fazecast:jSerialComm:1.1.1'
Buildr:
'com.fazecast:jSerialComm:jar:1.1.0'
'com.fazecast:jSerialComm:jar:1.1.1'
SBT:
libraryDependencies += "com.fazecast" % "jSerialComm" % "1.1.0"
libraryDependencies += "com.fazecast" % "jSerialComm" % "1.1.1"
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'
archivesBaseName = 'jSerialComm'
version = '1.1.0'
version = '1.1.1'
sourceCompatibility = 1.6
targetCompatibility = 1.6

View File

@ -28,12 +28,11 @@
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/serial.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include <asm/termios.h>
#include <asm/ioctls.h>
#include "LinuxHelperFunctions.h"
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);
}
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

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 getFriendlyName(const char* productFile, char* friendlyName);
unsigned int getBaudRateCode(int baudRate);
void setBaudRate(int portFD, int baudRate);
#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)
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
int baudRate = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "baudRate", "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 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);
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);
cfmakeraw(&options);
// 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)
options.c_cflag &= ~PARODD;
options.c_iflag = ((parityInt > 0) ? (INPCK | ISTRIP) : IGNPAR);
options.c_oflag = 0;
options.c_lflag = 0;
options.c_iflag &= ~(INPCK | IGNPAR);
options.c_iflag |= ((parityInt > 0) ? (INPCK | ISTRIP) : IGNPAR);
// Set baud rate
unsigned int baudRateCode = getBaudRateCode(baudRate);
if (baudRateCode != 0)
{
cfsetispeed(&options, baudRateCode);
cfsetospeed(&options, baudRateCode);
}
// Apply changes
tcsetattr(portFD, TCSANOW, &options);
int retVal = tcsetattr(portFD, TCSANOW, &options);
ioctl(portFD, TIOCEXCL); // Block non-root users from using this port
// Allow custom baud rate (only for true serial ports)
ioctl(portFD, TIOCGSERIAL, &serialInfo);
serialInfo.flags = ASYNC_SPD_CUST | ASYNC_LOW_LATENCY;
serialInfo.custom_divisor = serialInfo.baud_base / baudRate;
ioctl(portFD, TIOCSSERIAL, &serialInfo);
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_configFlowControl(JNIEnv *env, jobject obj)
@ -156,6 +156,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowCo
return JNI_FALSE;
// 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"));
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;
@ -167,13 +169,13 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowCo
// Set updated port parameters
options.c_cflag |= CTSRTSEnabled;
options.c_iflag |= XonXoffInEnabled | XonXoffOutEnabled;
options.c_oflag = 0;
options.c_lflag = 0;
options.c_iflag |= (XonXoffInEnabled | XonXoffOutEnabled);
// Apply changes
tcsetattr(portFD, TCSANOW, &options);
return JNI_TRUE;
int retVal = tcsetattr(portFD, TCSANOW, &options);
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)
@ -181,6 +183,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeou
// Get port timeouts from Java class
jclass serialCommClass = (*env)->GetObjectClass(env, obj);
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 readTimeout = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "readTimeout", "I"));
if (serialFD <= 0)
@ -225,7 +229,10 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeou
// Apply changes
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)
@ -236,6 +243,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventF
return JNI_FALSE;
// 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"));
// 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;
fcntl(serialFD, F_SETFL, flags);
tcsetattr(serialFD, TCSANOW, &options);
if (baudRateCode == 0) // Set custom baud rate
setBaudRate(serialFD, baudRate);
}
else
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.
*
* @author Will Hedgecock &lt;will.hedgecock@fazecast.com&gt;
* @version 1.1.0
* @version 1.1.1
* @see java.io.InputStream
* @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.
*
* @author Will Hedgecock &lt;will.hedgecock@fazecast.com&gt;
* @version 1.1.0
* @version 1.1.1
* @see java.util.EventListener
*/
public interface SerialPortDataListener extends EventListener

View File

@ -31,7 +31,7 @@ import java.util.EventObject;
* This class describes an asynchronous serial port event.
*
* @author Will Hedgecock &lt;will.hedgecock@fazecast.com&gt;
* @version 1.1.0
* @version 1.1.1
* @see java.util.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.
*
* @author Will Hedgecock &lt;will.hedgecock@fazecast.com&gt;
* @version 1.1.0
* @version 1.1.1
* @see com.fazecast.jSerialComm.SerialPortDataListener
* @see java.util.EventListener
*/