/////////////////////////////////////////////////////////////////////////////////////////////// // Win32 Communications Library for COM and USB // Developed for the JRCX Project // for the ÒThinking Outside the (Desktop) BoxÓ MindStorms/NSF Project // Author : Drew Jacobs // Institution: Villanova University // Last Revision : 07/22/03 // Permission is granted to distribute or modify this software for academic use // as long as this original authorship notice is retained in the source code. //////////////////////////////////////////////////////////////////////////////////////////////// #include #include #include "jni.h" #include "Communicator.h" #define WIN32_LEAN_AND_MEAN #define DEBUG 1 ////////////////////////////////////////////////////////////// HANDLE hPortFile; bool bOpen = false; ////////////////////////////////////////////////////////////// JNIEXPORT jboolean JNICALL Java_Communicator_openPort (JNIEnv *env, jobject obj, jstring port) { if (bOpen) { if (DEBUG) printf("WARNING: Port Already Open"); return true; } const char *str = env->GetStringUTFChars(port, 0); hPortFile = CreateFile(str, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (hPortFile == INVALID_HANDLE_VALUE) return false; PurgeComm(hPortFile, PURGE_TXCLEAR | PURGE_RXCLEAR); bOpen=true; return true; } ////////////////////////////////////////////////////////////// JNIEXPORT jboolean JNICALL Java_Communicator_setCommProperties (JNIEnv *ev, jobject obj, jint baud) { DCB dcb; dcb.DCBlength = sizeof(DCB); // sizeof(DCB) if(!GetCommState(hPortFile, &dcb)) return false; dcb.BaudRate = CBR_2400; dcb.fBinary = TRUE; dcb.fOutxCtsFlow = FALSE; dcb.fOutxDsrFlow = FALSE; dcb.fDtrControl = DTR_CONTROL_DISABLE; // DTR flow control type dcb.fDsrSensitivity = FALSE; // DSR sensitivity //dcb.fTXContinueOnXoff = 0; // XOFF continues Tx dcb.fOutX = FALSE; // XON/XOFF out flow control dcb.fInX = FALSE; // XON/XOFF in flow control //dcb.fErrorChar = 0; // enable error replacement dcb.fNull = FALSE; // enable null stripping dcb.fRtsControl = RTS_CONTROL_DISABLE; // RTS flow control dcb.fAbortOnError = FALSE; // abort reads/writes on error //dcb.XonLim = 100; //dcb.XoffLim = 100; dcb.ByteSize = 8; // number of bits/byte, 4-8 dcb.Parity = ODDPARITY; // 0-4=no,odd,even,mark,space dcb.StopBits = ONESTOPBIT; // 0,1,2 = 1, 1.5, 2 //dcb.XonChar = 1; //dcb.XoffChar = 2; //dcb.ErrorChar = 0; //dcb.EofChar = 0; //dcb.EvtChar = 0; dcb.fParity = TRUE; return SetCommState(hPortFile, &dcb); } ////////////////////////////////////////////////////////////// JNIEXPORT jboolean JNICALL Java_Communicator_write (JNIEnv *env, jobject obj, jbyteArray sendPacket) { DWORD numBytes; DWORD numWritten; jbyte* packet; numBytes = env->GetArrayLength(sendPacket); packet = env->GetByteArrayElements(sendPacket, 0); WriteFile(hPortFile, packet, numBytes, &numWritten, (struct _OVERLAPPED *)NULL); env->ReleaseByteArrayElements(sendPacket, packet, 0); FlushFileBuffers(hPortFile); if (numWritten != numBytes) return false; return true; } ////////////////////////////////////////////////////////////// JNIEXPORT jbyte JNICALL Java_Communicator_read (JNIEnv *env, jobject obj) { jbyte* ji = new jbyte[1]; DWORD numRead; if (!ReadFile(hPortFile, ji, 1, &numRead, (struct _OVERLAPPED *)NULL)) { DWORD Error = GetLastError(); DWORD Errors; COMSTAT cstat; ClearCommError(hPortFile, &Errors, &cstat); jclass jc = env->FindClass("jRCX/RCXException"); if (jc==0) return 0; env->ThrowNew(jc, "ReadFile Generated an Error while attempting to Read"); ji[0]=0; } if (numRead == 0) { jclass jc = env->FindClass("jRCX/RCXException"); if (jc==0) return 0; env->ThrowNew(jc, "ReadFile failed to read any bytes"); ji[0]=0; } return ji[0]; } ////////////////////////////////////////////////////////////// JNIEXPORT jboolean JNICALL Java_Communicator_setTimeout (JNIEnv *env, jobject obj, jint timeout) { COMMTIMEOUTS timeouts; timeouts.ReadIntervalTimeout = 20; timeouts.ReadTotalTimeoutMultiplier = 1; timeouts.WriteTotalTimeoutMultiplier = 0; timeouts.WriteTotalTimeoutConstant = 0; timeouts.ReadTotalTimeoutConstant = timeout; if(!SetCommTimeouts(hPortFile, &timeouts)) { return false; } return true; } ////////////////////////////////////////////////////////////// JNIEXPORT jboolean JNICALL Java_Communicator_closePort (JNIEnv *env, jobject obj) { if (!bOpen) { if (DEBUG) printf("WARNING: Port Already Closed"); return true; } CloseHandle(hPortFile); bOpen = false; return true; }