::iterator it = serialCommPorts.begin(); it != serialCommPorts.end(); ++it, ++i)
+ {
+ 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()));
+ env->SetObjectArrayElement(arrayObject, i, serialCommObject);
+ }
+ return arrayObject;
+}
+
+JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPort(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"));
+ 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_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_configTimeouts(env, obj))
+ env->SetBooleanField(obj, env->GetFieldID(env->GetObjectClass(obj), "isOpened", "Z"), 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->ReleaseStringUTFChars(portNameJString, portName);
+ return (serialPortHandle == INVALID_HANDLE_VALUE) ? JNI_FALSE : JNI_TRUE;
+}
+
+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);
+
+ // Get port parameters from Java class
+ HANDLE serialPortHandle = (HANDLE)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
+ 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"));
+ 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;
+
+ // Retrieve existing port configuration
+ if (!GetCommState(serialPortHandle, &dcbSerialParams))
+ return JNI_FALSE;
+
+ // Set updated port parameters
+ dcbSerialParams.BaudRate = baudRate;
+ dcbSerialParams.ByteSize = byteSize;
+ dcbSerialParams.StopBits = stopBits;
+ dcbSerialParams.Parity = parity;
+ dcbSerialParams.fParity = isParity;
+ dcbSerialParams.fBinary = TRUE;
+ dcbSerialParams.fAbortOnError = FALSE;
+
+ // Apply changes
+ return SetCommState(serialPortHandle, &dcbSerialParams);
+}
+
+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"));
+
+ // Get flow control parameters from Java class
+ int flowControl = env->GetIntField(obj, env->GetFieldID(serialCommClass, "flowControl", "I"));
+ 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) ||
+ ((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_DTR_ENABLED) > 0));
+ BYTE DTRValue = ((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_DTR_ENABLED) > 0) ? DTR_CONTROL_HANDSHAKE : DTR_CONTROL_ENABLE;
+ BYTE RTSValue = ((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_RTS_ENABLED) > 0) ? RTS_CONTROL_HANDSHAKE : RTS_CONTROL_ENABLE;
+ BOOL XonXoffInEnabled = ((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_XONXOFF_IN_ENABLED) > 0);
+ BOOL XonXoffOutEnabled = ((flowControl & com_fazecast_jSerialComm_SerialPort_FLOW_CONTROL_XONXOFF_OUT_ENABLED) > 0);
+
+ // Retrieve existing port configuration
+ if (!GetCommState(serialPortHandle, &dcbSerialParams))
+ return JNI_FALSE;
+
+ // Set updated port parameters
+ dcbSerialParams.fRtsControl = RTSValue;
+ dcbSerialParams.fOutxCtsFlow = CTSEnabled;
+ dcbSerialParams.fOutxDsrFlow = DSREnabled;
+ dcbSerialParams.fDtrControl = DTRValue;
+ dcbSerialParams.fDsrSensitivity = DSREnabled;
+ dcbSerialParams.fOutX = XonXoffOutEnabled;
+ dcbSerialParams.fInX = XonXoffInEnabled;
+ dcbSerialParams.fTXContinueOnXoff = TRUE;
+ dcbSerialParams.fErrorChar = FALSE;
+ dcbSerialParams.fNull = FALSE;
+ dcbSerialParams.fAbortOnError = FALSE;
+ dcbSerialParams.XonLim = 2048;
+ dcbSerialParams.XoffLim = 512;
+ dcbSerialParams.XonChar = (char)17;
+ dcbSerialParams.XoffChar = (char)19;
+
+ // Apply changes
+ return SetCommState(serialPortHandle, &dcbSerialParams);
+}
+
+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"));
+
+ // Set updated port timeouts
+ timeouts.WriteTotalTimeoutMultiplier = 0;
+ switch (timeoutMode)
+ {
+ case com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_SEMI_BLOCKING: // Read Semi-blocking
+ timeouts.ReadIntervalTimeout = MAXDWORD;
+ timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
+ timeouts.ReadTotalTimeoutConstant = readTimeout;
+ timeouts.WriteTotalTimeoutConstant = 10;
+ break;
+ case (com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_SEMI_BLOCKING | com_fazecast_jSerialComm_SerialPort_TIMEOUT_WRITE_SEMI_BLOCKING): // Read/Write Semi-blocking
+ timeouts.ReadIntervalTimeout = MAXDWORD;
+ timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
+ timeouts.ReadTotalTimeoutConstant = readTimeout;
+ timeouts.WriteTotalTimeoutConstant = writeTimeout;
+ break;
+ case (com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_SEMI_BLOCKING | com_fazecast_jSerialComm_SerialPort_TIMEOUT_WRITE_BLOCKING): // Read Semi-blocking/Write Blocking
+ timeouts.ReadIntervalTimeout = MAXDWORD;
+ timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
+ timeouts.ReadTotalTimeoutConstant = readTimeout;
+ timeouts.WriteTotalTimeoutConstant = writeTimeout;
+ break;
+ case com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_BLOCKING: // Read Blocking
+ timeouts.ReadIntervalTimeout = 0;
+ timeouts.ReadTotalTimeoutMultiplier = 0;
+ timeouts.ReadTotalTimeoutConstant = readTimeout;
+ timeouts.WriteTotalTimeoutConstant = 10;
+ break;
+ case (com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_BLOCKING | com_fazecast_jSerialComm_SerialPort_TIMEOUT_WRITE_SEMI_BLOCKING): // Read Blocking/Write Semi-blocking
+ timeouts.ReadIntervalTimeout = 0;
+ timeouts.ReadTotalTimeoutMultiplier = 0;
+ timeouts.ReadTotalTimeoutConstant = readTimeout;
+ timeouts.WriteTotalTimeoutConstant = writeTimeout;
+ break;
+ case (com_fazecast_jSerialComm_SerialPort_TIMEOUT_READ_BLOCKING | com_fazecast_jSerialComm_SerialPort_TIMEOUT_WRITE_BLOCKING): // Read/Write Blocking
+ timeouts.ReadIntervalTimeout = 0;
+ timeouts.ReadTotalTimeoutMultiplier = 0;
+ timeouts.ReadTotalTimeoutConstant = readTimeout;
+ timeouts.WriteTotalTimeoutConstant = writeTimeout;
+ break;
+ case com_fazecast_jSerialComm_SerialPort_TIMEOUT_NONBLOCKING: // Non-blocking
+ default:
+ timeouts.ReadIntervalTimeout = MAXDWORD;
+ timeouts.ReadTotalTimeoutMultiplier = 0;
+ timeouts.ReadTotalTimeoutConstant = 0;
+ timeouts.WriteTotalTimeoutConstant = 10;
+ break;
+ }
+
+ // Apply changes
+ return SetCommTimeouts(serialHandle, &timeouts);
+}
+
+JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePort(JNIEnv *env, jobject obj)
+{
+ // Purge any outstanding port operations
+ HANDLE serialPortHandle = (HANDLE)env->GetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"));
+ PurgeComm(serialPortHandle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
+
+ // 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);
+
+ 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"));
+ COMSTAT commInfo;
+ DWORD numBytesAvailable;
+
+ if (!ClearCommError(serialPortHandle, NULL, &commInfo))
+ return -1;
+ 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"));
+ OVERLAPPED overlappedStruct = {0};
+ overlappedStruct.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ char *readBuffer = (char*)malloc(bytesToRead);
+ DWORD numBytesRead = 0;
+ BOOL result;
+
+ // Read from serial port
+ if ((result = ReadFile(serialPortHandle, readBuffer, bytesToRead, NULL, &overlappedStruct)) != FALSE) // Immediately successful
+ GetOverlappedResult(serialPortHandle, &overlappedStruct, &numBytesRead, TRUE);
+ else if (GetLastError() != ERROR_IO_PENDING) // Problem occurred
+ {
+ // 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);
+ }
+ else // Pending read operation
+ {
+ switch (WaitForSingleObject(overlappedStruct.hEvent, INFINITE))
+ {
+ case WAIT_OBJECT_0:
+ 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);
+ }
+ break;
+ default:
+ // 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);
+ break;
+ }
+ }
+
+ // Return number of bytes read if successful
+ CloseHandle(overlappedStruct.hEvent);
+ env->SetByteArrayRegion(buffer, 0, numBytesRead, (jbyte*)readBuffer);
+ free(readBuffer);
+ return (result == TRUE) ? numBytesRead : -1;
+}
+
+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"));
+ OVERLAPPED overlappedStruct = {0};
+ overlappedStruct.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ jbyte *writeBuffer = env->GetByteArrayElements(buffer, 0);
+ DWORD numBytesWritten = 0;
+ BOOL result;
+
+ // Write to port
+ if ((result = WriteFile(serialPortHandle, writeBuffer, bytesToWrite, NULL, &overlappedStruct)) == FALSE)
+ {
+ if (GetLastError() != ERROR_IO_PENDING)
+ {
+ // 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);
+ }
+ else
+ {
+ switch (WaitForSingleObject(overlappedStruct.hEvent, INFINITE))
+ {
+ case WAIT_OBJECT_0:
+ 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);
+ }
+ break;
+ default:
+ // 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);
+ break;
+ }
+ }
+ }
+ else
+ GetOverlappedResult(serialPortHandle, &overlappedStruct, &numBytesWritten, TRUE);
+
+ // Return number of bytes written if successful
+ CloseHandle(overlappedStruct.hEvent);
+ env->ReleaseByteArrayElements(buffer, writeBuffer, JNI_ABORT);
+ return (result == TRUE) ? numBytesWritten : -1;
+}
+
+#endif
diff --git a/src/main/java/com/fazecast/jSerialComm/SerialPort.java b/src/main/java/com/fazecast/jSerialComm/SerialPort.java
new file mode 100644
index 0000000..b41b857
--- /dev/null
+++ b/src/main/java/com/fazecast/jSerialComm/SerialPort.java
@@ -0,0 +1,717 @@
+/*
+ * SerialPort.java
+ *
+ * Created on: Feb 25, 2012
+ * Last Updated on: Feb 27, 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 .
+ */
+
+package com.fazecast.jSerialComm;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * This class provides native access to serial ports and devices without requiring external libraries or tools.
+ *
+ * @author Will Hedgecock <will.hedgecock@gmail.com>
+ * @version 1.0
+ * @see java.io.InputStream
+ * @see java.io.OutputStream
+ */
+public class SerialPort
+{
+ // Static initializer loads correct native library for this machine
+ static
+ {
+ String OS = System.getProperty("os.name").toLowerCase();
+ String libraryPath = "", fileName = "";
+ String tempFileDirectory = System.getProperty("java.io.tmpdir");
+ if ((tempFileDirectory.charAt(tempFileDirectory.length()-1) != '\\') &&
+ (tempFileDirectory.charAt(tempFileDirectory.length()-1) != '/'))
+ tempFileDirectory += "/";
+
+ // Determine Operating System and architecture
+ if (OS.indexOf("win") >= 0)
+ {
+ if (System.getProperty("os.arch").indexOf("64") >= 0)
+ libraryPath = "Windows/x86_64";
+ else
+ libraryPath = "Windows/x86";
+ fileName = "jSerialComm.dll";
+ }
+ else if (OS.indexOf("mac") >= 0)
+ {
+ if (System.getProperty("os.arch").indexOf("64") >= 0)
+ libraryPath = "OSX/x86_64";
+ else
+ libraryPath = "OSX/x86";
+ fileName = "libjSerialComm.jnilib";
+ }
+ else if ((OS.indexOf("nix") >= 0) || (OS.indexOf("nux") >= 0))
+ {
+ if (System.getProperty("os.arch").indexOf("64") >= 0)
+ libraryPath = "Linux/x86_64";
+ else
+ libraryPath = "Linux/x86";
+ fileName = "libjSerialComm.so";
+ }
+ else
+ {
+ System.err.println("This operating system is not supported by the jSerialComm library.");
+ System.exit(-1);
+ }
+
+ // Get path of native library and copy file to working directory
+ File tempNativeLibrary = new File(tempFileDirectory + fileName);
+ tempNativeLibrary.deleteOnExit();
+ try
+ {
+ InputStream fileContents = SerialPort.class.getResourceAsStream("/" + libraryPath + "/" + fileName);
+ FileOutputStream destinationFileContents = new FileOutputStream(tempNativeLibrary);
+ byte transferBuffer[] = new byte[4096];
+ int numBytesRead;
+
+ while ((numBytesRead = fileContents.read(transferBuffer)) > 0)
+ destinationFileContents.write(transferBuffer, 0, numBytesRead);
+
+ fileContents.close();
+ destinationFileContents.close();
+ }
+ catch (Exception e) { e.printStackTrace(); }
+
+ // Load native library
+ System.load(tempFileDirectory + fileName);
+ }
+
+ /**
+ * Returns a list of all available serial ports on this machine.
+ *
+ * The serial ports can be accessed by iterating through each of the SerialPort objects in this array.
+ *
+ * Note that the {@link #openPort()} method must be called before any attempts to read from or write to the port. Likewise, {@link #closePort()} should be called when you are finished accessing the port.
+ *
+ * All serial port parameters or timeouts can be changed at any time after the port has been opened.
+ *
+ * @return An array of SerialPort objects.
+ */
+ static public native SerialPort[] getCommPorts();
+
+ // Parity Values
+ static final public int NO_PARITY = 0;
+ static final public int ODD_PARITY = 1;
+ static final public int EVEN_PARITY = 2;
+ static final public int MARK_PARITY = 3;
+ static final public int SPACE_PARITY = 4;
+
+ // Number of Stop Bits
+ static final public int ONE_STOP_BIT = 1;
+ static final public int ONE_POINT_FIVE_STOP_BITS = 2;
+ static final public int TWO_STOP_BITS = 3;
+
+ // Flow Control constants
+ static final public int FLOW_CONTROL_DISABLED = 0x00000000;
+ static final public int FLOW_CONTROL_RTS_ENABLED = 0x00000001;
+ static final public int FLOW_CONTROL_CTS_ENABLED = 0x00000010;
+ static final public int FLOW_CONTROL_DSR_ENABLED = 0x00000100;
+ static final public int FLOW_CONTROL_DTR_ENABLED = 0x00001000;
+ static final public int FLOW_CONTROL_XONXOFF_IN_ENABLED = 0x00010000;
+ static final public int FLOW_CONTROL_XONXOFF_OUT_ENABLED = 0x00100000;
+
+ // Timeout Modes
+ static final public int TIMEOUT_NONBLOCKING = 0x00000000;
+ static final public int TIMEOUT_READ_SEMI_BLOCKING = 0x00000001;
+ 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;
+
+ // Serial Port Parameters
+ private volatile int baudRate = 9600, dataBits = 8, stopBits = ONE_STOP_BIT, parity = NO_PARITY;
+ private volatile int timeoutMode = TIMEOUT_NONBLOCKING, readTimeout = 0, writeTimeout = 0, flowControl = 0;
+ private volatile SerialPortInputStream inputStream = null;
+ private volatile SerialPortOutputStream outputStream = null;
+ private volatile String portString, comPort;
+ private volatile long portHandle = -1l;
+ private volatile boolean isOpened = false;
+
+ /**
+ * Opens this serial port for reading and writing.
+ *
+ * All serial port parameters or timeouts can be changed at any time after the port has been opened.
+ *
+ * @return Whether the port was successfully opened.
+ */
+ public final native boolean openPort();
+
+ /**
+ * Closes this serial port.
+ *
+ * @return Whether the port was successfully closed.
+ */
+ public final native boolean closePort();
+
+ // Serial Port Setup Methods
+ private final native boolean configPort(); // Changes/sets serial port parameters as defined by this class
+ private final native boolean configFlowControl(); // Changes/sets flow control parameters as defined by this class
+ private final native boolean configTimeouts(); // Changes/sets serial port timeouts as defined by this class
+
+ /**
+ * Returns the number of bytes available without blocking if {@link #readBytes} were to be called immediately
+ * after this method returns.
+ *
+ * @return The number of bytes currently available to be read.
+ */
+ public final native int bytesAvailable();
+
+ /**
+ * Reads up to bytesToRead raw data bytes from the serial port and stores them in the buffer.
+ *
+ * The length of the byte buffer must be greater than or equal to the value passed in for bytesToRead
+ *
+ * If no timeouts were specified or the read timeout was set to 0, this call will block until bytesToRead bytes of data have been successfully read from the serial port.
+ * Otherwise, this method will return after bytesToRead bytes of data have been read or the number of milliseconds specified by the read timeout have elapsed,
+ * whichever comes first, regardless of the availability of more data.
+ *
+ * @param buffer The buffer into which the raw data is read.
+ * @param bytesToRead The number of bytes to read from the serial port.
+ * @return The number of bytes successfully read, or -1 if there was an error reading from the port.
+ */
+ public final native int readBytes(byte[] buffer, long bytesToRead);
+
+ /**
+ * Writes up to bytesToWrite raw data bytes from the buffer parameter to the serial port.
+ *
+ * The length of the byte buffer must be greater than or equal to the value passed in for bytesToWrite
+ *
+ * If no timeouts were specified or the write timeout was set to 0, this call will block until bytesToWrite bytes of data have been successfully written the serial port.
+ * Otherwise, this method will return after bytesToWrite bytes of data have been written or the number of milliseconds specified by the write timeout have elapsed,
+ * whichever comes first, regardless of the availability of more data.
+ *
+ * @param buffer The buffer containing the raw data to write to the serial port.
+ * @param bytesToWrite The number of bytes to write to the serial port.
+ * @return The number of bytes successfully written, or -1 if there was an error writing to the port.
+ */
+ public final native int writeBytes(byte[] buffer, long bytesToWrite);
+
+ // Default Constructor
+ public SerialPort() {}
+
+ /**
+ * Returns an {@link java.io.InputStream} object associated with this serial port.
+ *
+ * Allows for easier read access of the underlying data stream and abstracts away many low-level read details.
+ *
+ * Make sure to call the {@link java.io.InputStream#close()} method when you are done using this stream.
+ *
+ * @return An {@link java.io.InputStream} object associated with this serial port.
+ * @see java.io.InputStream
+ */
+ public final InputStream getInputStream()
+ {
+ if ((inputStream == null) && isOpened)
+ inputStream = new SerialPortInputStream();
+ return inputStream;
+ }
+
+ /**
+ * Returns an {@link java.io.OutputStream} object associated with this serial port.
+ *
+ * Allows for easier write access to the underlying data stream and abstracts away many low-level writing details.
+ *
+ * Make sure to call the {@link java.io.OutputStream#close()} method when you are done using this stream.
+ *
+ * @return An {@link java.io.OutputStream} object associated with this serial port.
+ * @see java.io.OutputStream
+ */
+ public final OutputStream getOutputStream()
+ {
+ if ((outputStream == null) && isOpened)
+ outputStream = new SerialPortOutputStream();
+ return outputStream;
+ }
+
+ /**
+ * Sets all serial port parameters at one time.
+ *
+ * Allows the user to set all port parameters with a single function call.
+ *
+ * The baud rate can be any arbitrary value specified by the user. The default value is 9600 baud. The data bits parameter
+ * specifies how many data bits to use per word. The default is 8, but any values from 5 to 8 are acceptable.
+ *
+ * The default number of stop bits is 1, but 2 bits can also be used or even 1.5 on Windows machines. Please use the built-in
+ * constants for this parameter ({@link #ONE_STOP_BIT}, {@link #ONE_POINT_FIVE_STOP_BITS}, {@link #TWO_STOP_BITS}).
+ *
+ * The parity parameter specifies how error detection is carried out. Again, the built-in constants should be used.
+ * Acceptable values are {@link #NO_PARITY}, {@link #EVEN_PARITY}, {@link #ODD_PARITY}, {@link #MARK_PARITY}, and {@link #SPACE_PARITY}.
+ *
+ * @param newBaudRate The desired baud rate for this serial port.
+ * @param newDataBits The number of data bits to use per word.
+ * @param newStopBits The number of stop bits to use.
+ * @param newParity The type of parity error-checking desired.
+ * @see #ONE_STOP_BIT
+ * @see #ONE_POINT_FIVE_STOP_BITS
+ * @see #TWO_STOP_BITS
+ * @see #NO_PARITY
+ * @see #EVEN_PARITY
+ * @see #ODD_PARITY
+ * @see #MARK_PARITY
+ * @see #SPACE_PARITY
+ */
+ public final void setComPortParameters(int newBaudRate, int newDataBits, int newStopBits, int newParity)
+ {
+ baudRate = newBaudRate;
+ dataBits = newDataBits;
+ stopBits = newStopBits;
+ parity = newParity;
+ configPort();
+ }
+
+ /**
+ * Sets the serial port read and write timeout parameters.
+ *
+ * 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
+ * timeouts are to be handled.
+ *
+ * Valid modes are:
+ *
+ * Non-blocking: {@link #TIMEOUT_NONBLOCKING}
+ * Read Semi-blocking: {@link #TIMEOUT_READ_SEMI_BLOCKING}
+ * Read/Write Semi-blocking: {@link #TIMEOUT_READ_SEMI_BLOCKING} | {@link #TIMEOUT_WRITE_SEMI_BLOCKING}
+ * Read Semi-Blocking/Write Full-blocking: {@link #TIMEOUT_READ_SEMI_BLOCKING} | {@link #TIMEOUT_WRITE_BLOCKING}
+ * Read Full-blocking: {@link #TIMEOUT_READ_BLOCKING}
+ * Read Full-blocking/Write Semi-blocking: {@link #TIMEOUT_READ_BLOCKING} | {@link #TIMEOUT_WRITE_SEMI_BLOCKING}
+ * Read/Write Full-blocking: {@link #TIMEOUT_READ_BLOCKING} | {@link #TIMEOUT_WRITE_BLOCKING}
+ *
+ * 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.
+ *
+ * The {@link #TIMEOUT_READ_SEMI_BLOCKING} or {@link #TIMEOUT_WRITE_SEMI_BLOCKING} modes specify that the corresponding calls will block until either
+ * newReadTimeout or newWriteTimeout milliseconds of inactivity have elapsed or at least 1 byte of data can be written or read.
+ *
+ * The {@link #TIMEOUT_READ_BLOCKING} or {@link #TIMEOUT_WRITE_BLOCKING} modes specify that the corresponding call will block until either
+ * newReadTimeout or newWriteTimeout milliseconds of inactivity have elapsed or the total number of requested bytes can be written or
+ * returned.
+ *
+ * A value of 0 for either newReadTimeout or newWriteTimeout 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).
+ *
+ * @param newTimeoutMode The new timeout mode as specified above.
+ * @param newReadTimeout The number of milliseconds of inactivity to tolerate before returning from a {@link #readBytes(byte[],long)} call.
+ * @param newWriteTimeout The number of milliseconds of inactivity to tolerate before returning from a {@link #writeBytes(byte[],long)} call.
+ */
+ public final void setComPortTimeouts(int newTimeoutMode, int newReadTimeout, int newWriteTimeout)
+ {
+ timeoutMode = newTimeoutMode;
+ readTimeout = newReadTimeout;
+ writeTimeout = newWriteTimeout;
+ configTimeouts();
+ }
+
+ /**
+ * Sets the desired baud rate for this serial port.
+ *
+ * The default baud rate is 9600 baud.
+ *
+ * @param newBaudRate The desired baud rate for this serial port.
+ */
+ public final void setBaudRate(int newBaudRate) { baudRate = newBaudRate; configPort(); }
+
+ /**
+ * Sets the desired number of data bits per word.
+ *
+ * The default number of data bits per word is 8.
+ *
+ * @param newDataBits The desired number of data bits per word.
+ */
+ public final void setNumDataBits(int newDataBits) { dataBits = newDataBits; configPort(); }
+
+ /**
+ * Sets the desired number of stop bits per word.
+ *
+ * The default number of stop bits per word is 2. Built-in stop-bit constants should be used
+ * in this method ({@link #ONE_STOP_BIT}, {@link #ONE_POINT_FIVE_STOP_BITS}, {@link #TWO_STOP_BITS}).
+ *
+ * Note that {@link #ONE_POINT_FIVE_STOP_BITS} stop bits may not be available on non-Windows systems.
+ *
+ * @param newStopBits The desired number of stop bits per word.
+ * @see #ONE_STOP_BIT
+ * @see #ONE_POINT_FIVE_STOP_BITS
+ * @see #TWO_STOP_BITS
+ */
+ public final void setNumStopBits(int newStopBits) { stopBits = newStopBits; configPort(); }
+
+ /**
+ * Specifies what kind of flow control to enable for this serial port.
+ *
+ * By default, no flow control is enabled. Built-in flow control constants should be used
+ * in this method ({@link #FLOW_CONTROL_RTS_ENABLED}, {@link #FLOW_CONTROL_CTS_ENABLED}, {@link #FLOW_CONTROL_DTR_ENABLED},
+ * {@link #FLOW_CONTROL_DSR_ENABLED}, {@link #FLOW_CONTROL_XONXOFF_IN_ENABLED}, {@link #FLOW_CONTROL_XONXOFF_OUT_ENABLED}), and can be OR'ed together.
+ *
+ * Valid flow control configurations are:
+ *
+ * None: {@link #FLOW_CONTROL_DISABLED}
+ * CTS: {@link #FLOW_CONTROL_CTS_ENABLED}
+ * RTS/CTS: {@link #FLOW_CONTROL_RTS_ENABLED} | {@link #FLOW_CONTROL_CTS_ENABLED}
+ * DSR: {@link #FLOW_CONTROL_DSR_ENABLED}
+ * DTR/DSR: {@link #FLOW_CONTROL_DTR_ENABLED} | {@link #FLOW_CONTROL_DSR_ENABLED}
+ * XOn/XOff: {@link #FLOW_CONTROL_XONXOFF_IN_ENABLED} | {@link #FLOW_CONTROL_XONXOFF_OUT_ENABLED}
+ *
+ * Note that only one valid flow control configuration can be used at any time. For example, attempting to use both XOn/XOff
+ * and RTS/CTS will most likely result in an unusable serial port.
+ *
+ * @param newFlowControlSettings The desired type of flow control to enable for this serial port.
+ * @see #FLOW_CONTROL_DISABLED
+ * @see #FLOW_CONTROL_RTS_ENABLED
+ * @see #FLOW_CONTROL_CTS_ENABLED
+ * @see #FLOW_CONTROL_DTR_ENABLED
+ * @see #FLOW_CONTROL_DSR_ENABLED
+ * @see #FLOW_CONTROL_XONXOFF_IN_ENABLED
+ * @see #FLOW_CONTROL_XONXOFF_OUT_ENABLED
+ */
+ public final void setFlowControl(int newFlowControlSettings) { flowControl = newFlowControlSettings; configFlowControl(); }
+
+ /**
+ * Sets the desired parity error-detection scheme to be used.
+ *
+ * The parity parameter specifies how error detection is carried out. The built-in parity constants should be used.
+ * Acceptable values are {@link #NO_PARITY}, {@link #EVEN_PARITY}, {@link #ODD_PARITY}, {@link #MARK_PARITY}, and {@link #SPACE_PARITY}.
+ *
+ * @param newParity The desired parity scheme to be used.
+ * @see #NO_PARITY
+ * @see #EVEN_PARITY
+ * @see #ODD_PARITY
+ * @see #MARK_PARITY
+ * @see #SPACE_PARITY
+ */
+ public final void setParity(int newParity) { parity = newParity; configPort(); }
+
+ /**
+ * Gets a descriptive string representing this serial port or the device connected to it.
+ *
+ * This description is generated by the operating system and may or may not be a good representation of the actual port or
+ * device it describes.
+ *
+ * @return A descriptive string representing this serial port.
+ */
+ public final String getDescriptivePortName() { return portString.trim(); }
+
+ /**
+ * Gets the operating system-defined device name corresponding to this serial port.
+ *
+ * @return The system-defined device name of this serial port.
+ */
+ public final String getSystemPortName() { return comPort.substring(comPort.lastIndexOf('\\')+1); }
+
+ /**
+ * Gets the current baud rate of the serial port.
+ *
+ * @return The current baud rate of the serial port.
+ */
+ public final int getBaudRate() { return baudRate; }
+
+ /**
+ * Gets the current number of data bits per word.
+ *
+ * @return The current number of data bits per word.
+ */
+ public final int getNumDataBits() { return dataBits; }
+
+ /**
+ * Gets the current number of stop bits per word.
+ *
+ * The return value should not be interpreted as an integer, but rather compared with the built-in stop bit constants
+ * ({@link #ONE_STOP_BIT}, {@link #ONE_POINT_FIVE_STOP_BITS}, {@link #TWO_STOP_BITS}).
+ *
+ * @return The current number of stop bits per word.
+ * @see #ONE_STOP_BIT
+ * @see #ONE_POINT_FIVE_STOP_BITS
+ * @see #TWO_STOP_BITS
+ */
+ public final int getNumStopBits() { return stopBits; }
+
+ /**
+ * Gets the current parity error-checking scheme.
+ *
+ * The return value should not be interpreted as an integer, but rather compared with the built-in parity constants
+ * ({@link #NO_PARITY}, {@link #EVEN_PARITY}, {@link #ODD_PARITY}, {@link #MARK_PARITY}, and {@link #SPACE_PARITY}).
+ *
+ * @return The current parity scheme.
+ * @see #NO_PARITY
+ * @see #EVEN_PARITY
+ * @see #ODD_PARITY
+ * @see #MARK_PARITY
+ * @see #SPACE_PARITY
+ */
+ public final int getParity() { return parity; }
+
+ /**
+ * Gets the number of milliseconds of inactivity to tolerate before returning from a {@link #readBytes(byte[],long)} call.
+ *
+ * A value of 0 indicates that a {@link #readBytes(byte[],long)} call will block forever until it has successfully read
+ * the indicated number of bytes from the serial port.
+ *
+ * Any value other than 0 indicates the number of milliseconds of inactivity that will be tolerated before the {@link #readBytes(byte[],long)}
+ * call will return.
+ *
+ * @return The number of milliseconds of inactivity to tolerate before returning from a {@link #readBytes(byte[],long)} call.
+ */
+ public final int getReadTimeout() { return readTimeout; }
+
+ /**
+ * Gets the number of milliseconds of inactivity to tolerate before returning from a {@link #writeBytes(byte[],long)} call.
+ *
+ * A value of 0 indicates that a {@link #writeBytes(byte[],long)} call will block forever until it has successfully written
+ * the indicated number of bytes to the serial port.
+ *
+ * Any value other than 0 indicates the number of milliseconds of inactivity that will be tolerated before the {@link #writeBytes(byte[],long)}
+ * call will return.
+ *
+ * @return The number of milliseconds of inactivity to tolerate before returning from a {@link #writeBytes(byte[],long)} call.
+ */
+ public final int getWriteTimeout() { return writeTimeout; }
+
+ /**
+ * Returns the flow control settings enabled on this serial port.
+ *
+ * The integer result should be masked with the built-in flow control constants to test if the desired setting is enabled.
+ * Valid flow control configurations are:
+ *
+ * None: {@link #FLOW_CONTROL_DISABLED}
+ * CTS: {@link #FLOW_CONTROL_CTS_ENABLED}
+ * RTS/CTS: {@link #FLOW_CONTROL_RTS_ENABLED} | {@link #FLOW_CONTROL_CTS_ENABLED}
+ * DSR: {@link #FLOW_CONTROL_DSR_ENABLED}
+ * DTR/DSR: {@link #FLOW_CONTROL_DTR_ENABLED} | {@link #FLOW_CONTROL_DSR_ENABLED}
+ * XOn/XOff: {@link #FLOW_CONTROL_XONXOFF_IN_ENABLED} | {@link #FLOW_CONTROL_XONXOFF_OUT_ENABLED}
+ *
+ * @return The flow control settings enabled on this serial port.
+ * @see #FLOW_CONTROL_DISABLED
+ * @see #FLOW_CONTROL_RTS_ENABLED
+ * @see #FLOW_CONTROL_CTS_ENABLED
+ * @see #FLOW_CONTROL_DTR_ENABLED
+ * @see #FLOW_CONTROL_DSR_ENABLED
+ * @see #FLOW_CONTROL_XONXOFF_IN_ENABLED
+ * @see #FLOW_CONTROL_XONXOFF_OUT_ENABLED
+ */
+ public final int getFlowControlSettings() { return flowControl; }
+
+ // InputStream interface class
+ private final class SerialPortInputStream extends InputStream
+ {
+ public SerialPortInputStream() {}
+
+ @Override
+ public final int available() throws IOException
+ {
+ if (!isOpened)
+ throw new IOException("This port appears to have been shutdown or disconnected.");
+
+ return bytesAvailable();
+ }
+
+ @Override
+ public final int read() throws IOException
+ {
+ byte[] buffer = new byte[1];
+ int bytesRead;
+
+ while (isOpened)
+ {
+ bytesRead = readBytes(buffer, 1l);
+ if (bytesRead > 0)
+ return ((int)buffer[0] & 0x000000FF);
+ }
+ throw new IOException("This port appears to have been shutdown or disconnected.");
+ }
+
+ @Override
+ public final int read(byte[] b) throws IOException
+ {
+ if (!isOpened)
+ throw new IOException("This port appears to have been shutdown or disconnected.");
+
+ return read(b, 0, b.length);
+
+ }
+
+ @Override
+ public final int read(byte[] b, int off, int len) throws IOException
+ {
+ if (!isOpened)
+ throw new IOException("This port appears to have been shutdown or disconnected.");
+ if (len == 0)
+ return 0;
+
+ byte[] buffer = new byte[len];
+ int numRead = readBytes(buffer, len);
+ if (numRead > 0)
+ System.arraycopy(buffer, 0, b, off, numRead);
+
+ return numRead;
+ }
+
+ @Override
+ public final long skip(long n) throws IOException
+ {
+ if (!isOpened)
+ throw new IOException("This port appears to have been shutdown or disconnected.");
+
+ byte[] buffer = new byte[(int)n];
+ return readBytes(buffer, n);
+ }
+ }
+
+ // OutputStream interface class
+ private final class SerialPortOutputStream extends OutputStream
+ {
+ public SerialPortOutputStream() {}
+
+ @Override
+ public final void write(int b) throws IOException
+ {
+ if (!isOpened)
+ throw new IOException("This port appears to have been shutdown or disconnected.");
+
+ byte[] buffer = new byte[1];
+ buffer[0] = (byte)(b & 0x000000FF);
+ if (writeBytes(buffer, 1l) < 0)
+ throw new IOException("This port appears to have been shutdown or disconnected.");
+ }
+
+ @Override
+ public final void write(byte[] b) throws IOException
+ {
+ if (!isOpened)
+ throw new IOException("This port appears to have been shutdown or disconnected.");
+
+ write(b, 0, b.length);
+ }
+
+ @Override
+ public final void write(byte[] b, int off, int len) throws IOException
+ {
+ if (!isOpened)
+ throw new IOException("This port appears to have been shutdown or disconnected.");
+
+ byte[] buffer = new byte[len];
+ System.arraycopy(b, off, buffer, 0, len);
+ if (writeBytes(buffer, len) < 0)
+ throw new IOException("This port appears to have been shutdown or disconnected.");
+ }
+ }
+
+ static public void main(String[] args)
+ {
+ SerialPort[] ports = SerialPort.getCommPorts();
+ System.out.println("\nPorts:\n");
+ for (int i = 0; i < ports.length; ++i)
+ System.out.println(" " + ports[i].getSystemPortName() + ": " + ports[i].getDescriptivePortName());
+ SerialPort ubxPort = ports[1];
+
+ byte[] readBuffer = new byte[2048];
+ System.out.println("\nOpening " + ubxPort.getDescriptivePortName() + ": " + ubxPort.openPort());
+ System.out.println("Setting read timeout mode to non-blocking");
+ ubxPort.setComPortTimeouts(TIMEOUT_NONBLOCKING, 1000, 0);
+ InputStream in = ubxPort.getInputStream();
+ try
+ {
+ for (int i = 0; i < 3; ++i)
+ {
+ System.out.println("\nReading #" + i);
+ System.out.println("Available: " + ubxPort.bytesAvailable());
+ int numRead = ubxPort.readBytes(readBuffer, readBuffer.length);
+ System.out.println("Read " + numRead + " bytes.");
+ }
+ in.close();
+ } catch (Exception e) { e.printStackTrace(); }
+ System.out.println("\nSetting read timeout mode to semi-blocking with a timeout of 200ms");
+ ubxPort.setComPortTimeouts(TIMEOUT_READ_SEMI_BLOCKING, 200, 0);
+ in = ubxPort.getInputStream();
+ try
+ {
+ for (int i = 0; i < 3; ++i)
+ {
+ System.out.println("\nReading #" + i);
+ System.out.println("Available: " + ubxPort.bytesAvailable());
+ int numRead = ubxPort.readBytes(readBuffer, readBuffer.length);
+ System.out.println("Read " + numRead + " bytes.");
+ }
+ in.close();
+ } catch (Exception e) { e.printStackTrace(); }
+ System.out.println("\nSetting read timeout mode to semi-blocking with no timeout");
+ ubxPort.setComPortTimeouts(TIMEOUT_READ_SEMI_BLOCKING, 0, 0);
+ in = ubxPort.getInputStream();
+ try
+ {
+ for (int i = 0; i < 3; ++i)
+ {
+ System.out.println("\nReading #" + i);
+ System.out.println("Available: " + ubxPort.bytesAvailable());
+ int numRead = ubxPort.readBytes(readBuffer, readBuffer.length);
+ System.out.println("Read " + numRead + " bytes.");
+ }
+ in.close();
+ } catch (Exception e) { e.printStackTrace(); }
+ System.out.println("\nSetting read timeout mode to blocking with a timeout of 100ms");
+ ubxPort.setComPortTimeouts(TIMEOUT_READ_BLOCKING, 100, 0);
+ in = ubxPort.getInputStream();
+ try
+ {
+ for (int i = 0; i < 3; ++i)
+ {
+ System.out.println("\nReading #" + i);
+ System.out.println("Available: " + ubxPort.bytesAvailable());
+ int numRead = ubxPort.readBytes(readBuffer, readBuffer.length);
+ System.out.println("Read " + numRead + " bytes.");
+ }
+ in.close();
+ } catch (Exception e) { e.printStackTrace(); }
+ System.out.println("\nSetting read timeout mode to blocking with no timeout");
+ ubxPort.setComPortTimeouts(TIMEOUT_READ_BLOCKING, 0, 0);
+ in = ubxPort.getInputStream();
+ try
+ {
+ for (int i = 0; i < 3; ++i)
+ {
+ System.out.println("\nReading #" + i);
+ System.out.println("Available: " + ubxPort.bytesAvailable());
+ int numRead = ubxPort.readBytes(readBuffer, readBuffer.length);
+ System.out.println("Read " + numRead + " bytes.");
+ }
+ in.close();
+ } catch (Exception e) { e.printStackTrace(); }
+ System.out.println("\n\nClosing " + ubxPort.getDescriptivePortName() + ": " + ubxPort.closePort());
+ try { Thread.sleep(1000); } catch (InterruptedException e1) { e1.printStackTrace(); }
+ System.out.println("Reopening " + ubxPort.getDescriptivePortName() + ": " + ubxPort.openPort() + "\n");
+ ubxPort.setComPortTimeouts(TIMEOUT_READ_BLOCKING, 1000, 0);
+ in = ubxPort.getInputStream();
+ try
+ {
+ for (int j = 0; j < 1000; ++j)
+ System.out.print((char)in.read());
+ in.close();
+ } catch (Exception e) { e.printStackTrace(); }
+
+ System.out.println("\nClosing " + ubxPort.getDescriptivePortName() + ": " + ubxPort.closePort());
+ }
+}
diff --git a/src/main/resources/Windows/x86/jSerialComm.dll b/src/main/resources/Windows/x86/jSerialComm.dll
new file mode 100644
index 0000000..714e966
Binary files /dev/null and b/src/main/resources/Windows/x86/jSerialComm.dll differ
diff --git a/src/main/resources/Windows/x86/jSerialComm.exp b/src/main/resources/Windows/x86/jSerialComm.exp
new file mode 100644
index 0000000..810edc9
Binary files /dev/null and b/src/main/resources/Windows/x86/jSerialComm.exp differ
diff --git a/src/main/resources/Windows/x86/jSerialComm.lib b/src/main/resources/Windows/x86/jSerialComm.lib
new file mode 100644
index 0000000..7a6b43f
Binary files /dev/null and b/src/main/resources/Windows/x86/jSerialComm.lib differ
diff --git a/src/main/resources/Windows/x86_64/jSerialComm.dll b/src/main/resources/Windows/x86_64/jSerialComm.dll
new file mode 100644
index 0000000..de2fcb6
Binary files /dev/null and b/src/main/resources/Windows/x86_64/jSerialComm.dll differ
diff --git a/src/main/resources/Windows/x86_64/jSerialComm.exp b/src/main/resources/Windows/x86_64/jSerialComm.exp
new file mode 100644
index 0000000..d6f8046
Binary files /dev/null and b/src/main/resources/Windows/x86_64/jSerialComm.exp differ
diff --git a/src/main/resources/Windows/x86_64/jSerialComm.lib b/src/main/resources/Windows/x86_64/jSerialComm.lib
new file mode 100644
index 0000000..01e6d27
Binary files /dev/null and b/src/main/resources/Windows/x86_64/jSerialComm.lib differ