| author | timkelly |
| Fri, 03 Sep 2010 14:56:39 -0500 | |
| changeset 1952 | bb7feef4fb1d |
| parent 1115 | f2b4c39f3e7b |
| permissions | -rw-r--r-- |
/* * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). * All rights reserved. * This component and the accompanying materials are made available * under the terms of the License "Eclipse Public License v1.0" * which accompanies this distribution, and is available * at the URL "http://www.eclipse.org/legal/epl-v10.html". * * Initial Contributors: * Nokia Corporation - initial contribution. * * Contributors: * * Description: * */ // GetTRKVersion.cpp : Defines the entry point for the DLL application. // #include "stdafx.h" #include "GetTRKVersion.h" #include "com_nokia_carbide_trk_support_service_TRKConnectedService.h" BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } #define MIN(x, y) (((x) < (y)) ? (x) : (y)) static const DWORD kNoPingError = -1; static const DWORD kNoVersionError = -2; const DWORD kBaudRates[] = { 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400 }; enum { FlowHardware = 1, FlowSoftware = 2 }; static void SetDCB(DCB* ioDCB, int baudIndex, int dataBits, int parity, int stopBits, int flowControl) { ioDCB->DCBlength = sizeof( DCB ); ioDCB->BaudRate = kBaudRates[baudIndex]; ioDCB->ByteSize = dataBits+4; ioDCB->Parity = parity; ioDCB->StopBits = stopBits; // setup hardware flow control if (flowControl == FlowHardware) ioDCB->fRtsControl = RTS_CONTROL_HANDSHAKE; else ioDCB->fRtsControl = RTS_CONTROL_DISABLE; ioDCB->fOutxCtsFlow = (flowControl == FlowHardware); ioDCB->fDtrControl = DTR_CONTROL_ENABLE; ioDCB->fDsrSensitivity = false; // setup software flow control if (flowControl == FlowSoftware) { ioDCB->fInX = ioDCB->fOutX = 1; ioDCB->XonChar = '\021'; // Ctrl-Q; ioDCB->XoffChar = '\023'; // Ctrl-S; ioDCB->XonLim = 100; ioDCB->XoffLim = 100; } else { ioDCB->fInX = ioDCB->fOutX = 0; } // other various settings ioDCB->fBinary = TRUE; ioDCB->fParity = TRUE; ioDCB->fNull = FALSE; ioDCB->fAbortOnError = FALSE; } static DWORD OpenSerialPort(const char* inPortName, int baudIndex, int dataBits, int parity, int stopBits, int flowControl, HANDLE& serialPortHandle) { serialPortHandle = CreateFile(inPortName, GENERIC_READ|GENERIC_WRITE, 0, // lock the port so no one else can get it NULL, // no attributes OPEN_EXISTING, 0, NULL ); if (serialPortHandle == (HANDLE)-1) { return GetLastError(); } if (!SetCommMask(serialPortHandle, EV_RXCHAR)) // WaitCommEvent notified by RX Events { CloseHandle(serialPortHandle); return GetLastError(); } if (!SetupComm(serialPortHandle, 4096, 4096)) // 4K Tx and Rx Buffers { CloseHandle(serialPortHandle); return GetLastError(); } // Get rid of any junk that might be sitting there. PurgeComm(serialPortHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ); // Using these settings, the ReadFile command will return immediately // rather than waiting for a timeout. COMMTIMEOUTS lclCommTimeOuts; lclCommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF; lclCommTimeOuts.ReadTotalTimeoutMultiplier = 0; lclCommTimeOuts.ReadTotalTimeoutConstant = 0; lclCommTimeOuts.WriteTotalTimeoutMultiplier = 0; lclCommTimeOuts.WriteTotalTimeoutConstant = 2001UL; if (!SetCommTimeouts(serialPortHandle, &lclCommTimeOuts)) { CloseHandle(serialPortHandle); return GetLastError(); } if (baudIndex >= 0) { DCB dcb; if (!GetCommState(serialPortHandle, &dcb)) { CloseHandle(serialPortHandle); return GetLastError(); } SetDCB(&dcb, baudIndex, dataBits, parity, stopBits, flowControl); if (!SetCommState(serialPortHandle, &dcb)) { CloseHandle(serialPortHandle); return GetLastError(); } } return ERROR_SUCCESS; } static void Disconnect(HANDLE serialPortHandle) { // disable event notification SetCommMask(serialPortHandle, 0); // drop DTR EscapeCommFunction(serialPortHandle, CLRDTR); // purge any outstanding reads/writes and close device handle PurgeComm(serialPortHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); CloseHandle(serialPortHandle); } // inData: Pointer to data buffer to send // inSize: Size of data to send static DWORD SendData(HANDLE serialPortHandle, const void* inData, unsigned long inSize) { DWORD lclNumBytes; if (WriteFile(serialPortHandle, inData, inSize, &lclNumBytes, NULL)) return ERROR_SUCCESS; return GetLastError(); } // inSize: Size of data to read in bytes // outData: Pointer to data buffer to read data into // outSize: Size actually read in bytes static DWORD ReadData(HANDLE serialPortHandle, unsigned long inSize, void* outData, unsigned long &outSize) { // Init our number of bytes read to zero outSize = 0; COMSTAT lclComStat; DWORD lclErrorFlags; DWORD lclLength; // clear out any errors in the channel and get the length of the buffer ClearCommError(serialPortHandle, &lclErrorFlags, &lclComStat); lclLength = MIN(inSize, lclComStat.cbInQue ); if (lclLength > 0) { // Read lclLength number of bytes into outData. if (!ReadFile(serialPortHandle, outData, lclLength, &outSize, NULL)) return GetLastError(); } return ERROR_SUCCESS; } static DWORD ReceiveData(HANDLE serialPortHandle, unsigned long timeout, unsigned long inSize, void* outData, unsigned long &outSize) { const unsigned long kSleepMillis = 10; DWORD error = 0; int maxIters = timeout/kSleepMillis; int i = 0; for (; i < maxIters; i++) { error = ReadData(serialPortHandle, inSize, outData, outSize); if (error != ERROR_SUCCESS) return error; if (outSize > 0) break; else Sleep(kSleepMillis); } if (i == maxIters) return kNoPingError; return ERROR_SUCCESS; } static bool IsVersions3EnabledTRK(long major, long minor, long micro) { return major > 3 || (major == 3 && minor > 2) || (major == 3 && minor == 2 && micro >= 4); } __declspec(dllexport) DWORD GetTRKVersion(const char* inPortName, int baudIndex, int dataBits, int parity, int stopBits, int flowControl, long version[4]) { // open the serial port HANDLE serialPortHandle = NULL; DWORD error = OpenSerialPort(inPortName, baudIndex, dataBits, parity, stopBits, flowControl, serialPortHandle); if (error != ERROR_SUCCESS) return error; // send a ping command unsigned char pingTxBuf[] = { 0x7e, 0x00, 0x00, 0xff, 0x7e }; error = SendData(serialPortHandle, &pingTxBuf, 5); if (error != ERROR_SUCCESS) { Disconnect(serialPortHandle); return error; } // receive response unsigned char pingRxBuf[16]; unsigned long pingRxSize = 0; error = ReceiveData(serialPortHandle, 2001UL, 16, pingRxBuf, pingRxSize); if (error != ERROR_SUCCESS) { Disconnect(serialPortHandle); return error; } // send get version command unsigned char versTxBuf[] = { 0x7e, 0x08, 0x01, 0xf6, 0x7e }; error = SendData(serialPortHandle, &versTxBuf, 5); if (error != ERROR_SUCCESS) { Disconnect(serialPortHandle); return error; } // receive response unsigned char versRxBuf[16]; unsigned long versRxSize = 0; error = ReceiveData(serialPortHandle, 2001UL, 16, versRxBuf, versRxSize); if (error != ERROR_SUCCESS) { Disconnect(serialPortHandle); if (error == kNoPingError) return kNoVersionError; // ping ok, but no version return error; } if (versRxSize >= 9) { version[0] = versRxBuf[4]; version[1] = versRxBuf[5]; version[2] = versRxBuf[8]; version[3] = 0; // unknown TRK if (IsVersions3EnabledTRK(version[0], version[1], version[2])) { // send versions3 command unsigned char vers3TxBuf[] = {0x7e, 0x51, 0x02, 0xac, 0x7e}; error = SendData(serialPortHandle, &vers3TxBuf, 5); if (error != ERROR_SUCCESS) { Disconnect(serialPortHandle); return error; } // receive response unsigned char vers3RxBuf[64]; unsigned long vers3RxSize = 0; error = ReceiveData(serialPortHandle, 2001UL, 64, vers3RxBuf, vers3RxSize); if (error != ERROR_SUCCESS) { Disconnect(serialPortHandle); return error; } version[3] = 1; // AppTRK unsigned char SYS_TRK_NAME[] = {0x0a, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x54, 0x52, 0x4b}; unsigned long SYS_TRK_NAME_LEN = sizeof(SYS_TRK_NAME); const int SYS_TRK_NAME_OFFSET = 10; if (vers3RxSize >= (SYS_TRK_NAME_LEN + SYS_TRK_NAME_OFFSET)) { unsigned char nameBuf[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; memcpy(nameBuf, vers3RxBuf + SYS_TRK_NAME_OFFSET, SYS_TRK_NAME_LEN); if (memcmp(nameBuf, SYS_TRK_NAME, SYS_TRK_NAME_LEN) == 0) version[3] = 2; // SysTRK } } } Disconnect(serialPortHandle); return ERROR_SUCCESS; } static const char* GetErrorText(DWORD error) { if (error == kNoPingError) return "TRK did not respond"; else if (error == kNoVersionError) return "TRK responded to PING, but not to GETVERSION command"; else if (error == ERROR_FILE_NOT_FOUND) return "Could not open the serial port"; static char msg[256]; FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &msg, sizeof(msg) - 1, NULL); return msg; } /* * Class: com_nokia_carbide_trk_support_service_TRKConnectedService * Method: getTRKVersionFromSerial * Signature: (Ljava/lang/String;IIIII[I)V */ JNIEXPORT void JNICALL Java_com_nokia_carbide_trk_support_service_TRKConnectedService_getTRKVersionFromSerial (JNIEnv* env, jclass, jstring jPortName, jint jBaud, jint jDataBits, jint jParity, jint jStopBits, jint jFlowControl, jintArray jVersionInts) { const char* portName = env->GetStringUTFChars(jPortName, NULL); jint versionInts[4]; DWORD error = GetTRKVersion(portName, jBaud, jDataBits, jParity, jStopBits, jFlowControl, versionInts); env->SetIntArrayRegion(jVersionInts, 0, 4, versionInts); env->ReleaseStringUTFChars(jPortName, portName); if (error > ERROR_SUCCESS) { jclass clazz = env->FindClass("Ljava/lang/Exception;"); env->ThrowNew(clazz, GetErrorText(error)); } }