diff --git a/README.md b/README.txt similarity index 53% rename from README.md rename to README.txt index 1f98fcdd3..c5fba559c 100644 --- a/README.md +++ b/README.txt @@ -1,8 +1,72 @@ -jSSC-0.9.0 Release version (21.12.2011) +jSSC-2.8.0 Release version (24.01.2014) -This version contains native libs for Windows(x86, x86-64), Linux(x86, x86-64), Solaris(x86, x86-64), Mac OS X(x86, x86-64, PPC, PPC64). +This version contains native libs for Windows(x86, x86-64), Linux(x86, x86-64, ARM soft & hard float), Solaris(x86, x86-64), Mac OS X(x86, x86-64, PPC, PPC64). All native libs contains in the jssc.jar file and you don't need manage native libs manually. +In this build: + + Fixes: + * Important! Fixed bug with port handles potential leakage + + Additions: + * Added method "writeString(String string, String charsetName)" + * Added method "getNativeLibraryVersion" in "SerialNativeInterface" class + * Enabled Java and Native libraries versions mismatch check + +With Best Regards, Sokolov Alexey aka scream3r. + +============= Previous Builds ============== + +/////////////////////////////////////////// +//jSSC-2.6.0 Release version (01.06.2013)// +/////////////////////////////////////////// + +In this build: + + Note: Linux x86 and x86-64 was builded on Ubuntu 10.04 and don't depends GLIBC-2.15 unlike jSSC-2.5.0 + + Additions: + * Added os.name - "Darwin" and os.arch - "universal" support. It can be useful for MacOS X developers. + * Added ttyO to Linux RegExp for listing OMAP serial devices. + * Added JSSC_IGNPAR and JSSC_PARMRK properties for enabling IGNPAR and PARMRK flags in _nix termios structure. + +/////////////////////////////////////////// +//jSSC-2.5.0 Release version (27.04.2013)// +/////////////////////////////////////////// + +In this build: + + Fixes: + * Important! Fixed bug with garbage reading on Linux, MacOSX, Solaris, cause of incorrect using of VMIN and VTIME. Now "read" methods works correctly and are blocking like in Windows + * Important! Fixed error with garbage reading in Windows using jSSC after another application used serial port. To prevent this effect COMMTIMEOUTS structure zeroing added to setParams() method + * Important! The port handle now stored in variable of type "long" instead of "int", to prevent potential problems with type conversions on Win64 + * Fixed MacOS X 10.8 bug with native lib loading (*.dylib -> *.jnilib) + * Fixed Linux error with exclusive access to serial port (TIOCEXCL). TIOCNXCL added to closePort() method for clearing exclusive access + * Fixed Windows native lib port name concatenation error + * Fixed native lib extraction path if user home is read only, in this situation lib will be extracted to tmp folder + * Null port name fix. If try to invoke method openPort() for SerialPort(null) object, exception TYPE_NULL_NOT_PERMITTED will be thrown + * Enabled TIOCEXCL support in Solaris + + Additions: + * Added ARM Soft & Hard float support (Tested of Raspberry Pi with Oracle JDK(6-7-8)) + * Added ttyACM, ttyAMA, rfcomm to Linux RegExp and tty.usbmodem to MacOS X RegExp + * Added precompiled RegExp's for Linux, Solaris, MacOS X for more faster port listing + * Added private common for Linux, Solaris, MacOS X method getUnixBasedPortNames() for listing serial ports + * Rewrited comparator for sorting port names. Now it's a common comparator for Windows, Linux, Solaris and MacOS X + * Added some syntax sugar to SerialPortList class, for changing search path, RegExp and comparator + * Added timeouts for read operations and SerialPortTimeoutException class for catching timeout exceptions + * Added JSSC_NO_TIOCEXCL JVM property for disable using of exclusive access to serial port + * Added termios(_nix) and DCB(Windows) structure cheking on port opening, it helps separate real serial devices from others + * Added "ERR_" constants into SerialNativeInterface + * Added new exception TYPE_INCORRECT_SERIAL_PORT + * Added new exception TYPE_PERMISSION_DENIED. It can be very useful for _nix based system if user have no permissions for using serial device + +And other little modifications... + +/////////////////////////////////////////// +//jSSC-0.9.0 Release version (21.12.2011)// +/////////////////////////////////////////// + In this build: * Added Solaris support (x86, x86-64) * Added Mac OS X support 10.5 and higher(x86, x86-64, PPC, PPC64) @@ -25,10 +89,6 @@ Important Note: * Included javadoc and source codes -With Best Regards, Sokolov Alexey. - -============= Previous Builds ============== - ///////////////////////////////////////// //jSSC-0.8 Release version (28.11.2011)// ///////////////////////////////////////// diff --git a/src/cpp/_nix_based/jssc.cpp b/src/cpp/_nix_based/jssc.cpp index 149a6e1d2..634b62018 100644 --- a/src/cpp/_nix_based/jssc.cpp +++ b/src/cpp/_nix_based/jssc.cpp @@ -1,5 +1,5 @@ /* jSSC (Java Simple Serial Connector) - serial port communication library. - * © Alexey Sokolov (scream3r), 2010-2011. + * © Alexey Sokolov (scream3r), 2010-2014. * * This file is part of jSSC. * @@ -30,43 +30,73 @@ #include #include //-D_TS_ERRNO use for Solaris C++ compiler +#include //since 2.5.0 + #ifdef __linux__ #include #endif #ifdef __SunOS #include //Needed for FIONREAD in Solaris + #include //Needed for select() function #endif #ifdef __APPLE__ #include //Needed for IOSSIOSPEED in Mac OS X (Non standard baudrate) #endif #include -#include "jssc_SerialNativeInterface.h" +#include "../jssc_SerialNativeInterface.h" -//#include //-lCstd use for Solaris linker +//#include //-lCstd use for Solaris linker +/* + * Get native library version + */ +JNIEXPORT jstring JNICALL Java_jssc_SerialNativeInterface_getNativeLibraryVersion(JNIEnv *env, jobject object) { + return env->NewStringUTF(jSSC_NATIVE_LIB_VERSION); +} /* OK */ -/* Port opening */ -JNIEXPORT jint JNICALL Java_jssc_SerialNativeInterface_openPort(JNIEnv *env, jobject object, jstring portName){ +/* + * Port opening + * + * In 2.2.0 added useTIOCEXCL + */ +JNIEXPORT jlong JNICALL Java_jssc_SerialNativeInterface_openPort(JNIEnv *env, jobject object, jstring portName, jboolean useTIOCEXCL){ const char* port = env->GetStringUTFChars(portName, JNI_FALSE); - jint hComm; - hComm = open(port, O_RDWR | O_NOCTTY | O_NDELAY); + jlong hComm = open(port, O_RDWR | O_NOCTTY | O_NDELAY); if(hComm != -1){ - #if defined TIOCEXCL && !defined __SunOS - ioctl(hComm, TIOCEXCL);//since 0.9 - #endif - int flags = fcntl(hComm, F_GETFL, 0); - flags &= ~O_NDELAY; - fcntl(hComm, F_SETFL, flags); + //since 2.2.0 -> (check termios structure for separating real serial devices from others) + termios *settings = new termios(); + if(tcgetattr(hComm, settings) == 0){ + #if defined TIOCEXCL //&& !defined __SunOS + if(useTIOCEXCL == JNI_TRUE){ + ioctl(hComm, TIOCEXCL); + } + #endif + int flags = fcntl(hComm, F_GETFL, 0); + flags &= ~O_NDELAY; + fcntl(hComm, F_SETFL, flags); + } + else { + close(hComm);//since 2.7.0 + hComm = jssc_SerialNativeInterface_ERR_INCORRECT_SERIAL_PORT;//-4; + } + delete settings; + //<- since 2.2.0 } else {//since 0.9 -> if(errno == EBUSY){//Port busy - hComm = -1; + hComm = jssc_SerialNativeInterface_ERR_PORT_BUSY;//-1 } else if(errno == ENOENT){//Port not found - hComm = -2; + hComm = jssc_SerialNativeInterface_ERR_PORT_NOT_FOUND;//-2; + }//-> since 2.2.0 + else if(errno == EACCES){//Permission denied + hComm = jssc_SerialNativeInterface_ERR_PERMISSION_DENIED;//-3; } + else { + hComm = jssc_SerialNativeInterface_ERR_PORT_NOT_FOUND;//-2; + }//<- since 2.2.0 }//<- since 0.9 env->ReleaseStringUTFChars(portName, port); return hComm; @@ -197,12 +227,19 @@ int getDataBitsByNum(jint byteSize) { } } +//since 2.6.0 -> +const jint PARAMS_FLAG_IGNPAR = 1; +const jint PARAMS_FLAG_PARMRK = 2; +//<- since 2.6.0 + /* OK */ /* * Set serial port settings + * + * In 2.6.0 added flags parameter */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setParams - (JNIEnv *env, jobject object, jint portHandle, jint baudRate, jint byteSize, jint stopBits, jint parity, jboolean setRTS, jboolean setDTR){ + (JNIEnv *env, jobject object, jlong portHandle, jint baudRate, jint byteSize, jint stopBits, jint parity, jboolean setRTS, jboolean setDTR, jint flags){ jboolean returnValue = JNI_FALSE; speed_t baudRateValue = getBaudRateByNum(baudRate); @@ -276,12 +313,21 @@ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setParams settings->c_cflag &= ~CRTSCTS; settings->c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ECHOCTL | ECHOPRT | ECHOKE | ISIG | IEXTEN); - settings->c_iflag &= ~(IXON | IXOFF | IXANY | INPCK | PARMRK | ISTRIP | IGNBRK | BRKINT | INLCR | IGNCR| ICRNL); + settings->c_iflag &= ~(IXON | IXOFF | IXANY | INPCK | IGNPAR | PARMRK | ISTRIP | IGNBRK | BRKINT | INLCR | IGNCR| ICRNL); #ifdef IUCLC settings->c_iflag &= ~IUCLC; #endif settings->c_oflag &= ~OPOST; + //since 2.6.0 -> + if((flags & PARAMS_FLAG_IGNPAR) == PARAMS_FLAG_IGNPAR){ + settings->c_iflag |= IGNPAR; + } + if((flags & PARAMS_FLAG_PARMRK) == PARAMS_FLAG_PARMRK){ + settings->c_iflag |= PARMRK; + } + //<- since 2.6.0 + //since 0.9 -> settings->c_cc[VMIN] = 0; settings->c_cc[VTIME] = 0; @@ -375,7 +421,7 @@ const jint PURGE_TXCLEAR = 0x0004; * PurgeComm */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_purgePort - (JNIEnv *env, jobject object, jint portHandle, jint flags){ + (JNIEnv *env, jobject object, jlong portHandle, jint flags){ int clearValue = -1; if((flags & PURGE_RXCLEAR) && (flags & PURGE_TXCLEAR)){ clearValue = TCIOFLUSH; @@ -398,7 +444,10 @@ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_purgePort /* OK */ /* Closing the port */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_closePort - (JNIEnv *env, jobject object, jint portHandle){ + (JNIEnv *env, jobject object, jlong portHandle){ +#if defined TIOCNXCL //&& !defined __SunOS + ioctl(portHandle, TIOCNXCL);//since 2.1.0 Clear exclusive port access on closing +#endif return close(portHandle) == 0 ? JNI_TRUE : JNI_FALSE; } @@ -407,7 +456,7 @@ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_closePort * Setting events mask */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setEventsMask - (JNIEnv *env, jobject object, jint portHandle, jint mask){ + (JNIEnv *env, jobject object, jlong portHandle, jint mask){ //Don't needed in linux, implemented in java code return JNI_TRUE; } @@ -417,7 +466,7 @@ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setEventsMask * Getting events mask */ JNIEXPORT jint JNICALL Java_jssc_SerialNativeInterface_getEventsMask - (JNIEnv *env, jobject object, jint portHandle){ + (JNIEnv *env, jobject object, jlong portHandle){ //Don't needed in linux, implemented in java code return -1; } @@ -427,7 +476,7 @@ JNIEXPORT jint JNICALL Java_jssc_SerialNativeInterface_getEventsMask * RTS line status changing (ON || OFF) */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setRTS - (JNIEnv *env, jobject object, jint portHandle, jboolean enabled){ + (JNIEnv *env, jobject object, jlong portHandle, jboolean enabled){ int returnValue = 0; int lineStatus; ioctl(portHandle, TIOCMGET, &lineStatus); @@ -446,7 +495,7 @@ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setRTS * DTR line status changing (ON || OFF) */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setDTR - (JNIEnv *env, jobject object, jint portHandle, jboolean enabled){ + (JNIEnv *env, jobject object, jlong portHandle, jboolean enabled){ int returnValue = 0; int lineStatus; ioctl(portHandle, TIOCMGET, &lineStatus); @@ -465,7 +514,7 @@ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setDTR * Writing data to the port */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_writeBytes - (JNIEnv *env, jobject object, jint portHandle, jbyteArray buffer){ + (JNIEnv *env, jobject object, jlong portHandle, jbyteArray buffer){ jbyte* jBuffer = env->GetByteArrayElements(buffer, JNI_FALSE); jint bufferSize = env->GetArrayLength(buffer); jint result = write(portHandle, jBuffer, (size_t)bufferSize); @@ -476,21 +525,27 @@ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_writeBytes /* OK */ /* * Reading data from the port + * + * Rewrited in 2.5.0 (using select() function for correct block reading in MacOS X) */ JNIEXPORT jbyteArray JNICALL Java_jssc_SerialNativeInterface_readBytes - (JNIEnv *env, jobject object, jint portHandle, jint byteCount){ -#ifdef __SunOS - jbyte *lpBuffer = new jbyte[byteCount];//Need for CC compiler - read(portHandle, lpBuffer, byteCount); -#else - jbyte lpBuffer[byteCount]; - read(portHandle, &lpBuffer, byteCount); -#endif + (JNIEnv *env, jobject object, jlong portHandle, jint byteCount){ + fd_set read_fd_set; + jbyte *lpBuffer = new jbyte[byteCount]; + int byteRemains = byteCount; + while(byteRemains > 0) { + FD_ZERO(&read_fd_set); + FD_SET(portHandle, &read_fd_set); + select(portHandle + 1, &read_fd_set, NULL, NULL, NULL); + int result = read(portHandle, lpBuffer + (byteCount - byteRemains), byteRemains); + if(result > 0){ + byteRemains -= result; + } + } + FD_CLR(portHandle, &read_fd_set); jbyteArray returnArray = env->NewByteArray(byteCount); env->SetByteArrayRegion(returnArray, 0, byteCount, lpBuffer); -#ifdef __SunOS - delete(lpBuffer); -#endif + delete lpBuffer; return returnArray; } @@ -499,7 +554,7 @@ JNIEXPORT jbyteArray JNICALL Java_jssc_SerialNativeInterface_readBytes * Get bytes count in serial port buffers (Input and Output) */ JNIEXPORT jintArray JNICALL Java_jssc_SerialNativeInterface_getBuffersBytesCount - (JNIEnv *env, jobject object, jint portHandle){ + (JNIEnv *env, jobject object, jlong portHandle){ jint returnValues[2]; returnValues[0] = -1; //Input buffer returnValues[1] = -1; //Output buffer @@ -521,7 +576,7 @@ const jint FLOWCONTROL_XONXOFF_OUT = 8; * Setting flow control mode */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setFlowControlMode - (JNIEnv *env, jobject object, jint portHandle, jint mask){ + (JNIEnv *env, jobject object, jlong portHandle, jint mask){ jboolean returnValue = JNI_FALSE; termios *settings = new termios(); if(tcgetattr(portHandle, settings) == 0){ @@ -551,7 +606,7 @@ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setFlowControlMode * Getting flow control mode */ JNIEXPORT jint JNICALL Java_jssc_SerialNativeInterface_getFlowControlMode - (JNIEnv *env, jobject object, jint portHandle){ + (JNIEnv *env, jobject object, jlong portHandle){ jint returnValue = 0; termios *settings = new termios(); if(tcgetattr(portHandle, settings) == 0){ @@ -573,7 +628,7 @@ JNIEXPORT jint JNICALL Java_jssc_SerialNativeInterface_getFlowControlMode * Send break for setted duration */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_sendBreak - (JNIEnv *env, jobject object, jint portHandle, jint duration){ + (JNIEnv *env, jobject object, jlong portHandle, jint duration){ jboolean returnValue = JNI_FALSE; if(duration > 0){ if(ioctl(portHandle, TIOCSBRK, 0) >= 0){ @@ -597,7 +652,7 @@ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_sendBreak * Return "statusLines" from ioctl(portHandle, TIOCMGET, &statusLines) * Need for "_waitEvents" and "_getLinesStatus" */ -int getLinesStatus(jint portHandle) { +int getLinesStatus(jlong portHandle) { int statusLines; ioctl(portHandle, TIOCMGET, &statusLines); return statusLines; @@ -615,7 +670,7 @@ int getLinesStatus(jint portHandle) { * 3 - Overrun * 4 - Parity */ -void getInterruptsCount(jint portHandle, int intArray[]) { +void getInterruptsCount(jlong portHandle, int intArray[]) { #ifdef TIOCGICOUNT struct serial_icounter_struct *icount = new serial_icounter_struct(); if(ioctl(portHandle, TIOCGICOUNT, icount) >= 0){ @@ -661,7 +716,7 @@ const jint events[] = {INTERRUPT_BREAK, * */ JNIEXPORT jobjectArray JNICALL Java_jssc_SerialNativeInterface_waitEvents - (JNIEnv *env, jobject object, jint portHandle) { + (JNIEnv *env, jobject object, jlong portHandle) { jclass intClass = env->FindClass("[I"); jobjectArray returnArray = env->NewObjectArray(sizeof(events)/sizeof(jint), intClass, NULL); @@ -784,7 +839,7 @@ JNIEXPORT jobjectArray JNICALL Java_jssc_SerialNativeInterface_getSerialPortName * returnValues[3] - RLSD(DCD) */ JNIEXPORT jintArray JNICALL Java_jssc_SerialNativeInterface_getLinesStatus - (JNIEnv *env, jobject object, jint portHandle){ + (JNIEnv *env, jobject object, jlong portHandle){ jint returnValues[4]; for(jint i = 0; i < 4; i++){ returnValues[i] = 0; diff --git a/src/cpp/jssc_SerialNativeInterface.h b/src/cpp/jssc_SerialNativeInterface.h index 259da6749..7029b1bbe 100644 --- a/src/cpp/jssc_SerialNativeInterface.h +++ b/src/cpp/jssc_SerialNativeInterface.h @@ -1,5 +1,5 @@ /* jSSC (Java Simple Serial Connector) - serial port communication library. - * © Alexey Sokolov (scream3r), 2010-2011. + * © Alexey Sokolov (scream3r), 2010-2014. * * This file is part of jSSC. * @@ -31,6 +31,10 @@ #ifdef __cplusplus extern "C" { #endif + +#undef jSSC_NATIVE_LIB_VERSION +#define jSSC_NATIVE_LIB_VERSION "2.8" + #undef jssc_SerialNativeInterface_OS_LINUX #define jssc_SerialNativeInterface_OS_LINUX 0L #undef jssc_SerialNativeInterface_OS_WINDOWS @@ -39,117 +43,133 @@ extern "C" { #define jssc_SerialNativeInterface_OS_SOLARIS 2L #undef jssc_SerialNativeInterface_OS_MAC_OS_X #define jssc_SerialNativeInterface_OS_MAC_OS_X 3L +#undef jssc_SerialNativeInterface_ERR_PORT_BUSY +#define jssc_SerialNativeInterface_ERR_PORT_BUSY -1LL +#undef jssc_SerialNativeInterface_ERR_PORT_NOT_FOUND +#define jssc_SerialNativeInterface_ERR_PORT_NOT_FOUND -2LL +#undef jssc_SerialNativeInterface_ERR_PERMISSION_DENIED +#define jssc_SerialNativeInterface_ERR_PERMISSION_DENIED -3LL +#undef jssc_SerialNativeInterface_ERR_INCORRECT_SERIAL_PORT +#define jssc_SerialNativeInterface_ERR_INCORRECT_SERIAL_PORT -4LL +/* + * Class: jssc_SerialNativeInterface + * Method: getNativeLibraryVersion + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_jssc_SerialNativeInterface_getNativeLibraryVersion + (JNIEnv *, jobject); + /* * Class: jssc_SerialNativeInterface * Method: openPort - * Signature: (Ljava/lang/String;)I + * Signature: (Ljava/lang/String;Z)J */ -JNIEXPORT jint JNICALL Java_jssc_SerialNativeInterface_openPort - (JNIEnv *, jobject, jstring); +JNIEXPORT jlong JNICALL Java_jssc_SerialNativeInterface_openPort + (JNIEnv *, jobject, jstring, jboolean); /* * Class: jssc_SerialNativeInterface * Method: setParams - * Signature: (IIIIIZZ)Z + * Signature: (JIIIIZZI)Z */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setParams - (JNIEnv *, jobject, jint, jint, jint, jint, jint, jboolean, jboolean); + (JNIEnv *, jobject, jlong, jint, jint, jint, jint, jboolean, jboolean, jint); /* * Class: jssc_SerialNativeInterface * Method: purgePort - * Signature: (II)Z + * Signature: (JI)Z */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_purgePort - (JNIEnv *, jobject, jint, jint); + (JNIEnv *, jobject, jlong, jint); /* * Class: jssc_SerialNativeInterface * Method: closePort - * Signature: (I)Z + * Signature: (J)Z */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_closePort - (JNIEnv *, jobject, jint); + (JNIEnv *, jobject, jlong); /* * Class: jssc_SerialNativeInterface * Method: setEventsMask - * Signature: (II)Z + * Signature: (JI)Z */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setEventsMask - (JNIEnv *, jobject, jint, jint); + (JNIEnv *, jobject, jlong, jint); /* * Class: jssc_SerialNativeInterface * Method: getEventsMask - * Signature: (I)I + * Signature: (J)I */ JNIEXPORT jint JNICALL Java_jssc_SerialNativeInterface_getEventsMask - (JNIEnv *, jobject, jint); + (JNIEnv *, jobject, jlong); /* * Class: jssc_SerialNativeInterface * Method: waitEvents - * Signature: (I)[[I + * Signature: (J)[[I */ JNIEXPORT jobjectArray JNICALL Java_jssc_SerialNativeInterface_waitEvents - (JNIEnv *, jobject, jint); + (JNIEnv *, jobject, jlong); /* * Class: jssc_SerialNativeInterface * Method: setRTS - * Signature: (IZ)Z + * Signature: (JZ)Z */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setRTS - (JNIEnv *, jobject, jint, jboolean); + (JNIEnv *, jobject, jlong, jboolean); /* * Class: jssc_SerialNativeInterface * Method: setDTR - * Signature: (IZ)Z + * Signature: (JZ)Z */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setDTR - (JNIEnv *, jobject, jint, jboolean); + (JNIEnv *, jobject, jlong, jboolean); /* * Class: jssc_SerialNativeInterface * Method: readBytes - * Signature: (II)[B + * Signature: (JI)[B */ JNIEXPORT jbyteArray JNICALL Java_jssc_SerialNativeInterface_readBytes - (JNIEnv *, jobject, jint, jint); + (JNIEnv *, jobject, jlong, jint); /* * Class: jssc_SerialNativeInterface * Method: writeBytes - * Signature: (I[B)Z + * Signature: (J[B)Z */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_writeBytes - (JNIEnv *, jobject, jint, jbyteArray); + (JNIEnv *, jobject, jlong, jbyteArray); /* * Class: jssc_SerialNativeInterface * Method: getBuffersBytesCount - * Signature: (I)[I + * Signature: (J)[I */ JNIEXPORT jintArray JNICALL Java_jssc_SerialNativeInterface_getBuffersBytesCount - (JNIEnv *, jobject, jint); + (JNIEnv *, jobject, jlong); /* * Class: jssc_SerialNativeInterface * Method: setFlowControlMode - * Signature: (II)Z + * Signature: (JI)Z */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setFlowControlMode - (JNIEnv *, jobject, jint, jint); + (JNIEnv *, jobject, jlong, jint); /* * Class: jssc_SerialNativeInterface * Method: getFlowControlMode - * Signature: (I)I + * Signature: (J)I */ JNIEXPORT jint JNICALL Java_jssc_SerialNativeInterface_getFlowControlMode - (JNIEnv *, jobject, jint); + (JNIEnv *, jobject, jlong); /* * Class: jssc_SerialNativeInterface @@ -162,18 +182,18 @@ JNIEXPORT jobjectArray JNICALL Java_jssc_SerialNativeInterface_getSerialPortName /* * Class: jssc_SerialNativeInterface * Method: getLinesStatus - * Signature: (I)[I + * Signature: (J)[I */ JNIEXPORT jintArray JNICALL Java_jssc_SerialNativeInterface_getLinesStatus - (JNIEnv *, jobject, jint); + (JNIEnv *, jobject, jlong); /* * Class: jssc_SerialNativeInterface * Method: sendBreak - * Signature: (II)Z + * Signature: (JI)Z */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_sendBreak - (JNIEnv *, jobject, jint, jint); + (JNIEnv *, jobject, jlong, jint); #ifdef __cplusplus } diff --git a/src/cpp/windows/jssc.c++ b/src/cpp/windows/jssc.c++ index ba1c2cf47..08428ded3 100644 --- a/src/cpp/windows/jssc.c++ +++ b/src/cpp/windows/jssc.c++ @@ -1,5 +1,5 @@ /* jSSC (Java Simple Serial Connector) - serial port communication library. - * © Alexey Sokolov (scream3r), 2010-2011. + * © Alexey Sokolov (scream3r), 2010-2014. * * This file is part of jSSC. * @@ -25,47 +25,70 @@ #include #include #include -#include "jssc_SerialNativeInterface.h" +#include "../jssc_SerialNativeInterface.h" + +//#include + +/* + * Get native library version + */ +JNIEXPORT jstring JNICALL Java_jssc_SerialNativeInterface_getNativeLibraryVersion(JNIEnv *env, jobject object) { + return env->NewStringUTF(jSSC_NATIVE_LIB_VERSION); +} /* * Port opening. + * + * In 2.2.0 added useTIOCEXCL (not used in Windows, only for compatibility with _nix version) */ -JNIEXPORT jint JNICALL Java_jssc_SerialNativeInterface_openPort(JNIEnv *env, jobject object, jstring portName){ +JNIEXPORT jlong JNICALL Java_jssc_SerialNativeInterface_openPort(JNIEnv *env, jobject object, jstring portName, jboolean useTIOCEXCL){ char prefix[] = "\\\\.\\"; const char* port = env->GetStringUTFChars(portName, JNI_FALSE); - strcat(prefix, port); - HANDLE hComm; - hComm = CreateFile(prefix, - GENERIC_READ | GENERIC_WRITE, - 0, - 0, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, - 0); + + //since 2.1.0 -> string concat fix + char portFullName[strlen(prefix) + strlen(port) + 1]; + strcpy(portFullName, prefix); + strcat(portFullName, port); + //<- since 2.1.0 + + HANDLE hComm = CreateFile(portFullName, + GENERIC_READ | GENERIC_WRITE, + 0, + 0, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, + 0); env->ReleaseStringUTFChars(portName, port); - //since 0.9 -> - if(hComm == INVALID_HANDLE_VALUE){ + + //since 2.3.0 -> + if(hComm != INVALID_HANDLE_VALUE){ + DCB *dcb = new DCB(); + if(!GetCommState(hComm, dcb)){ + CloseHandle(hComm);//since 2.7.0 + hComm = (HANDLE)jssc_SerialNativeInterface_ERR_INCORRECT_SERIAL_PORT;//(-4)Incorrect serial port + } + delete dcb; + } + else { DWORD errorValue = GetLastError(); if(errorValue == ERROR_ACCESS_DENIED){ - hComm = (HANDLE)-1;//Port busy + hComm = (HANDLE)jssc_SerialNativeInterface_ERR_PORT_BUSY;//(-1)Port busy } else if(errorValue == ERROR_FILE_NOT_FOUND){ - hComm = (HANDLE)-2;//Port not found + hComm = (HANDLE)jssc_SerialNativeInterface_ERR_PORT_NOT_FOUND;//(-2)Port not found } } - //<- since 0.9 -#if defined(_X86_) - return (jint)hComm; -#elif defined(__x86_64) - return (intptr_t)hComm; -#endif + //<- since 2.3.0 + return (jlong)hComm;//since 2.4.0 changed to jlong }; /* * Setting serial port params. + * + * In 2.6.0 added flags (not used in Windows, only for compatibility with _nix version) */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setParams - (JNIEnv *env, jobject object, jint portHandle, jint baudRate, jint byteSize, jint stopBits, jint parity, jboolean setRTS, jboolean setDTR){ + (JNIEnv *env, jobject object, jlong portHandle, jint baudRate, jint byteSize, jint stopBits, jint parity, jboolean setRTS, jboolean setDTR, jint flags){ HANDLE hComm = (HANDLE)portHandle; DCB *dcb = new DCB(); jboolean returnValue = JNI_FALSE; @@ -104,7 +127,19 @@ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setParams //<- since 0.8 if(SetCommState(hComm, dcb)){ - returnValue = JNI_TRUE; + + //since 2.1.0 -> previously setted timeouts by another application should be cleared + COMMTIMEOUTS *lpCommTimeouts = new COMMTIMEOUTS(); + lpCommTimeouts->ReadIntervalTimeout = 0; + lpCommTimeouts->ReadTotalTimeoutConstant = 0; + lpCommTimeouts->ReadTotalTimeoutMultiplier = 0; + lpCommTimeouts->WriteTotalTimeoutConstant = 0; + lpCommTimeouts->WriteTotalTimeoutMultiplier = 0; + if(SetCommTimeouts(hComm, lpCommTimeouts)){ + returnValue = JNI_TRUE; + } + delete lpCommTimeouts; + //<- since 2.1.0 } } delete dcb; @@ -115,7 +150,7 @@ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setParams * PurgeComm */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_purgePort - (JNIEnv *env, jobject object, jint portHandle, jint flags){ + (JNIEnv *env, jobject object, jlong portHandle, jint flags){ HANDLE hComm = (HANDLE)portHandle; DWORD dwFlags = (DWORD)flags; return (PurgeComm(hComm, dwFlags) ? JNI_TRUE : JNI_FALSE); @@ -125,7 +160,7 @@ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_purgePort * Port closing */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_closePort - (JNIEnv *env, jobject object, jint portHandle){ + (JNIEnv *env, jobject object, jlong portHandle){ HANDLE hComm = (HANDLE)portHandle; return (CloseHandle(hComm) ? JNI_TRUE : JNI_FALSE); } @@ -134,7 +169,7 @@ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_closePort * Set events mask */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setEventsMask - (JNIEnv *env, jobject object, jint portHandle, jint mask){ + (JNIEnv *env, jobject object, jlong portHandle, jint mask){ HANDLE hComm = (HANDLE)portHandle; DWORD dwEvtMask = (DWORD)mask; return (SetCommMask(hComm, dwEvtMask) ? JNI_TRUE : JNI_FALSE); @@ -144,7 +179,7 @@ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setEventsMask * Get events mask */ JNIEXPORT jint JNICALL Java_jssc_SerialNativeInterface_getEventsMask - (JNIEnv *env, jobject object, jint portHandle){ + (JNIEnv *env, jobject object, jlong portHandle){ HANDLE hComm = (HANDLE)portHandle; DWORD lpEvtMask; if(GetCommMask(hComm, &lpEvtMask)){ @@ -159,7 +194,7 @@ JNIEXPORT jint JNICALL Java_jssc_SerialNativeInterface_getEventsMask * Change RTS line state (ON || OFF) */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setRTS - (JNIEnv *env, jobject object, jint portHandle, jboolean enabled){ + (JNIEnv *env, jobject object, jlong portHandle, jboolean enabled){ HANDLE hComm = (HANDLE)portHandle; if(enabled == JNI_TRUE){ return (EscapeCommFunction(hComm, SETRTS) ? JNI_TRUE : JNI_FALSE); @@ -173,7 +208,7 @@ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setRTS * Change DTR line state (ON || OFF) */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setDTR - (JNIEnv *env, jobject object, jint portHandle, jboolean enabled){ + (JNIEnv *env, jobject object, jlong portHandle, jboolean enabled){ HANDLE hComm = (HANDLE)portHandle; if(enabled == JNI_TRUE){ return (EscapeCommFunction(hComm, SETDTR) ? JNI_TRUE : JNI_FALSE); @@ -189,7 +224,7 @@ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setDTR * buffer - byte array for sending */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_writeBytes - (JNIEnv *env, jobject object, jint portHandle, jbyteArray buffer){ + (JNIEnv *env, jobject object, jlong portHandle, jbyteArray buffer){ HANDLE hComm = (HANDLE)portHandle; DWORD lpNumberOfBytesTransferred; DWORD lpNumberOfBytesWritten; @@ -219,7 +254,7 @@ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_writeBytes * byteCount - count of bytes for reading */ JNIEXPORT jbyteArray JNICALL Java_jssc_SerialNativeInterface_readBytes - (JNIEnv *env, jobject object, jint portHandle, jint byteCount){ + (JNIEnv *env, jobject object, jlong portHandle, jint byteCount){ HANDLE hComm = (HANDLE)portHandle; DWORD lpNumberOfBytesTransferred; DWORD lpNumberOfBytesRead; @@ -246,7 +281,7 @@ JNIEXPORT jbyteArray JNICALL Java_jssc_SerialNativeInterface_readBytes * Get bytes count in serial port buffers (Input and Output) */ JNIEXPORT jintArray JNICALL Java_jssc_SerialNativeInterface_getBuffersBytesCount - (JNIEnv *env, jobject object, jint portHandle){ + (JNIEnv *env, jobject object, jlong portHandle){ HANDLE hComm = (HANDLE)portHandle; jint returnValues[2]; returnValues[0] = -1; @@ -281,7 +316,7 @@ const jint FLOWCONTROL_XONXOFF_OUT = 8; * since 0.8 */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setFlowControlMode - (JNIEnv *env, jobject object, jint portHandle, jint mask){ + (JNIEnv *env, jobject object, jlong portHandle, jint mask){ HANDLE hComm = (HANDLE)portHandle; jboolean returnValue = JNI_FALSE; DCB *dcb = new DCB(); @@ -318,7 +353,7 @@ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_setFlowControlMode * since 0.8 */ JNIEXPORT jint JNICALL Java_jssc_SerialNativeInterface_getFlowControlMode - (JNIEnv *env, jobject object, jint portHandle){ + (JNIEnv *env, jobject object, jlong portHandle){ HANDLE hComm = (HANDLE)portHandle; jint returnValue = 0; DCB *dcb = new DCB(); @@ -346,7 +381,7 @@ JNIEXPORT jint JNICALL Java_jssc_SerialNativeInterface_getFlowControlMode * since 0.8 */ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_sendBreak - (JNIEnv *env, jobject object, jint portHandle, jint duration){ + (JNIEnv *env, jobject object, jlong portHandle, jint duration){ HANDLE hComm = (HANDLE)portHandle; jboolean returnValue = JNI_FALSE; if(duration > 0){ @@ -365,7 +400,7 @@ JNIEXPORT jboolean JNICALL Java_jssc_SerialNativeInterface_sendBreak * portHandle - port handle */ JNIEXPORT jobjectArray JNICALL Java_jssc_SerialNativeInterface_waitEvents - (JNIEnv *env, jobject object, jint portHandle) { + (JNIEnv *env, jobject object, jlong portHandle) { HANDLE hComm = (HANDLE)portHandle; DWORD lpEvtMask = 0; DWORD lpNumberOfBytesTransferred = 0; @@ -631,7 +666,7 @@ JNIEXPORT jobjectArray JNICALL Java_jssc_SerialNativeInterface_getSerialPortName * */ JNIEXPORT jintArray JNICALL Java_jssc_SerialNativeInterface_getLinesStatus - (JNIEnv *env, jobject object, jint portHandle){ + (JNIEnv *env, jobject object, jlong portHandle){ HANDLE hComm = (HANDLE)portHandle; DWORD lpModemStat; jint returnValues[4]; diff --git a/src/java/jssc/SerialNativeInterface.java b/src/java/jssc/SerialNativeInterface.java index 2dcfbce7c..c5264f5e8 100644 --- a/src/java/jssc/SerialNativeInterface.java +++ b/src/java/jssc/SerialNativeInterface.java @@ -1,5 +1,5 @@ /* jSSC (Java Simple Serial Connector) - serial port communication library. - * © Alexey Sokolov (scream3r), 2010-2011. + * © Alexey Sokolov (scream3r), 2010-2014. * * This file is part of jSSC. * @@ -24,9 +24,11 @@ */ package jssc; +import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; +import java.io.InputStreamReader; /** * @@ -34,7 +36,7 @@ */ public class SerialNativeInterface { - private static final String libVersion = "0.9"; //jSSC-0.9.0 Release from 21.12.2011 + 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; @@ -44,6 +46,36 @@ public class SerialNativeInterface { 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; @@ -52,6 +84,13 @@ public class SerialNativeInterface { 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"; @@ -65,7 +104,7 @@ else if(osName.equals("SunOS")){ osName = "solaris"; osType = OS_SOLARIS; } - else if(osName.equals("Mac OS X")){ + 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 @@ -73,14 +112,42 @@ else if(osName.equals("Mac OS X")){ if(architecture.equals("i386") || architecture.equals("i686")){ architecture = "x86"; } - else if(architecture.equals("amd64")){ + 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 = userHome + fileSeparator + ".jssc" + fileSeparator + osName; + 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)){ @@ -101,8 +168,13 @@ else if(architecture.equals("amd64")){ } } - if(loadLib){ + 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 + ")"); + } } } @@ -222,14 +294,24 @@ 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 int openPort(String portName); + public native long openPort(String portName, boolean useTIOCEXCL); /** * Setting the parameters of opened port @@ -241,10 +323,11 @@ public static String getLibraryMinorSuffix() { * @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(int handle, int baudRate, int dataBits, int stopBits, int parity, boolean setRTS, boolean setDTR); + 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 @@ -254,7 +337,7 @@ public static String getLibraryMinorSuffix() { * * @return If the operation is successfully completed, the method returns true, otherwise false */ - public native boolean purgePort(int handle, int flags); + public native boolean purgePort(long handle, int flags); /** * Close port @@ -263,7 +346,7 @@ public static String getLibraryMinorSuffix() { * * @return If the operation is successfully completed, the method returns true, otherwise false */ - public native boolean closePort(int handle); + public native boolean closePort(long handle); /** * Set events mask @@ -273,7 +356,7 @@ public static String getLibraryMinorSuffix() { * * @return If the operation is successfully completed, the method returns true, otherwise false */ - public native boolean setEventsMask(int handle, int mask); + public native boolean setEventsMask(long handle, int mask); /** * Get events mask @@ -282,7 +365,7 @@ public static String getLibraryMinorSuffix() { * * @return Method returns event mask as a variable of int type */ - public native int getEventsMask(int handle); + public native int getEventsMask(long handle); /** * Wait events @@ -292,7 +375,7 @@ public static String getLibraryMinorSuffix() { * @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(int handle); + public native int[][] waitEvents(long handle); /** * Change RTS line state @@ -302,7 +385,7 @@ public static String getLibraryMinorSuffix() { * * @return If the operation is successfully completed, the method returns true, otherwise false */ - public native boolean setRTS(int handle, boolean value); + public native boolean setRTS(long handle, boolean value); /** * Change DTR line state @@ -312,7 +395,7 @@ public static String getLibraryMinorSuffix() { * * @return If the operation is successfully completed, the method returns true, otherwise false */ - public native boolean setDTR(int handle, boolean value); + public native boolean setDTR(long handle, boolean value); /** * Read data from port @@ -322,7 +405,7 @@ public static String getLibraryMinorSuffix() { * * @return Method returns the array of read bytes */ - public native byte[] readBytes(int handle, int byteCount); + public native byte[] readBytes(long handle, int byteCount); /** * Write data to port @@ -332,7 +415,7 @@ public static String getLibraryMinorSuffix() { * * @return If the operation is successfully completed, the method returns true, otherwise false */ - public native boolean writeBytes(int handle, byte[] buffer); + public native boolean writeBytes(long handle, byte[] buffer); /** * Get bytes count in buffers of port @@ -345,7 +428,7 @@ public static String getLibraryMinorSuffix() { * * @since 0.8 */ - public native int[] getBuffersBytesCount(int handle); + public native int[] getBuffersBytesCount(long handle); /** * Set flow control mode @@ -357,7 +440,7 @@ public static String getLibraryMinorSuffix() { * * @since 0.8 */ - public native boolean setFlowControlMode(int handle, int mask); + public native boolean setFlowControlMode(long handle, int mask); /** * Get flow control mode @@ -368,7 +451,7 @@ public static String getLibraryMinorSuffix() { * * @since 0.8 */ - public native int getFlowControlMode(int handle); + public native int getFlowControlMode(long handle); /** * Get serial port names like an array of String @@ -388,7 +471,7 @@ public static String getLibraryMinorSuffix() { *
element 2 - RING line state
*
element 3 - RLSD line state
*/ - public native int[] getLinesStatus(int handle); + public native int[] getLinesStatus(long handle); /** * Send Break singnal for setted duration @@ -399,5 +482,5 @@ public static String getLibraryMinorSuffix() { * * @since 0.8 */ - public native boolean sendBreak(int handle, int duration); + public native boolean sendBreak(long handle, int duration); } diff --git a/src/java/jssc/SerialPort.java b/src/java/jssc/SerialPort.java index 6985f7662..e5f43b402 100644 --- a/src/java/jssc/SerialPort.java +++ b/src/java/jssc/SerialPort.java @@ -1,5 +1,5 @@ /* jSSC (Java Simple Serial Connector) - serial port communication library. - * © Alexey Sokolov (scream3r), 2010-2011. + * © Alexey Sokolov (scream3r), 2010-2014. * * This file is part of jSSC. * @@ -24,6 +24,10 @@ */ package jssc; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Method; +import java.nio.charset.Charset; + /** * * @author scream3r @@ -32,13 +36,16 @@ public class SerialPort { private SerialNativeInterface serialInterface; private SerialPortEventListener eventListener; - private int portHandle; + 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; @@ -103,6 +110,11 @@ public class SerialPort { 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) { this.portName = portName; serialInterface = new SerialNativeInterface(); @@ -140,15 +152,26 @@ public boolean openPort() throws SerialPortException { if(portOpened){ throw new SerialPortException(portName, "openPort()", SerialPortException.TYPE_PORT_ALREADY_OPENED); } - portHandle = serialInterface.openPort(portName); - //since 0.9.0 -> - if(portHandle == -1){ + 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 == -2){ + else if(portHandle == SerialNativeInterface.ERR_PORT_NOT_FOUND){ throw new SerialPortException(portName, "openPort()", SerialPortException.TYPE_PORT_NOT_FOUND); } - //<- since 0.9.0 + 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; } @@ -166,14 +189,7 @@ else if(portHandle == -2){ * @throws SerialPortException */ public boolean setParams(int baudRate, int dataBits, int stopBits, int parity) throws SerialPortException { - checkPortOpened("setParams()"); - if(stopBits == 1){ - stopBits = 0; - } - else if(stopBits == 3){ - stopBits = 1; - } - return serialInterface.setParams(portHandle, baudRate, dataBits, stopBits, parity, true, true); + return setParams(baudRate, dataBits, stopBits, parity, true, true); } /** @@ -200,7 +216,14 @@ public boolean setParams(int baudRate, int dataBits, int stopBits, int parity, b else if(stopBits == 3){ stopBits = 1; } - return serialInterface.setParams(portHandle, baudRate, dataBits, stopBits, parity, setRTS, setDTR); + 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); } /** @@ -354,6 +377,20 @@ public boolean writeString(String string) throws SerialPortException { 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 * @@ -417,7 +454,7 @@ public String readString(int byteCount) throws SerialPortException { } /** - * Read Hex string from port (example: FF OA FF). Separator by default is a space + * Read Hex string from port (example: FF 0A FF). Separator by default is a space * * @param byteCount count of bytes for reading * @@ -433,7 +470,7 @@ public String readHexString(int byteCount) throws SerialPortException { } /** - * Read Hex string from port with setted separator (example if separator is "::": FF::OA::FF) + * Read Hex string from port with setted separator (example if separator is "::": FF::0A::FF) * * @param byteCount count of bytes for reading * @@ -509,6 +546,141 @@ public int[] readIntArray(int byteCount) throws SerialPortException { 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 { + checkPortOpened("readBytes()"); + waitBytesWithTimeout("readBytes()", byteCount, timeout); + return readBytes(byteCount); + } + + /** + * 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 * @@ -609,7 +781,7 @@ public String[] readHexStringArray() throws SerialPortException { * @since 0.8 */ public int[] readIntArray() throws SerialPortException { - checkPortOpened("readHex()"); + checkPortOpened("readIntArray()"); int byteCount = getInputBufferBytesCount(); if(byteCount <= 0){ return null; @@ -800,27 +972,7 @@ public boolean isRLSD() throws SerialPortException { * @throws SerialPortException */ public void addEventListener(SerialPortEventListener listener) throws SerialPortException { - checkPortOpened("addEventListener()"); - if(!eventListenerAdded){ - if(maskAssigned){ - eventListener = listener; - eventThread = getNewEventThread(); - eventThread.setName("EventThread " + portName); - eventThread.start(); - eventListenerAdded = true; - } - else { - setEventsMask(MASK_RXCHAR); - eventListener = listener; - eventThread = getNewEventThread(); - eventThread.setName("EventThread " + portName); - eventThread.start(); - eventListenerAdded = true; - } - } - else { - throw new SerialPortException(portName, "addEventListener()", SerialPortException.TYPE_LISTENER_ALREADY_ADDED); - } + addEventListener(listener, MASK_RXCHAR, false); } /** @@ -834,12 +986,45 @@ public void addEventListener(SerialPortEventListener listener) throws SerialPort * @throws SerialPortException */ public void addEventListener(SerialPortEventListener listener, int mask) throws SerialPortException { + 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){ - setEventsMask(mask); + 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; } @@ -887,6 +1072,7 @@ public boolean removeEventListener() throws SerialPortException { } } } + methodErrorOccurred = null; eventListenerAdded = false; return true; } @@ -924,6 +1110,15 @@ public void run() { 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); + } + }*/ } } } diff --git a/src/java/jssc/SerialPortEvent.java b/src/java/jssc/SerialPortEvent.java index 19f69aec3..01ec73243 100644 --- a/src/java/jssc/SerialPortEvent.java +++ b/src/java/jssc/SerialPortEvent.java @@ -1,5 +1,5 @@ /* jSSC (Java Simple Serial Connector) - serial port communication library. - * © Alexey Sokolov (scream3r), 2010-2011. + * © Alexey Sokolov (scream3r), 2010-2014. * * This file is part of jSSC. * diff --git a/src/java/jssc/SerialPortEventListener.java b/src/java/jssc/SerialPortEventListener.java index d7214e778..9a2441aa8 100644 --- a/src/java/jssc/SerialPortEventListener.java +++ b/src/java/jssc/SerialPortEventListener.java @@ -1,5 +1,5 @@ /* jSSC (Java Simple Serial Connector) - serial port communication library. - * © Alexey Sokolov (scream3r), 2010-2011. + * © Alexey Sokolov (scream3r), 2010-2014. * * This file is part of jSSC. * diff --git a/src/java/jssc/SerialPortException.java b/src/java/jssc/SerialPortException.java index 0d1c1000a..18aca2f93 100644 --- a/src/java/jssc/SerialPortException.java +++ b/src/java/jssc/SerialPortException.java @@ -1,5 +1,5 @@ /* jSSC (Java Simple Serial Connector) - serial port communication library. - * © Alexey Sokolov (scream3r), 2010-2011. + * © Alexey Sokolov (scream3r), 2010-2014. * * This file is part of jSSC. * @@ -52,6 +52,14 @@ public class SerialPortException extends Exception { * @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; diff --git a/src/java/jssc/SerialPortList.java b/src/java/jssc/SerialPortList.java index 513181cf5..5af9a95ea 100644 --- a/src/java/jssc/SerialPortList.java +++ b/src/java/jssc/SerialPortList.java @@ -1,5 +1,5 @@ /* jSSC (Java Simple Serial Connector) - serial port communication library. - * © Alexey Sokolov (scream3r), 2010-2011. + * © Alexey Sokolov (scream3r), 2010-2014. * * This file is part of jSSC. * @@ -24,14 +24,10 @@ */ package jssc; -import java.io.BufferedReader; import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Comparator; import java.util.TreeSet; +import java.util.regex.Pattern; /** * @@ -40,153 +36,311 @@ public class SerialPortList { private static SerialNativeInterface serialInterface; - private static Comparator comparator = new Comparator() { + 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) { - int result = 0; - if(valueA.toLowerCase().contains("com") && valueB.toLowerCase().contains("com")){ - try { - int index1 = Integer.valueOf(valueA.toLowerCase().replace("com", "")); - int index2 = Integer.valueOf(valueB.toLowerCase().replace("com", "")); - result = index1 - index2; + + 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; } - catch (Exception ex) { - result = valueA.compareToIgnoreCase(valueB); + else { + break; } - } - else { - result = valueA.compareToIgnoreCase(valueB); } - return result; + try { + returnValues[0] = Integer.valueOf(numberValue); + } + catch (Exception ex) { + //Do nothing + } + return returnValues; } }; - - static { - serialInterface = new SerialNativeInterface(); - } - + //<-since 2.1.0 + /** - * Get sorted array of serial ports in the system + * 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() { - if(SerialNativeInterface.getOsType() == SerialNativeInterface.OS_LINUX){ - return getLinuxPortNames(); - } - else if(SerialNativeInterface.getOsType() == SerialNativeInterface.OS_SOLARIS){//since 0.9.0 -> - return getSolarisPortNames(); - } - else if(SerialNativeInterface.getOsType() == SerialNativeInterface.OS_MAC_OS_X){ - return getMacOSXPortNames(); - }//<-since 0.9.0 - String[] portNames = serialInterface.getSerialPortNames(); - if(portNames == null){ - return new String[]{}; - } - TreeSet ports = new TreeSet(comparator); - ports.addAll(Arrays.asList(portNames)); - return ports.toArray(new String[ports.size()]); + 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 serial port names in Linux OS (This method was completely rewrited in 0.8-tb4) + * Get sorted array of serial ports in the system matched pattern + * + * @param pattern RegExp pattern for matching port names (not null) * - * @return + * @return String array. If there is no ports in the system String[] + * + * @since 2.3.0 */ - private static String[] getLinuxPortNames() { - String[] returnArray = new String[]{}; - try { - Process dmesgProcess = Runtime.getRuntime().exec("dmesg"); - BufferedReader reader = new BufferedReader(new InputStreamReader(dmesgProcess.getInputStream())); - TreeSet portsTree = new TreeSet(); - ArrayList portsList = new ArrayList(); - String buffer = ""; - while((buffer = reader.readLine()) != null && !buffer.isEmpty()){ - if(buffer.matches(".*(ttyS|ttyUSB)[0-9]{1,3}.*")){ - String[] tmp = buffer.split(" "); - for(String value : tmp){ - if(value.matches("(ttyS|ttyUSB)[0-9]{1,3}")){ - portsTree.add("/dev/" + value); - } - } - } - } - for(String portName : portsTree){ - SerialPort serialPort = new SerialPort(portName); - try { - if(serialPort.openPort()){ - portsList.add(portName); - serialPort.closePort(); - } - } - catch (SerialPortException ex) { - //since 0.9.0 -> - if(ex.getExceptionType().equals(SerialPortException.TYPE_PORT_BUSY)){ - portsList.add(portName); - } - //<- since 0.9.0 - } - } - returnArray = portsList.toArray(returnArray); - reader.close(); + 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[]{}; } - catch (IOException ex) { - //Do nothing + if(SerialNativeInterface.getOsType() == SerialNativeInterface.OS_WINDOWS){ + return getWindowsPortNames(pattern, comparator); } - return returnArray; + return getUnixBasedPortNames(searchPath, pattern, comparator); } /** - * Get serial port names in Solaris OS + * Get serial port names in Windows * - * @since 0.9.0 + * @since 2.3.0 */ - private static String[] getSolarisPortNames() { - String[] returnArray = new String[]{}; - File dir = new File("/dev/term"); - if(dir.exists() && dir.isDirectory()){ - File[] files = dir.listFiles(); - if(files.length > 0){ - TreeSet portsTree = new TreeSet(); - ArrayList portsList = new ArrayList(); - for(File file : files){ - if(!file.isDirectory() && !file.isFile() && file.getName().matches("[0-9]*|[a-z]*")){ - portsTree.add("/dev/term/" + file.getName()); - } - } - for(String portName : portsTree){ - portsList.add(portName); - } - returnArray = portsList.toArray(returnArray); + 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 returnArray; + return ports.toArray(new String[ports.size()]); } /** - * Get serial port names in Mac OS X - * - * @since 0.9.0 + * Universal method for getting port names of _nix based systems */ - private static String[] getMacOSXPortNames() { + 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("/dev"); + File dir = new File(searchPath); if(dir.exists() && dir.isDirectory()){ File[] files = dir.listFiles(); if(files.length > 0){ - TreeSet portsTree = new TreeSet(); - ArrayList portsList = new ArrayList(); + TreeSet portsTree = new TreeSet(comparator); for(File file : files){ - if(!file.isDirectory() && !file.isFile() && file.getName().matches("tty.(serial.*|usbserial.*)")){ - portsTree.add("/dev/" + file.getName()); + 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); } } - for(String portName : portsTree){ - portsList.add(portName); - } - returnArray = portsList.toArray(returnArray); + returnArray = portsTree.toArray(returnArray); } } return returnArray; diff --git a/src/java/jssc/SerialPortTimeoutException.java b/src/java/jssc/SerialPortTimeoutException.java new file mode 100644 index 000000000..802535c3a --- /dev/null +++ b/src/java/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; + } +} diff --git a/src/java/libs/linux/libjSSC-0.9_x86.so b/src/java/libs/linux/libjSSC-0.9_x86.so deleted file mode 100644 index fa08c409f..000000000 Binary files a/src/java/libs/linux/libjSSC-0.9_x86.so and /dev/null differ diff --git a/src/java/libs/linux/libjSSC-0.9_x86_64.so b/src/java/libs/linux/libjSSC-0.9_x86_64.so deleted file mode 100644 index 2639593aa..000000000 Binary files a/src/java/libs/linux/libjSSC-0.9_x86_64.so and /dev/null differ diff --git a/src/java/libs/linux/libjSSC-2.8_armhf.so b/src/java/libs/linux/libjSSC-2.8_armhf.so new file mode 100644 index 000000000..3742fbe08 Binary files /dev/null and b/src/java/libs/linux/libjSSC-2.8_armhf.so differ diff --git a/src/java/libs/linux/libjSSC-2.8_armsf.so b/src/java/libs/linux/libjSSC-2.8_armsf.so new file mode 100644 index 000000000..894ec8087 Binary files /dev/null and b/src/java/libs/linux/libjSSC-2.8_armsf.so differ diff --git a/src/java/libs/linux/libjSSC-2.8_x86.so b/src/java/libs/linux/libjSSC-2.8_x86.so new file mode 100644 index 000000000..8ea5d6e21 Binary files /dev/null and b/src/java/libs/linux/libjSSC-2.8_x86.so differ diff --git a/src/java/libs/linux/libjSSC-2.8_x86_64.so b/src/java/libs/linux/libjSSC-2.8_x86_64.so new file mode 100644 index 000000000..1108cb5f2 Binary files /dev/null and b/src/java/libs/linux/libjSSC-2.8_x86_64.so differ diff --git a/src/java/libs/mac_os_x/libjSSC-0.9_ppc.jnilib b/src/java/libs/mac_os_x/libjSSC-0.9_ppc.jnilib deleted file mode 100644 index 27b869497..000000000 Binary files a/src/java/libs/mac_os_x/libjSSC-0.9_ppc.jnilib and /dev/null differ diff --git a/src/java/libs/mac_os_x/libjSSC-0.9_ppc64.jnilib b/src/java/libs/mac_os_x/libjSSC-0.9_ppc64.jnilib deleted file mode 100644 index 96319f6d4..000000000 Binary files a/src/java/libs/mac_os_x/libjSSC-0.9_ppc64.jnilib and /dev/null differ diff --git a/src/java/libs/mac_os_x/libjSSC-0.9_x86_64.jnilib b/src/java/libs/mac_os_x/libjSSC-0.9_x86_64.jnilib deleted file mode 100644 index 393cfd5f2..000000000 Binary files a/src/java/libs/mac_os_x/libjSSC-0.9_x86_64.jnilib and /dev/null differ diff --git a/src/java/libs/mac_os_x/libjSSC-2.8_ppc.jnilib b/src/java/libs/mac_os_x/libjSSC-2.8_ppc.jnilib new file mode 100644 index 000000000..bdba1fca8 Binary files /dev/null and b/src/java/libs/mac_os_x/libjSSC-2.8_ppc.jnilib differ diff --git a/src/java/libs/mac_os_x/libjSSC-2.8_ppc64.jnilib b/src/java/libs/mac_os_x/libjSSC-2.8_ppc64.jnilib new file mode 100644 index 000000000..f32ae9be7 Binary files /dev/null and b/src/java/libs/mac_os_x/libjSSC-2.8_ppc64.jnilib differ diff --git a/src/java/libs/mac_os_x/libjSSC-0.9_x86.jnilib b/src/java/libs/mac_os_x/libjSSC-2.8_x86.jnilib similarity index 50% rename from src/java/libs/mac_os_x/libjSSC-0.9_x86.jnilib rename to src/java/libs/mac_os_x/libjSSC-2.8_x86.jnilib index 025becf36..103909220 100644 Binary files a/src/java/libs/mac_os_x/libjSSC-0.9_x86.jnilib and b/src/java/libs/mac_os_x/libjSSC-2.8_x86.jnilib differ diff --git a/src/java/libs/mac_os_x/libjSSC-2.8_x86_64.jnilib b/src/java/libs/mac_os_x/libjSSC-2.8_x86_64.jnilib new file mode 100644 index 000000000..10dc27e43 Binary files /dev/null and b/src/java/libs/mac_os_x/libjSSC-2.8_x86_64.jnilib differ diff --git a/src/java/libs/solaris/libjSSC-0.9_x86.so b/src/java/libs/solaris/libjSSC-0.9_x86.so deleted file mode 100644 index 1a2b6af9a..000000000 Binary files a/src/java/libs/solaris/libjSSC-0.9_x86.so and /dev/null differ diff --git a/src/java/libs/solaris/libjSSC-0.9_x86_64.so b/src/java/libs/solaris/libjSSC-0.9_x86_64.so deleted file mode 100644 index 931b44cb5..000000000 Binary files a/src/java/libs/solaris/libjSSC-0.9_x86_64.so and /dev/null differ diff --git a/src/java/libs/solaris/libjSSC-2.8_x86.so b/src/java/libs/solaris/libjSSC-2.8_x86.so new file mode 100644 index 000000000..3e6a3a3d5 Binary files /dev/null and b/src/java/libs/solaris/libjSSC-2.8_x86.so differ diff --git a/src/java/libs/solaris/libjSSC-2.8_x86_64.so b/src/java/libs/solaris/libjSSC-2.8_x86_64.so new file mode 100644 index 000000000..b67dccbae Binary files /dev/null and b/src/java/libs/solaris/libjSSC-2.8_x86_64.so differ diff --git a/src/java/libs/windows/jSSC-0.9_x86.dll b/src/java/libs/windows/jSSC-0.9_x86.dll deleted file mode 100644 index 9f0fcec9e..000000000 Binary files a/src/java/libs/windows/jSSC-0.9_x86.dll and /dev/null differ diff --git a/src/java/libs/windows/jSSC-0.9_x86_64.dll b/src/java/libs/windows/jSSC-0.9_x86_64.dll deleted file mode 100644 index bb3cb2f2a..000000000 Binary files a/src/java/libs/windows/jSSC-0.9_x86_64.dll and /dev/null differ diff --git a/src/java/libs/windows/jSSC-2.8_x86.dll b/src/java/libs/windows/jSSC-2.8_x86.dll new file mode 100644 index 000000000..8ff7541a0 Binary files /dev/null and b/src/java/libs/windows/jSSC-2.8_x86.dll differ diff --git a/src/java/libs/windows/jSSC-2.8_x86_64.dll b/src/java/libs/windows/jSSC-2.8_x86_64.dll new file mode 100644 index 000000000..d4e19e069 Binary files /dev/null and b/src/java/libs/windows/jSSC-2.8_x86_64.dll differ