/*------------------------------------------------------------------------- | rxtx is a native interface to serial ports in java. | Copyright 2002-2004 Michal Hobot MichalHobot@netscape.net | Copyright 1997-2004 by Trent Jarvi taj@parcelfarce.linux.theplanet.co.uk | | This library is free software; you can redistribute it and/or | modify it under the terms of the GNU Library General Public | License as published by the Free Software Foundation; either | version 2 of the License, or (at your option) any later version. | | This library 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 | Library General Public License for more details. | | You should have received a copy of the GNU Library General Public | License along with this library; if not, write to the Free | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --------------------------------------------------------------------------*/ #include "StdAfx.h" #include "rxtxHelpers.h" /* Initialize accept: none perform: Initialize the native library return: none exceptions: none comments: * Class: gnu_io_RXTXPort * Method: Initialize * Signature: ()V */ JNIEXPORT void JNICALL Java_gnu_io_RXTXPort_Initialize(JNIEnv *env, jclass cls) { } /* open accept: The device to open. ie "COM1:" perform: open the device return: handle exceptions: IOExcepiton comments: Very often people complain about not being able to get past this function and it turns out to be permissions on the device file or bios has the device disabled. * Class: gnu_io_RXTXPort * Method: open * Signature: (Ljava/lang/String{ })I */ JNIEXPORT jint JNICALL Java_gnu_io_RXTXPort_open(JNIEnv *env, jobject jobj, jstring name) { DCB PortDCB; COMMTIMEOUTS CommTimeouts; LPCWSTR lpMsgBuf; EventInfoStruct *EventInfo; DWORD dwErr; LPCWSTR wszName = env->GetStringChars(name, NULL); HANDLE hPort = CreateFileW(wszName, // Pointer to the name of the port GENERIC_READ | GENERIC_WRITE,// Access (read-write) mode 0, // Share mode NULL, // Pointer to the security attribute OPEN_EXISTING,// How to open the serial port 0, // Port attributes NULL); // Handle to port with attribute to copy // If it fails to open the port, return FALSE. if ( hPort == INVALID_HANDLE_VALUE ) { // Could not open the port. CreateErrorMsg(GetLastError(), lpMsgBuf); throw_java_exceptionW(env, PORT_IN_USE_EXCEPTION, L"open - CreateFile", lpMsgBuf ); // Free the buffers. ReleaseErrorMsg(lpMsgBuf); env->ReleaseStringChars(name, wszName); return (jint)INVALID_HANDLE_VALUE; } PortDCB.DCBlength = sizeof (DCB); // Get the default port setting information. GetCommState(hPort, &PortDCB); // Change the DCB structure settings. PortDCB.fBinary = TRUE; // Binary mode; no EOF check PortDCB.fParity = TRUE; // Enable parity checking PortDCB.fOutxDsrFlow = FALSE; // No DSR output flow control PortDCB.fDtrControl = DTR_CONTROL_HANDSHAKE;// DTR flow control type PortDCB.fDsrSensitivity = FALSE; // DSR sensitivity PortDCB.fTXContinueOnXoff = TRUE; // XOFF continues Tx PortDCB.fErrorChar = FALSE; // Disable error replacement PortDCB.fNull = FALSE; // Disable null stripping PortDCB.fRtsControl = RTS_CONTROL_ENABLE;// RTS flow control PortDCB.fAbortOnError = FALSE; // Do not abort reads/writes on error // Configure the port according to the specifications of the DCB structure. if (!SetCommState(hPort, &PortDCB)) { // Could not set comm port state CreateErrorMsg(GetLastError(), lpMsgBuf); throw_java_exceptionW(env, PORT_IN_USE_EXCEPTION, L"open - SetCommState", lpMsgBuf); // Free the buffers. ReleaseErrorMsg(lpMsgBuf); env->ReleaseStringChars(name, wszName); return (jint)INVALID_HANDLE_VALUE; } // Retrieve the time-out parameters for all read and write operations // on the port. GetCommTimeouts(hPort, &CommTimeouts); // Change the COMMTIMEOUTS structure settings. CommTimeouts.ReadIntervalTimeout = 0; CommTimeouts.ReadTotalTimeoutMultiplier = 0; CommTimeouts.ReadTotalTimeoutConstant = MAXDWORD; CommTimeouts.WriteTotalTimeoutMultiplier = 10; CommTimeouts.WriteTotalTimeoutConstant = 1000; // Set the time-out parameters for all read and write operations // on the port. if (!SetCommTimeouts(hPort, &CommTimeouts)) { // Unable to set the time-out parameters CreateErrorMsg(GetLastError(), lpMsgBuf); throw_java_exceptionW(env, PORT_IN_USE_EXCEPTION, L"open - SetCommTimeouts", lpMsgBuf); // Free the buffers. ReleaseErrorMsg(lpMsgBuf); env->ReleaseStringChars(name, wszName); return (jint)INVALID_HANDLE_VALUE; } // SETRTS: Sends the RTS (request-to-send) signal. EscapeCommFunction(hPort, SETRTS); if(dwErr = InitialiseEventInfoStruct(hPort, &EventInfo)) { // Unable to set up EventInfo structure for event processing CreateErrorMsg(dwErr, lpMsgBuf); throw_java_exceptionW(env, IO_EXCEPTION, L"open - InitialiseEventInfoStruct", lpMsgBuf); // Free the buffers. ReleaseErrorMsg(lpMsgBuf); env->ReleaseStringChars(name, wszName); return (jint)INVALID_HANDLE_VALUE; } jclass cls = env->GetObjectClass(jobj); jfieldID jfEis = env->GetFieldID(cls, "eis", "I"); if( !jfEis ) { IF_DEBUG ( env->ExceptionDescribe(); ) env->ExceptionClear(); // Free the buffers. env->ReleaseStringChars(name, wszName); return (jint)INVALID_HANDLE_VALUE; } env->SetIntField(jobj, jfEis, (jint)EventInfo); env->ReleaseStringChars(name, wszName); // Returning HANDLE (which is a pointer) as file descriptor... Anyway, 32 bits are 32 bits return (jint)hPort; } /* nativeSetSerialPortParams accept: speed, data bits, stop bits, parity perform: set the serial port parameters return: void exceptions: UnsupportedCommOperationException * Class: gnu_io_RXTXPort * Method: nativeSetSerialPortParams * Signature: (IIII)V */ JNIEXPORT void JNICALL Java_gnu_io_RXTXPort_nativeSetSerialPortParams(JNIEnv *env, jobject jobj, jint speed, jint dataBits, jint stopBits, jint parity) { DCB PortDCB; LPCWSTR lpMsgBuf; HANDLE hPort = get_fd(env, jobj); PortDCB.DCBlength = sizeof(DCB); IF_DEBUG ( printj(env, L"--- RXTXPort.nativeSetSerialPortParams(%ld, %ld, %ld, %ld) called\n", speed, dataBits, stopBits, parity); ) // Get the default port setting information. if(!GetCommState(hPort, &PortDCB)) { //Unable to get configuration of the serial port CreateErrorMsg(GetLastError(), lpMsgBuf); throw_java_exceptionW(env, UNSUPPORTED_COMM_OPERATION, L"nativeSetSerialPortParams - GetCommState", lpMsgBuf); // Free the buffers. ReleaseErrorMsg(lpMsgBuf); return; } // Change the DCB structure settings. PortDCB.BaudRate = speed; // Current baud PortDCB.ByteSize = (BYTE)dataBits; // Number of bits/byte, 4-8 PortDCB.Parity = (BYTE)parity; // 0-4=no,odd,even,mark,space switch(stopBits) { case gnu_io_RXTXPort_STOPBITS_1: PortDCB.StopBits = ONESTOPBIT; break; case gnu_io_RXTXPort_STOPBITS_2: PortDCB.StopBits = TWOSTOPBITS; break; case gnu_io_RXTXPort_STOPBITS_1_5: PortDCB.StopBits = ONE5STOPBITS; break; default: throw_java_exceptionW(env, UNSUPPORTED_COMM_OPERATION, L"nativeSetSerialPortParams", L"Incorrect stopBits"); } // Configure the port according to the specifications of the DCB structure. if (!SetCommState (hPort, &PortDCB)) { //Unable to configure the serial port CreateErrorMsg(GetLastError(), lpMsgBuf); throw_java_exceptionW(env, UNSUPPORTED_COMM_OPERATION, L"nativeSetSerialPortParams - SetCommState", lpMsgBuf); // Free the buffers. ReleaseErrorMsg(lpMsgBuf); return; } } /* setflowcontrol accept: flowmode FLOWCONTROL_NONE none FLOWCONTROL_RTSCTS_IN hardware flow control FLOWCONTROL_RTSCTS_OUT "" FLOWCONTROL_XONXOFF_IN input software flow control FLOWCONTROL_XONXOFF_OUT output software flow control perform: set flow control to flowmode return: none exceptions: UnsupportedCommOperationException comments: there is no differentiation between input and output hardware flow control * Class: gnu_io_RXTXPort * Method: setflowcontrol * Signature: (I)V */ JNIEXPORT void JNICALL Java_gnu_io_RXTXPort_setflowcontrol(JNIEnv *env, jobject jobj, jint flowcontrol) { DCB PortDCB; LPCWSTR lpMsgBuf; IF_DEBUG ( printj(env, L"--- RXTXPort.setflowcontrol(%ld) called\n", flowcontrol); ) HANDLE hPort = get_fd(env, jobj); PortDCB.DCBlength = sizeof(DCB); if(!GetCommState (hPort, &PortDCB)) { //Unable to get configuration of the serial port CreateErrorMsg(GetLastError(), lpMsgBuf); throw_java_exceptionW(env, UNSUPPORTED_COMM_OPERATION, L"setflowcontrol - GetCommState", lpMsgBuf); // Free the buffers. ReleaseErrorMsg(lpMsgBuf); return; } if(flowcontrol & (gnu_io_RXTXPort_FLOWCONTROL_RTSCTS_IN | gnu_io_RXTXPort_FLOWCONTROL_RTSCTS_OUT)) PortDCB.fRtsControl = RTS_CONTROL_HANDSHAKE; else PortDCB.fRtsControl = RTS_CONTROL_ENABLE; if(flowcontrol & gnu_io_RXTXPort_FLOWCONTROL_RTSCTS_OUT) PortDCB.fOutxCtsFlow = TRUE; else PortDCB.fOutxCtsFlow = FALSE; if(flowcontrol & gnu_io_RXTXPort_FLOWCONTROL_XONXOFF_IN) PortDCB.fInX = TRUE; else PortDCB.fInX = FALSE; if(flowcontrol & gnu_io_RXTXPort_FLOWCONTROL_XONXOFF_OUT) PortDCB.fOutX = TRUE; else PortDCB.fOutX = FALSE; // Configure the port according to the specifications of the DCB structure. if (!SetCommState (hPort, &PortDCB)) { // Could not set params CreateErrorMsg(GetLastError(), lpMsgBuf); throw_java_exceptionW(env, UNSUPPORTED_COMM_OPERATION, L"setflowcontrol - SetCommState", lpMsgBuf); // Free the buffers. ReleaseErrorMsg(lpMsgBuf); return; } } /* NativegetReceiveTimeout accept: none perform: get termios.c_cc[VTIME] return: VTIME comments: see NativeEnableReceiveTimeoutThreshold * Class: gnu_io_RXTXPort * Method: NativegetReceiveTimeout * Signature: ()I */ JNIEXPORT jint JNICALL Java_gnu_io_RXTXPort_NativegetReceiveTimeout(JNIEnv *env, jobject jobj) { COMMTIMEOUTS CommTimeouts; LPCWSTR lpMsgBuf; HANDLE hPort = get_fd(env, jobj); IF_DEBUG ( printj(env, L"--- RXTXPort.NativegetReceiveTimeout() called\n"); ) // Retrieve the time-out parameters for all read and write operations on the port. if (!GetCommTimeouts(hPort, &CommTimeouts)) { // Unable to get the time-out parameters CreateErrorMsg(GetLastError(), lpMsgBuf); throw_java_exceptionW(env, IO_EXCEPTION, L"NativegetReceiveTimeout - GetCommTimeouts", lpMsgBuf); // Free the buffers. ReleaseErrorMsg(lpMsgBuf); return -1; } // As far as I know c_cc is byte table return CommTimeouts.ReadIntervalTimeout/100 <= 255 ? CommTimeouts.ReadIntervalTimeout / 100 : 255; } /* NativeisReceiveTimeoutEnabled accept: none perform: determine if VTIME is none 0 return: JNI_TRUE if VTIME > 0 else JNI_FALSE comments: see NativeEnableReceiveTimeoutThreshold * Class: gnu_io_RXTXPort * Method: NativeisReceiveTimeoutEnabled * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_gnu_io_RXTXPort_NativeisReceiveTimeoutEnabled(JNIEnv *env, jobject jobj) { COMMTIMEOUTS CommTimeouts; LPCWSTR lpMsgBuf; HANDLE hPort = get_fd(env, jobj); IF_DEBUG ( printj(env, L"--- RXTXPort.NativeisReceiveTimeoutEnabled() called\n"); ) // Retrieve the time-out parameters for all read and write operations // on the port. if (!GetCommTimeouts(hPort, &CommTimeouts)) { // Unable to get the time-out parameters CreateErrorMsg(GetLastError(), lpMsgBuf); throw_java_exceptionW(env, IO_EXCEPTION, L"NativeisReceiveTimeoutEnabled - GetCommTimeouts", lpMsgBuf); // Free the buffers. ReleaseErrorMsg(lpMsgBuf); return -1; } return CommTimeouts.ReadIntervalTimeout || CommTimeouts.ReadTotalTimeoutConstant || CommTimeouts.ReadTotalTimeoutMultiplier ? JNI_TRUE : JNI_FALSE; } /* NativeEnableReceiveTimeoutThreshold accept: int threshold, int vtime,int buffer perform: Set c_cc->VMIN to threshold and c_cc=>VTIME to vtime return: void exceptions: IOException comments: This is actually all handled in read with select in canonical input mode. * Class: gnu_io_RXTXPort * Method: NativeEnableReceiveTimeoutThreshold * Signature: (III)V */ JNIEXPORT void JNICALL Java_gnu_io_RXTXPort_NativeEnableReceiveTimeoutThreshold(JNIEnv *env, jobject jobj, jint time, jint threshold, jint InputBuffer) { COMMTIMEOUTS CommTimeouts; LPCWSTR lpMsgBuf; HANDLE hPort = get_fd(env, jobj); IF_DEBUG ( printj(env, L"--- RXTXPort.NativeEnableReceiveTimeoutThreshold(%ld, %ld) called\n", time, threshold); ) // Retrieve the time-out parameters for all read and write operations // on the port. if (!GetCommTimeouts(hPort, &CommTimeouts)) { // Unable to get the time-out parameters CreateErrorMsg(GetLastError(), lpMsgBuf); throw_java_exceptionW(env, IO_EXCEPTION, L"NativeEnableReceiveTimeoutThreshold - GetCommTimeouts", lpMsgBuf); // Free the buffers. ReleaseErrorMsg(lpMsgBuf); return; } /* ------ from javax.comm.CommPort javadoc ------------------------------------------------------------- | Threshold | Timeout |Read Buffer Size | Read Behaviour |State |Value |State |Value| | |disabled| - |disabled| - | n bytes | block until any data is available |enabled |m bytes|disabled| - | n bytes | block until min(m,n) bytes are available |disabled| - |enabled |x ms | n bytes | block for x ms or until any data is available |enabled |m bytes|enabled |x ms | n bytes | block for x ms or until min(m,n) bytes are available -------------------------------------------------------------------------------------------------------- Enabling the Timeout OR Threshold with a value a zero is a special case. This causes the underlying driver to poll for incoming data instead being event driven. Otherwise, the behaviour is identical to having both the Timeout and Threshold disabled. */ // Following is based on my understanding of timeout parameters meaning. // Not completely precise (threshold?!) if(time == 0) { // polling mode - return if no data CommTimeouts.ReadIntervalTimeout = MAXDWORD; CommTimeouts.ReadTotalTimeoutMultiplier = MAXDWORD; CommTimeouts.ReadTotalTimeoutConstant = 1; } else if(time == -1) { // disable timeout CommTimeouts.ReadIntervalTimeout = 0; CommTimeouts.ReadTotalTimeoutMultiplier = 0; CommTimeouts.ReadTotalTimeoutConstant = 0; } else { // set timeout CommTimeouts.ReadIntervalTimeout = 0; CommTimeouts.ReadTotalTimeoutMultiplier = 0; CommTimeouts.ReadTotalTimeoutConstant = time; } // Set the time-out parameters for all read and write operations // on the port. if (!SetCommTimeouts (hPort, &CommTimeouts)) { // Unable to set the time-out parameters CreateErrorMsg(GetLastError(), lpMsgBuf); throw_java_exceptionW(env, IO_EXCEPTION, L"NativeEnableReceiveTimeoutThreshold - SetCommTimeouts", lpMsgBuf); // Free the buffers. ReleaseErrorMsg(lpMsgBuf); return; } } /* isDTR accept: none perform: check status of DTR return: true if TIOCM_DTR is set false if TIOCM_DTR is not set exceptions: none comments: DTR stands for Data Terminal Ready * Class: gnu_io_RXTXPort * Method: isDTR * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_gnu_io_RXTXPort_isDTR(JNIEnv *env, jobject jobj) { DCB PortDCB; HANDLE hPort = get_fd(env, jobj); PortDCB.DCBlength = sizeof(DCB); // Get the default port setting information. if(!GetCommState(hPort, &PortDCB)) { GetLastError(); return JNI_FALSE; } // This is not completely correct: I assume that nobody's playing with // manually setting/resetting DTR. Instead, DTR is in handshake mode (ON unless // port closed) or disable mode (OFF). // So, don't use EscapeCommFunction(SETDTR/CLRDTR) in this library! return PortDCB.fDtrControl != DTR_CONTROL_DISABLE ? JNI_TRUE : JNI_FALSE; } /* setDTR accept: new DTR state perform: if state is true, TIOCM_DTR is set if state is false, TIOCM_DTR is unset return: none exceptions: none comments: DTR stands for Data Terminal Ready * Class: gnu_io_RXTXPort * Method: setDTR * Signature: (Z)V */ JNIEXPORT void JNICALL Java_gnu_io_RXTXPort_setDTR(JNIEnv *env, jobject jobj, jboolean state) { DCB PortDCB; HANDLE hPort = get_fd(env, jobj); PortDCB.DCBlength = sizeof(DCB); // Don't use EscapeCommFunction(SETDTR/CLRDTR) in this library! // Get the default port setting information. if(!GetCommState (hPort, &PortDCB)) { //Unable to get configuration of the serial port GetLastError(); return; } if(state == JNI_TRUE) PortDCB.fDtrControl = DTR_CONTROL_HANDSHAKE; else PortDCB.fDtrControl = DTR_CONTROL_DISABLE; // Configure the port according to the specifications of the DCB structure. if (!SetCommState (hPort, &PortDCB)) { //Unable to configure the serial port GetLastError(); return; } } /* setRTS accept: state flag to set/unset. perform: depends on the state flag if true TIOCM_RTS is set if false TIOCM_RTS is unset return: none exceptions: none comments: tcsetattr with c_cflag CRTS_IFLOW * Class: gnu_io_RXTXPort * Method: setRTS * Signature: (Z)V */ JNIEXPORT void JNICALL Java_gnu_io_RXTXPort_setRTS(JNIEnv *env, jobject jobj, jboolean state) { HANDLE hPort = get_fd(env, jobj); // EscapeCommFunction will fail if there's RTS/CTS flowcontrol. If it is incorrect, // we could turn flowcontrol off when getting to this function if(state == JNI_TRUE) EscapeCommFunction(hPort, SETRTS); else EscapeCommFunction(hPort, CLRRTS); } /* setDSR accept: state flag to set/unset. perform: depends on the state flag if true TIOCM_DSR is set if false TIOCM_DSR is unset return: none exceptions: none comments: tcsetattr with c_cflag CRTS_IFLOW * Class: gnu_io_RXTXPort * Method: setDSR * Signature: (Z)V */ JNIEXPORT void JNICALL Java_gnu_io_RXTXPort_setDSR(JNIEnv *env, jobject jobj, jboolean state) { DCB PortDCB; HANDLE hPort = get_fd(env, jobj); PortDCB.DCBlength = sizeof(DCB); // Get the default port setting information. if(!GetCommState (hPort, &PortDCB)) { //Unable to get configuration of the serial port GetLastError(); return; } // Change the DCB structure settings. if(state != JNI_FALSE) PortDCB.fOutxDsrFlow = TRUE; else PortDCB.fOutxDsrFlow = FALSE; // Configure the port according to the specifications of the DCB // structure. if (!SetCommState (hPort, &PortDCB)) { //Unable to configure the serial port GetLastError(); return; } } /* isCTS accept: none perform: check status of CTS return: true if TIOCM_CTS is set false if TIOCM_CTS is not set exceptions: none comments: CTS stands for Clear To Send. * Class: gnu_io_RXTXPort * Method: isCTS * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_gnu_io_RXTXPort_isCTS(JNIEnv *env, jobject jobj) { DWORD ModemStat; HANDLE hPort = get_fd(env, jobj); if(!GetCommModemStatus(hPort, &ModemStat)) return JNI_FALSE; return ModemStat|MS_CTS_ON ? JNI_TRUE : JNI_FALSE; } /* isDSR accept: none perform: check status of DSR return: true if TIOCM_DSR is set false if TIOCM_DSR is not set exceptions: none comments: DSR stands for Data Set Ready * Class: gnu_io_RXTXPort * Method: isDSR * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_gnu_io_RXTXPort_isDSR(JNIEnv *env, jobject jobj) { DWORD ModemStat; HANDLE hPort = get_fd(env, jobj); if(!GetCommModemStatus(hPort, &ModemStat)) return JNI_FALSE; return ModemStat|MS_DSR_ON ? JNI_TRUE : JNI_FALSE; } /* isCD accept: none perform: check status of CD return: true if TIOCM_CD is set false if TIOCM_CD is not set exceptions: none comments: CD stands for Carrier Detect The following comment has been made... "well, it works, there might ofcourse be a bug, but making DCD permanently on fixed it for me so I don't care" * Class: gnu_io_RXTXPort * Method: isCD * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_gnu_io_RXTXPort_isCD(JNIEnv *env, jobject jobj) { DWORD ModemStat; HANDLE hPort = get_fd(env, jobj); if(!GetCommModemStatus(hPort, &ModemStat)) return JNI_FALSE; return ModemStat|MS_RLSD_ON ? JNI_TRUE : JNI_FALSE; } /* isRI accept: none perform: check status of RI return: true if TIOCM_RI is set false if TIOCM_RI is not set exceptions: none comments: RI stands for Ring Indicator * Class: gnu_io_RXTXPort * Method: isRI * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_gnu_io_RXTXPort_isRI(JNIEnv *env, jobject jobj) { DWORD ModemStat; HANDLE hPort = get_fd(env, jobj); if(!GetCommModemStatus(hPort, &ModemStat)) return JNI_FALSE; return ModemStat|MS_RING_ON ? JNI_TRUE : JNI_FALSE; } /* isRTS accept: none perform: check status of RTS return: true if TIOCM_RTS is set false if TIOCM_RTS is not set exceptions: none comments: tcgetattr with c_cflag CRTS_IFLOW * Class: gnu_io_RXTXPort * Method: isRTS * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_gnu_io_RXTXPort_isRTS(JNIEnv *env, jobject jobj) { DCB PortDCB; HANDLE hPort = get_fd(env, jobj); PortDCB.DCBlength = sizeof(DCB); if(!GetCommState (hPort, &PortDCB)) { //Unable to get configuration of the serial port GetLastError(); return JNI_FALSE; } if(PortDCB.fRtsControl == RTS_CONTROL_DISABLE) return JNI_FALSE; if(PortDCB.fRtsControl == RTS_CONTROL_ENABLE) return JNI_TRUE; if(PortDCB.fRtsControl == RTS_CONTROL_HANDSHAKE) { //MessageBox(NULL, L"Undefined condition: isRTS() but control is RTS_CONTROL_HANDSHAKE\r\nReturning FALSE", L"Warning", MB_OK | MB_ICONWARNING | MB_SETFOREGROUND); printj(env, L"Undefined condition: isRTS() but control is RTS_CONTROL_HANDSHAKE. Returning FALSE\n"); return JNI_FALSE; } return JNI_FALSE; } /* sendBreak accept: duration in milliseconds. perform: send break for actual time. not less than 0.25 seconds. exceptions: none comments: not very precise * Class: gnu_io_RXTXPort * Method: sendBreak * Signature: (I)V */ JNIEXPORT void JNICALL Java_gnu_io_RXTXPort_sendBreak(JNIEnv *env, jobject jobj, jint duration) { HANDLE hPort = get_fd(env, jobj); SetCommBreak(hPort); Sleep(duration); ClearCommBreak(hPort); } /* writeByte accept: byte to write (passed as int) perform: write a single byte to the port return: none exceptions: IOException * Class: gnu_io_RXTXPort * Method: writeByte * Signature: (IZ)V */ JNIEXPORT void JNICALL Java_gnu_io_RXTXPort_writeByte(JNIEnv *env, jobject jobj, jint b, jboolean i) { DWORD dwNumBytesWritten; LPCWSTR lpMsgBuf; HANDLE hPort = get_fd(env, jobj); BYTE bb = (BYTE)b; do { if (!WriteFile(hPort, // Port handle &bb, // Pointer to the data to write 1, // Number of bytes to write &dwNumBytesWritten, // Pointer to the number of bytes written NULL)) // Must be NULL for Windows CE { // WriteFile failed. Report error. CreateErrorMsg(GetLastError(), lpMsgBuf); throw_java_exceptionW(env, IO_EXCEPTION, L"writeByte - WriteFile", lpMsgBuf ); // Free the buffers. ReleaseErrorMsg(lpMsgBuf); return; } } while(dwNumBytesWritten == 0); } /* writeArray accept: jbarray: bytes used for writing off: offset in array to start writing len: Number of bytes to write perform: write length bytes of jbarray return: none exceptions: IOException * Class: gnu_io_RXTXPort * Method: writeArray * Signature: ([BIIZ)V */ JNIEXPORT void JNICALL Java_gnu_io_RXTXPort_writeArray(JNIEnv *env, jobject jobj, jbyteArray b, jint off, jint len, jboolean i) { LPCWSTR lpMsgBuf; DWORD dwNumBytesWritten; jint total=0; HANDLE hPort = get_fd(env, jobj); jbyte *body = env->GetByteArrayElements(b, NULL); do { IF_DEBUG ( printj(env, L"--- writeArray - %d bytes to write\n", len-total); ) if (!WriteFile(hPort, // Port handle body+total+off, // Pointer to the data to write len-total, // Number of bytes to write &dwNumBytesWritten, // Pointer to the number of bytes written NULL)) // Must be NULL for Windows CE { // WriteFile failed. Report error. CreateErrorMsg(GetLastError(), lpMsgBuf); throw_java_exceptionW(env, IO_EXCEPTION, L"writeArray - WriteFile", lpMsgBuf ); // Free the buffers. ReleaseErrorMsg(lpMsgBuf); env->ReleaseByteArrayElements(b, body, JNI_ABORT); return; } total += dwNumBytesWritten; } while( total < len ); env->ReleaseByteArrayElements(b, body, JNI_ABORT); } /* nativeDrain accept: none perform: wait until all data is transmitted return: none exceptions: IOException comments: java.io.OutputStream.flush() is equivalent to tcdrain, not tcflush, which throws away unsent bytes count logic added to avoid infinite loops when EINTR is true... Thread.yeild() was suggested. * Class: gnu_io_RXTXPort * Method: nativeDrain * Signature: ()V */ JNIEXPORT jboolean JNICALL Java_gnu_io_RXTXPort_nativeDrain(JNIEnv *env, jobject jobj, jboolean i) { //COMSTAT Stat; //DWORD dwErrors; HANDLE hPort = get_fd(env, jobj); IF_DEBUG ( printj(env, L"--- RXTXPort.nativeDrain() called\n"); ) /* if(!FlushFileBuffers(hPort)) { IF_DEBUG ( printj(env, L"!!! FlushFileBuffers() error %ld\n", GetLastError()); ) return JNI_FALSE; } */ // Alternative implementation: /* do { if(!ClearCommError(hPort, &dwErrors, &Stat)) { GetLastError(); return; } Sleep(10); } while(Stat.cbOutQue > 0);*/ return JNI_FALSE; } /* nativeavailable accept: none perform: find out the number of bytes available for reading return: available bytes -1 on error exceptions: none /// should be IOException * Class: gnu_io_RXTXPort * Method: nativeavailable * Signature: ()I */ JNIEXPORT jint JNICALL Java_gnu_io_RXTXPort_nativeavailable(JNIEnv *env, jobject jobj) { DWORD dwErrors; COMSTAT Stat; LPCWSTR lpMsgBuf; HANDLE hPort = get_fd(env, jobj); IF_DEBUG ( printj(env, L"--- RXTXPort.nativeavailable() called"); ) if(!ClearCommError(hPort, &dwErrors, &Stat)) { CreateErrorMsg(GetLastError(), lpMsgBuf); throw_java_exceptionW(env, IO_EXCEPTION, L"nativeavailable - ClearCommError", lpMsgBuf ); // Free the buffers. ReleaseErrorMsg(lpMsgBuf); return -1; } IF_DEBUG ( printj(env, L" - returning %ld\n", Stat.cbInQue); ) return Stat.cbInQue; } /* readByte accept: none perform: Read a single byte from the port return: The byte read exceptions: IOException * Class: gnu_io_RXTXPort * Method: readByte * Signature: ()I */ JNIEXPORT jint JNICALL Java_gnu_io_RXTXPort_readByte(JNIEnv *env, jobject jobj) { BYTE bb; DWORD dwNumBytesRead; LPCWSTR lpMsgBuf; HANDLE hPort = get_fd(env, jobj); if (!ReadFile(hPort, &bb, 1, &dwNumBytesRead, NULL)) { // ReadFile failed. Report error. CreateErrorMsg(GetLastError(), lpMsgBuf); throw_java_exceptionW(env, IO_EXCEPTION, L"readByte - ReadFile", lpMsgBuf); // Free the buffers. ReleaseErrorMsg(lpMsgBuf); return -1; } return dwNumBytesRead > 0 ? bb : -1; } /* readArray accept: offset (offset to start storing data in the jbarray) and Length (bytes to read) perform: read bytes from the port into a byte array return: bytes read on success 0 on read timeout exceptions: IOException comments: throws ArrayIndexOutOfBoundsException if asked to read more than SSIZE_MAX bytes * Class: gnu_io_RXTXPort * Method: readArray * Signature: ([BII)I */ JNIEXPORT jint JNICALL Java_gnu_io_RXTXPort_readArray(JNIEnv *env, jobject jobj, jbyteArray b, jint off, jint len) { LPCWSTR lpMsgBuf; DWORD dwNumBytesRead, dwTotalRead = 0; jint threshold; HANDLE hPort = get_fd(env, jobj); if(len < 0) { throw_java_exceptionW(env, ARRAY_INDEX_OUT_OF_BOUNDS, L"readArray", L"Negative number of character to read"); return -1; } jbyte *body = env->GetByteArrayElements(b, NULL); threshold = get_java_int_var(env, jobj, "threshold"); do { if (!ReadFile(hPort, (unsigned char *)(body+off), len, &dwNumBytesRead, NULL)) { // ReadFile failed. Report error. CreateErrorMsg(GetLastError(), lpMsgBuf); throw_java_exceptionW(env, IO_EXCEPTION, L"readArray - WriteFile", lpMsgBuf ); // Free the buffers. ReleaseErrorMsg(lpMsgBuf); env->ReleaseByteArrayElements(b, body, JNI_ABORT); return -1; } dwTotalRead += dwNumBytesRead; } while(dwNumBytesRead > 0 && threshold != 0 && dwTotalRead <= (DWORD)len && dwTotalRead < (DWORD)threshold); env->ReleaseByteArrayElements(b, body, 0); return dwTotalRead; } /* eventLoop accept: none perform: periodically check for SerialPortEvents return: none exceptions: none comments: please keep this function clean. * Class: gnu_io_RXTXPort * Method: eventLoop * Signature: ()V */ JNIEXPORT void JNICALL Java_gnu_io_RXTXPort_eventLoop(JNIEnv *env, jobject jobj) { jfieldID jfMonitorThreadCloseLock, jfMonitorThreadLock, jfMonThreadisInterrupted; jmethodID jmSendEvent; HANDLE hCommEventThread; DWORD dwThreadID, dwWaitResult, dwEvent; int RetVal; HANDLE hPort = get_fd(env, jobj); EventInfoStruct *EventInfo = get_eis(env, jobj); IF_DEBUG ( printj(env, L"--- RXTXPort.eventLoop() start\n"); ) jclass cls = env->GetObjectClass(jobj); // Get pointers to some Java variables and methods: if( !(jfMonitorThreadLock = env->GetFieldID(cls, "MonitorThreadLock", "Z")) || !(jfMonThreadisInterrupted = env->GetFieldID(cls, "monThreadisInterrupted", "Z")) || !(jfMonitorThreadCloseLock = env->GetFieldID(cls, "MonitorThreadCloseLock", "Z")) || !(jmSendEvent = env->GetMethodID(cls, "sendEvent", "(IZ)Z")) ) { IF_DEBUG ( env->ExceptionDescribe(); ) env->ExceptionClear(); return; } hCommEventThread = CreateThread(NULL, 0, CommEventThread, (LPVOID)EventInfo, 0, &dwThreadID); if(hCommEventThread == NULL) { LPCWSTR lpMsgBuf; CreateErrorMsg(GetLastError(), lpMsgBuf); printj(env, L"!!! eventLoop - CreateThread() error: %s\n", lpMsgBuf); ReleaseErrorMsg(lpMsgBuf); return; } CloseHandle(hCommEventThread); do { if(env->GetBooleanField(jobj, jfMonThreadisInterrupted) == JNI_TRUE) { IF_DEBUG ( printj(env, L"--- RXTXPort.eventLoop() interrupted - exiting\n"); ) CloseHandle(EventInfo->eventHandle); env->SetBooleanField(jobj, jfMonitorThreadCloseLock, JNI_FALSE); return; } if(EventInfo->eventThreadReady) { // Thread is ready to work - pass signal to Java IF_DEBUG ( printj(env, L"--- RXTXPort.eventLoop() - EventThread is ready\n"); ) env->SetBooleanField(jobj, jfMonitorThreadLock, JNI_FALSE); EventInfo->eventThreadReady = false; } if((dwWaitResult = WaitForSingleObject(EventInfo->eventHandle, 250)) == WAIT_FAILED) { IF_DEBUG ( LPCWSTR lpMsgBuf; CreateErrorMsg(GetLastError(), lpMsgBuf); printj(env, L"!!! eventLoop - WaitForSingleObject() error: %s\n", lpMsgBuf); ReleaseErrorMsg(lpMsgBuf); ) CloseHandle(EventInfo->eventHandle); env->SetBooleanField(jobj, jfMonitorThreadCloseLock, JNI_FALSE); return; } if(dwWaitResult == WAIT_OBJECT_0) { dwEvent = EventInfo->event; // Clearing event - event thread will continue EventInfo->event = 0; // Send events to Java if(RetVal = SendEvents(env, jobj, dwEvent, EventInfo, jmSendEvent)) { IF_DEBUG ( printj(env, L"!!! eventLoop - SendEvents() result: %d\n", RetVal); ) CloseHandle(EventInfo->eventHandle); env->SetBooleanField(jobj, jfMonitorThreadCloseLock, JNI_FALSE); return; } } else { IF_DEBUG ( //printj(env, L"--- eventLoop() looping\n"); MessageBeep(MB_OK); ) } } while(TRUE); } /* interruptEventLoop accept: nothing perform: sets monThreadisInterrupted return: nothing exceptions: none comments: real monitoring thread will stay until port is closed * Class: gnu_io_RXTXPort * Method: interruptEventLoop * Signature: ()V */ JNIEXPORT void JNICALL Java_gnu_io_RXTXPort_interruptEventLoop(JNIEnv *env, jobject jobj) { jfieldID jfid; HANDLE hPort = get_fd(env, jobj); jclass cls = env->GetObjectClass(jobj); jfid = env->GetFieldID(cls, "monThreadisInterrupted", "Z"); env->SetBooleanField(jobj, jfid, JNI_TRUE); } /* nativeSetEventFlag accept: fd for finding the struct, event to flag, flag. perform: toggle the flag return: none exceptions: none comments: all the logic used to be done in Java but its too noisy * Class: gnu_io_RXTXPort * Method: nativeSetEventFlag * Signature: (IIZ)V */ JNIEXPORT void JNICALL Java_gnu_io_RXTXPort_nativeSetEventFlag(JNIEnv *env, jobject jobj, jint fd, jint event, jboolean flag) { DWORD dwErr, NewFlag; EventInfoStruct *EventInfo = get_eis(env, jobj); HANDLE hPort = (HANDLE)fd; IF_DEBUG ( printj(env, L"--- nativeSetEventFlag(%ld, %d) called\n", event, (int)flag); ) switch(event) { case SPE_DATA_AVAILABLE: NewFlag = EV_RXCHAR; break; case SPE_OUTPUT_BUFFER_EMPTY: NewFlag = EV_TXEMPTY; break; case SPE_CTS: NewFlag = EV_CTS; break; case SPE_DSR: NewFlag = EV_DSR; break; case SPE_RI: NewFlag = EV_RING; break; case SPE_CD: NewFlag = EV_RLSD; break; case SPE_OE: case SPE_PE: case SPE_FE: NewFlag = EV_ERR; break; case SPE_BI: NewFlag = EV_BREAK; break; } if(flag == JNI_TRUE) EventInfo->ef = EventInfo->ef | NewFlag; else EventInfo->ef = EventInfo->ef & ~NewFlag; if(!SetCommMask(hPort, EventInfo->ef)) { dwErr = GetLastError(); IF_DEBUG ( LPCWSTR lpMsgBuf; CreateErrorMsg(dwErr, lpMsgBuf); printj(env, L"!!! nativeSetEventFlag - SetCommMask() error: %ld %s\n", dwErr, lpMsgBuf ); ReleaseErrorMsg(lpMsgBuf); ) return; } } /* nativeClose accept: none perform: get the fd from the java end and close it return: none exceptions: none * Class: gnu_io_RXTXPort * Method: nativeClose * Signature: (Ljava/lang/String{ })V */ JNIEXPORT void JNICALL Java_gnu_io_RXTXPort_nativeClose(JNIEnv *env, jobject jobj, jstring name) { HANDLE hPort = get_fd(env, jobj); IF_DEBUG ( LPCWSTR wszName = env->GetStringChars(name, NULL); printj(env, L"--- RXTXPort.nativeClose(%s) called\n", wszName); env->ReleaseStringChars(name, wszName); ) if (!CloseHandle(hPort)) { GetLastError(); return; } } /* nativeGetParityErrorChar accept: - perform: check the ParityErrorChar return: The ParityErrorChar as an jbyte. exceptions: UnsupportedCommOperationException if not implemented comments: It appears the Parity char is usually \0. The windows API allows for this to be changed. I cant find may examples of this being done. Maybe for a reason. Use a direct call to the termios file until we find a solution. * Class: gnu_io_RXTXPort * Method: nativeGetParityErrorChar * Signature: ()I */ JNIEXPORT jbyte JNICALL Java_gnu_io_RXTXPort_nativeGetParityErrorChar(JNIEnv *env, jobject jobj) { DCB PortDCB; LPCWSTR lpMsgBuf; HANDLE hPort = get_fd(env, jobj); PortDCB.DCBlength = sizeof(DCB); IF_DEBUG ( printj(env, L"--- RXTXPort.nativeGetParityErrorChar() called\n"); ) // Get port setting information. if(!GetCommState(hPort, &PortDCB)) { //Unable to get configuration of the serial port CreateErrorMsg(GetLastError(), lpMsgBuf); IF_DEBUG ( printj(env, L"!!! nativeGetParityErrorChar - GetCommState() error: %s\n", lpMsgBuf); ) ReleaseErrorMsg(lpMsgBuf); return -1; } return (jbyte)PortDCB.ErrorChar; } /* nativeSetParityErrorChar accept: the ParityArrorCharacter as an int. perform: Set the ParityErrorChar return: JNI_TRUE on success exceptions: UnsupportedCommOperationException if not implemented comments: It appears the Parity char is usually \0. The windows API allows for this to be changed. I cant find may examples of this being done. Maybe for a reason. Use a direct call to the termios file until we find a solution. * Class: gnu_io_RXTXPort * Method: nativeSetParityErrorChar * Signature: (B)Z */ JNIEXPORT jboolean JNICALL Java_gnu_io_RXTXPort_nativeSetParityErrorChar(JNIEnv *env, jobject jobj, jbyte b) { DCB PortDCB; LPCWSTR lpMsgBuf; HANDLE hPort = get_fd(env, jobj); PortDCB.DCBlength = sizeof(DCB); IF_DEBUG ( printj(env, L"--- RXTXPort.nativeSetParityErrorChar(%#x) called\n", (int)b); ) // Get port setting information. if(!GetCommState(hPort, &PortDCB)) { //Unable to get configuration of the serial port CreateErrorMsg(GetLastError(), lpMsgBuf); IF_DEBUG ( printj(env, L"!!! nativeSetParityErrorChar - GetCommState() error: %s\n", lpMsgBuf); ) ReleaseErrorMsg(lpMsgBuf); return JNI_FALSE; } if(b != 0) { PortDCB.fErrorChar = TRUE; PortDCB.fParity = TRUE; PortDCB.ErrorChar = b; } else { PortDCB.fErrorChar = FALSE; PortDCB.fParity = FALSE; PortDCB.ErrorChar = 0; } if (!SetCommState(hPort, &PortDCB)) { CreateErrorMsg(GetLastError(), lpMsgBuf); IF_DEBUG ( printj(env, L"!!! nativeSetParityErrorChar - SetCommState() error: %s\n", lpMsgBuf); ) ReleaseErrorMsg(lpMsgBuf); return JNI_FALSE; } return JNI_TRUE; } /* nativeGetEndOfInputChar accept: - perform: check the EndOf InputChar return: the EndOfInputChar as an jbyte. -1 on error exceptions: UnsupportedCommOperationException if not implemented comments: * Class: gnu_io_RXTXPort * Method: nativeGetEndOfInputChar * Signature: ()I */ JNIEXPORT jbyte JNICALL Java_gnu_io_RXTXPort_nativeGetEndOfInputChar(JNIEnv *env, jobject jobj) { DCB PortDCB; LPCWSTR lpMsgBuf; HANDLE hPort = get_fd(env, jobj); PortDCB.DCBlength = sizeof(DCB); IF_DEBUG ( printj(env, L"--- RXTXPort.nativeGetEndOfInputChar() called\n"); ) // Get port setting information. if(!GetCommState(hPort, &PortDCB)) { //Unable to get configuration of the serial port CreateErrorMsg(GetLastError(), lpMsgBuf); IF_DEBUG ( printj(env, L"!!! nativeGetEndOfInputChar - GetCommState() error: %s\n", lpMsgBuf); ) ReleaseErrorMsg(lpMsgBuf); return -1; } return (jbyte)PortDCB.EofChar; } /* nativeSetEndOfInputChar accept: The EndOfInputChar as an int perform: set the EndOfInputChar return: JNI_TRUE on success exceptions: UnsupportedCommOperationException if not implemented comments: This may cause troubles on Windows. Lets give it a shot and see what happens. See termios.c for the windows bits. EofChar = val; fBinary = false; //winapi docs say always use true. ? * Class: gnu_io_RXTXPort * Method: nativeSetEndOfInputChar * Signature: (B)Z */ JNIEXPORT jboolean JNICALL Java_gnu_io_RXTXPort_nativeSetEndOfInputChar(JNIEnv *env, jobject jobj, jbyte b) { DCB PortDCB; LPCWSTR lpMsgBuf; HANDLE hPort = get_fd(env, jobj); PortDCB.DCBlength = sizeof(DCB); IF_DEBUG ( printj(env, L"--- RXTXPort.nativeSetEndOfInputChar(%#x) called\n", (int)b); ) // Get port setting information. if(!GetCommState(hPort, &PortDCB)) { //Unable to get configuration of the serial port CreateErrorMsg(GetLastError(), lpMsgBuf); IF_DEBUG ( printj(env, L"!!! nativeSetEndOfInputChar - GetCommState() error: %s\n", lpMsgBuf); ) ReleaseErrorMsg(lpMsgBuf); return JNI_FALSE; } if( b != 0) { PortDCB.fBinary = FALSE; PortDCB.EofChar = b; } else { PortDCB.fBinary = TRUE; PortDCB.EofChar = 0; } if (!SetCommState(hPort, &PortDCB)) { CreateErrorMsg(GetLastError(), lpMsgBuf); IF_DEBUG ( printj(env, L"!!! nativeSetEndOfInputChar - SetCommState() error: %s\n", lpMsgBuf); ) throw_java_exceptionW(env, UNSUPPORTED_COMM_OPERATION, L"nativeSetEndOfInputChar", lpMsgBuf); ReleaseErrorMsg(lpMsgBuf); return JNI_FALSE; } return JNI_TRUE; } /* * Class: gnu_io_RXTXPort * Method: nativeSetUartType * Signature: (Ljava/lang/String{ }Z)Z */ JNIEXPORT jboolean JNICALL Java_gnu_io_RXTXPort_nativeSetUartType(JNIEnv *env, jobject jobj, jstring type, jboolean test) { throw_java_exceptionW(env, UNSUPPORTED_COMM_OPERATION, L"nativeSetUartType", L"Operation not implemented"); return JNI_FALSE; } /* * Class: gnu_io_RXTXPort * Method: nativeGetUartType * Signature: ()Ljava/lang/String{ } */ JNIEXPORT jstring JNICALL Java_gnu_io_RXTXPort_nativeGetUartType(JNIEnv *env, jobject jobj) { throw_java_exceptionW(env, UNSUPPORTED_COMM_OPERATION, L"nativeSetUartType", L"Operation not implemented"); return env->NewStringUTF("Unknown"); } /* * Class: gnu_io_RXTXPort * Method: nativeSetBaudBase * Signature: (I)Z */ JNIEXPORT jboolean JNICALL Java_gnu_io_RXTXPort_nativeSetBaudBase(JNIEnv *env, jobject jobj, jint baudBase) { throw_java_exceptionW(env, UNSUPPORTED_COMM_OPERATION, L"nativeSetBaudBase", L"Operation not implemented"); return JNI_FALSE; } /* * Class: gnu_io_RXTXPort * Method: nativeGetBaudBase * Signature: ()I */ JNIEXPORT jint JNICALL Java_gnu_io_RXTXPort_nativeGetBaudBase(JNIEnv *env, jobject jobj) { throw_java_exceptionW(env, UNSUPPORTED_COMM_OPERATION, L"nativeGetBaudBase", L"Operation not implemented"); return -1; } /* * Class: gnu_io_RXTXPort * Method: nativeSetDivisor * Signature: (I)Z */ JNIEXPORT jboolean JNICALL Java_gnu_io_RXTXPort_nativeSetDivisor(JNIEnv *env, jobject jobj, jint divisor) { throw_java_exceptionW(env, UNSUPPORTED_COMM_OPERATION, L"nativeSetDivisor", L"Operation not implemented"); return JNI_FALSE; } /* * Class: gnu_io_RXTXPort * Method: nativeGetDivisor * Signature: ()I */ JNIEXPORT jint JNICALL Java_gnu_io_RXTXPort_nativeGetDivisor(JNIEnv *env, jobject jobj) { throw_java_exceptionW(env, UNSUPPORTED_COMM_OPERATION, L"nativeGetDivisor", L"Operation not implemented"); return -1; } /* * Class: gnu_io_RXTXPort * Method: nativeSetLowLatency * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_gnu_io_RXTXPort_nativeSetLowLatency(JNIEnv *env, jobject jobj) { throw_java_exceptionW(env, UNSUPPORTED_COMM_OPERATION, L"nativeSetLowLatency", L"Operation not implemented"); return JNI_FALSE; } /* * Class: gnu_io_RXTXPort * Method: nativeGetLowLatency * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_gnu_io_RXTXPort_nativeGetLowLatency(JNIEnv *env, jobject jobj) { throw_java_exceptionW(env, UNSUPPORTED_COMM_OPERATION, L"nativeGetLowLatency", L"Operation not implemented"); return JNI_FALSE; } /* * Class: gnu_io_RXTXPort * Method: nativeSetCallOutHangup * Signature: (Z)Z */ JNIEXPORT jboolean JNICALL Java_gnu_io_RXTXPort_nativeSetCallOutHangup(JNIEnv *env, jobject jobj, jboolean noHup) { throw_java_exceptionW(env, UNSUPPORTED_COMM_OPERATION, L"nativeSetCallOutHangup", L"Operation not implemented"); return JNI_FALSE; } /* * Class: gnu_io_RXTXPort * Method: nativeGetCallOutHangup * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_gnu_io_RXTXPort_nativeGetCallOutHangup(JNIEnv *env, jobject jobj) { throw_java_exceptionW(env, UNSUPPORTED_COMM_OPERATION, L"nativeGetCallOutHangup", L"Operation not implemented"); return JNI_FALSE; }