Removed all dependencies on libstdc++ (pure C now), fixed bug with dropping MSB on Linux when set to 8N1.
This commit is contained in:
parent
f49e8803a4
commit
3bcda2e64e
47
INSTALL
47
INSTALL
|
@ -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"]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* AndroidHelperFunctions.cpp
|
||||
* AndroidHelperFunctions.c
|
||||
*
|
||||
* Created on: Mar 10, 2015
|
||||
* Last Updated on: Mar 10, 2015
|
|
@ -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
|
|
@ -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
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* LinuxHelperFunctions.cpp
|
||||
* LinuxHelperFunctions.c
|
||||
*
|
||||
* Created on: Mar 10, 2015
|
||||
* Last Updated on: Mar 10, 2015
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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)
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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__
|
|
@ -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 <will.hedgecock@fazecast.com>
|
||||
* @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
|
|||
* Read Full-blocking: {@link #TIMEOUT_READ_BLOCKING}<br>
|
||||
* Read Full-blocking/Write Semi-blocking: {@link #TIMEOUT_READ_BLOCKING} | {@link #TIMEOUT_WRITE_SEMI_BLOCKING}<br>
|
||||
* Read/Write Full-blocking: {@link #TIMEOUT_READ_BLOCKING} | {@link #TIMEOUT_WRITE_BLOCKING}<br>
|
||||
* 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).
|
||||
*
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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 <will.hedgecock@gmail.com>
|
||||
* @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());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue