diff --git a/java_console/io/src/com/rusefi/binaryprotocol/BinaryProtocol.java b/java_console/io/src/com/rusefi/binaryprotocol/BinaryProtocol.java
index 2ce9df93d3..17c6e60f3b 100644
--- a/java_console/io/src/com/rusefi/binaryprotocol/BinaryProtocol.java
+++ b/java_console/io/src/com/rusefi/binaryprotocol/BinaryProtocol.java
@@ -63,6 +63,7 @@ public class BinaryProtocol {
private final IncomingDataBuffer incomingData;
private boolean isBurnPending;
+ // todo: this ioLock needs better documentation!
private final Object ioLock = new Object();
private final Object imageLock = new Object();
private ConfigurationImage controller;
@@ -199,6 +200,7 @@ public class BinaryProtocol {
dropPending();
stream.write((SWITCH_TO_BINARY_COMMAND + "\n").getBytes());
+ // todo: document why is ioLock needed here?
synchronized (ioLock) {
boolean isTimeout = incomingData.waitForBytes(2, start, "switch to binary");
if (isTimeout) {
diff --git a/java_console/jssc/jssc.iml b/java_console/jssc/jssc.iml
new file mode 100644
index 0000000000..c90834f2d6
--- /dev/null
+++ b/java_console/jssc/jssc.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/java_console/jssc/jssc.jar b/java_console/jssc/jssc.jar
new file mode 100644
index 0000000000..fbeb225b4b
Binary files /dev/null and b/java_console/jssc/jssc.jar differ
diff --git a/java_console/jssc/readme.txt b/java_console/jssc/readme.txt
new file mode 100644
index 0000000000..892eed6987
--- /dev/null
+++ b/java_console/jssc/readme.txt
@@ -0,0 +1 @@
+this is custom build of JSSC with additional logging - it's only useful during debugging.
\ No newline at end of file
diff --git a/java_console/jssc/src/jssc/SerialNativeInterface.java b/java_console/jssc/src/jssc/SerialNativeInterface.java
new file mode 100644
index 0000000000..c5264f5e8a
--- /dev/null
+++ b/java_console/jssc/src/jssc/SerialNativeInterface.java
@@ -0,0 +1,486 @@
+/* jSSC (Java Simple Serial Connector) - serial port communication library.
+ * © Alexey Sokolov (scream3r), 2010-2014.
+ *
+ * This file is part of jSSC.
+ *
+ * jSSC 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.
+ *
+ * jSSC 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 jSSC. If not, see .
+ *
+ * If you use jSSC in public project you can inform me about this by e-mail,
+ * of course if you want it.
+ *
+ * e-mail: scream3r.org@gmail.com
+ * web-site: http://scream3r.org | http://code.google.com/p/java-simple-serial-connector/
+ */
+package jssc;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+/**
+ *
+ * @author scream3r
+ */
+public class SerialNativeInterface {
+
+ private static final String libVersion = "2.8"; //jSSC-2.8.0 Release from 24.01.2014
+ private static final String libMinorSuffix = "0"; //since 0.9.0
+
+ public static final int OS_LINUX = 0;
+ public static final int OS_WINDOWS = 1;
+ public static final int OS_SOLARIS = 2;//since 0.9.0
+ public static final int OS_MAC_OS_X = 3;//since 0.9.0
+
+ private static int osType = -1;
+
+ /**
+ * @since 2.3.0
+ */
+ public static final long ERR_PORT_BUSY = -1;
+ /**
+ * @since 2.3.0
+ */
+ public static final long ERR_PORT_NOT_FOUND = -2;
+ /**
+ * @since 2.3.0
+ */
+ public static final long ERR_PERMISSION_DENIED = -3;
+ /**
+ * @since 2.3.0
+ */
+ public static final long ERR_INCORRECT_SERIAL_PORT = -4;
+
+ /**
+ * @since 2.6.0
+ */
+ public static final String PROPERTY_JSSC_NO_TIOCEXCL = "JSSC_NO_TIOCEXCL";
+ /**
+ * @since 2.6.0
+ */
+ public static final String PROPERTY_JSSC_IGNPAR = "JSSC_IGNPAR";
+ /**
+ * @since 2.6.0
+ */
+ public static final String PROPERTY_JSSC_PARMRK = "JSSC_PARMRK";
+
+ static {
+ String libFolderPath;
+ String libName;
+
+ String osName = System.getProperty("os.name");
+ String architecture = System.getProperty("os.arch");
+ String userHome = System.getProperty("user.home");
+ String fileSeparator = System.getProperty("file.separator");
+ String tmpFolder = System.getProperty("java.io.tmpdir");
+
+ //since 2.3.0 ->
+ String libRootFolder = new File(userHome).canWrite() ? userHome : tmpFolder;
+ //<- since 2.3.0
+
+ String javaLibPath = System.getProperty("java.library.path");//since 2.1.0
+
+ if(osName.equals("Linux")){
+ osName = "linux";
+ osType = OS_LINUX;
+ }
+ else if(osName.startsWith("Win")){
+ osName = "windows";
+ osType = OS_WINDOWS;
+ }//since 0.9.0 ->
+ else if(osName.equals("SunOS")){
+ osName = "solaris";
+ osType = OS_SOLARIS;
+ }
+ else if(osName.equals("Mac OS X") || osName.equals("Darwin")){//os.name "Darwin" since 2.6.0
+ osName = "mac_os_x";
+ osType = OS_MAC_OS_X;
+ }//<- since 0.9.0
+
+ if(architecture.equals("i386") || architecture.equals("i686")){
+ architecture = "x86";
+ }
+ else if(architecture.equals("amd64") || architecture.equals("universal")){//os.arch "universal" since 2.6.0
+ architecture = "x86_64";
+ }
+ else if(architecture.equals("arm")) {//since 2.1.0
+ String floatStr = "sf";
+ if(javaLibPath.toLowerCase().contains("gnueabihf") || javaLibPath.toLowerCase().contains("armhf")){
+ floatStr = "hf";
+ }
+ else {
+ try {
+ Process readelfProcess = Runtime.getRuntime().exec("readelf -A /proc/self/exe");
+ BufferedReader reader = new BufferedReader(new InputStreamReader(readelfProcess.getInputStream()));
+ String buffer = "";
+ while((buffer = reader.readLine()) != null && !buffer.isEmpty()){
+ if(buffer.toLowerCase().contains("Tag_ABI_VFP_args".toLowerCase())){
+ floatStr = "hf";
+ break;
+ }
+ }
+ reader.close();
+ }
+ catch (Exception ex) {
+ //Do nothing
+ }
+ }
+ architecture = "arm" + floatStr;
+ }
+
+ libFolderPath = libRootFolder + fileSeparator + ".jssc" + fileSeparator + osName;
+ libName = "jSSC-" + libVersion + "_" + architecture;
+ libName = System.mapLibraryName(libName);
+
+ if(libName.endsWith(".dylib")){//Since 2.1.0 MacOSX 10.8 fix
+ libName = libName.replace(".dylib", ".jnilib");
+ }
+
+ boolean loadLib = false;
+
+ if(isLibFolderExist(libFolderPath)){
+ if(isLibFileExist(libFolderPath + fileSeparator + libName)){
+ loadLib = true;
+ }
+ else {
+ if(extractLib((libFolderPath + fileSeparator + libName), osName, libName)){
+ loadLib = true;
+ }
+ }
+ }
+ else {
+ if(new File(libFolderPath).mkdirs()){
+ if(extractLib((libFolderPath + fileSeparator + libName), osName, libName)){
+ loadLib = true;
+ }
+ }
+ }
+
+ if (loadLib) {
+ System.load(libFolderPath + fileSeparator + libName);
+ String versionBase = getLibraryBaseVersion();
+ String versionNative = getNativeLibraryVersion();
+ if (!versionBase.equals(versionNative)) {
+ System.err.println("Warning! jSSC Java and Native versions mismatch (Java: " + versionBase + ", Native: " + versionNative + ")");
+ }
+ }
+ }
+
+ /**
+ * Is library folder exists
+ *
+ * @param libFolderPath
+ *
+ * @since 0.8
+ */
+ private static boolean isLibFolderExist(String libFolderPath) {
+ boolean returnValue = false;
+ File folder = new File(libFolderPath);
+ if(folder.exists() && folder.isDirectory()){
+ returnValue = true;
+ }
+ return returnValue;
+ }
+
+ /**
+ * Is library file exists
+ *
+ * @param libFilePath
+ *
+ * @since 0.8
+ */
+ private static boolean isLibFileExist(String libFilePath) {
+ boolean returnValue = false;
+ File folder = new File(libFilePath);
+ if(folder.exists() && folder.isFile()){
+ returnValue = true;
+ }
+ return returnValue;
+ }
+
+ /**
+ * Extract lib to lib folder
+ *
+ * @param libFilePath
+ * @param osName
+ * @param libName
+ *
+ * @since 0.8
+ */
+ private static boolean extractLib(String libFilePath, String osName, String libName) {
+ boolean returnValue = false;
+ File libFile = new File(libFilePath);
+ InputStream input = null;
+ FileOutputStream output = null;
+ input = SerialNativeInterface.class.getResourceAsStream("/libs/" + osName + "/" + libName);
+ if(input != null){
+ int read;
+ byte[] buffer = new byte[4096];
+ try {
+ output = new FileOutputStream(libFilePath);
+ while((read = input.read(buffer)) != -1){
+ output.write(buffer, 0, read);
+ }
+ output.close();
+ input.close();
+ returnValue = true;
+ }
+ catch (Exception ex) {
+ try {
+ output.close();
+ if(libFile.exists()){
+ libFile.delete();
+ }
+ }
+ catch (Exception ex_out) {
+ //Do nothing
+ }
+ try {
+ input.close();
+ }
+ catch (Exception ex_in) {
+ //Do nothing
+ }
+ }
+ }
+ return returnValue;
+ }
+
+ /**
+ * Get OS type (OS_LINUX || OS_WINDOWS || OS_SOLARIS)
+ *
+ * @since 0.8
+ */
+ public static int getOsType() {
+ return osType;
+ }
+
+ /**
+ * Get jSSC version. The version of library is Base Version + Minor Suffix
+ *
+ * @since 0.8
+ */
+ public static String getLibraryVersion() {
+ return libVersion + "." + libMinorSuffix;
+ }
+
+ /**
+ * Get jSSC Base Version
+ *
+ * @since 0.9.0
+ */
+ public static String getLibraryBaseVersion() {
+ return libVersion;
+ }
+
+ /**
+ * Get jSSC minor suffix. For example in version 0.8.1 - 1 is a minor suffix
+ *
+ * @since 0.9.0
+ */
+ public static String getLibraryMinorSuffix() {
+ return libMinorSuffix;
+ }
+
+ /**
+ * Get jSSC native library version
+ *
+ * @return native lib version (for jSSC-2.8.0 should be 2.8 for example)
+ *
+ * @since 2.8.0
+ */
+ public static native String getNativeLibraryVersion();
+
+ /**
+ * Open port
+ *
+ * @param portName name of port for opening
+ * @param useTIOCEXCL enable/disable using of TIOCEXCL. Take effect only on *nix based systems
+ *
+ * @return handle of opened port or -1 if opening of the port was unsuccessful
+ */
+ public native long openPort(String portName, boolean useTIOCEXCL);
+
+ /**
+ * Setting the parameters of opened port
+ *
+ * @param handle handle of opened port
+ * @param baudRate data transfer rate
+ * @param dataBits number of data bits
+ * @param stopBits number of stop bits
+ * @param parity parity
+ * @param setRTS initial state of RTS line (ON/OFF)
+ * @param setDTR initial state of DTR line (ON/OFF)
+ * @param flags additional Native settings. Take effect only on *nix based systems
+ *
+ * @return If the operation is successfully completed, the method returns true, otherwise false
+ */
+ public native boolean setParams(long handle, int baudRate, int dataBits, int stopBits, int parity, boolean setRTS, boolean setDTR, int flags);
+
+ /**
+ * Purge of input and output buffer
+ *
+ * @param handle handle of opened port
+ * @param flags flags specifying required actions for purgePort method
+ *
+ * @return If the operation is successfully completed, the method returns true, otherwise false
+ */
+ public native boolean purgePort(long handle, int flags);
+
+ /**
+ * Close port
+ *
+ * @param handle handle of opened port
+ *
+ * @return If the operation is successfully completed, the method returns true, otherwise false
+ */
+ public native boolean closePort(long handle);
+
+ /**
+ * Set events mask
+ *
+ * @param handle handle of opened port
+ * @param mask events mask
+ *
+ * @return If the operation is successfully completed, the method returns true, otherwise false
+ */
+ public native boolean setEventsMask(long handle, int mask);
+
+ /**
+ * Get events mask
+ *
+ * @param handle handle of opened port
+ *
+ * @return Method returns event mask as a variable of int type
+ */
+ public native int getEventsMask(long handle);
+
+ /**
+ * Wait events
+ *
+ * @param handle handle of opened port
+ *
+ * @return Method returns two-dimensional array containing event types and their values
+ * (events[i][0] - event type, events[i][1] - event value).
+ */
+ public native int[][] waitEvents(long handle);
+
+ /**
+ * Change RTS line state
+ *
+ * @param handle handle of opened port
+ * @param value true - ON, false - OFF
+ *
+ * @return If the operation is successfully completed, the method returns true, otherwise false
+ */
+ public native boolean setRTS(long handle, boolean value);
+
+ /**
+ * Change DTR line state
+ *
+ * @param handle handle of opened port
+ * @param value true - ON, false - OFF
+ *
+ * @return If the operation is successfully completed, the method returns true, otherwise false
+ */
+ public native boolean setDTR(long handle, boolean value);
+
+ /**
+ * Read data from port
+ *
+ * @param handle handle of opened port
+ * @param byteCount count of bytes required to read
+ *
+ * @return Method returns the array of read bytes
+ */
+ public native byte[] readBytes(long handle, int byteCount);
+
+ /**
+ * Write data to port
+ *
+ * @param handle handle of opened port
+ * @param buffer array of bytes to write
+ *
+ * @return If the operation is successfully completed, the method returns true, otherwise false
+ */
+ public native boolean writeBytes(long handle, byte[] buffer);
+
+ /**
+ * Get bytes count in buffers of port
+ *
+ * @param handle handle of opened port
+ *
+ * @return Method returns the array that contains info about bytes count in buffers:
+ *
element 0 - input buffer
+ *
element 1 - output buffer
+ *
+ * @since 0.8
+ */
+ public native int[] getBuffersBytesCount(long handle);
+
+ /**
+ * Set flow control mode
+ *
+ * @param handle handle of opened port
+ * @param mask mask of flow control mode
+ *
+ * @return If the operation is successfully completed, the method returns true, otherwise false
+ *
+ * @since 0.8
+ */
+ public native boolean setFlowControlMode(long handle, int mask);
+
+ /**
+ * Get flow control mode
+ *
+ * @param handle handle of opened port
+ *
+ * @return Mask of setted flow control mode
+ *
+ * @since 0.8
+ */
+ public native int getFlowControlMode(long handle);
+
+ /**
+ * Get serial port names like an array of String
+ *
+ * @return unsorted array of String with port names
+ */
+ public native String[] getSerialPortNames();
+
+ /**
+ * Getting lines states
+ *
+ * @param handle handle of opened port
+ *
+ * @return Method returns the array containing information about lines in following order:
+ *
element 0 - CTS line state
+ *
element 1 - DSR line state
+ *
element 2 - RING line state
+ *
element 3 - RLSD line state
+ */
+ public native int[] getLinesStatus(long handle);
+
+ /**
+ * Send Break singnal for setted duration
+ *
+ * @param handle handle of opened port
+ * @param duration duration of Break signal
+ * @return If the operation is successfully completed, the method returns true, otherwise false
+ *
+ * @since 0.8
+ */
+ public native boolean sendBreak(long handle, int duration);
+}
diff --git a/java_console/jssc/src/jssc/SerialPort.java b/java_console/jssc/src/jssc/SerialPort.java
new file mode 100644
index 0000000000..7bf43887c6
--- /dev/null
+++ b/java_console/jssc/src/jssc/SerialPort.java
@@ -0,0 +1,1343 @@
+/* jSSC (Java Simple Serial Connector) - serial port communication library.
+ * © Alexey Sokolov (scream3r), 2010-2014.
+ *
+ * This file is part of jSSC.
+ *
+ * jSSC 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.
+ *
+ * jSSC 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 jSSC. If not, see .
+ *
+ * If you use jSSC in public project you can inform me about this by e-mail,
+ * of course if you want it.
+ *
+ * e-mail: scream3r.org@gmail.com
+ * web-site: http://scream3r.org | http://code.google.com/p/java-simple-serial-connector/
+ */
+package jssc;
+
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Method;
+import java.nio.charset.Charset;
+import java.util.Date;
+
+/**
+ *
+ * @author scream3r
+ */
+public class SerialPort {
+
+ private SerialNativeInterface serialInterface;
+ private SerialPortEventListener eventListener;
+ private long portHandle;
+ private String portName;
+ private boolean portOpened = false;
+ private boolean maskAssigned = false;
+ private boolean eventListenerAdded = false;
+
+ //since 2.2.0 ->
+ private Method methodErrorOccurred = null;
+ //<- since 2.2.0
+
+ public static final int BAUDRATE_110 = 110;
+ public static final int BAUDRATE_300 = 300;
+ public static final int BAUDRATE_600 = 600;
+ public static final int BAUDRATE_1200 = 1200;
+ public static final int BAUDRATE_4800 = 4800;
+ public static final int BAUDRATE_9600 = 9600;
+ public static final int BAUDRATE_14400 = 14400;
+ public static final int BAUDRATE_19200 = 19200;
+ public static final int BAUDRATE_38400 = 38400;
+ public static final int BAUDRATE_57600 = 57600;
+ public static final int BAUDRATE_115200 = 115200;
+ public static final int BAUDRATE_128000 = 128000;
+ public static final int BAUDRATE_256000 = 256000;
+
+
+ public static final int DATABITS_5 = 5;
+ public static final int DATABITS_6 = 6;
+ public static final int DATABITS_7 = 7;
+ public static final int DATABITS_8 = 8;
+
+
+ public static final int STOPBITS_1 = 1;
+ public static final int STOPBITS_2 = 2;
+ public static final int STOPBITS_1_5 = 3;
+
+
+ public static final int PARITY_NONE = 0;
+ public static final int PARITY_ODD = 1;
+ public static final int PARITY_EVEN = 2;
+ public static final int PARITY_MARK = 3;
+ public static final int PARITY_SPACE = 4;
+
+
+ public static final int PURGE_RXABORT = 0x0002;
+ public static final int PURGE_RXCLEAR = 0x0008;
+ public static final int PURGE_TXABORT = 0x0001;
+ public static final int PURGE_TXCLEAR = 0x0004;
+
+
+ public static final int MASK_RXCHAR = 1;
+ public static final int MASK_RXFLAG = 2;
+ public static final int MASK_TXEMPTY = 4;
+ public static final int MASK_CTS = 8;
+ public static final int MASK_DSR = 16;
+ public static final int MASK_RLSD = 32;
+ public static final int MASK_BREAK = 64;
+ public static final int MASK_ERR = 128;
+ public static final int MASK_RING = 256;
+
+
+ //since 0.8 ->
+ public static final int FLOWCONTROL_NONE = 0;
+ public static final int FLOWCONTROL_RTSCTS_IN = 1;
+ public static final int FLOWCONTROL_RTSCTS_OUT = 2;
+ public static final int FLOWCONTROL_XONXOFF_IN = 4;
+ public static final int FLOWCONTROL_XONXOFF_OUT = 8;
+ //<- since 0.8
+
+ //since 0.8 ->
+ public static final int ERROR_FRAME = 0x0008;
+ public static final int ERROR_OVERRUN = 0x0002;
+ public static final int ERROR_PARITY = 0x0004;
+ //<- since 0.8
+
+ //since 2.6.0 ->
+ private static final int PARAMS_FLAG_IGNPAR = 1;
+ private static final int PARAMS_FLAG_PARMRK = 2;
+ //<- since 2.6.0
+
+ public SerialPort(String portName) {
+ log("init " + portName);
+ this.portName = portName;
+ serialInterface = new SerialNativeInterface();
+ }
+
+ /**
+ * Getting port name under operation
+ *
+ * @return Method returns port name under operation as a String
+ */
+ public String getPortName(){
+ return portName;
+ }
+
+ /**
+ * Getting port state
+ *
+ * @return Method returns true if port is open, otherwise false
+ */
+ public boolean isOpened() {
+ return portOpened;
+ }
+
+ /**
+ * Port opening
+ *
+ * Note: If port busy TYPE_PORT_BUSY exception will be thrown.
+ * If port not found TYPE_PORT_NOT_FOUND exception will be thrown.
+ *
+ * @return If the operation is successfully completed, the method returns true
+ *
+ * @throws SerialPortException
+ */
+ public boolean openPort() throws SerialPortException {
+ Throwable e = new Throwable();
+ e.printStackTrace();
+ log("openPort");
+ if(portOpened){
+ throw new SerialPortException(portName, "openPort()", SerialPortException.TYPE_PORT_ALREADY_OPENED);
+ }
+ if(portName != null){
+ boolean useTIOCEXCL = (System.getProperty(SerialNativeInterface.PROPERTY_JSSC_NO_TIOCEXCL) == null &&
+ System.getProperty(SerialNativeInterface.PROPERTY_JSSC_NO_TIOCEXCL.toLowerCase()) == null);
+ portHandle = serialInterface.openPort(portName, useTIOCEXCL);//since 2.3.0 -> (if JSSC_NO_TIOCEXCL defined, exclusive lock for serial port will be disabled)
+ }
+ else {
+ throw new SerialPortException(portName, "openPort()", SerialPortException.TYPE_NULL_NOT_PERMITTED);//since 2.1.0 -> NULL port name fix
+ }
+ if(portHandle == SerialNativeInterface.ERR_PORT_BUSY){
+ throw new SerialPortException(portName, "openPort()", SerialPortException.TYPE_PORT_BUSY);
+ }
+ else if(portHandle == SerialNativeInterface.ERR_PORT_NOT_FOUND){
+ throw new SerialPortException(portName, "openPort()", SerialPortException.TYPE_PORT_NOT_FOUND);
+ }
+ else if(portHandle == SerialNativeInterface.ERR_PERMISSION_DENIED){
+ throw new SerialPortException(portName, "openPort()", SerialPortException.TYPE_PERMISSION_DENIED);
+ }
+ else if(portHandle == SerialNativeInterface.ERR_INCORRECT_SERIAL_PORT){
+ throw new SerialPortException(portName, "openPort()", SerialPortException.TYPE_INCORRECT_SERIAL_PORT);
+ }
+ portOpened = true;
+ return true;
+ }
+
+ /**
+ * Setting the parameters of port. RTS and DTR lines are enabled by default
+ *
+ * @param baudRate data transfer rate
+ * @param dataBits number of data bits
+ * @param stopBits number of stop bits
+ * @param parity parity
+ *
+ * @return If the operation is successfully completed, the method returns true, otherwise false
+ *
+ * @throws SerialPortException
+ */
+ public boolean setParams(int baudRate, int dataBits, int stopBits, int parity) throws SerialPortException {
+ return setParams(baudRate, dataBits, stopBits, parity, true, true);
+ }
+
+ /**
+ * Setting the parameters of port
+ *
+ * @param baudRate data transfer rate
+ * @param dataBits number of data bits
+ * @param stopBits number of stop bits
+ * @param parity parity
+ * @param setRTS initial state of RTS line(ON/OFF)
+ * @param setDTR initial state of DTR line(ON/OFF)
+ *
+ * @return If the operation is successfully completed, the method returns true, otherwise false
+ *
+ * @throws SerialPortException
+ *
+ * @since 0.8
+ */
+ public boolean setParams(int baudRate, int dataBits, int stopBits, int parity, boolean setRTS, boolean setDTR) throws SerialPortException {
+ log("setParams " + baudRate + " " + dataBits + " " + stopBits + " " + parity + " " + setRTS + " " + setDTR);
+ checkPortOpened("setParams()");
+ if(stopBits == 1){
+ stopBits = 0;
+ }
+ else if(stopBits == 3){
+ stopBits = 1;
+ }
+ int flags = 0;
+ if(System.getProperty(SerialNativeInterface.PROPERTY_JSSC_IGNPAR) != null || System.getProperty(SerialNativeInterface.PROPERTY_JSSC_IGNPAR.toLowerCase()) != null){
+ flags |= PARAMS_FLAG_IGNPAR;
+ }
+ if(System.getProperty(SerialNativeInterface.PROPERTY_JSSC_PARMRK) != null || System.getProperty(SerialNativeInterface.PROPERTY_JSSC_PARMRK.toLowerCase()) != null){
+ flags |= PARAMS_FLAG_PARMRK;
+ }
+ return serialInterface.setParams(portHandle, baudRate, dataBits, stopBits, parity, setRTS, setDTR, flags);
+ }
+
+ /**
+ * Purge of input and output buffer. Required flags shall be sent to the input. Variables with prefix
+ * "PURGE_", for example "PURGE_RXCLEAR". Sent parameter "flags" is additive value,
+ * so addition of flags is allowed. For example, if input or output buffer shall be purged,
+ * parameter "PURGE_RXCLEAR | PURGE_TXCLEAR".
+ *
Note: some devices or drivers may not support this function
+ *
+ * @return If the operation is successfully completed, the method returns true, otherwise false.
+ *
+ * @throws SerialPortException
+ */
+ public boolean purgePort(int flags) throws SerialPortException {
+ log("purgePort " + flags);
+ checkPortOpened("purgePort()");
+ return serialInterface.purgePort(portHandle, flags);
+ }
+
+ /**
+ * Events mask for Linux OS
+ *
+ * @since 0.8
+ */
+ private int linuxMask;
+
+ /**
+ * Set events mask. Required flags shall be sent to the input. Variables with prefix
+ * "MASK_", shall be used as flags, for example "MASK_RXCHAR".
+ * Sent parameter "mask" is additive value, so addition of flags is allowed.
+ * For example if messages about data receipt and CTS and DSR status changing
+ * shall be received, it is required to set the mask - "MASK_RXCHAR | MASK_CTS | MASK_DSR"
+ *
+ * @return If the operation is successfully completed, the method returns true, otherwise false
+ *
+ * @throws SerialPortException
+ */
+ public boolean setEventsMask(int mask) throws SerialPortException {
+ Throwable e = new Throwable();
+ e.printStackTrace();
+ log("setEventsMask " + mask);
+ checkPortOpened("setEventsMask()");
+ if(SerialNativeInterface.getOsType() == SerialNativeInterface.OS_LINUX ||
+ SerialNativeInterface.getOsType() == SerialNativeInterface.OS_SOLARIS ||
+ SerialNativeInterface.getOsType() == SerialNativeInterface.OS_MAC_OS_X){//since 0.9.0
+ linuxMask = mask;
+ if(mask > 0){
+ maskAssigned = true;
+ }
+ else {
+ maskAssigned = false;
+ }
+ return true;
+ }
+ boolean returnValue = serialInterface.setEventsMask(portHandle, mask);
+ if(!returnValue){
+ throw new SerialPortException(portName, "setEventsMask()", SerialPortException.TYPE_CANT_SET_MASK);
+ }
+ if(mask > 0){
+ maskAssigned = true;
+ }
+ else {
+ maskAssigned = false;
+ }
+ return returnValue;
+ }
+
+ /**
+ * Getting events mask for the port
+ *
+ * @return Method returns events mask as int type variable. This variable is an additive value
+ *
+ * @throws SerialPortException
+ */
+ public int getEventsMask() throws SerialPortException {
+ checkPortOpened("getEventsMask()");
+ if(SerialNativeInterface.getOsType() == SerialNativeInterface.OS_LINUX ||
+ SerialNativeInterface.getOsType() == SerialNativeInterface.OS_SOLARIS ||
+ SerialNativeInterface.getOsType() == SerialNativeInterface.OS_MAC_OS_X){//since 0.9.0
+ return linuxMask;
+ }
+ return serialInterface.getEventsMask(portHandle);
+ }
+
+ /**
+ * Getting events mask for the port is Linux OS (for internal use)
+ *
+ * @since 0.8
+ */
+ private int getLinuxMask() {
+ return linuxMask;
+ }
+
+ /**
+ * Change RTS line state. Set "true" for switching ON and "false" for switching OFF RTS line
+ *
+ * @return If the operation is successfully completed, the method returns true, otherwise false
+ *
+ * @throws SerialPortException
+ */
+ public boolean setRTS(boolean enabled) throws SerialPortException {
+ log("setRTS " + enabled);
+ checkPortOpened("setRTS()");
+ return serialInterface.setRTS(portHandle, enabled);
+ }
+
+ /**
+ * Change DTR line state. Set "true" for switching ON and "false" for switching OFF DTR line
+ *
+ * @return If the operation is successfully completed, the method returns true, otherwise false
+ *
+ * @throws SerialPortException
+ */
+ public boolean setDTR(boolean enabled) throws SerialPortException {
+ log("setDTR " + enabled);
+ checkPortOpened("setDTR()");
+ return serialInterface.setDTR(portHandle, enabled);
+ }
+
+ /**
+ * Write byte array to port
+ *
+ * @return If the operation is successfully completed, the method returns true, otherwise false
+ *
+ * @throws SerialPortException
+ */
+ public boolean writeBytes(byte[] buffer) throws SerialPortException {
+ checkPortOpened("writeBytes()");
+ return serialInterface.writeBytes(portHandle, buffer);
+ }
+
+ /**
+ * Write single byte to port
+ *
+ * @return If the operation is successfully completed, the method returns true, otherwise false
+ *
+ * @throws SerialPortException
+ *
+ * @since 0.8
+ */
+ public boolean writeByte(byte singleByte) throws SerialPortException {
+ checkPortOpened("writeByte()");
+ return writeBytes(new byte[]{singleByte});
+ }
+
+ /**
+ * Write String to port
+ *
+ * @return If the operation is successfully completed, the method returns true, otherwise false
+ *
+ * @throws SerialPortException
+ *
+ * @since 0.8
+ */
+ public boolean writeString(String string) throws SerialPortException {
+ checkPortOpened("writeString()");
+ return writeBytes(string.getBytes());
+ }
+
+ /**
+ * Write String to port
+ *
+ * @return If the operation is successfully completed, the method returns true, otherwise false
+ *
+ * @throws SerialPortException
+ *
+ * @since 2.8.0
+ */
+ public boolean writeString(String string, String charsetName) throws SerialPortException, UnsupportedEncodingException {
+ checkPortOpened("writeString()");
+ return writeBytes(string.getBytes(charsetName));
+ }
+
+ /**
+ * Write int value (in range from 0 to 255 (0x00 - 0xFF)) to port
+ *
+ * @return If the operation is successfully completed, the method returns true, otherwise false
+ *
+ * @throws SerialPortException
+ *
+ * @since 0.8
+ */
+ public boolean writeInt(int singleInt) throws SerialPortException {
+ checkPortOpened("writeInt()");
+ return writeBytes(new byte[]{(byte)singleInt});
+ }
+
+ /**
+ * Write int array (in range from 0 to 255 (0x00 - 0xFF)) to port
+ *
+ * @return If the operation is successfully completed, the method returns true, otherwise false
+ *
+ * @throws SerialPortException
+ *
+ * @since 0.8
+ */
+ public boolean writeIntArray(int[] buffer) throws SerialPortException {
+ checkPortOpened("writeIntArray()");
+ byte[] byteArray = new byte[buffer.length];
+ for(int i = 0; i < buffer.length; i++){
+ byteArray[i] = (byte)buffer[i];
+ }
+ return writeBytes(byteArray);
+ }
+
+ /**
+ * Read byte array from port
+ *
+ * @param byteCount count of bytes for reading
+ *
+ * @return byte array with "byteCount" length
+ *
+ * @throws SerialPortException
+ */
+ public byte[] readBytes(int byteCount) throws SerialPortException {
+ log("readBytes " + byteCount);
+ checkPortOpened("readBytes()");
+ return serialInterface.readBytes(portHandle, byteCount);
+ }
+
+ /**
+ * Read string from port
+ *
+ * @param byteCount count of bytes for reading
+ *
+ * @return byte array with "byteCount" length converted to String
+ *
+ * @throws SerialPortException
+ *
+ * @since 0.8
+ */
+ public String readString(int byteCount) throws SerialPortException {
+ checkPortOpened("readString()");
+ return new String(readBytes(byteCount));
+ }
+
+ /**
+ * Read Hex string from port (example: FF 0A FF). Separator by default is a space
+ *
+ * @param byteCount count of bytes for reading
+ *
+ * @return byte array with "byteCount" length converted to Hexadecimal String
+ *
+ * @throws SerialPortException
+ *
+ * @since 0.8
+ */
+ public String readHexString(int byteCount) throws SerialPortException {
+ checkPortOpened("readHexString()");
+ return readHexString(byteCount, " ");
+ }
+
+ /**
+ * Read Hex string from port with setted separator (example if separator is "::": FF::0A::FF)
+ *
+ * @param byteCount count of bytes for reading
+ *
+ * @return byte array with "byteCount" length converted to Hexadecimal String
+ *
+ * @throws SerialPortException
+ *
+ * @since 0.8
+ */
+ public String readHexString(int byteCount, String separator) throws SerialPortException {
+ checkPortOpened("readHexString()");
+ String[] strBuffer = readHexStringArray(byteCount);
+ String returnString = "";
+ boolean insertSeparator = false;
+ for(String value : strBuffer){
+ if(insertSeparator){
+ returnString += separator;
+ }
+ returnString += value;
+ insertSeparator = true;
+ }
+ return returnString;
+ }
+
+ /**
+ * Read Hex String array from port
+ *
+ * @param byteCount count of bytes for reading
+ *
+ * @return String array with "byteCount" length and Hexadecimal String values
+ *
+ * @throws SerialPortException
+ *
+ * @since 0.8
+ */
+ public String[] readHexStringArray(int byteCount) throws SerialPortException {
+ checkPortOpened("readHexStringArray()");
+ int[] intBuffer = readIntArray(byteCount);
+ String[] strBuffer = new String[intBuffer.length];
+ for(int i = 0; i < intBuffer.length; i++){
+ String value = Integer.toHexString(intBuffer[i]).toUpperCase();
+ if(value.length() == 1) {
+ value = "0" + value;
+ }
+ strBuffer[i] = value;
+ }
+ return strBuffer;
+ }
+
+ /**
+ * Read int array from port
+ *
+ * @param byteCount count of bytes for reading
+ *
+ * @return int array with values in range from 0 to 255
+ *
+ * @throws SerialPortException
+ *
+ * @since 0.8
+ */
+ public int[] readIntArray(int byteCount) throws SerialPortException {
+ checkPortOpened("readIntArray()");
+ byte[] buffer = readBytes(byteCount);
+ int[] intBuffer = new int[buffer.length];
+ for(int i = 0; i < buffer.length; i++){
+ if(buffer[i] < 0){
+ intBuffer[i] = 256 + buffer[i];
+ }
+ else {
+ intBuffer[i] = buffer[i];
+ }
+ }
+ return intBuffer;
+ }
+
+ private void waitBytesWithTimeout(String methodName, int byteCount, int timeout) throws SerialPortException, SerialPortTimeoutException {
+ checkPortOpened("waitBytesWithTimeout()");
+ boolean timeIsOut = true;
+ long startTime = System.currentTimeMillis();
+ while((System.currentTimeMillis() - startTime) < timeout){
+ if(getInputBufferBytesCount() >= byteCount){
+ timeIsOut = false;
+ break;
+ }
+ try {
+ Thread.sleep(0, 100);//Need to sleep some time to prevent high CPU loading
+ }
+ catch (InterruptedException ex) {
+ //Do nothing
+ }
+ }
+ if(timeIsOut){
+ throw new SerialPortTimeoutException(portName, methodName, timeout);
+ }
+ }
+
+ /**
+ * Read byte array from port
+ *
+ * @param byteCount count of bytes for reading
+ * @param timeout timeout in milliseconds
+ *
+ * @return byte array with "byteCount" length
+ *
+ * @throws SerialPortException
+ * @throws SerialPortTimeoutException
+ *
+ * @since 2.0
+ */
+ public byte[] readBytes(int byteCount, int timeout) throws SerialPortException, SerialPortTimeoutException {
+ log("readBytes " + byteCount + " " + timeout);
+ checkPortOpened("readBytes()");
+ waitBytesWithTimeout("readBytes()", byteCount, timeout);
+ return readBytes(byteCount);
+ }
+
+ public static void log(String s) {
+ System.out.println(new Date() + ": custom JSSC " + s);
+ }
+
+ /**
+ * Read string from port
+ *
+ * @param byteCount count of bytes for reading
+ * @param timeout timeout in milliseconds
+ *
+ * @return byte array with "byteCount" length converted to String
+ *
+ * @throws SerialPortException
+ * @throws SerialPortTimeoutException
+ *
+ * @since 2.0
+ */
+ public String readString(int byteCount, int timeout) throws SerialPortException, SerialPortTimeoutException {
+ checkPortOpened("readString()");
+ waitBytesWithTimeout("readString()", byteCount, timeout);
+ return readString(byteCount);
+ }
+
+ /**
+ * Read Hex string from port (example: FF 0A FF). Separator by default is a space
+ *
+ * @param byteCount count of bytes for reading
+ * @param timeout timeout in milliseconds
+ *
+ * @return byte array with "byteCount" length converted to Hexadecimal String
+ *
+ * @throws SerialPortException
+ * @throws SerialPortTimeoutException
+ *
+ * @since 2.0
+ */
+ public String readHexString(int byteCount, int timeout) throws SerialPortException, SerialPortTimeoutException {
+ checkPortOpened("readHexString()");
+ waitBytesWithTimeout("readHexString()", byteCount, timeout);
+ return readHexString(byteCount);
+ }
+
+ /**
+ * Read Hex string from port with setted separator (example if separator is "::": FF::0A::FF)
+ *
+ * @param byteCount count of bytes for reading
+ * @param timeout timeout in milliseconds
+ *
+ * @return byte array with "byteCount" length converted to Hexadecimal String
+ *
+ * @throws SerialPortException
+ * @throws SerialPortTimeoutException
+ *
+ * @since 2.0
+ */
+ public String readHexString(int byteCount, String separator, int timeout) throws SerialPortException, SerialPortTimeoutException {
+ checkPortOpened("readHexString()");
+ waitBytesWithTimeout("readHexString()", byteCount, timeout);
+ return readHexString(byteCount, separator);
+ }
+
+ /**
+ * Read Hex String array from port
+ *
+ * @param byteCount count of bytes for reading
+ * @param timeout timeout in milliseconds
+ *
+ * @return String array with "byteCount" length and Hexadecimal String values
+ *
+ * @throws SerialPortException
+ * @throws SerialPortTimeoutException
+ *
+ * @since 2.0
+ */
+ public String[] readHexStringArray(int byteCount, int timeout) throws SerialPortException, SerialPortTimeoutException {
+ checkPortOpened("readHexStringArray()");
+ waitBytesWithTimeout("readHexStringArray()", byteCount, timeout);
+ return readHexStringArray(byteCount);
+ }
+
+ /**
+ * Read int array from port
+ *
+ * @param byteCount count of bytes for reading
+ * @param timeout timeout in milliseconds
+ *
+ * @return int array with values in range from 0 to 255
+ *
+ * @throws SerialPortException
+ * @throws SerialPortTimeoutException
+ *
+ * @since 2.0
+ */
+ public int[] readIntArray(int byteCount, int timeout) throws SerialPortException, SerialPortTimeoutException {
+ checkPortOpened("readIntArray()");
+ waitBytesWithTimeout("readIntArray()", byteCount, timeout);
+ return readIntArray(byteCount);
+ }
+
+ /**
+ * Read all available bytes from port like a byte array
+ *
+ * @return If input buffer is empty null will be returned, else byte array with all data from port
+ *
+ * @throws SerialPortException
+ *
+ * @since 0.8
+ */
+ public byte[] readBytes() throws SerialPortException {
+ checkPortOpened("readBytes()");
+ int byteCount = getInputBufferBytesCount();
+ if(byteCount <= 0){
+ return null;
+ }
+ return readBytes(byteCount);
+ }
+
+ /**
+ * Read all available bytes from port like a String
+ *
+ * @return If input buffer is empty null will be returned, else byte array with all data from port converted to String
+ *
+ * @throws SerialPortException
+ *
+ * @since 0.8
+ */
+ public String readString() throws SerialPortException {
+ checkPortOpened("readString()");
+ int byteCount = getInputBufferBytesCount();
+ if(byteCount <= 0){
+ return null;
+ }
+ return readString(byteCount);
+ }
+
+ /**
+ * Read all available bytes from port like a Hex String
+ *
+ * @return If input buffer is empty null will be returned, else byte array with all data from port converted to Hex String
+ *
+ * @throws SerialPortException
+ *
+ * @since 0.8
+ */
+ public String readHexString() throws SerialPortException {
+ checkPortOpened("readHexString()");
+ int byteCount = getInputBufferBytesCount();
+ if(byteCount <= 0){
+ return null;
+ }
+ return readHexString(byteCount);
+ }
+
+ /**
+ * Read all available bytes from port like a Hex String with setted separator
+ *
+ * @return If input buffer is empty null will be returned, else byte array with all data from port converted to Hex String
+ *
+ * @throws SerialPortException
+ *
+ * @since 0.8
+ */
+ public String readHexString(String separator) throws SerialPortException {
+ checkPortOpened("readHexString()");
+ int byteCount = getInputBufferBytesCount();
+ if(byteCount <= 0){
+ return null;
+ }
+ return readHexString(byteCount, separator);
+ }
+
+ /**
+ * Read all available bytes from port like a Hex String array
+ *
+ * @return If input buffer is empty null will be returned, else byte array with all data from port converted to Hex String array
+ *
+ * @throws SerialPortException
+ *
+ * @since 0.8
+ */
+ public String[] readHexStringArray() throws SerialPortException {
+ checkPortOpened("readHexStringArray()");
+ int byteCount = getInputBufferBytesCount();
+ if(byteCount <= 0){
+ return null;
+ }
+ return readHexStringArray(byteCount);
+ }
+
+ /**
+ * Read all available bytes from port like a int array (values in range from 0 to 255)
+ *
+ * @return If input buffer is empty null will be returned, else byte array with all data from port converted to int array
+ *
+ * @throws SerialPortException
+ *
+ * @since 0.8
+ */
+ public int[] readIntArray() throws SerialPortException {
+ checkPortOpened("readIntArray()");
+ int byteCount = getInputBufferBytesCount();
+ if(byteCount <= 0){
+ return null;
+ }
+ return readIntArray(byteCount);
+ }
+
+ /**
+ * Get count of bytes in input buffer
+ *
+ * @return Count of bytes in input buffer or -1 if error occured
+ *
+ * @throws SerialPortException
+ *
+ * @since 0.8
+ */
+ public int getInputBufferBytesCount() throws SerialPortException {
+ checkPortOpened("getInputBufferBytesCount()");
+ int result = serialInterface.getBuffersBytesCount(portHandle)[0];
+ log("getInputBufferBytesCount=" + result);
+ return result;
+ }
+
+ /**
+ * Get count of bytes in output buffer
+ *
+ * @return Count of bytes in output buffer or -1 if error occured
+ *
+ * @throws SerialPortException
+ *
+ * @since 0.8
+ */
+ public int getOutputBufferBytesCount() throws SerialPortException {
+ checkPortOpened("getOutputBufferBytesCount()");
+ int result = serialInterface.getBuffersBytesCount(portHandle)[1];
+ log("getInputBufferBytesCount=" + result);
+ return result;
+ }
+
+ /**
+ * Set flow control mode. For required mode use variables with prefix "FLOWCONTROL_".
+ * Example of hardware flow control mode(RTS/CTS): setFlowControlMode(FLOWCONTROL_RTSCTS_IN | FLOWCONTROL_RTSCTS_OUT);
+ *
+ * @return If the operation is successfully completed, the method returns true, otherwise false
+ *
+ * @throws SerialPortException
+ *
+ * @since 0.8
+ */
+ public boolean setFlowControlMode(int mask) throws SerialPortException {
+ log("setFlowControlMode " + mask);
+ checkPortOpened("setFlowControlMode()");
+ return serialInterface.setFlowControlMode(portHandle, mask);
+ }
+
+ /**
+ * Get flow control mode
+ *
+ * @return Mask of setted flow control mode
+ *
+ * @throws SerialPortException
+ *
+ * @since 0.8
+ */
+ public int getFlowControlMode() throws SerialPortException {
+ checkPortOpened("getFlowControlMode()");
+ return serialInterface.getFlowControlMode(portHandle);
+ }
+
+ /**
+ * Send Break singnal for setted duration
+ *
+ * @param duration duration of Break signal
+ *
+ * @return If the operation is successfully completed, the method returns true, otherwise false
+ *
+ * @throws SerialPortException
+ *
+ * @since 0.8
+ */
+ public boolean sendBreak(int duration)throws SerialPortException {
+ log("sendBreak");
+ checkPortOpened("sendBreak()");
+ return serialInterface.sendBreak(portHandle, duration);
+ }
+
+ private int[][] waitEvents() {
+ return serialInterface.waitEvents(portHandle);
+ }
+
+ /**
+ * Check port opened (since jSSC-0.8 String "EMPTY" was replaced with "portName" variable)
+ *
+ * @param methodName method name
+ *
+ * @throws SerialPortException
+ */
+ private void checkPortOpened(String methodName) throws SerialPortException {
+ if(!portOpened){
+ throw new SerialPortException(portName, methodName, SerialPortException.TYPE_PORT_NOT_OPENED);
+ }
+ }
+
+ /**
+ * Getting lines status. Lines status is sent as 0 – OFF and 1 - ON
+ *
+ * @return Method returns the array containing information about lines in following order:
+ *
element 0 - CTS line state
+ *
element 1 - DSR line state
+ *
element 2 - RING line state
+ *
element 3 - RLSD line state
+ *
+ * @throws SerialPortException
+ */
+ public int[] getLinesStatus() throws SerialPortException {
+ checkPortOpened("getLinesStatus()");
+ return serialInterface.getLinesStatus(portHandle);
+ }
+
+ /**
+ * Get state of CTS line
+ *
+ * @return If line is active, method returns true, otherwise false
+ *
+ * @throws SerialPortException
+ */
+ public boolean isCTS() throws SerialPortException {
+ log("isCTS");
+ checkPortOpened("isCTS()");
+ if(serialInterface.getLinesStatus(portHandle)[0] == 1){
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ /**
+ * Get state of DSR line
+ *
+ * @return If line is active, method returns true, otherwise false
+ *
+ * @throws SerialPortException
+ */
+ public boolean isDSR() throws SerialPortException {
+ log("isDSR");
+ checkPortOpened("isDSR()");
+ if(serialInterface.getLinesStatus(portHandle)[1] == 1){
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ /**
+ * Get state of RING line
+ *
+ * @return If line is active, method returns true, otherwise false
+ *
+ * @throws SerialPortException
+ */
+ public boolean isRING() throws SerialPortException {
+ log("isRING");
+ checkPortOpened("isRING()");
+ if(serialInterface.getLinesStatus(portHandle)[2] == 1){
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ /**
+ * Get state of RLSD line
+ *
+ * @return If line is active, method returns true, otherwise false
+ *
+ * @throws SerialPortException
+ */
+ public boolean isRLSD() throws SerialPortException {
+ log("isRLSD");
+ checkPortOpened("isRLSD()");
+ if(serialInterface.getLinesStatus(portHandle)[3] == 1){
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ /**
+ * Add event listener. Object of "SerialPortEventListener" type shall
+ * be sent to the method. This object shall be properly described, as it will
+ * be in charge for handling of occurred events. This method will independently
+ * set the mask in "MASK_RXCHAR" state if it was not set beforehand
+ *
+ * @throws SerialPortException
+ */
+ public void addEventListener(SerialPortEventListener listener) throws SerialPortException {
+ log("addEventListener " + listener);
+ addEventListener(listener, MASK_RXCHAR, false);
+ }
+
+ /**
+ * Add event listener. Object of "SerialPortEventListener" type shall be sent
+ * to the method. This object shall be properly described, as it will be in
+ * charge for handling of occurred events. Also events mask shall be sent to
+ * this method, to do it use variables with prefix "MASK_" for example "MASK_RXCHAR"
+ *
+ * @see #setEventsMask(int) setEventsMask(int mask)
+ *
+ * @throws SerialPortException
+ */
+ public void addEventListener(SerialPortEventListener listener, int mask) throws SerialPortException {
+ log("addEventListener " + listener + " " + mask);
+ addEventListener(listener, mask, true);
+ }
+
+ /**
+ * Internal method. Add event listener. Object of "SerialPortEventListener" type shall be sent
+ * to the method. This object shall be properly described, as it will be in
+ * charge for handling of occurred events. Also events mask shall be sent to
+ * this method, to do it use variables with prefix "MASK_" for example "MASK_RXCHAR". If
+ * overwriteMask == true and mask has been already assigned it value will be rewrited by mask
+ * value, if overwriteMask == false and mask has been already assigned the new mask value will be ignored,
+ * if there is no assigned mask to this serial port the mask value will be used for setting it up in spite of
+ * overwriteMask value
+ *
+ * @see #setEventsMask(int) setEventsMask(int mask)
+ *
+ * @throws SerialPortException
+ */
+ private void addEventListener(SerialPortEventListener listener, int mask, boolean overwriteMask) throws SerialPortException {
+ checkPortOpened("addEventListener()");
+ if(!eventListenerAdded){
+ if((maskAssigned && overwriteMask) || !maskAssigned) {
+ setEventsMask(mask);
+ }
+ eventListener = listener;
+ eventThread = getNewEventThread();
+ eventThread.setName("EventThread " + portName);
+ //since 2.2.0 ->
+ try {
+ Method method = eventListener.getClass().getMethod("errorOccurred", new Class[]{SerialPortException.class});
+ method.setAccessible(true);
+ methodErrorOccurred = method;
+ }
+ catch (SecurityException ex) {
+ //Do nothing
+ }
+ catch (NoSuchMethodException ex) {
+ //Do nothing
+ }
+ //<- since 2.2.0
+ eventThread.start();
+ eventListenerAdded = true;
+ }
+ else {
+ throw new SerialPortException(portName, "addEventListener()", SerialPortException.TYPE_LISTENER_ALREADY_ADDED);
+ }
+ }
+
+ /**
+ * Create new EventListener Thread depending on the type of operating system
+ *
+ * @since 0.8
+ */
+ private EventThread getNewEventThread() {
+ if(SerialNativeInterface.getOsType() == SerialNativeInterface.OS_LINUX ||
+ SerialNativeInterface.getOsType() == SerialNativeInterface.OS_SOLARIS ||
+ SerialNativeInterface.getOsType() == SerialNativeInterface.OS_MAC_OS_X){//since 0.9.0
+ return new LinuxEventThread();
+ }
+ return new EventThread();
+ }
+
+ /**
+ * Delete event listener. Mask is set to 0. So at the next addition of event
+ * handler you shall set required event mask again
+ *
+ * @return If the operation is successfully completed, the method returns true, otherwise false
+ *
+ * @throws SerialPortException
+ */
+ public boolean removeEventListener() throws SerialPortException {
+ checkPortOpened("removeEventListener()");
+ if(!eventListenerAdded){
+ throw new SerialPortException(portName, "removeEventListener()", SerialPortException.TYPE_CANT_REMOVE_LISTENER);
+ }
+ eventThread.terminateThread();
+ setEventsMask(0);
+ if(Thread.currentThread().getId() != eventThread.getId()){
+ if(eventThread.isAlive()){
+ try {
+ eventThread.join(5000);
+ }
+ catch (InterruptedException ex) {
+ throw new SerialPortException(portName, "removeEventListener()", SerialPortException.TYPE_LISTENER_THREAD_INTERRUPTED);
+ }
+ }
+ }
+ methodErrorOccurred = null;
+ eventListenerAdded = false;
+ return true;
+ }
+
+ /**
+ * Close port. This method deletes event listener first, then closes the port
+ *
+ * @return If the operation is successfully completed, the method returns true, otherwise false
+ *
+ * @throws SerialPortException
+ */
+ public boolean closePort() throws SerialPortException {
+ checkPortOpened("closePort()");
+ if(eventListenerAdded){
+ removeEventListener();
+ }
+ boolean returnValue = serialInterface.closePort(portHandle);
+ if(returnValue){
+ maskAssigned = false;
+ portOpened = false;
+ }
+ return returnValue;
+ }
+
+ private EventThread eventThread;
+
+ private class EventThread extends Thread {
+
+ private boolean threadTerminated = false;
+
+ @Override
+ public void run() {
+ while(!threadTerminated){
+ int[][] eventArray = waitEvents();
+ for(int i = 0; i < eventArray.length; i++){
+ if(eventArray[i][0] > 0 && !threadTerminated){
+ eventListener.serialEvent(new SerialPortEvent(portName, eventArray[i][0], eventArray[i][1]));
+ //FIXME
+ /*if(methodErrorOccurred != null){
+ try {
+ methodErrorOccurred.invoke(eventListener, new Object[]{new SerialPortException("port", "method", "exception")});
+ }
+ catch (Exception ex) {
+ System.out.println(ex);
+ }
+ }*/
+ }
+ }
+ }
+ }
+
+ private void terminateThread(){
+ threadTerminated = true;
+ }
+ }
+
+ /**
+ * EventListener for Linux OS
+ *
+ * @since 0.8
+ */
+ private class LinuxEventThread extends EventThread {
+
+ //Essential interruptions for events: BREAK, ERR, TXEMPTY
+ private final int INTERRUPT_BREAK = 512;
+ private final int INTERRUPT_TX = 1024;
+ private final int INTERRUPT_FRAME = 2048;
+ private final int INTERRUPT_OVERRUN = 4096;
+ private final int INTERRUPT_PARITY = 8192;
+
+ //Count of interruptions
+ private int interruptBreak;
+ private int interruptTX;
+ private int interruptFrame;
+ private int interruptOverrun;
+ private int interruptParity;
+
+ //Previous states if lines (then state change event will be generated)
+ private int preCTS;
+ private int preDSR;
+ private int preRLSD;
+ private int preRING;
+
+ //Need to get initial states
+ public LinuxEventThread(){
+ int[][] eventArray = waitEvents();
+ for(int i = 0; i < eventArray.length; i++){
+ int eventType = eventArray[i][0];
+ int eventValue = eventArray[i][1];
+ switch(eventType){
+ case INTERRUPT_BREAK:
+ interruptBreak = eventValue;
+ break;
+ case INTERRUPT_TX:
+ interruptTX = eventValue;
+ break;
+ case INTERRUPT_FRAME:
+ interruptFrame = eventValue;
+ break;
+ case INTERRUPT_OVERRUN:
+ interruptOverrun = eventValue;
+ break;
+ case INTERRUPT_PARITY:
+ interruptParity = eventValue;
+ break;
+ case MASK_CTS:
+ preCTS = eventValue;
+ break;
+ case MASK_DSR:
+ preDSR = eventValue;
+ break;
+ case MASK_RING:
+ preRING = eventValue;
+ break;
+ case MASK_RLSD:
+ preRLSD = eventValue;
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void run() {
+ while(!super.threadTerminated){
+ int[][] eventArray = waitEvents();
+ int mask = getLinuxMask();
+ boolean interruptTxChanged = false;
+ int errorMask = 0;
+ for(int i = 0; i < eventArray.length; i++){
+ boolean sendEvent = false;
+ int eventType = eventArray[i][0];
+ int eventValue = eventArray[i][1];
+ if(eventType > 0 && !super.threadTerminated){
+ switch(eventType){
+ case INTERRUPT_BREAK:
+ if(eventValue != interruptBreak){
+ interruptBreak = eventValue;
+ if((mask & MASK_BREAK) == MASK_BREAK){
+ eventType = MASK_BREAK;
+ eventValue = 0;
+ sendEvent = true;
+ }
+ }
+ break;
+ case INTERRUPT_TX:
+ if(eventValue != interruptTX){
+ interruptTX = eventValue;
+ interruptTxChanged = true;
+ }
+ break;
+ case INTERRUPT_FRAME:
+ if(eventValue != interruptFrame){
+ interruptFrame = eventValue;
+ errorMask |= ERROR_FRAME;
+ }
+ break;
+ case INTERRUPT_OVERRUN:
+ if(eventValue != interruptOverrun){
+ interruptOverrun = eventValue;
+ errorMask |= ERROR_OVERRUN;
+ }
+ break;
+ case INTERRUPT_PARITY:
+ if(eventValue != interruptParity){
+ interruptParity = eventValue;
+ errorMask |= ERROR_PARITY;
+ }
+ if((mask & MASK_ERR) == MASK_ERR && errorMask != 0){
+ eventType = MASK_ERR;
+ eventValue = errorMask;
+ sendEvent = true;
+ }
+ break;
+ case MASK_CTS:
+ if(eventValue != preCTS){
+ preCTS = eventValue;
+ if((mask & MASK_CTS) == MASK_CTS){
+ sendEvent = true;
+ }
+ }
+ break;
+ case MASK_DSR:
+ if(eventValue != preDSR){
+ preDSR = eventValue;
+ if((mask & MASK_DSR) == MASK_DSR){
+ sendEvent = true;
+ }
+ }
+ break;
+ case MASK_RING:
+ if(eventValue != preRING){
+ preRING = eventValue;
+ if((mask & MASK_RING) == MASK_RING){
+ sendEvent = true;
+ }
+ }
+ break;
+ case MASK_RLSD: /*DCD*/
+ if(eventValue != preRLSD){
+ preRLSD = eventValue;
+ if((mask & MASK_RLSD) == MASK_RLSD){
+ sendEvent = true;
+ }
+ }
+ break;
+ case MASK_RXCHAR:
+ if(((mask & MASK_RXCHAR) == MASK_RXCHAR) && (eventValue > 0)){
+ sendEvent = true;
+ }
+ break;
+ /*case MASK_RXFLAG:
+ //Do nothing at this moment
+ if(((mask & MASK_RXFLAG) == MASK_RXFLAG) && (eventValue > 0)){
+ sendEvent = true;
+ }
+ break;*/
+ case MASK_TXEMPTY:
+ if(((mask & MASK_TXEMPTY) == MASK_TXEMPTY) && (eventValue == 0) && interruptTxChanged){
+ sendEvent = true;
+ }
+ break;
+ }
+ if(sendEvent){
+ eventListener.serialEvent(new SerialPortEvent(portName, eventType, eventValue));
+ }
+ }
+ }
+ //Need to sleep some time
+ try {
+ Thread.sleep(0, 100);
+ }
+ catch (Exception ex) {
+ //Do nothing
+ }
+ }
+ }
+ }
+}
diff --git a/java_console/jssc/src/jssc/SerialPortEvent.java b/java_console/jssc/src/jssc/SerialPortEvent.java
new file mode 100644
index 0000000000..dd167ded22
--- /dev/null
+++ b/java_console/jssc/src/jssc/SerialPortEvent.java
@@ -0,0 +1,193 @@
+/* jSSC (Java Simple Serial Connector) - serial port communication library.
+ * © Alexey Sokolov (scream3r), 2010-2014.
+ *
+ * This file is part of jSSC.
+ *
+ * jSSC 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.
+ *
+ * jSSC 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 jSSC. If not, see .
+ *
+ * If you use jSSC in public project you can inform me about this by e-mail,
+ * of course if you want it.
+ *
+ * e-mail: scream3r.org@gmail.com
+ * web-site: http://scream3r.org | http://code.google.com/p/java-simple-serial-connector/
+ */
+package jssc;
+
+/**
+ *
+ * @author scream3r
+ */
+public class SerialPortEvent {
+
+ private String portName;
+ private int eventType;
+ private int eventValue;
+
+ public static final int RXCHAR = 1;
+ public static final int RXFLAG = 2;
+ public static final int TXEMPTY = 4;
+ public static final int CTS = 8;
+ public static final int DSR = 16;
+ public static final int RLSD = 32;
+ public static final int BREAK = 64;
+ public static final int ERR = 128;
+ public static final int RING = 256;
+
+ public SerialPortEvent(String portName, int eventType, int eventValue){
+ SerialPort.log("SerialPortEvent " + portName + " " + eventType + " " + eventValue);
+ this.portName = portName;
+ this.eventType = eventType;
+ this.eventValue = eventValue;
+ }
+
+ /**
+ * Getting port name which sent the event
+ */
+ public String getPortName() {
+ return portName;
+ }
+
+ /**
+ * Getting event type
+ */
+ public int getEventType() {
+ return eventType;
+ }
+
+ /**
+ * Getting event value
+ *
+ *
Event values depending on their types:
+ *
RXCHAR - bytes count in input buffer
+ *
RXFLAG - bytes count in input buffer (Not supported in Linux)
+ *
TXEMPTY - bytes count in output buffer
+ *
CTS - state of CTS line (0 - OFF, 1 - ON)
+ *
DSR - state of DSR line (0 - OFF, 1 - ON)
+ *
RLSD - state of RLSD line (0 - OFF, 1 - ON)
+ *
BREAK - 0
+ *
RING - state of RING line (0 - OFF, 1 - ON)
+ *
ERR - mask of errors
+ */
+ public int getEventValue() {
+ return eventValue;
+ }
+
+ /**
+ * Method returns true if event of type "RXCHAR" is received and otherwise false
+ */
+ public boolean isRXCHAR() {
+ if(eventType == RXCHAR){
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ /**
+ * Method returns true if event of type "RXFLAG" is received and otherwise false
+ */
+ public boolean isRXFLAG() {
+ if(eventType == RXFLAG){
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ /**
+ * Method returns true if event of type "TXEMPTY" is received and otherwise false
+ */
+ public boolean isTXEMPTY() {
+ if(eventType == TXEMPTY){
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ /**
+ * Method returns true if event of type "CTS" is received and otherwise false
+ */
+ public boolean isCTS() {
+ if(eventType == CTS){
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ /**
+ * Method returns true if event of type "DSR" is received and otherwise false
+ */
+ public boolean isDSR() {
+ if(eventType == DSR){
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ /**
+ * Method returns true if event of type "RLSD" is received and otherwise false
+ */
+ public boolean isRLSD() {
+ if(eventType == RLSD){
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ /**
+ * Method returns true if event of type "BREAK" is received and otherwise false
+ */
+ public boolean isBREAK() {
+ if(eventType == BREAK){
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ /**
+ * Method returns true if event of type "ERR" is received and otherwise false
+ */
+ public boolean isERR() {
+ if(eventType == ERR){
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ /**
+ * Method returns true if event of type "RING" is received and otherwise false
+ */
+ public boolean isRING() {
+ if(eventType == RING){
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+}
diff --git a/java_console/jssc/src/jssc/SerialPortEventListener.java b/java_console/jssc/src/jssc/SerialPortEventListener.java
new file mode 100644
index 0000000000..9a2441aa87
--- /dev/null
+++ b/java_console/jssc/src/jssc/SerialPortEventListener.java
@@ -0,0 +1,34 @@
+/* jSSC (Java Simple Serial Connector) - serial port communication library.
+ * © Alexey Sokolov (scream3r), 2010-2014.
+ *
+ * This file is part of jSSC.
+ *
+ * jSSC 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.
+ *
+ * jSSC 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 jSSC. If not, see .
+ *
+ * If you use jSSC in public project you can inform me about this by e-mail,
+ * of course if you want it.
+ *
+ * e-mail: scream3r.org@gmail.com
+ * web-site: http://scream3r.org | http://code.google.com/p/java-simple-serial-connector/
+ */
+package jssc;
+
+/**
+ *
+ * @author scream3r
+ */
+public interface SerialPortEventListener {
+
+ public abstract void serialEvent(SerialPortEvent serialPortEvent);
+}
diff --git a/java_console/jssc/src/jssc/SerialPortException.java b/java_console/jssc/src/jssc/SerialPortException.java
new file mode 100644
index 0000000000..18aca2f937
--- /dev/null
+++ b/java_console/jssc/src/jssc/SerialPortException.java
@@ -0,0 +1,95 @@
+/* jSSC (Java Simple Serial Connector) - serial port communication library.
+ * © Alexey Sokolov (scream3r), 2010-2014.
+ *
+ * This file is part of jSSC.
+ *
+ * jSSC 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.
+ *
+ * jSSC 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 jSSC. If not, see .
+ *
+ * If you use jSSC in public project you can inform me about this by e-mail,
+ * of course if you want it.
+ *
+ * e-mail: scream3r.org@gmail.com
+ * web-site: http://scream3r.org | http://code.google.com/p/java-simple-serial-connector/
+ */
+package jssc;
+
+/**
+ *
+ * @author scream3r
+ */
+public class SerialPortException extends Exception {
+
+ final public static String TYPE_PORT_ALREADY_OPENED = "Port already opened";
+ final public static String TYPE_PORT_NOT_OPENED = "Port not opened";
+ final public static String TYPE_CANT_SET_MASK = "Can't set mask";
+ final public static String TYPE_LISTENER_ALREADY_ADDED = "Event listener already added";
+ final public static String TYPE_LISTENER_THREAD_INTERRUPTED = "Event listener thread interrupted";
+ final public static String TYPE_CANT_REMOVE_LISTENER = "Can't remove event listener, because listener not added";
+ /**
+ * @since 0.8
+ */
+ final public static String TYPE_PARAMETER_IS_NOT_CORRECT = "Parameter is not correct";
+ /**
+ * @since 0.8
+ */
+ final public static String TYPE_NULL_NOT_PERMITTED = "Null not permitted";
+ /**
+ * @since 0.9.0
+ */
+ final public static String TYPE_PORT_BUSY = "Port busy";
+ /**
+ * @since 0.9.0
+ */
+ final public static String TYPE_PORT_NOT_FOUND = "Port not found";
+ /**
+ * @since 2.2.0
+ */
+ final public static String TYPE_PERMISSION_DENIED = "Permission denied";
+ /**
+ * @since 2.3.0
+ */
+ final public static String TYPE_INCORRECT_SERIAL_PORT = "Incorrect serial port";
+
+ private String portName;
+ private String methodName;
+ private String exceptionType;
+
+ public SerialPortException(String portName, String methodName, String exceptionType){
+ super("Port name - " + portName + "; Method name - " + methodName + "; Exception type - " + exceptionType + ".");
+ this.portName = portName;
+ this.methodName = methodName;
+ this.exceptionType = exceptionType;
+ }
+
+ /**
+ * Getting port name during operation with which the exception was called
+ */
+ public String getPortName(){
+ return portName;
+ }
+
+ /**
+ * Getting method name during execution of which the exception was called
+ */
+ public String getMethodName(){
+ return methodName;
+ }
+
+ /**
+ * Getting exception type
+ */
+ public String getExceptionType(){
+ return exceptionType;
+ }
+}
diff --git a/java_console/jssc/src/jssc/SerialPortList.java b/java_console/jssc/src/jssc/SerialPortList.java
new file mode 100644
index 0000000000..5af9a95ea0
--- /dev/null
+++ b/java_console/jssc/src/jssc/SerialPortList.java
@@ -0,0 +1,348 @@
+/* jSSC (Java Simple Serial Connector) - serial port communication library.
+ * © Alexey Sokolov (scream3r), 2010-2014.
+ *
+ * This file is part of jSSC.
+ *
+ * jSSC 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.
+ *
+ * jSSC 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 jSSC. If not, see .
+ *
+ * If you use jSSC in public project you can inform me about this by e-mail,
+ * of course if you want it.
+ *
+ * e-mail: scream3r.org@gmail.com
+ * web-site: http://scream3r.org | http://code.google.com/p/java-simple-serial-connector/
+ */
+package jssc;
+
+import java.io.File;
+import java.util.Comparator;
+import java.util.TreeSet;
+import java.util.regex.Pattern;
+
+/**
+ *
+ * @author scream3r
+ */
+public class SerialPortList {
+
+ private static SerialNativeInterface serialInterface;
+ private static final Pattern PORTNAMES_REGEXP;
+ private static final String PORTNAMES_PATH;
+
+ static {
+ serialInterface = new SerialNativeInterface();
+ switch (SerialNativeInterface.getOsType()) {
+ case SerialNativeInterface.OS_LINUX: {
+ PORTNAMES_REGEXP = Pattern.compile("(ttyS|ttyUSB|ttyACM|ttyAMA|rfcomm|ttyO)[0-9]{1,3}");
+ PORTNAMES_PATH = "/dev/";
+ break;
+ }
+ case SerialNativeInterface.OS_SOLARIS: {
+ PORTNAMES_REGEXP = Pattern.compile("[0-9]*|[a-z]*");
+ PORTNAMES_PATH = "/dev/term/";
+ break;
+ }
+ case SerialNativeInterface.OS_MAC_OS_X: {
+ PORTNAMES_REGEXP = Pattern.compile("tty.(serial|usbserial|usbmodem).*");
+ PORTNAMES_PATH = "/dev/";
+ break;
+ }
+ case SerialNativeInterface.OS_WINDOWS: {
+ PORTNAMES_REGEXP = Pattern.compile("");
+ PORTNAMES_PATH = "";
+ break;
+ }
+ default: {
+ PORTNAMES_REGEXP = null;
+ PORTNAMES_PATH = null;
+ break;
+ }
+ }
+ }
+
+ //since 2.1.0 -> Fully rewrited port name comparator
+ private static final Comparator PORTNAMES_COMPARATOR = new Comparator() {
+
+ @Override
+ public int compare(String valueA, String valueB) {
+
+ if(valueA.equalsIgnoreCase(valueB)){
+ return valueA.compareTo(valueB);
+ }
+
+ int minLength = Math.min(valueA.length(), valueB.length());
+
+ int shiftA = 0;
+ int shiftB = 0;
+
+ for(int i = 0; i < minLength; i++){
+ char charA = valueA.charAt(i - shiftA);
+ char charB = valueB.charAt(i - shiftB);
+ if(charA != charB){
+ if(Character.isDigit(charA) && Character.isDigit(charB)){
+ int[] resultsA = getNumberAndLastIndex(valueA, i - shiftA);
+ int[] resultsB = getNumberAndLastIndex(valueB, i - shiftB);
+
+ if(resultsA[0] != resultsB[0]){
+ return resultsA[0] - resultsB[0];
+ }
+
+ if(valueA.length() < valueB.length()){
+ i = resultsA[1];
+ shiftB = resultsA[1] - resultsB[1];
+ }
+ else {
+ i = resultsB[1];
+ shiftA = resultsB[1] - resultsA[1];
+ }
+ }
+ else {
+ if(Character.toLowerCase(charA) - Character.toLowerCase(charB) != 0){
+ return Character.toLowerCase(charA) - Character.toLowerCase(charB);
+ }
+ }
+ }
+ }
+ return valueA.compareToIgnoreCase(valueB);
+ }
+
+ /**
+ * Evaluate port index/number from startIndex to the number end. For example:
+ * for port name serial-123-FF you should invoke this method with startIndex = 7
+ *
+ * @return If port index/number correctly evaluated it value will be returned
+ * returnArray[0] = index/number
+ * returnArray[1] = stopIndex
+ *
+ * If incorrect:
+ * returnArray[0] = -1
+ * returnArray[1] = startIndex
+ *
+ * For this name serial-123-FF result is:
+ * returnArray[0] = 123
+ * returnArray[1] = 10
+ */
+ private int[] getNumberAndLastIndex(String str, int startIndex) {
+ String numberValue = "";
+ int[] returnValues = {-1, startIndex};
+ for(int i = startIndex; i < str.length(); i++){
+ returnValues[1] = i;
+ char c = str.charAt(i);
+ if(Character.isDigit(c)){
+ numberValue += c;
+ }
+ else {
+ break;
+ }
+ }
+ try {
+ returnValues[0] = Integer.valueOf(numberValue);
+ }
+ catch (Exception ex) {
+ //Do nothing
+ }
+ return returnValues;
+ }
+ };
+ //<-since 2.1.0
+
+ /**
+ * Get sorted array of serial ports in the system using default settings:
+ *
+ * Search path
+ * Windows - ""(always ignored)
+ * Linux - "/dev/"
+ * Solaris - "/dev/term/"
+ * MacOSX - "/dev/"
+ *
+ * RegExp
+ * Windows - ""
+ * Linux - "(ttyS|ttyUSB|ttyACM|ttyAMA|rfcomm)[0-9]{1,3}"
+ * Solaris - "[0-9]*|[a-z]*"
+ * MacOSX - "tty.(serial|usbserial|usbmodem).*"
+ *
+ * @return String array. If there is no ports in the system String[]
+ * with zero length will be returned (since jSSC-0.8 in previous versions null will be returned)
+ */
+ public static String[] getPortNames() {
+ return getPortNames(PORTNAMES_PATH, PORTNAMES_REGEXP, PORTNAMES_COMPARATOR);
+ }
+
+ /**
+ * Get sorted array of serial ports in the system located on searchPath
+ *
+ * @param searchPath Path for searching serial ports (not null)
+ * The default search paths:
+ * Linux, MacOSX: /dev/
+ * Solaris: /dev/term/
+ * Windows: this parameter ingored
+ *
+ * @return String array. If there is no ports in the system String[]
+ *
+ * @since 2.3.0
+ */
+ public static String[] getPortNames(String searchPath) {
+ return getPortNames(searchPath, PORTNAMES_REGEXP, PORTNAMES_COMPARATOR);
+ }
+
+ /**
+ * Get sorted array of serial ports in the system matched pattern
+ *
+ * @param pattern RegExp pattern for matching port names (not null)
+ *
+ * @return String array. If there is no ports in the system String[]
+ *
+ * @since 2.3.0
+ */
+ public static String[] getPortNames(Pattern pattern) {
+ return getPortNames(PORTNAMES_PATH, pattern, PORTNAMES_COMPARATOR);
+ }
+
+ /**
+ * Get sorted array of serial ports in the system matched pattern
+ *
+ * @param comparator Comparator for sotring port names (not null)
+ *
+ * @return String array. If there is no ports in the system String[]
+ *
+ * @since 2.3.0
+ */
+ public static String[] getPortNames(Comparator comparator) {
+ return getPortNames(PORTNAMES_PATH, PORTNAMES_REGEXP, comparator);
+ }
+
+ /**
+ * Get sorted array of serial ports in the system located on searchPath, matched pattern
+ *
+ * @param searchPath Path for searching serial ports (not null)
+ * The default search paths:
+ * Linux, MacOSX: /dev/
+ * Solaris: /dev/term/
+ * Windows: this parameter ingored
+ * @param pattern RegExp pattern for matching port names (not null)
+ *
+ * @return String array. If there is no ports in the system String[]
+ *
+ * @since 2.3.0
+ */
+ public static String[] getPortNames(String searchPath, Pattern pattern) {
+ return getPortNames(searchPath, pattern, PORTNAMES_COMPARATOR);
+ }
+
+ /**
+ * Get sorted array of serial ports in the system located on searchPath and sorted by comparator
+ *
+ * @param searchPath Path for searching serial ports (not null)
+ * The default search paths:
+ * Linux, MacOSX: /dev/
+ * Solaris: /dev/term/
+ * Windows: this parameter ingored
+ * @param comparator Comparator for sotring port names (not null)
+ *
+ * @return String array. If there is no ports in the system String[]
+ *
+ * @since 2.3.0
+ */
+ public static String[] getPortNames(String searchPath, Comparator comparator) {
+ return getPortNames(searchPath, PORTNAMES_REGEXP, comparator);
+ }
+
+ /**
+ * Get sorted array of serial ports in the system matched pattern and sorted by comparator
+ *
+ * @param pattern RegExp pattern for matching port names (not null)
+ * @param comparator Comparator for sotring port names (not null)
+ *
+ * @return String array. If there is no ports in the system String[]
+ *
+ * @since 2.3.0
+ */
+ public static String[] getPortNames(Pattern pattern, Comparator comparator) {
+ return getPortNames(PORTNAMES_PATH, pattern, comparator);
+ }
+
+ /**
+ * Get sorted array of serial ports in the system located on searchPath, matched pattern and sorted by comparator
+ *
+ * @param searchPath Path for searching serial ports (not null)
+ * The default search paths:
+ * Linux, MacOSX: /dev/
+ * Solaris: /dev/term/
+ * Windows: this parameter ingored
+ * @param pattern RegExp pattern for matching port names (not null)
+ * @param comparator Comparator for sotring port names (not null)
+ *
+ * @return String array. If there is no ports in the system String[]
+ *
+ * @since 2.3.0
+ */
+ public static String[] getPortNames(String searchPath, Pattern pattern, Comparator comparator) {
+ if(searchPath == null || pattern == null || comparator == null){
+ return new String[]{};
+ }
+ if(SerialNativeInterface.getOsType() == SerialNativeInterface.OS_WINDOWS){
+ return getWindowsPortNames(pattern, comparator);
+ }
+ return getUnixBasedPortNames(searchPath, pattern, comparator);
+ }
+
+ /**
+ * Get serial port names in Windows
+ *
+ * @since 2.3.0
+ */
+ private static String[] getWindowsPortNames(Pattern pattern, Comparator comparator) {
+ String[] portNames = serialInterface.getSerialPortNames();
+ if(portNames == null){
+ return new String[]{};
+ }
+ TreeSet ports = new TreeSet(comparator);
+ for(String portName : portNames){
+ if(pattern.matcher(portName).find()){
+ ports.add(portName);
+ }
+ }
+ return ports.toArray(new String[ports.size()]);
+ }
+
+ /**
+ * Universal method for getting port names of _nix based systems
+ */
+ private static String[] getUnixBasedPortNames(String searchPath, Pattern pattern, Comparator comparator) {
+ searchPath = (searchPath.equals("") ? searchPath : (searchPath.endsWith("/") ? searchPath : searchPath + "/"));
+ String[] returnArray = new String[]{};
+ File dir = new File(searchPath);
+ if(dir.exists() && dir.isDirectory()){
+ File[] files = dir.listFiles();
+ if(files.length > 0){
+ TreeSet portsTree = new TreeSet(comparator);
+ for(File file : files){
+ String fileName = file.getName();
+ if(!file.isDirectory() && !file.isFile() && pattern.matcher(fileName).find()){
+ String portName = searchPath + fileName;
+ long portHandle = serialInterface.openPort(portName, false);//Open port without TIOCEXCL
+ if(portHandle < 0 && portHandle != SerialNativeInterface.ERR_PORT_BUSY){
+ continue;
+ }
+ else if(portHandle != SerialNativeInterface.ERR_PORT_BUSY) {
+ serialInterface.closePort(portHandle);
+ }
+ portsTree.add(portName);
+ }
+ }
+ returnArray = portsTree.toArray(returnArray);
+ }
+ }
+ return returnArray;
+ }
+}
diff --git a/java_console/jssc/src/jssc/SerialPortTimeoutException.java b/java_console/jssc/src/jssc/SerialPortTimeoutException.java
new file mode 100644
index 0000000000..802535c3ad
--- /dev/null
+++ b/java_console/jssc/src/jssc/SerialPortTimeoutException.java
@@ -0,0 +1,64 @@
+/* jSSC (Java Simple Serial Connector) - serial port communication library.
+ * © Alexey Sokolov (scream3r), 2010-2014.
+ *
+ * This file is part of jSSC.
+ *
+ * jSSC 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.
+ *
+ * jSSC 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 jSSC. If not, see .
+ *
+ * If you use jSSC in public project you can inform me about this by e-mail,
+ * of course if you want it.
+ *
+ * e-mail: scream3r.org@gmail.com
+ * web-site: http://scream3r.org | http://code.google.com/p/java-simple-serial-connector/
+ */
+package jssc;
+
+/**
+ *
+ * @author scream3r
+ */
+public class SerialPortTimeoutException extends Exception {
+
+ private String portName;
+ private String methodName;
+ private int timeoutValue;
+
+ public SerialPortTimeoutException(String portName, String methodName, int timeoutValue) {
+ super("Port name - " + portName + "; Method name - " + methodName + "; Serial port operation timeout (" + timeoutValue + " ms).");
+ this.portName = portName;
+ this.methodName = methodName;
+ this.timeoutValue = timeoutValue;
+ }
+
+ /**
+ * Getting port name during operation with which the exception was called
+ */
+ public String getPortName(){
+ return portName;
+ }
+
+ /**
+ * Getting method name during execution of which the exception was called
+ */
+ public String getMethodName(){
+ return methodName;
+ }
+
+ /**
+ * Getting timeout value in millisecond
+ */
+ public int getTimeoutValue(){
+ return timeoutValue;
+ }
+}