Removed all dependencies on libstdc++ (pure C now), fixed bug with dropping MSB on Linux when set to 8N1.

This commit is contained in:
hedgecrw85 2015-05-04 18:48:48 -05:00
parent f49e8803a4
commit 3bcda2e64e
44 changed files with 677 additions and 417 deletions

47
INSTALL
View File

@ -12,19 +12,19 @@ Gradle can be downloaded from https://gradle.org/
Once the Java SDK 1.6 has been installed, ensure that you have an environment variable called JDK_HOME set to the base directory of your JDK installation. Once this has been done, refer to the section corresponding to your specific Operating System for further instructions.
Please note, if you would like to edit any of the source code or view it in an IDE (such as Eclipse), you can automatically build the Eclipse project files by entering the following on a command line or terminal from the base directory of this project (.../jSerialComm/): gradle eclipse
You can then Import the project using the "Existing Project into Workspace" import tool in Eclipse. (Note that if you use Eclipse as an IDE, you will probably want to install the Eclipse CDT plugin for proper handling of the C/C++ source code)
You can then Import the project using the "Existing Project into Workspace" import tool in Eclipse. (Note that if you use Eclipse as an IDE, you will probably want to install the Eclipse CDT plugin for proper handling of the C source code)
------------
LINUX/UNIX
------------
Ensure that the following tools are installed on your Linux distribution: g++ make glibc-devel.x86_64 glibc-devel.i686 libstdc++-devel.x86_64 libstdc++-devel.i686 (on some distros, these may be called multilib tools for gcc and binutils)
Ensure that the following tools are installed on your Linux distribution: gcc make glibc-devel.x86_64 glibc-devel.i686 (on some distros, these may be called multilib tools for gcc and binutils)
Ensure that the JDK_HOME environment variable has been set for the 1.6 version of your Java SDK. The correct directory can usually be found by entering the following command: readlink -f /usr/bin/java
Export the result of this command UP TO BUT NOT INCLUDING the /jre/... portion using the 'export' command. For example, if 'readlink' produced "/usr/lib/jvm/java-6-jdk/jre/bin/java" as an output, the export command would look like: export JDK_HOME=/usr/lib/jvm/java-6-jdk
Change directories to the following project directory: ".../jSerialComm/src/main/cpp/Linux/"
Change directories to the following project directory: ".../jSerialComm/src/main/c/Linux/"
Run the following commands in order:
@ -35,16 +35,16 @@ gradle build
The resulting jSerialComm library can be found in the project directory ".../jSerialComm/build/libs/" under the name "jSerialComm-{VERSION}.jar"
-------------------------------------
--------------------------------------
ARM-BASED MOBILE LINUX (NON-ANDROID)
-------------------------------------
--------------------------------------
Ensure that you have a cross-compiler installed on your Linux distribution capable of compiling for ARM-based architectures. I prefer crosstool-ng for this purpose.
Ensure that the JDK_HOME environment variable has been set for the 1.6 version of your Java SDK. The correct directory can usually be found by entering the following command: readlink -f /usr/bin/java
Export the result of this command UP TO BUT NOT INCLUDING the /jre/... portion using the 'export' command. For example, if 'readlink' produced "/usr/lib/jvm/java-6-jdk/jre/bin/java" as an output, the export command would look like: export JDK_HOME=/usr/lib/jvm/java-6-jdk
Change directories to the following project directory: ".../jSerialComm/src/main/cpp/Linux/"
Change directories to the following project directory: ".../jSerialComm/src/main/c/Linux/"
Run the following commands in order:
@ -55,13 +55,30 @@ gradle build
The resulting jSerialComm library can be found in the project directory ".../jSerialComm/build/libs/" under the name "jSerialComm-{VERSION}.jar"
---------
ANDROID
---------
Ensure that the Android NDK is installed on your system. For purposes of these instructions, assume that it is installed at {NDK_HOME}.
Change directories to the following project directory: ".../jSerialComm/src/main/c/Android/"
Run the following commands in order:
{NDK_HOME}/ndk-build
cd ../../../..
gradle build
The resulting jSerialComm library can be found in the project directory ".../jSerialComm/build/libs/" under the name "jSerialComm-{VERSION}.jar"
----------
MAC OS X
----------
Ensure that Xcode is installed on your system. If it is not, it can be downloaded via the App Store. You must also make sure that the Xcode Command Line Tools are installed. This can be done by entering the following command in a terminal: xcode-select --install
Change directories to the following project directory: ".../jSerialComm/src/main/cpp/OSX/"
Change directories to the following project directory: ".../jSerialComm/src/main/c/OSX/"
Run the following commands in order:
@ -78,7 +95,7 @@ The resulting jSerialComm library can be found in the project directory ".../jSe
Ensure that the Visual Studio C++ Compiler is installed on your system. If it is not, you can download a free version (Visual C++ 2010 Express) from https://www.visualstudio.com/downloads/download-visual-studio-vs.
Open up a command prompt (Run->'cmd') and change to the following project directory: "...\jSerialComm\src\main\cpp\Windows\"
Open up a command prompt (Run->'cmd') and change to the following project directory: "...\jSerialComm\src\main\c\Windows\"
On Windows, the Visual Studio Compiler must be configured to build either 32- or 64-bit binaries but never both at the same time. Therefore, you will have to build binaries for the two architectures separately.
For the following commands, {VC_DIRECTORY} is the installation directory of your Visual Studio C++ Compiler (for example: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC). Run the following commands in order:
@ -106,31 +123,31 @@ Maven:
<dependency>
<groupId>com.fazecast</groupId>
<artifactId>jSerialComm</artifactId>
<version>1.2.2</version>
<version>1.3.0</version>
</dependency>
Ivy:
<dependency org="com.fazecast" name="jSerialComm" rev="1.2.2"/>
<dependency org="com.fazecast" name="jSerialComm" rev="1.3.0"/>
Grape:
@Grapes(
@Grab(group='com.fazecast', module='jSerialComm', version='1.2.2')
@Grab(group='com.fazecast', module='jSerialComm', version='1.3.0')
)
Gradle:
'com.fazecast:jSerialComm:1.2.2'
'com.fazecast:jSerialComm:1.3.0'
Buildr:
'com.fazecast:jSerialComm:jar:1.2.2'
'com.fazecast:jSerialComm:jar:1.3.0'
SBT:
libraryDependencies += "com.fazecast" % "jSerialComm" % "1.2.2"
libraryDependencies += "com.fazecast" % "jSerialComm" % "1.3.0"
Leiningen:
[com.fazecast/jSerialComm "1.2.2"]
[com.fazecast/jSerialComm "1.3.0"]

View File

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

View File

