Fix problem with sbs config xml parsing. Make sure to trim error message to avoid erroneously adding an error when there is none. Fix problem with adding system includes for variants.
/*
* 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));
}
}