@ -1,5 +1,5 @@
/*
* AndroidHelperFunctions.cpp
* AndroidHelperFunctions.c
*
* Created on: Mar 10, 2015
* Last Updated on: Mar 10, 2015

View File

@ -1,8 +1,8 @@
/*
* SerialPort_Android.cpp
* SerialPort_Android.c
*
* Created on: Mar 13, 2015
* Last Updated on: Mar 13, 2015
* Last Updated on: Apr 30, 2015
* Author: Will Hedgecock
*
* Copyright (C) 2012-2015 Fazecast, Inc.
@ -38,29 +38,41 @@
#include "com_fazecast_jSerialComm_SerialPort.h"
#include "AndroidHelperFunctions.h"
JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommPorts(JNIEnv *env, jclass serialCommClass)
{
// Get relevant SerialComm methods and IDs
jmethodID serialCommConstructor = (*env)->GetMethodID(env, serialCommClass, "<init>", "()V");
jfieldID portStringID = (*env)->GetFieldID(env, serialCommClass, "portString", "Ljava/lang/String;");
jfieldID comPortID = (*env)->GetFieldID(env, serialCommClass, "comPort", "Ljava/lang/String;");
// Cached class, method, and field IDs
int serialPortFD = -1;
jclass serialCommClass;
jmethodID serialCommConstructor;
jfieldID comPortField;
jfieldID portStringField;
jfieldID isOpenedField;
jfieldID baudRateField;
jfieldID dataBitsField;
jfieldID stopBitsField;
jfieldID parityField;
jfieldID flowControlField;
jfieldID timeoutModeField;
jfieldID readTimeoutField;
jfieldID writeTimeoutField;
jfieldID eventFlagsField;
JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommPorts(JNIEnv *env, jclass serialComm)
{
// Enumerate serial ports on machine
charPairVector serialPorts = { (char**)malloc(1), (char**)malloc(1), 0 };
recursiveSearchForComPorts(&serialPorts, "/sys/devices/");
jobjectArray arrayObject = (*env)->NewObjectArray(env, serialPorts.length, serialCommClass, 0);
int index = 0, i;
int i;
for (i = 0; i < serialPorts.length; ++i)
{
// Create new SerialComm object containing the enumerated values
jobject serialCommObject = (*env)->NewObject(env, serialCommClass, serialCommConstructor);
(*env)->SetObjectField(env, serialCommObject, portStringID, (*env)->NewStringUTF(env, serialPorts.second[i]));
(*env)->SetObjectField(env, serialCommObject, comPortID, (*env)->NewStringUTF(env, serialPorts.first[i]));
(*env)->SetObjectField(env, serialCommObject, portStringField, (*env)->NewStringUTF(env, serialPorts.second[i]));
(*env)->SetObjectField(env, serialCommObject, comPortField, (*env)->NewStringUTF(env, serialPorts.first[i]));
free(serialPorts.first[i]);
free(serialPorts.second[i]);
// Add new SerialComm object to array
(*env)->SetObjectArrayElement(env, arrayObject, index++, serialCommObject);
(*env)->SetObjectArrayElement(env, arrayObject, i, serialCommObject);
}
free(serialPorts.first);
free(serialPorts.second);
@ -68,66 +80,89 @@ JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommP
return arrayObject;
}
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrary(JNIEnv *env, jclass serialComm)
{
// Cache class and method ID as global references
serialCommClass = (jclass)(*env)->NewGlobalRef(env, serialComm);
serialCommConstructor = (*env)->GetMethodID(env, serialCommClass, "<init>", "()V");
// Cache
comPortField = (*env)->GetFieldID(env, serialCommClass, "comPort", "Ljava/lang/String;");
portStringField = (*env)->GetFieldID(env, serialCommClass, "portString", "Ljava/lang/String;");
isOpenedField = (*env)->GetFieldID(env, serialCommClass, "isOpened", "Z");
baudRateField = (*env)->GetFieldID(env, serialCommClass, "baudRate", "I");
dataBitsField = (*env)->GetFieldID(env, serialCommClass, "dataBits", "I");
stopBitsField = (*env)->GetFieldID(env, serialCommClass, "stopBits", "I");
parityField = (*env)->GetFieldID(env, serialCommClass, "parity", "I");
flowControlField = (*env)->GetFieldID(env, serialCommClass, "flowControl", "I");
timeoutModeField = (*env)->GetFieldID(env, serialCommClass, "timeoutMode", "I");
readTimeoutField = (*env)->GetFieldID(env, serialCommClass, "readTimeout", "I");
writeTimeoutField = (*env)->GetFieldID(env, serialCommClass, "writeTimeout", "I");
eventFlagsField = (*env)->GetFieldID(env, serialCommClass, "eventFlags", "I");
}
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_uninitializeLibrary(JNIEnv *env, jclass serialComm)
{
// Delete the cache global reference
(*env)->DeleteGlobalRef(env, serialCommClass);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(JNIEnv *env, jobject obj)
{
int fdSerial;
jstring portNameJString = (jstring)(*env)->GetObjectField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "comPort", "Ljava/lang/String;"));
jstring portNameJString = (jstring)(*env)->GetObjectField(env, obj, comPortField);
const char *portName = (*env)->GetStringUTFChars(env, portNameJString, NULL);
// Try to open existing serial port with read/write access
if ((fdSerial = open(portName, O_RDWR | O_NOCTTY | O_NONBLOCK)) > 0)
if ((serialPortFD = open(portName, O_RDWR | O_NOCTTY | O_NONBLOCK)) > 0)
{
// Set port handle in Java structure
(*env)->SetLongField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "portHandle", "J"), fdSerial);
// Configure the port parameters and timeouts
if (Java_com_fazecast_jSerialComm_SerialPort_configPort(env, obj) && Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(env, obj) &&
Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(env, obj))
(*env)->SetBooleanField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "isOpened", "Z"), JNI_TRUE);
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_TRUE);
else
{
// Close the port if there was a problem setting the parameters
close(fdSerial);
fdSerial = -1;
(*env)->SetLongField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "portHandle", "J"), -1l);
(*env)->SetBooleanField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "isOpened", "Z"), JNI_FALSE);
close(serialPortFD);
serialPortFD = -1;
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
}
}
(*env)->ReleaseStringUTFChars(env, portNameJString, portName);
return (fdSerial == -1) ? JNI_FALSE : JNI_TRUE;
return (serialPortFD == -1) ? JNI_FALSE : JNI_TRUE;
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(JNIEnv *env, jobject obj)
{
struct termios options = { 0 };
jclass serialCommClass = (*env)->GetObjectClass(env, obj);
int portFD = (int)(*env)->GetLongField(env, obj, (*env)->GetFieldID(env, serialCommClass, "portHandle", "J"));
if (portFD <= 0)
if (serialPortFD <= 0)
return JNI_FALSE;
struct termios options = { 0 };
// 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"));
int stopBitsInt = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "stopBits", "I"));
int parityInt = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "parity", "I"));
int baudRate = (*env)->GetIntField(env, obj, baudRateField);
int byteSizeInt = (*env)->GetIntField(env, obj, dataBitsField);
int stopBitsInt = (*env)->GetIntField(env, obj, stopBitsField);
int parityInt = (*env)->GetIntField(env, obj, parityField);
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);
// Clear any serial port flags
fcntl(portFD, F_SETFL, 0);
fcntl(serialPortFD, F_SETFL, 0);
// Set raw-mode to allow the use of tcsetattr() and ioctl()
tcgetattr(portFD, &options);
tcgetattr(serialPortFD, &options);
cfmakeraw(&options);
// Set updated port parameters
options.c_cflag = (byteSize | stopBits | parity | CLOCAL | CREAD);
if (parityInt == com_fazecast_jSerialComm_SerialPort_SPACE_PARITY)
options.c_cflag &= ~PARODD;
options.c_iflag &= ~(INPCK | IGNPAR);
options.c_iflag |= ((parityInt > 0) ? (INPCK | ISTRIP) : IGNPAR);
options.c_iflag &= ~(INPCK | IGNPAR | PARMRK | ISTRIP);
if (byteSizeInt < 8)
options.c_iflag |= ISTRIP;
if (parityInt != 0)
options.c_iflag |= (INPCK | IGNPAR);
// Set baud rate
unsigned int baudRateCode = getBaudRateCode(baudRate);
@ -138,60 +173,56 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J
}
// Apply changes
int retVal = tcsetattr(portFD, TCSANOW, &options);
ioctl(portFD, TIOCEXCL); // Block non-root users from using this port
int retVal = tcsetattr(serialPortFD, TCSANOW, &options);
ioctl(serialPortFD, TIOCEXCL); // Block non-root users from using this port
if (baudRateCode == 0) // Set custom baud rate
setBaudRate(portFD, baudRate);
setBaudRate(serialPortFD, baudRate);
return ((retVal == 0) ? JNI_TRUE : JNI_FALSE);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(JNIEnv *env, jobject obj)
{
struct termios options = { 0 };
jclass serialCommClass = (*env)->GetObjectClass(env, obj);
int portFD = (int)(*env)->GetLongField(env, obj, (*env)->GetFieldID(env, serialCommClass, "portHandle", "J"));
if (portFD <= 0)
if (serialPortFD <= 0)
return JNI_FALSE;
struct termios options = { 0 };
// Get port parameters from Java class
int baudRate = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "baudRate", "I"));
int baudRate = (*env)->GetIntField(env, obj, baudRateField);
unsigned int baudRateCode = getBaudRateCode(baudRate);
int flowControl = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "flowControl", "I"));
int flowControl = (*env)->GetIntField(env, obj, flowControlField);
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;
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
tcgetattr(portFD, &options);
tcgetattr(serialPortFD, &options);
// Set updated port parameters
options.c_cflag |= CTSRTSEnabled;
options.c_iflag |= XonXoffInEnabled | XonXoffOutEnabled;
// Apply changes
int retVal = tcsetattr(portFD, TCSANOW, &options);
int retVal = tcsetattr(serialPortFD, TCSANOW, &options);
if (baudRateCode == 0) // Set custom baud rate
setBaudRate(portFD, baudRate);
setBaudRate(serialPortFD, baudRate);
return ((retVal == 0) ? JNI_TRUE : JNI_FALSE);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(JNIEnv *env, jobject obj)
{
// 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)
if (serialPortFD <= 0)
return JNI_FALSE;
int baudRate = (*env)->GetIntField(env, obj, baudRateField);
unsigned int baudRateCode = getBaudRateCode(baudRate);
int timeoutMode = (*env)->GetIntField(env, obj, timeoutModeField);
int readTimeout = (*env)->GetIntField(env, obj, readTimeoutField);
// Retrieve existing port configuration
struct termios options = { 0 };
tcgetattr(serialFD, &options);
int flags = fcntl(serialFD, F_GETFL);
tcgetattr(serialPortFD, &options);
int flags = fcntl(serialPortFD, F_GETFL);
// Set updated port timeouts
if (((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_SEMI_BLOCKING) > 0) && (readTimeout > 0)) // Read Semi-blocking with timeout
@ -218,6 +249,12 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeou
options.c_cc[VMIN] = 1;
options.c_cc[VTIME] = 0;
}
else if ((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_SCANNER) > 0) // Scanner Mode
{
flags &= ~O_NONBLOCK;
options.c_cc[VMIN] = 1;
options.c_cc[VTIME] = 1;
}
else // Non-blocking
{
flags |= O_NONBLOCK;
@ -226,38 +263,36 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeou
}
// Apply changes
fcntl(serialFD, F_SETFL, flags);
int retVal = tcsetattr(serialFD, TCSANOW, &options);
fcntl(serialPortFD, F_SETFL, flags);
int retVal = tcsetattr(serialPortFD, TCSANOW, &options);
if (baudRateCode == 0) // Set custom baud rate
setBaudRate(serialFD, baudRate);
setBaudRate(serialPortFD, baudRate);
return ((retVal == 0) ? JNI_TRUE : JNI_FALSE);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(JNIEnv *env, jobject obj)
{
jclass serialCommClass = (*env)->GetObjectClass(env, obj);
int serialFD = (int)(*env)->GetLongField(env, obj, (*env)->GetFieldID(env, serialCommClass, "portHandle", "J"));
if (serialFD <= 0)
if (serialPortFD <= 0)
return JNI_FALSE;
// Get event flags from Java class
int baudRate = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "baudRate", "I"));
int baudRate = (*env)->GetIntField(env, obj, baudRateField);
unsigned int baudRateCode = getBaudRateCode(baudRate);
int eventsToMonitor = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "eventFlags", "I"));
int eventsToMonitor = (*env)->GetIntField(env, obj, eventFlagsField);
// Change read timeouts if we are monitoring data received
if ((eventsToMonitor & com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_RECEIVED) > 0)
{
struct termios options = { 0 };
tcgetattr(serialFD, &options);
int flags = fcntl(serialFD, F_GETFL);
tcgetattr(serialPortFD, &options);
int flags = fcntl(serialPortFD, F_GETFL);
flags &= ~O_NONBLOCK;
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = 10;
fcntl(serialFD, F_SETFL, flags);
tcsetattr(serialFD, TCSANOW, &options);
fcntl(serialPortFD, F_SETFL, flags);
tcsetattr(serialPortFD, TCSANOW, &options);
if (baudRateCode == 0) // Set custom baud rate
setBaudRate(serialFD, baudRate);
setBaudRate(serialPortFD, baudRate);
}
else
Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(env, obj);
@ -268,42 +303,37 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventF
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNIEnv *env, jobject obj)
{
jclass serialCommClass = (*env)->GetObjectClass(env, obj);
int serialFD = (int)(*env)->GetLongField(env, obj, (*env)->GetFieldID(env, serialCommClass, "portHandle", "J"));
if (serialFD <= 0)
if (serialPortFD <= 0)
return 0;
// Initialize the waiting set and the timeouts
struct timeval timeout = { 1, 0 };
fd_set waitingSet;
FD_ZERO(&waitingSet);
FD_SET(serialFD, &waitingSet);
FD_SET(serialPortFD, &waitingSet);
// Wait for a serial port event
int retVal = select(serialFD + 1, &waitingSet, NULL, NULL, &timeout);
int retVal = select(serialPortFD + 1, &waitingSet, NULL, NULL, &timeout);
if (retVal <= 0)
return 0;
return (FD_ISSET(serialFD, &waitingSet)) ? com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_AVAILABLE : 0;
return (FD_ISSET(serialPortFD, &waitingSet)) ? com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_AVAILABLE : 0;
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNative(JNIEnv *env, jobject obj)
{
// Close port
int portFD = (int)(*env)->GetLongField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "portHandle", "J"));
if (portFD <= 0)
if (serialPortFD <= 0)
return JNI_TRUE;
close(portFD);
(*env)->SetLongField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "portHandle", "J"), -1l);
(*env)->SetBooleanField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "isOpened", "Z"), JNI_FALSE);
close(serialPortFD);
serialPortFD = -1;
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
return JNI_TRUE;
}
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(JNIEnv *env, jobject obj)
{
int serialPortFD = (int)(*env)->GetLongField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "portHandle", "J"));
int numBytesAvailable = -1;
if (serialPortFD > 0)
ioctl(serialPortFD, FIONREAD, &numBytesAvailable);
@ -313,12 +343,10 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(J
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv *env, jobject obj, jbyteArray buffer, jlong bytesToRead)
{
// Get port handle and read timeout from Java class
jclass serialCommClass = (*env)->GetObjectClass(env, obj);
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 serialPortFD = (int)(*env)->GetLongField(env, obj, (*env)->GetFieldID(env, serialCommClass, "portHandle", "J"));
if (serialPortFD == -1)
if (serialPortFD <= 0)
return -1;
int timeoutMode = (*env)->GetIntField(env, obj, timeoutModeField);
int readTimeout = (*env)->GetIntField(env, obj, readTimeoutField);
int numBytesRead, numBytesReadTotal = 0, bytesRemaining = bytesToRead;
char* readBuffer = (char*)malloc(bytesToRead);
@ -332,8 +360,8 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
{
// Problem reading, close port
close(serialPortFD);
(*env)->SetLongField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "portHandle", "J"), -1l);
(*env)->SetBooleanField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "isOpened", "Z"), JNI_FALSE);
serialPortFD = -1;
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
break;
}
@ -361,8 +389,8 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
{
// Problem reading, close port
close(serialPortFD);
(*env)->SetLongField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "portHandle", "J"), -1l);
(*env)->SetBooleanField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "isOpened", "Z"), JNI_FALSE);
serialPortFD = -1;
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
break;
}
@ -382,8 +410,8 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
{
// Problem reading, close port
close(serialPortFD);
(*env)->SetLongField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "portHandle", "J"), -1l);
(*env)->SetBooleanField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "isOpened", "Z"), JNI_FALSE);
serialPortFD = -1;
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
}
else
numBytesReadTotal = numBytesRead;
@ -397,8 +425,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jbyteArray buffer, jlong bytesToWrite)
{
int serialPortFD = (int)(*env)->GetLongField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "portHandle", "J"));
if (serialPortFD == -1)
if (serialPortFD <= 0)
return -1;
jbyte *writeBuffer = (*env)->GetByteArrayElements(env, buffer, 0);
int numBytesWritten;
@ -408,8 +435,8 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn
{
// Problem writing, close port
close(serialPortFD);
(*env)->SetLongField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "portHandle", "J"), -1l);
(*env)->SetBooleanField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "isOpened", "Z"), JNI_FALSE);
serialPortFD = -1;
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
}
// Return number of bytes written if successful

View File

@ -47,6 +47,8 @@ extern "C" {
#define com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_BLOCKING 256L
#undef com_fazecast_jSerialComm_SerialPort_TIMEOUT_WRITE_BLOCKING
#define com_fazecast_jSerialComm_SerialPort_TIMEOUT_WRITE_BLOCKING 4096L
#undef com_fazecast_jSerialComm_SerialPort_TIMEOUT_SCANNER
#define com_fazecast_jSerialComm_SerialPort_TIMEOUT_SCANNER 65536L
#undef com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_AVAILABLE
#define com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_AVAILABLE 1L
#undef com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_RECEIVED
@ -61,6 +63,22 @@ extern "C" {
JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommPorts
(JNIEnv *, jclass);
/*
* Class: com_fazecast_jSerialComm_SerialPort
* Method: initializeLibrary
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrary
(JNIEnv *, jclass);
/*
* Class: com_fazecast_jSerialComm_SerialPort
* Method: uninitializeLibrary
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_uninitializeLibrary
(JNIEnv *, jclass);
/*
* Class: com_fazecast_jSerialComm_SerialPort
* Method: openPortNative

View File

@ -1,5 +1,5 @@
/*
* LinuxHelperFunctions.cpp
* LinuxHelperFunctions.c
*
* Created on: Mar 10, 2015
* Last Updated on: Mar 10, 2015

View File

@ -47,7 +47,7 @@ JAVA_CLASS = $(JAVA_CLASS_DIR)/SerialPort.class
# Define phony and suffix rules
.PHONY: all checkdirs linux32 linux64 arm armv5 armv6 armv6-hf armv7 armv7-hf armv8 armv8_64
.SUFFIXES:
.SUFFIXES: .c .o .class .java .h
.SUFFIXES: .cpp .c .o .class .java .h
# Default build target builds both 32 and 64 bit libraries
all : linux32 linux64

View File

@ -1,8 +1,8 @@
/*
* SerialPort_Linux.cpp
* SerialPort_Linux.c
*
* Created on: Feb 25, 2012
* Last Updated on: Feb 27, 2015
* Last Updated on: May 04, 2015
* Author: Will Hedgecock
*
* Copyright (C) 2012-2015 Fazecast, Inc.
@ -39,29 +39,41 @@
#include "../com_fazecast_jSerialComm_SerialPort.h"
#include "LinuxHelperFunctions.h"
JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommPorts(JNIEnv *env, jclass serialCommClass)
{
// Get relevant SerialComm methods and IDs
jmethodID serialCommConstructor = (*env)->GetMethodID(env, serialCommClass, "<init>", "()V");
jfieldID portStringID = (*env)->GetFieldID(env, serialCommClass, "portString", "Ljava/lang/String;");
jfieldID comPortID = (*env)->GetFieldID(env, serialCommClass, "comPort", "Ljava/lang/String;");
// Cached class, method, and field IDs
int serialPortFD = -1;
jclass serialCommClass;
jmethodID serialCommConstructor;
jfieldID comPortField;
jfieldID portStringField;
jfieldID isOpenedField;
jfieldID baudRateField;
jfieldID dataBitsField;
jfieldID stopBitsField;
jfieldID parityField;
jfieldID flowControlField;
jfieldID timeoutModeField;
jfieldID readTimeoutField;
jfieldID writeTimeoutField;
jfieldID eventFlagsField;
JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommPorts(JNIEnv *env, jclass serialComm)
{
// Enumerate serial ports on machine
charPairVector serialPorts = { (char**)malloc(1), (char**)malloc(1), 0 };
recursiveSearchForComPorts(&serialPorts, "/sys/devices/");
jobjectArray arrayObject = (*env)->NewObjectArray(env, serialPorts.length, serialCommClass, 0);
int index = 0, i;
int i;
for (i = 0; i < serialPorts.length; ++i)
{
// Create new SerialComm object containing the enumerated values
jobject serialCommObject = (*env)->NewObject(env, serialCommClass, serialCommConstructor);
(*env)->SetObjectField(env, serialCommObject, portStringID, (*env)->NewStringUTF(env, serialPorts.second[i]));
(*env)->SetObjectField(env, serialCommObject, comPortID, (*env)->NewStringUTF(env, serialPorts.first[i]));
(*env)->SetObjectField(env, serialCommObject, portStringField, (*env)->NewStringUTF(env, serialPorts.second[i]));
(*env)->SetObjectField(env, serialCommObject, comPortField, (*env)->NewStringUTF(env, serialPorts.first[i]));
free(serialPorts.first[i]);
free(serialPorts.second[i]);
// Add new SerialComm object to array
(*env)->SetObjectArrayElement(env, arrayObject, index++, serialCommObject);
(*env)->SetObjectArrayElement(env, arrayObject, i, serialCommObject);
}
free(serialPorts.first);
free(serialPorts.second);
@ -69,67 +81,90 @@ JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommP
return arrayObject;
}
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrary(JNIEnv *env, jclass serialComm)
{
// Cache class and method ID as global references
serialCommClass = (jclass)(*env)->NewGlobalRef(env, serialComm);
serialCommConstructor = (*env)->GetMethodID(env, serialCommClass, "<init>", "()V");
// Cache
comPortField = (*env)->GetFieldID(env, serialCommClass, "comPort", "Ljava/lang/String;");
portStringField = (*env)->GetFieldID(env, serialCommClass, "portString", "Ljava/lang/String;");
isOpenedField = (*env)->GetFieldID(env, serialCommClass, "isOpened", "Z");
baudRateField = (*env)->GetFieldID(env, serialCommClass, "baudRate", "I");
dataBitsField = (*env)->GetFieldID(env, serialCommClass, "dataBits", "I");
stopBitsField = (*env)->GetFieldID(env, serialCommClass, "stopBits", "I");
parityField = (*env)->GetFieldID(env, serialCommClass, "parity", "I");
flowControlField = (*env)->GetFieldID(env, serialCommClass, "flowControl", "I");
timeoutModeField = (*env)->GetFieldID(env, serialCommClass, "timeoutMode", "I");
readTimeoutField = (*env)->GetFieldID(env, serialCommClass, "readTimeout", "I");
writeTimeoutField = (*env)->GetFieldID(env, serialCommClass, "writeTimeout", "I");
eventFlagsField = (*env)->GetFieldID(env, serialCommClass, "eventFlags", "I");
}
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_uninitializeLibrary(JNIEnv *env, jclass serialComm)
{
// Delete the cache global reference
(*env)->DeleteGlobalRef(env, serialCommClass);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(JNIEnv *env, jobject obj)
{
int fdSerial;
jstring portNameJString = (jstring)(*env)->GetObjectField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "comPort", "Ljava/lang/String;"));
jstring portNameJString = (jstring)(*env)->GetObjectField(env, obj, comPortField);
const char *portName = (*env)->GetStringUTFChars(env, portNameJString, NULL);
// Try to open existing serial port with read/write access
if ((fdSerial = open(portName, O_RDWR | O_NOCTTY | O_NONBLOCK)) > 0)
if ((serialPortFD = open(portName, O_RDWR | O_NOCTTY | O_NONBLOCK)) > 0)
{
// Set port handle in Java structure
(*env)->SetLongField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "portHandle", "J"), fdSerial);
// Configure the port parameters and timeouts
if (Java_com_fazecast_jSerialComm_SerialPort_configPort(env, obj) && Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(env, obj) &&
Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(env, obj))
(*env)->SetBooleanField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "isOpened", "Z"), JNI_TRUE);
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_TRUE);
else
{
// Close the port if there was a problem setting the parameters
close(fdSerial);
fdSerial = -1;
(*env)->SetLongField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "portHandle", "J"), -1l);
(*env)->SetBooleanField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "isOpened", "Z"), JNI_FALSE);
close(serialPortFD);
serialPortFD = -1;
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
}
}
(*env)->ReleaseStringUTFChars(env, portNameJString, portName);
return (fdSerial == -1) ? JNI_FALSE : JNI_TRUE;
return (serialPortFD == -1) ? JNI_FALSE : JNI_TRUE;
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(JNIEnv *env, jobject obj)
{
if (serialPortFD <= 0)
return JNI_FALSE;
struct termios options = { 0 };
struct serial_struct serialInfo = { 0 };
jclass serialCommClass = (*env)->GetObjectClass(env, obj);
int portFD = (int)(*env)->GetLongField(env, obj, (*env)->GetFieldID(env, serialCommClass, "portHandle", "J"));
if (portFD <= 0)
return JNI_FALSE;
// 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"));
int stopBitsInt = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "stopBits", "I"));
int parityInt = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "parity", "I"));
int baudRate = (*env)->GetIntField(env, obj, baudRateField);
int byteSizeInt = (*env)->GetIntField(env, obj, dataBitsField);
int stopBitsInt = (*env)->GetIntField(env, obj, stopBitsField);
int parityInt = (*env)->GetIntField(env, obj, parityField);
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);
// Clear any serial port flags
fcntl(portFD, F_SETFL, 0);
fcntl(serialPortFD, F_SETFL, 0);
// Set raw-mode to allow the use of tcsetattr() and ioctl()
tcgetattr(portFD, &options);
tcgetattr(serialPortFD, &options);
cfmakeraw(&options);
// Set updated port parameters
options.c_cflag = (byteSize | stopBits | parity | CLOCAL | CREAD);
if (parityInt == com_fazecast_jSerialComm_SerialPort_SPACE_PARITY)
options.c_cflag &= ~PARODD;
options.c_iflag &= ~(INPCK | IGNPAR);
options.c_iflag |= ((parityInt > 0) ? (INPCK | ISTRIP) : IGNPAR);
options.c_iflag &= ~(INPCK | IGNPAR | PARMRK | ISTRIP);
if (byteSizeInt < 8)
options.c_iflag |= ISTRIP;
if (parityInt != 0)
options.c_iflag |= (INPCK | IGNPAR);
// Set baud rate
unsigned int baudRateCode = getBaudRateCode(baudRate);
@ -140,60 +175,56 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J
}
// Apply changes
int retVal = tcsetattr(portFD, TCSANOW, &options);
ioctl(portFD, TIOCEXCL); // Block non-root users from using this port
int retVal = tcsetattr(serialPortFD, TCSANOW, &options);
ioctl(serialPortFD, TIOCEXCL); // Block non-root users from using this port
if (baudRateCode == 0) // Set custom baud rate
setBaudRate(portFD, baudRate);
setBaudRate(serialPortFD, baudRate);
return ((retVal == 0) ? JNI_TRUE : JNI_FALSE);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(JNIEnv *env, jobject obj)
{
struct termios options = { 0 };
jclass serialCommClass = (*env)->GetObjectClass(env, obj);
int portFD = (int)(*env)->GetLongField(env, obj, (*env)->GetFieldID(env, serialCommClass, "portHandle", "J"));
if (portFD <= 0)
if (serialPortFD <= 0)
return JNI_FALSE;
struct termios options = { 0 };
// Get port parameters from Java class
int baudRate = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "baudRate", "I"));
int baudRate = (*env)->GetIntField(env, obj, baudRateField);
unsigned int baudRateCode = getBaudRateCode(baudRate);
int flowControl = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "flowControl", "I"));
int flowControl = (*env)->GetIntField(env, obj, flowControlField);
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;
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
tcgetattr(portFD, &options);
tcgetattr(serialPortFD, &options);
// Set updated port parameters
options.c_cflag |= CTSRTSEnabled;
options.c_iflag |= (XonXoffInEnabled | XonXoffOutEnabled);
// Apply changes
int retVal = tcsetattr(portFD, TCSANOW, &options);
int retVal = tcsetattr(serialPortFD, TCSANOW, &options);
if (baudRateCode == 0) // Set custom baud rate
setBaudRate(portFD, baudRate);
setBaudRate(serialPortFD, baudRate);
return ((retVal == 0) ? JNI_TRUE : JNI_FALSE);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(JNIEnv *env, jobject obj)
{
// 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)
if (serialPortFD <= 0)
return JNI_FALSE;
int baudRate = (*env)->GetIntField(env, obj, baudRateField);
unsigned int baudRateCode = getBaudRateCode(baudRate);
int timeoutMode = (*env)->GetIntField(env, obj, timeoutModeField);
int readTimeout = (*env)->GetIntField(env, obj, readTimeoutField);
// Retrieve existing port configuration
struct termios options = { 0 };
tcgetattr(serialFD, &options);
int flags = fcntl(serialFD, F_GETFL);
tcgetattr(serialPortFD, &options);
int flags = fcntl(serialPortFD, F_GETFL);
// Set updated port timeouts
if (((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_SEMI_BLOCKING) > 0) && (readTimeout > 0)) // Read Semi-blocking with timeout
@ -220,6 +251,12 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeou
options.c_cc[VMIN] = 1;
options.c_cc[VTIME] = 0;
}
else if ((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_SCANNER) > 0) // Scanner Mode
{
flags &= ~O_NONBLOCK;
options.c_cc[VMIN] = 1;
options.c_cc[VTIME] = 1;
}
else // Non-blocking
{
flags |= O_NONBLOCK;
@ -228,38 +265,36 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeou
}
// Apply changes
fcntl(serialFD, F_SETFL, flags);
int retVal = tcsetattr(serialFD, TCSANOW, &options);
fcntl(serialPortFD, F_SETFL, flags);
int retVal = tcsetattr(serialPortFD, TCSANOW, &options);
if (baudRateCode == 0) // Set custom baud rate
setBaudRate(serialFD, baudRate);
setBaudRate(serialPortFD, baudRate);
return ((retVal == 0) ? JNI_TRUE : JNI_FALSE);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(JNIEnv *env, jobject obj)
{
jclass serialCommClass = (*env)->GetObjectClass(env, obj);
int serialFD = (int)(*env)->GetLongField(env, obj, (*env)->GetFieldID(env, serialCommClass, "portHandle", "J"));
if (serialFD <= 0)
if (serialPortFD <= 0)
return JNI_FALSE;
// Get event flags from Java class
int baudRate = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "baudRate", "I"));
int baudRate = (*env)->GetIntField(env, obj, baudRateField);
unsigned int baudRateCode = getBaudRateCode(baudRate);
int eventsToMonitor = (*env)->GetIntField(env, obj, (*env)->GetFieldID(env, serialCommClass, "eventFlags", "I"));
int eventsToMonitor = (*env)->GetIntField(env, obj, eventFlagsField);
// Change read timeouts if we are monitoring data received
if ((eventsToMonitor & com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_RECEIVED) > 0)
{
struct termios options = { 0 };
tcgetattr(serialFD, &options);
int flags = fcntl(serialFD, F_GETFL);
tcgetattr(serialPortFD, &options);
int flags = fcntl(serialPortFD, F_GETFL);
flags &= ~O_NONBLOCK;
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = 10;
fcntl(serialFD, F_SETFL, flags);
tcsetattr(serialFD, TCSANOW, &options);
fcntl(serialPortFD, F_SETFL, flags);
tcsetattr(serialPortFD, TCSANOW, &options);
if (baudRateCode == 0) // Set custom baud rate
setBaudRate(serialFD, baudRate);
setBaudRate(serialPortFD, baudRate);
}
else
Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(env, obj);
@ -270,42 +305,37 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventF
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNIEnv *env, jobject obj)
{
jclass serialCommClass = (*env)->GetObjectClass(env, obj);
int serialFD = (int)(*env)->GetLongField(env, obj, (*env)->GetFieldID(env, serialCommClass, "portHandle", "J"));
if (serialFD <= 0)
if (serialPortFD <= 0)
return 0;
// Initialize the waiting set and the timeouts
struct timeval timeout = { 1, 0 };
fd_set waitingSet;
FD_ZERO(&waitingSet);
FD_SET(serialFD, &waitingSet);
FD_SET(serialPortFD, &waitingSet);
// Wait for a serial port event
int retVal = select(serialFD + 1, &waitingSet, NULL, NULL, &timeout);
int retVal = select(serialPortFD + 1, &waitingSet, NULL, NULL, &timeout);
if (retVal <= 0)
return 0;
return (FD_ISSET(serialFD, &waitingSet)) ? com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_AVAILABLE : 0;
return (FD_ISSET(serialPortFD, &waitingSet)) ? com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_AVAILABLE : 0;
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNative(JNIEnv *env, jobject obj)
{
// Close port
int portFD = (int)(*env)->GetLongField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "portHandle", "J"));
if (portFD <= 0)
if (serialPortFD <= 0)
return JNI_TRUE;
close(portFD);
(*env)->SetLongField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "portHandle", "J"), -1l);
(*env)->SetBooleanField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "isOpened", "Z"), JNI_FALSE);
close(serialPortFD);
serialPortFD = -1;
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
return JNI_TRUE;
}
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(JNIEnv *env, jobject obj)
{
int serialPortFD = (int)(*env)->GetLongField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "portHandle", "J"));
int numBytesAvailable = -1;
if (serialPortFD > 0)
ioctl(serialPortFD, FIONREAD, &numBytesAvailable);
@ -315,12 +345,10 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(J
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv *env, jobject obj, jbyteArray buffer, jlong bytesToRead)
{
// Get port handle and read timeout from Java class
jclass serialCommClass = (*env)->GetObjectClass(env, obj);
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 serialPortFD = (int)(*env)->GetLongField(env, obj, (*env)->GetFieldID(env, serialCommClass, "portHandle", "J"));
if (serialPortFD == -1)
if (serialPortFD <= 0)
return -1;
int timeoutMode = (*env)->GetIntField(env, obj, timeoutModeField);
int readTimeout = (*env)->GetIntField(env, obj, readTimeoutField);
int numBytesRead, numBytesReadTotal = 0, bytesRemaining = bytesToRead;
char* readBuffer = (char*)malloc(bytesToRead);
@ -334,8 +362,8 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
{
// Problem reading, close port
close(serialPortFD);
(*env)->SetLongField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "portHandle", "J"), -1l);
(*env)->SetBooleanField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "isOpened", "Z"), JNI_FALSE);
serialPortFD = -1;
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
break;
}
@ -363,8 +391,8 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
{
// Problem reading, close port
close(serialPortFD);
(*env)->SetLongField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "portHandle", "J"), -1l);
(*env)->SetBooleanField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "isOpened", "Z"), JNI_FALSE);
serialPortFD = -1;
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
break;
}
@ -384,8 +412,8 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
{
// Problem reading, close port
close(serialPortFD);
(*env)->SetLongField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "portHandle", "J"), -1l);
(*env)->SetBooleanField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "isOpened", "Z"), JNI_FALSE);
serialPortFD = -1;
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
}
else
numBytesReadTotal = numBytesRead;
@ -399,8 +427,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jbyteArray buffer, jlong bytesToWrite)
{
int serialPortFD = (int)(*env)->GetLongField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "portHandle", "J"));
if (serialPortFD == -1)
if (serialPortFD <= 0)
return -1;
jbyte *writeBuffer = (*env)->GetByteArrayElements(env, buffer, 0);
int numBytesWritten;
@ -410,8 +437,8 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn
{
// Problem writing, close port
close(serialPortFD);
(*env)->SetLongField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "portHandle", "J"), -1l);
(*env)->SetBooleanField(env, obj, (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "isOpened", "Z"), JNI_FALSE);
serialPortFD = -1;
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
}
// Return number of bytes written if successful

View File

@ -1,9 +1,10 @@
# OSX specific library variables
COMPILE := g++
LINK := g++
COMPILE := gcc
LINK := gcc
CFLAGS :=
LDFLAGS := -dynamiclib
INCLUDES := -I"/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers"
JDK_HOME = /Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home
INCLUDES := -I"$(JDK_HOME)/include" -I"$(JDK_HOME)/include/darwin"
LIBRARIES := -framework Cocoa -framework IOKit -framework JavaVM
DELETE := @rm
MKDIR := @mkdir
@ -11,25 +12,24 @@ COPY := @cp
MOVE := @mv
PRINT := @echo
FULL_CLASS := com.fazecast.jSerialComm.SerialPort
JDK_HOME = /System/Library/Frameworks/JavaVM.framework/Versions/Current
JAVAC := javac
JAVAH := javah -jni
JFLAGS := -source 1.6 -target 1.6 -Xlint:-options
LIBRARY_NAME := libjSerialComm.jnilib
SOURCES := SerialPort_OSX.cpp
SOURCES := SerialPort_OSX.c
JAVA_SOURCE_DIR = ../../../../src/main/java/com/fazecast/jSerialComm
RESOURCE_DIR = ../../../../src/main/resources/OSX
BUILD_DIR = ../../../../bin/OSX
JAVA_CLASS_DIR = $(BUILD_DIR)/../com/fazecast/jSerialComm
OBJECTSx86 = $(BUILD_DIR)/x86/$(SOURCES:.cpp=.o)
OBJECTSx86_64 = $(BUILD_DIR)/x86_64/$(SOURCES:.cpp=.o)
OBJECTSx86 = $(BUILD_DIR)/x86/$(SOURCES:.c=.o)
OBJECTSx86_64 = $(BUILD_DIR)/x86_64/$(SOURCES:.c=.o)
JNI_HEADER = ../com_fazecast_jSerialComm_SerialPort.h
JAVA_CLASS = $(JAVA_CLASS_DIR)/SerialPort.class
# Define phony and suffix rules
.PHONY: all osx32 osx64 checkdirs
.SUFFIXES:
.SUFFIXES: .cpp .o .class .java .h
.SUFFIXES: .cpp .c .o .class .java .h
# Default build target builds both 32 and 64 bit libraries
all : osx32 osx64
@ -65,10 +65,10 @@ $(BUILD_DIR)/x86/$(LIBRARY_NAME) : $(JNI_HEADER) $(OBJECTSx86)
$(BUILD_DIR)/x86_64/$(LIBRARY_NAME) : $(JNI_HEADER) $(OBJECTSx86_64)
$(LINK) $(LDFLAGS) $(ARCH) -o $@ $(OBJECTSx86_64) $(LIBRARIES)
# Suffix rules to get from *.cpp -> *.o
$(BUILD_DIR)/x86/%.o : %.cpp
# Suffix rules to get from *.c -> *.o
$(BUILD_DIR)/x86/%.o : %.c
$(COMPILE) $(INCLUDES) $(CFLAGS) $(ARCH) -c $< -o $@
$(BUILD_DIR)/x86_64/%.o : %.cpp
$(BUILD_DIR)/x86_64/%.o : %.c
$(COMPILE) $(INCLUDES) $(CFLAGS) $(ARCH) -c $< -o $@
# Rule to build JNI header file

View File

@ -1,8 +1,8 @@
/*
* SerialPort_OSX.cpp
* SerialPort_OSX.c
*
* Created on: Feb 25, 2012
* Last Updated on: Mar 17, 2015
* Last Updated on: Apr 30, 2015
* Author: Will Hedgecock
*
* Copyright (C) 2012-2015 Fazecast, Inc.
@ -27,7 +27,7 @@
#ifndef CMSPAR
#define CMSPAR 010000000000
#endif
#include <cstdlib>
#include <stdlib.h>
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/serial/IOSerialKeys.h>
@ -39,18 +39,30 @@
#include <sys/time.h>
#include "../com_fazecast_jSerialComm_SerialPort.h"
JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommPorts(JNIEnv *env, jclass serialCommClass)
// Cached class, method, and field IDs
int serialPortFD = -1;
jclass serialCommClass;
jmethodID serialCommConstructor;
jfieldID comPortField;
jfieldID portStringField;
jfieldID isOpenedField;
jfieldID baudRateField;
jfieldID dataBitsField;
jfieldID stopBitsField;
jfieldID parityField;
jfieldID flowControlField;
jfieldID timeoutModeField;
jfieldID readTimeoutField;
jfieldID writeTimeoutField;
jfieldID eventFlagsField;
JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommPorts(JNIEnv *env, jclass serialComm)
{
io_object_t serialPort;
io_iterator_t serialPortIterator;
int numValues = 0;
char portString[1024], comPort[1024];
// Get relevant SerialComm methods and IDs
jmethodID serialCommConstructor = env->GetMethodID(serialCommClass, "<init>", "()V");
jfieldID portStringID = env->GetFieldID(serialCommClass, "portString", "Ljava/lang/String;");
jfieldID comPortID = env->GetFieldID(serialCommClass, "comPort", "Ljava/lang/String;");
// Enumerate serial ports on machine
IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching(kIOSerialBSDServiceValue), &serialPortIterator);
while ((serialPort = IOIteratorNext(serialPortIterator)))
@ -59,7 +71,7 @@ JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommP
IOObjectRelease(serialPort);
}
IOIteratorReset(serialPortIterator);
jobjectArray arrayObject = env->NewObjectArray(numValues, serialCommClass, 0);
jobjectArray arrayObject = (*env)->NewObjectArray(env, numValues, serialCommClass, 0);
for (int i = 0; i < numValues; ++i)
{
// Get serial port information
@ -96,12 +108,12 @@ JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommP
CFRelease(comPortRef);
// Create new SerialComm object containing the enumerated values
jobject serialCommObject = env->NewObject(serialCommClass, serialCommConstructor);
env->SetObjectField(serialCommObject, portStringID, env->NewStringUTF(portString));
env->SetObjectField(serialCommObject, comPortID, env->NewStringUTF(comPort));
jobject serialCommObject = (*env)->NewObject(env, serialCommClass, serialCommConstructor);
(*env)->SetObjectField(env, serialCommObject, portStringField, (*env)->NewStringUTF(env, portString));
(*env)->SetObjectField(env, serialCommObject, comPortField, (*env)->NewStringUTF(env, comPort));
// Add new SerialComm object to array
env->SetObjectArrayElement(arrayObject, i, serialCommObject);
(*env)->SetObjectArrayElement(env, arrayObject, i, serialCommObject);
IOObjectRelease(serialPort);
}
IOObjectRelease(serialPortIterator);
@ -109,116 +121,137 @@ JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommP
return arrayObject;
}
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrary(JNIEnv *env, jclass serialComm)
{
// Cache class and method ID as global references
serialCommClass = (jclass)(*env)->NewGlobalRef(env, serialComm);
serialCommConstructor = (*env)->GetMethodID(env, serialCommClass, "<init>", "()V");
// Cache
comPortField = (*env)->GetFieldID(env, serialCommClass, "comPort", "Ljava/lang/String;");
portStringField = (*env)->GetFieldID(env, serialCommClass, "portString", "Ljava/lang/String;");
isOpenedField = (*env)->GetFieldID(env, serialCommClass, "isOpened", "Z");
baudRateField = (*env)->GetFieldID(env, serialCommClass, "baudRate", "I");
dataBitsField = (*env)->GetFieldID(env, serialCommClass, "dataBits", "I");
stopBitsField = (*env)->GetFieldID(env, serialCommClass, "stopBits", "I");
parityField = (*env)->GetFieldID(env, serialCommClass, "parity", "I");
flowControlField = (*env)->GetFieldID(env, serialCommClass, "flowControl", "I");
timeoutModeField = (*env)->GetFieldID(env, serialCommClass, "timeoutMode", "I");
readTimeoutField = (*env)->GetFieldID(env, serialCommClass, "readTimeout", "I");
writeTimeoutField = (*env)->GetFieldID(env, serialCommClass, "writeTimeout", "I");
eventFlagsField = (*env)->GetFieldID(env, serialCommClass, "eventFlags", "I");
}
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_uninitializeLibrary(JNIEnv *env, jclass serialComm)
{
// Delete the cache global reference
(*env)->DeleteGlobalRef(env, serialCommClass);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(JNIEnv *env, jobject obj)
{
int fdSerial;
jstring portNameJString = (jstring)env->GetObjectField(obj, env->GetFieldID(env->GetObjectClass(obj), "comPort", "Ljava/lang/String;"));
const char *portName = env->GetStringUTFChars(portNameJString, NULL);
jstring portNameJString = (jstring)(*env)->GetObjectField(env, obj, comPortField);
const char *portName = (*env)->GetStringUTFChars(env, portNameJString, NULL);
// Try to open existing serial port with read/write access
if ((fdSerial = open(portName, O_RDWR | O_NOCTTY | O_NONBLOCK)) > 0)
if ((serialPortFD = open(portName, O_RDWR | O_NOCTTY | O_NONBLOCK)) > 0)
{
// Set port handle in Java structure
env->SetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"), fdSerial);
// Configure the port parameters and timeouts
if (Java_com_fazecast_jSerialComm_SerialPort_configPort(env, obj) && Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(env, obj) &&
Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(env, obj))
env->SetBooleanField(obj, env->GetFieldID(env->GetObjectClass(obj), "isOpened", "Z"), JNI_TRUE);
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_TRUE);
else
{
// Close the port if there was a problem setting the parameters
close(fdSerial);
fdSerial = -1;
env->SetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"), -1l);
env->SetBooleanField(obj, env->GetFieldID(env->GetObjectClass(obj), "isOpened", "Z"), JNI_FALSE);
close(serialPortFD);
serialPortFD = -1;
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
}
}
env->ReleaseStringUTFChars(portNameJString, portName);
return (fdSerial == -1) ? JNI_FALSE : JNI_TRUE;
(*env)->ReleaseStringUTFChars(env, portNameJString, portName);
return (serialPortFD == -1) ? JNI_FALSE : JNI_TRUE;
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(JNIEnv *env, jobject obj)
{
struct termios options;
jclass serialCommClass = env->GetObjectClass(obj);
int portFD = (int)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
if (portFD <= 0)
if (serialPortFD <= 0)
return JNI_FALSE;
struct termios options = { 0 };
// Block non-root users from using this port
if (ioctl(portFD, TIOCEXCL) == -1)
if (ioctl(serialPortFD, TIOCEXCL) == -1)
return JNI_FALSE;
// Clear any serial port flags
fcntl(serialPortFD, F_SETFL, 0);
// Set raw-mode to allow the use of tcsetattr() and ioctl()
if (fcntl(portFD, F_SETFL, 0) == -1)
return JNI_FALSE;
tcgetattr(portFD, &options);
tcgetattr(serialPortFD, &options);
cfmakeraw(&options);
// Get port parameters from Java class
speed_t baudRate = env->GetIntField(obj, env->GetFieldID(serialCommClass, "baudRate", "I"));
int byteSizeInt = env->GetIntField(obj, env->GetFieldID(serialCommClass, "dataBits", "I"));
int stopBitsInt = env->GetIntField(obj, env->GetFieldID(serialCommClass, "stopBits", "I"));
int parityInt = env->GetIntField(obj, env->GetFieldID(serialCommClass, "parity", "I"));
speed_t baudRate = (*env)->GetIntField(env, obj, baudRateField);
int byteSizeInt = (*env)->GetIntField(env, obj, dataBitsField);
int stopBitsInt = (*env)->GetIntField(env, obj, stopBitsField);
int parityInt = (*env)->GetIntField(env, obj, parityField);
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);
// Set updated port parameters
cfsetspeed(&options, B38400);
options.c_cflag |= (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_iflag &= ~(INPCK | IGNPAR | PARMRK | ISTRIP);
if (byteSizeInt < 8)
options.c_iflag |= ISTRIP;
if (parityInt != 0)
options.c_iflag |= (INPCK | IGNPAR);
// Apply changes
if (tcsetattr(portFD, TCSANOW, &options) == -1)
if (tcsetattr(serialPortFD, TCSANOW, &options) == -1)
return JNI_FALSE;
return (ioctl(portFD, IOSSIOSPEED, &baudRate) == -1) ? JNI_FALSE : JNI_TRUE;
return (ioctl(serialPortFD, IOSSIOSPEED, &baudRate) == -1) ? JNI_FALSE : JNI_TRUE;
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(JNIEnv *env, jobject obj)
{
struct termios options;
jclass serialCommClass = env->GetObjectClass(obj);
int portFD = (int)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
if (portFD <= 0)
if (serialPortFD <= 0)
return JNI_FALSE;
struct termios options;
// Get port parameters from Java class
int flowControl = env->GetIntField(obj, env->GetFieldID(serialCommClass, "flowControl", "I"));
int flowControl = (*env)->GetIntField(env, obj, flowControlField);
tcflag_t CTSRTSEnabled = ((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_CTS_ENABLED) > 0) ? CCTS_OFLOW : 0;
CTSRTSEnabled |= ((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_RTS_ENABLED) > 0) ? CRTS_IFLOW : 0;
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
tcgetattr(portFD, &options);
tcgetattr(serialPortFD, &options);
// Set updated port parameters
options.c_cflag |= CTSRTSEnabled;
options.c_iflag |= (XonXoffInEnabled | XonXoffOutEnabled);
// Apply changes
return (tcsetattr(portFD, TCSANOW, &options) == -1) ? JNI_FALSE : JNI_TRUE;
return (tcsetattr(serialPortFD, TCSANOW, &options) == -1) ? JNI_FALSE : JNI_TRUE;
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(JNIEnv *env, jobject obj)
{
// Get port timeouts from Java class
jclass serialCommClass = env->GetObjectClass(obj);
int serialFD = (int)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
int timeoutMode = env->GetIntField(obj, env->GetFieldID(serialCommClass, "timeoutMode", "I"));
int readTimeout = env->GetIntField(obj, env->GetFieldID(serialCommClass, "readTimeout", "I"));
if (serialFD <= 0)
if (serialPortFD <= 0)
return JNI_FALSE;
int timeoutMode = (*env)->GetIntField(env, obj, timeoutModeField);
int readTimeout = (*env)->GetIntField(env, obj, readTimeoutField);
// Retrieve existing port configuration
struct termios options;
tcgetattr(serialFD, &options);
int flags = fcntl(serialFD, F_GETFL);
tcgetattr(serialPortFD, &options);
int flags = fcntl(serialPortFD, F_GETFL);
// Set updated port timeouts
if (((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_SEMI_BLOCKING) > 0) && (readTimeout > 0)) // Read Semi-blocking with timeout
@ -245,6 +278,12 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeou
options.c_cc[VMIN] = 1;
options.c_cc[VTIME] = 0;
}
else if ((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_SCANNER) > 0) // Scanner Mode
{
flags &= ~O_NONBLOCK;
options.c_cc[VMIN] = 1;
options.c_cc[VTIME] = 1;
}
else // Non-blocking
{
flags |= O_NONBLOCK;
@ -253,32 +292,30 @@ 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;
fcntl(serialPortFD, F_SETFL, flags);
return (tcsetattr(serialPortFD, TCSANOW, &options) == 0) ? JNI_TRUE : JNI_FALSE;
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(JNIEnv *env, jobject obj)
{
jclass serialCommClass = env->GetObjectClass(obj);
int serialFD = (int)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
if (serialFD <= 0)
if (serialPortFD <= 0)
return JNI_FALSE;
// Get event flags from Java class
int eventsToMonitor = env->GetIntField(obj, env->GetFieldID(serialCommClass, "eventFlags", "I"));
int eventsToMonitor = (*env)->GetIntField(env, obj, eventFlagsField);
jboolean retVal = JNI_FALSE;
// Change read timeouts if we are monitoring data received
if ((eventsToMonitor & com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_RECEIVED) > 0)
{
struct termios options;
tcgetattr(serialFD, &options);
int flags = fcntl(serialFD, F_GETFL);
tcgetattr(serialPortFD, &options);
int flags = fcntl(serialPortFD, F_GETFL);
flags &= ~O_NONBLOCK;
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = 10;
fcntl(serialFD, F_SETFL, flags);
retVal = (tcsetattr(serialFD, TCSANOW, &options) == 0) ? JNI_TRUE : JNI_FALSE;
fcntl(serialPortFD, F_SETFL, flags);
retVal = (tcsetattr(serialPortFD, TCSANOW, &options) == 0) ? JNI_TRUE : JNI_FALSE;
}
else
retVal = Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(env, obj);
@ -288,43 +325,38 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventF
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNIEnv *env, jobject obj)
{
jclass serialCommClass = env->GetObjectClass(obj);
int serialFD = (int)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
if (serialFD <= 0)
if (serialPortFD <= 0)
return 0;
// Initialize the waiting set and the timeouts
struct timeval timeout = { 1, 0 };
fd_set waitingSet;
FD_ZERO(&waitingSet);
FD_SET(serialFD, &waitingSet);
FD_SET(serialPortFD, &waitingSet);
// Wait for a serial port event
int retVal = select(serialFD + 1, &waitingSet, NULL, NULL, &timeout);
int retVal = select(serialPortFD + 1, &waitingSet, NULL, NULL, &timeout);
if (retVal <= 0)
return 0;
return (FD_ISSET(serialFD, &waitingSet)) ? com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_AVAILABLE : 0;
return (FD_ISSET(serialPortFD, &waitingSet)) ? com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_AVAILABLE : 0;
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNative(JNIEnv *env, jobject obj)
{
// Close port
int portFD = (int)env->GetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"));
if (portFD <= 0)
if (serialPortFD <= 0)
return JNI_TRUE;
tcdrain(portFD);
close(portFD);
env->SetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"), -1l);
env->SetBooleanField(obj, env->GetFieldID(env->GetObjectClass(obj), "isOpened", "Z"), JNI_FALSE);
tcdrain(serialPortFD);
close(serialPortFD);
serialPortFD = -1;
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
return JNI_TRUE;
}
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(JNIEnv *env, jobject obj)
{
int serialPortFD = (int)env->GetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"));
int numBytesAvailable = -1;
if (serialPortFD > 0)
ioctl(serialPortFD, FIONREAD, &numBytesAvailable);
@ -334,12 +366,10 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(J
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv *env, jobject obj, jbyteArray buffer, jlong bytesToRead)
{
// Get port handle and read timeout from Java class
jclass serialCommClass = env->GetObjectClass(obj);
int timeoutMode = env->GetIntField(obj, env->GetFieldID(serialCommClass, "timeoutMode", "I"));
int readTimeout = env->GetIntField(obj, env->GetFieldID(serialCommClass, "readTimeout", "I"));
int serialPortFD = (int)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
if (serialPortFD == -1)
if (serialPortFD <= 0)
return -1;
int timeoutMode = (*env)->GetIntField(env, obj, timeoutModeField);
int readTimeout = (*env)->GetIntField(env, obj, readTimeoutField);
int numBytesRead, numBytesReadTotal = 0, bytesRemaining = bytesToRead;
char* readBuffer = (char*)malloc(bytesToRead);
@ -353,8 +383,8 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
{
// Problem reading, close port
close(serialPortFD);
env->SetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"), -1l);
env->SetBooleanField(obj, env->GetFieldID(env->GetObjectClass(obj), "isOpened", "Z"), JNI_FALSE);
serialPortFD = -1;
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
break;
}
@ -382,8 +412,8 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
{
// Problem reading, close port
close(serialPortFD);
env->SetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"), -1l);
env->SetBooleanField(obj, env->GetFieldID(env->GetObjectClass(obj), "isOpened", "Z"), JNI_FALSE);
serialPortFD = -1;
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
break;
}
@ -403,25 +433,24 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
{
// Problem reading, close port
close(serialPortFD);
env->SetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"), -1l);
env->SetBooleanField(obj, env->GetFieldID(env->GetObjectClass(obj), "isOpened", "Z"), JNI_FALSE);
serialPortFD = -1;
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
}
else
numBytesReadTotal = numBytesRead;
}
// Return number of bytes read if successful
env->SetByteArrayRegion(buffer, 0, numBytesReadTotal, (jbyte*)readBuffer);
(*env)->SetByteArrayRegion(env, buffer, 0, numBytesReadTotal, (jbyte*)readBuffer);
free(readBuffer);
return (numBytesRead == -1) ? -1 : numBytesReadTotal;
}
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jbyteArray buffer, jlong bytesToWrite)
{
int serialPortFD = (int)env->GetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"));
if (serialPortFD <= 0)
return -1;
jbyte *writeBuffer = env->GetByteArrayElements(buffer, 0);
jbyte *writeBuffer = (*env)->GetByteArrayElements(env, buffer, 0);
int numBytesWritten;
// Write to port
@ -429,12 +458,12 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn
{
// Problem writing, close port
close(serialPortFD);
env->SetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"), -1l);
env->SetBooleanField(obj, env->GetFieldID(env->GetObjectClass(obj), "isOpened", "Z"), JNI_FALSE);
serialPortFD = -1;
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
}
// Return number of bytes written if successful
env->ReleaseByteArrayElements(buffer, writeBuffer, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, buffer, writeBuffer, JNI_ABORT);
return numBytesWritten;
}

View File

@ -16,20 +16,20 @@ JAVAC = "$(JDK_HOME)\bin\javac"
JAVAH = "$(JDK_HOME)\bin\javah" -jni
JFLAGS = -source 1.6 -target 1.6 -Xlint:-options
LIBRARY_NAME = jSerialComm.dll
SOURCES = SerialPort_Windows.cpp
SOURCES = SerialPort_Windows.c WindowsHelperFunctions.c
JAVA_SOURCE_DIR = ..\..\..\..\src\main\java\com\fazecast\jSerialComm
RESOURCE_DIR = ..\..\..\..\src\main\resources\Windows
BUILD_DIR = ..\..\..\..\bin\Windows
JAVA_CLASS_DIR = $(BUILD_DIR)\..\com\fazecast\jSerialComm
OBJECTSx86 = $(BUILD_DIR)\x86\$(SOURCES:.cpp=.obj)
OBJECTSx86_64 = $(BUILD_DIR)\x86_64\$(SOURCES:.cpp=.obj)
OBJECTSx86 = $(BUILD_DIR)\x86\SerialPort_Windows.obj $(BUILD_DIR)\x86\WindowsHelperFunctions.obj
OBJECTSx86_64 = $(BUILD_DIR)\x86_64\SerialPort_Windows.obj $(BUILD_DIR)\x86_64\WindowsHelperFunctions.obj
JNI_HEADER = ..\com_fazecast_jSerialComm_SerialPort.h
JAVA_CLASS = $(JAVA_CLASS_DIR)\SerialPort.class
# Define phony and suffix rules
.PHONY: all win32 win64 checkdirs clean
.SUFFIXES:
.SUFFIXES: .cpp .obj .class .java .h
.SUFFIXES: .c .obj .class .java .h
# Default build target not possible due to different architecture compilers
all :
@ -72,11 +72,11 @@ $(BUILD_DIR)\x86\$(LIBRARY_NAME) : $(JNI_HEADER) $(OBJECTSx86)
$(BUILD_DIR)\x86_64\$(LIBRARY_NAME) : $(JNI_HEADER) $(OBJECTSx86_64)
$(LINK) $(LDFLAGS) /MACHINE:X64 /OUT:$@ $(OBJECTSx86_64) $(LIBRARIES)
# Suffix rules to get from *.cpp -> *.obj
$(OBJECTSx86_64) : $(*B).cpp
$(COMPILE) $(CFLAGS) $(INCLUDES) $? -Fo$@
$(OBJECTSx86) : $(*B).cpp
$(COMPILE) $(CFLAGS) $(INCLUDES) $? -Fo$@
# Suffix rules to get from *.c -> *.obj
$(OBJECTSx86_64) :
$(COMPILE) $(CFLAGS) $(INCLUDES) $(*B).c -Fo$@
$(OBJECTSx86) :
$(COMPILE) $(CFLAGS) $(INCLUDES) $(*B).c -Fo$@
# Rule to build JNI header file
$(JNI_HEADER) : $(JAVA_CLASS)

View File

@ -1,8 +1,8 @@
/*
* SerialPort_Windows.cpp
* SerialPort_Windows.c
*
* Created on: Feb 25, 2012
* Last Updated on: Feb 27, 2015
* Last Updated on: May 04, 2015
* Author: Will Hedgecock
*
* Copyright (C) 2012-2015 Fazecast, Inc.
@ -29,12 +29,29 @@
#define NTDDI_VERSION NTDDI_WINXP
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <cstdlib>
#include <string>
#include <map>
#include <stdlib.h>
#include <string.h>
#include "../com_fazecast_jSerialComm_SerialPort.h"
#include "WindowsHelperFunctions.h"
JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommPorts(JNIEnv *env, jclass serialCommClass)
// Cached class, method, and field IDs
HANDLE serialPortHandle = INVALID_HANDLE_VALUE;
jclass serialCommClass;
jmethodID serialCommConstructor;
jfieldID comPortField;
jfieldID portStringField;
jfieldID isOpenedField;
jfieldID baudRateField;
jfieldID dataBitsField;
jfieldID stopBitsField;
jfieldID parityField;
jfieldID flowControlField;
jfieldID timeoutModeField;
jfieldID readTimeoutField;
jfieldID writeTimeoutField;
jfieldID eventFlagsField;
JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommPorts(JNIEnv *env, jclass serialComm)
{
HKEY keyHandle1, keyHandle2, keyHandle3, keyHandle4, keyHandle5;
DWORD numSubKeys1, numSubKeys2, numSubKeys3, numValues;
@ -43,7 +60,7 @@ JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommP
DWORD subKeyLength1, subKeyLength2, subKeyLength3, friendlyNameLength;
// Enumerate serial ports on machine
std::map<std::string, std::string> serialCommPorts;
charPairVector serialCommPorts = { (char**)malloc(1), (char**)malloc(1), 0 };
if ((RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_QUERY_VALUE, &keyHandle1) == ERROR_SUCCESS) &&
(RegQueryInfoKey(keyHandle1, NULL, NULL, NULL, NULL, NULL, NULL, &numValues, &maxValueLength, &maxComPortLength, NULL, NULL) == ERROR_SUCCESS))
{
@ -64,11 +81,11 @@ JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommP
if ((RegEnumValue(keyHandle1, i, valueName, &valueLength, NULL, &keyType, (BYTE*)comPort, &comPortLength) == ERROR_SUCCESS) && (keyType == REG_SZ))
{
// Set port name and description
std::string comPortString = (comPort[0] == '\\') ? std::string(strrchr(comPort, '\\') + 1) : std::string(comPort);
std::string descriptionString = strrchr(valueName, '\\') ? std::string(strrchr(valueName, '\\') + 1) : std::string(valueName);
char* comPortString = (comPort[0] == '\\') ? (strrchr(comPort, '\\') + 1) : comPort;
char* descriptionString = strrchr(valueName, '\\') ? (strrchr(valueName, '\\') + 1) : valueName;
// Add new SerialComm object to vector
serialCommPorts[comPortString] = descriptionString;
push_back(&serialCommPorts, comPortString, descriptionString);
}
}
@ -134,13 +151,19 @@ JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommP
(RegQueryValueEx(keyHandle4, "FriendlyName", NULL, &keyType, (BYTE*)friendlyName, &friendlyNameLength) == ERROR_SUCCESS) && (keyType == REG_SZ))
{
// Set port name and description
std::string comPortString = (comPort[0] == '\\') ? std::string(strrchr(comPort, '\\') + 1) : std::string(comPort);
std::string descriptionString = std::string(friendlyName);
char* comPortString = (comPort[0] == '\\') ? (strrchr(comPort, '\\') + 1) : comPort;
char* descriptionString = friendlyName;
// Update friendly name if COM port is actually connected and present in the port list
std::map<std::string, std::string>::iterator it = serialCommPorts.find(comPortString);
if (it != serialCommPorts.end())
it->second = descriptionString;
int i;
for (i = 0; i < serialCommPorts.length; ++i)
if (strcmp(serialCommPorts.first[i], comPortString) == 0)
{
free(serialCommPorts.second[i]);
serialCommPorts.second[i] = (char*)malloc(strlen(descriptionString)+1);
strcpy(serialCommPorts.second[i], descriptionString);
break;
}
}
// Clean up memory
@ -174,43 +197,73 @@ JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommP
}
// Get relevant SerialComm methods and fill in com port array
jmethodID serialCommConstructor = env->GetMethodID(serialCommClass, "<init>", "()V");
jobjectArray arrayObject = env->NewObjectArray(serialCommPorts.size(), serialCommClass, 0);
int i = 0;
for (std::map<std::string, std::string>::iterator it = serialCommPorts.begin(); it != serialCommPorts.end(); ++it, ++i)
jobjectArray arrayObject = env->NewObjectArray(serialCommPorts.length, serialCommClass, 0);
char systemPortName[128];
int i;
for (i = 0; i < serialCommPorts.length; ++i)
{
// Create new SerialComm object containing the enumerated values
jobject serialCommObject = env->NewObject(serialCommClass, serialCommConstructor);
env->SetObjectField(serialCommObject, env->GetFieldID(serialCommClass, "comPort", "Ljava/lang/String;"), env->NewStringUTF((std::string("\\\\.\\") + it->first).c_str()));
env->SetObjectField(serialCommObject, env->GetFieldID(serialCommClass, "portString", "Ljava/lang/String;"), env->NewStringUTF(it->second.c_str()));
strcpy(systemPortName, "\\\\.\\");
strcat(systemPortName, serialCommPorts.first[i]);
env->SetObjectField(serialCommObject, comPortField, env->NewStringUTF(systemPortName));
env->SetObjectField(serialCommObject, portStringField, env->NewStringUTF(serialCommPorts.second[i]));
free(serialCommPorts.first[i]);
free(serialCommPorts.second[i]);
// Add new SerialComm object to array
env->SetObjectArrayElement(arrayObject, i, serialCommObject);
}
free(serialCommPorts.first);
free(serialCommPorts.second);
return arrayObject;
}
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrary(JNIEnv *env, jclass serialComm)
{
// Cache class and method ID as global references
serialCommClass = (jclass)env->NewGlobalRef(serialComm);
serialCommConstructor = env->GetMethodID(serialCommClass, "<init>", "()V");
// Cache
comPortField = env->GetFieldID(serialCommClass, "comPort", "Ljava/lang/String;");
portStringField = env->GetFieldID(serialCommClass, "portString", "Ljava/lang/String;");
isOpenedField = env->GetFieldID(serialCommClass, "isOpened", "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");
timeoutModeField = env->GetFieldID(serialCommClass, "timeoutMode", "I");
readTimeoutField = env->GetFieldID(serialCommClass, "readTimeout", "I");
writeTimeoutField = env->GetFieldID(serialCommClass, "writeTimeout", "I");
eventFlagsField = env->GetFieldID(serialCommClass, "eventFlags", "I");
}
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_uninitializeLibrary(JNIEnv *env, jclass serialComm)
{
// Delete the cache global reference
env->DeleteGlobalRef(serialCommClass);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(JNIEnv *env, jobject obj)
{
jclass serialCommClass = env->GetObjectClass(obj);
jstring portNameJString = (jstring)env->GetObjectField(obj, env->GetFieldID(serialCommClass, "comPort", "Ljava/lang/String;"));
HANDLE serialPortHandle = (HANDLE)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
jstring portNameJString = (jstring)env->GetObjectField(obj, comPortField);
const char *portName = env->GetStringUTFChars(portNameJString, NULL);
// Try to open existing serial port with read/write access
if ((serialPortHandle = CreateFile(portName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_OVERLAPPED, NULL)) != INVALID_HANDLE_VALUE)
{
// Set port handle in Java structure
env->SetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"), (jlong)serialPortHandle);
// Configure the port parameters and timeouts
if (Java_com_fazecast_jSerialComm_SerialPort_configPort(env, obj) && Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(env, obj) &&
Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(env, obj))
env->SetBooleanField(obj, env->GetFieldID(env->GetObjectClass(obj), "isOpened", "Z"), JNI_TRUE);
env->SetBooleanField(obj, isOpenedField, JNI_TRUE);
else
{
// Close the port if there was a problem setting the parameters
CloseHandle(serialPortHandle);
serialPortHandle = INVALID_HANDLE_VALUE;
env->SetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"), (jlong)INVALID_HANDLE_VALUE);
env->SetBooleanField(obj, env->GetFieldID(env->GetObjectClass(obj), "isOpened", "Z"), JNI_FALSE);
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
}
}
@ -220,18 +273,16 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNati
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(JNIEnv *env, jobject obj)
{
DCB dcbSerialParams = {0};
dcbSerialParams.DCBlength = sizeof(DCB);
jclass serialCommClass = env->GetObjectClass(obj);
HANDLE serialPortHandle = (HANDLE)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
if (serialPortHandle == INVALID_HANDLE_VALUE)
return JNI_FALSE;
DCB dcbSerialParams = {0};
dcbSerialParams.DCBlength = sizeof(DCB);
// Get port parameters from Java class
DWORD baudRate = (DWORD)env->GetIntField(obj, env->GetFieldID(serialCommClass, "baudRate", "I"));
BYTE byteSize = (BYTE)env->GetIntField(obj, env->GetFieldID(serialCommClass, "dataBits", "I"));
int stopBitsInt = env->GetIntField(obj, env->GetFieldID(serialCommClass, "stopBits", "I"));
int parityInt = env->GetIntField(obj, env->GetFieldID(serialCommClass, "parity", "I"));
DWORD baudRate = (DWORD)env->GetIntField(obj, baudRateField);
BYTE byteSize = (BYTE)env->GetIntField(obj, dataBitsField);
int stopBitsInt = env->GetIntField(obj, stopBitsField);
int parityInt = env->GetIntField(obj, parityField);
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;
@ -255,15 +306,13 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowControl(JNIEnv *env, jobject obj)
{
DCB dcbSerialParams = {0};
dcbSerialParams.DCBlength = sizeof(DCB);
jclass serialCommClass = env->GetObjectClass(obj);
HANDLE serialPortHandle = (HANDLE)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
if (serialPortHandle == INVALID_HANDLE_VALUE)
return JNI_FALSE;
DCB dcbSerialParams = {0};
dcbSerialParams.DCBlength = sizeof(DCB);
// Get flow control parameters from Java class
int flowControl = env->GetIntField(obj, env->GetFieldID(serialCommClass, "flowControl", "I"));
int flowControl = env->GetIntField(obj, flowControlField);
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) ||
@ -301,14 +350,12 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowCo
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeouts(JNIEnv *env, jobject obj)
{
// Get port timeouts from Java class
COMMTIMEOUTS timeouts = {0};
jclass serialCommClass = env->GetObjectClass(obj);
HANDLE serialHandle = (HANDLE)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
int timeoutMode = env->GetIntField(obj, env->GetFieldID(serialCommClass, "timeoutMode", "I"));
DWORD readTimeout = (DWORD)env->GetIntField(obj, env->GetFieldID(serialCommClass, "readTimeout", "I"));
DWORD writeTimeout = (DWORD)env->GetIntField(obj, env->GetFieldID(serialCommClass, "writeTimeout", "I"));
if (serialHandle == INVALID_HANDLE_VALUE)
if (serialPortHandle == INVALID_HANDLE_VALUE)
return JNI_FALSE;
COMMTIMEOUTS timeouts = {0};
int timeoutMode = env->GetIntField(obj, timeoutModeField);
DWORD readTimeout = (DWORD)env->GetIntField(obj, readTimeoutField);
DWORD writeTimeout = (DWORD)env->GetIntField(obj, writeTimeoutField);
// Set updated port timeouts
timeouts.WriteTotalTimeoutMultiplier = 0;
@ -350,6 +397,12 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeou
timeouts.ReadTotalTimeoutConstant = readTimeout;
timeouts.WriteTotalTimeoutConstant = writeTimeout;
break;
case com_fazecast_jSerialComm_SerialPort_TIMEOUT_SCANNER: // Scanner Mode
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
timeouts.ReadTotalTimeoutConstant = 0x0FFFFFFF;
timeouts.WriteTotalTimeoutConstant = 0;
break;
case com_fazecast_jSerialComm_SerialPort_TIMEOUT_NONBLOCKING: // Non-blocking
default:
timeouts.ReadIntervalTimeout = MAXDWORD;
@ -360,18 +413,16 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeou
}
// Apply changes
return SetCommTimeouts(serialHandle, &timeouts);
return SetCommTimeouts(serialPortHandle, &timeouts);
}
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventFlags(JNIEnv *env, jobject obj)
{
jclass serialCommClass = env->GetObjectClass(obj);
HANDLE serialPortHandle = (HANDLE)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
if (serialPortHandle == INVALID_HANDLE_VALUE)
return JNI_FALSE;
// Get event flags from Java class
int eventsToMonitor = env->GetIntField(obj, env->GetFieldID(serialCommClass, "eventFlags", "I"));
int eventsToMonitor = env->GetIntField(obj, eventFlagsField);
int eventFlags = 0;
if (((eventsToMonitor & com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_AVAILABLE) > 0) ||
((eventsToMonitor & com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_RECEIVED) > 0))
@ -399,8 +450,6 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventF
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNIEnv *env, jobject obj)
{
jclass serialCommClass = env->GetObjectClass(obj);
HANDLE serialPortHandle = (HANDLE)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
if (serialPortHandle == INVALID_HANDLE_VALUE)
return 0;
OVERLAPPED overlappedStruct = {0};
@ -420,8 +469,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNI
// Problem reading, close port
CloseHandle(serialPortHandle);
serialPortHandle = INVALID_HANDLE_VALUE;
env->SetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"), (jlong)INVALID_HANDLE_VALUE);
env->SetBooleanField(obj, env->GetFieldID(env->GetObjectClass(obj), "isOpened", "Z"), JNI_FALSE);
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
}
else if (GetOverlappedResult(serialPortHandle, &overlappedStruct, &numBytesRead, TRUE) == FALSE)
numBytesRead = 0;
@ -436,7 +484,6 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNI
JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNative(JNIEnv *env, jobject obj)
{
// Purge any outstanding port operations
HANDLE serialPortHandle = (HANDLE)env->GetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"));
if (serialPortHandle == INVALID_HANDLE_VALUE)
return JNI_TRUE;
PurgeComm(serialPortHandle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
@ -444,30 +491,26 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNat
// Close port
BOOL retVal = CloseHandle(serialPortHandle);
serialPortHandle = INVALID_HANDLE_VALUE;
env->SetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"), (jlong)INVALID_HANDLE_VALUE);
env->SetBooleanField(obj, env->GetFieldID(env->GetObjectClass(obj), "isOpened", "Z"), JNI_FALSE);
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
return (retVal == 0) ? JNI_FALSE : JNI_TRUE;
}
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(JNIEnv *env, jobject obj)
{
HANDLE serialPortHandle = (HANDLE)env->GetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"));
if (serialPortHandle == INVALID_HANDLE_VALUE)
return -1;
COMSTAT commInfo;
DWORD numBytesAvailable;
if (!ClearCommError(serialPortHandle, NULL, &commInfo))
return -1;
numBytesAvailable = commInfo.cbInQue;
DWORD numBytesAvailable = commInfo.cbInQue;
return (jint)numBytesAvailable;
}
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv *env, jobject obj, jbyteArray buffer, jlong bytesToRead)
{
HANDLE serialPortHandle = (HANDLE)env->GetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"));
if (serialPortHandle == INVALID_HANDLE_VALUE)
return -1;
OVERLAPPED overlappedStruct = {0};
@ -489,16 +532,14 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
// Problem reading, close port
CloseHandle(serialPortHandle);
serialPortHandle = INVALID_HANDLE_VALUE;
env->SetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"), (jlong)INVALID_HANDLE_VALUE);
env->SetBooleanField(obj, env->GetFieldID(env->GetObjectClass(obj), "isOpened", "Z"), JNI_FALSE);
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
}
else if ((result = GetOverlappedResult(serialPortHandle, &overlappedStruct, &numBytesRead, TRUE)) == FALSE)
{
// Problem reading, close port
CloseHandle(serialPortHandle);
serialPortHandle = INVALID_HANDLE_VALUE;
env->SetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"), (jlong)INVALID_HANDLE_VALUE);
env->SetBooleanField(obj, env->GetFieldID(env->GetObjectClass(obj), "isOpened", "Z"), JNI_FALSE);
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
}
}
@ -511,7 +552,6 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jbyteArray buffer, jlong bytesToWrite)
{
HANDLE serialPortHandle = (HANDLE)env->GetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"));
if (serialPortHandle == INVALID_HANDLE_VALUE)
return -1;
OVERLAPPED overlappedStruct = {0};
@ -533,16 +573,14 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn
// Problem writing, close port
CloseHandle(serialPortHandle);
serialPortHandle = INVALID_HANDLE_VALUE;
env->SetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"), (jlong)INVALID_HANDLE_VALUE);
env->SetBooleanField(obj, env->GetFieldID(env->GetObjectClass(obj), "isOpened", "Z"), JNI_FALSE);
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
}
else if ((result = GetOverlappedResult(serialPortHandle, &overlappedStruct, &numBytesWritten, TRUE)) == FALSE)
{
// Problem reading, close port
CloseHandle(serialPortHandle);
serialPortHandle = INVALID_HANDLE_VALUE;
env->SetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"), (jlong)INVALID_HANDLE_VALUE);
env->SetBooleanField(obj, env->GetFieldID(env->GetObjectClass(obj), "isOpened", "Z"), JNI_FALSE);
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
}
}

View File

@ -0,0 +1,49 @@
/*
* WindowsHelperFunctions.c
*
* Created on: May 05, 2015
* Last Updated on: May 05, 2015
* Author: Will Hedgecock
*
* Copyright (C) 2012-2015 Fazecast, Inc.
*
* This file is part of jSerialComm.
*
* jSerialComm is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* jSerialComm is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with jSerialComm. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef _WIN32
#include <stdlib.h>
#include <string.h>
#include "WindowsHelperFunctions.h"
void push_back(struct charPairVector* vector, const char* firstString, const char* secondString)
{
// Allocate memory for new string storage
vector->length++;
char** newMemory = (char**)realloc(vector->first, vector->length*sizeof(char*));
if (newMemory)
vector->first = newMemory;
newMemory = (char**)realloc(vector->second, vector->length*sizeof(char*));
if (newMemory)
vector->second = newMemory;
// Store new strings
vector->first[vector->length-1] = (char*)malloc(strlen(firstString)+1);
vector->second[vector->length-1] = (char*)malloc(strlen(secondString)+1);
strcpy(vector->first[vector->length-1], firstString);
strcpy(vector->second[vector->length-1], secondString);
}
#endif

View File

@ -0,0 +1,36 @@
/*
* WindowsHelperFunctions.h
*
* Created on: May 05, 2015
* Last Updated on: May 05, 2015
* Author: Will Hedgecock
*
* Copyright (C) 2012-2015 Fazecast, Inc.
*
* This file is part of jSerialComm.
*
* jSerialComm is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* jSerialComm is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with jSerialComm. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __WINDOWS_HELPER_FUNCTIONS_HEADER_H__
#define __WINDOWS_HELPER_FUNCTIONS_HEADER_H__
typedef struct charPairVector
{
char **first, **second;
size_t length;
} charPairVector;
void push_back(struct charPairVector* vector, const char* firstString, const char* secondString);
#endif // #ifndef __WINDOWS_HELPER_FUNCTIONS_HEADER_H__

View File

@ -2,7 +2,7 @@
* SerialPort.java
*
* Created on: Feb 25, 2012
* Last Updated on: Apr 04, 2015
* Last Updated on: May 04, 2015
* Author: Will Hedgecock
*
* Copyright (C) 2012-2015 Fazecast, Inc.
@ -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.2.2
* @version 1.3.0
* @see java.io.InputStream
* @see java.io.OutputStream
*/
@ -160,6 +160,7 @@ public final class SerialPort
// Load native library
System.load(tempFileName);
initializeLibrary();
}
/**
@ -225,6 +226,7 @@ public final class SerialPort
static final public int TIMEOUT_WRITE_SEMI_BLOCKING = 0x00000010;
static final public int TIMEOUT_READ_BLOCKING = 0x00000100;
static final public int TIMEOUT_WRITE_BLOCKING = 0x00001000;
static final public int TIMEOUT_SCANNER = 0x00010000;
// Serial Port Listening Events
static final public int LISTENING_EVENT_DATA_AVAILABLE = 0x00000001;
@ -239,7 +241,6 @@ public final class SerialPort
private volatile SerialPortDataListener userDataListener = null;
private volatile SerialPortEventListener serialEventListener = null;
private volatile String portString, comPort;
private volatile long portHandle = -1l;
private volatile boolean isOpened = false;
/**
@ -259,6 +260,8 @@ public final class SerialPort
String grantPermissions = "chmod 666 " + getSystemPortName() + "\nexit\n";
Process process = Runtime.getRuntime().exec("su -c " + grantPermissions);
process.waitFor();
if (process.exitValue() != 0)
return false;
} catch (Exception e) { return false; }
}
@ -291,6 +294,8 @@ public final class SerialPort
}
// Serial Port Setup Methods
private static native void initializeLibrary(); // Initializes the JNI code
private static native void uninitializeLibrary(); // Un-initializes the JNI code
private final native boolean openPortNative(); // Opens serial port
private final native boolean closePortNative(); // Closes serial port
private final native boolean configPort(); // Changes/sets serial port parameters as defined by this class
@ -467,7 +472,7 @@ public final class SerialPort
* Sets the serial port read and write timeout parameters.
* <p>
* The built-in timeout mode constants should be used ({@link #TIMEOUT_NONBLOCKING}, {@link #TIMEOUT_READ_SEMI_BLOCKING},
* {@link #TIMEOUT_WRITE_SEMI_BLOCKING}, {@link #TIMEOUT_READ_BLOCKING}, {@link #TIMEOUT_WRITE_BLOCKING}) to specify how
* {@link #TIMEOUT_WRITE_SEMI_BLOCKING}, {@link #TIMEOUT_READ_BLOCKING}, {@link #TIMEOUT_WRITE_BLOCKING}, {@link #TIMEOUT_SCANNER}) to specify how
* timeouts are to be handled.
* <p>
* Valid modes are:
@ -479,6 +484,7 @@ public final class SerialPort
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Read Full-blocking: {@link #TIMEOUT_READ_BLOCKING}<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Read Full-blocking/Write Semi-blocking: {@link #TIMEOUT_READ_BLOCKING} | {@link #TIMEOUT_WRITE_SEMI_BLOCKING}<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Read/Write Full-blocking: {@link #TIMEOUT_READ_BLOCKING} | {@link #TIMEOUT_WRITE_BLOCKING}<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Scanner: {@link #TIMEOUT_SCANNER}<br>
* <p>
* The {@link #TIMEOUT_NONBLOCKING} mode specifies that the corresponding {@link #readBytes(byte[],long)} or {@link #writeBytes(byte[],long)} call
* will return immediately with any available data.
@ -490,6 +496,9 @@ public final class SerialPort
* <i>newReadTimeout</i> or <i>newWriteTimeout</i> milliseconds have elapsed since the start of the call or the total number of requested bytes can be written or
* returned.
* <p>
* The {@link #TIMEOUT_SCANNER} mode is intended for use with the Java {@link java.util.Scanner} class for reading from the serial port. In this mode,
* manually specified timeouts are ignored to ensure compatibility with the Java specification.
* <p>
* A value of 0 for either <i>newReadTimeout</i> or <i>newWriteTimeout</i> indicates that a {@link #readBytes(byte[],long)} or
* {@link #writeBytes(byte[],long)} call should block forever until it can return successfully (based upon the current timeout mode specified).
*

View File

@ -2,7 +2,7 @@
* SerialPortTest.java
*
* Created on: Feb 27, 2015
* Last Updated on: Mar 12, 2015
* Last Updated on: May 05, 2015
* Author: Will Hedgecock
*
* Copyright (C) 2012-2015 Fazecast, Inc.
@ -32,7 +32,7 @@ import java.util.Scanner;
* This class provides a test case for the jSerialComm library.
*
* @author Will Hedgecock &lt;will.hedgecock@gmail.com&gt;
* @version 2.0
* @version 1.3.0
* @see java.io.InputStream
* @see java.io.OutputStream
*/
@ -60,7 +60,7 @@ public class SerialPortTest
SerialPort[] ports = SerialPort.getCommPorts();
System.out.println("\nAvailable Ports:\n");
for (int i = 0; i < ports.length; ++i)
System.out.println(" " + ports[i].getSystemPortName() + ": " + ports[i].getDescriptivePortName());
System.out.println(" [" + i + "] " + ports[i].getSystemPortName() + ": " + ports[i].getDescriptivePortName());
SerialPort ubxPort;
System.out.print("\nChoose your desired serial port or enter -1 to specify a port directly: ");
int serialPortChoice = 0;
@ -76,8 +76,12 @@ public class SerialPortTest
ubxPort = ports[serialPortChoice];
byte[] readBuffer = new byte[2048];
System.out.println("\nOpening " + ubxPort.getDescriptivePortName() + ": " + ubxPort.openPort());
boolean openedSuccessfully = ubxPort.openPort();
System.out.println("\nOpening " + ubxPort.getSystemPortName() + ": " + ubxPort.getDescriptivePortName() + ": " + openedSuccessfully);
if (!openedSuccessfully)
return;
System.out.println("Setting read timeout mode to non-blocking");
ubxPort.setBaudRate(115200);
ubxPort.setComPortTimeouts(SerialPort.TIMEOUT_NONBLOCKING, 1000, 0);
try
{
@ -169,7 +173,13 @@ public class SerialPortTest
System.out.print((char)in.read());
in.close();
} catch (Exception e) { e.printStackTrace(); }
System.out.println("\n\nEntering Java-based InputStream in Scanner mode and reading 200 lines\n");
ubxPort.setComPortTimeouts(SerialPort.TIMEOUT_SCANNER, 0, 0);
Scanner scanner = new Scanner(ubxPort.getInputStream());
for (int i = 1; i < 201; ++i)
if (scanner.hasNextLine())
System.out.println("Full Line #" + i + ": " + scanner.nextLine());
scanner.close();
System.out.println("\n\nClosing " + ubxPort.getDescriptivePortName() + ": " + ubxPort.closePort());
}
}