connectivity/com.nokia.tcf/native/TCFNative/TCFCommSerial/RealSerialComm.cpp
changeset 60 9d2210c8eed2
child 366 b054461d2f85
equal deleted inserted replaced
59:c892c53c664e 60:9d2210c8eed2
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 // RealSerialComm.cpp: implementation of the CRealSerialComm class.
       
    18 //
       
    19 //////////////////////////////////////////////////////////////////////
       
    20 
       
    21 #include "stdafx.h"
       
    22 #include "RealSerialComm.h"
       
    23 //#include "pn_const.h"
       
    24 //#include "OSTConstants.h"
       
    25 #include "Connection.h"
       
    26 
       
    27 #ifdef _DEBUG
       
    28 static char sLogMsg[3000];
       
    29 #endif
       
    30 //////////////////////////////////////////////////////////////////////
       
    31 // Construction/Destruction
       
    32 //////////////////////////////////////////////////////////////////////
       
    33 #ifdef _DEBUG
       
    34 #define LogErrorText(err) { if (err > 0) GetErrorText(err); }
       
    35 #define LogErrorText2(err) { if (err > 0) GetErrorText2(err); }
       
    36 #else
       
    37 #define LogErrorText(err) {}
       
    38 #define LogErrorText2(err) {}
       
    39 #endif
       
    40 
       
    41 #ifdef _DEBUG
       
    42 #define DUMPCOMSTAT(x) DumpComStat(x)
       
    43 #define DUMPCOMSTATP(x) DumpComStatP(x)
       
    44 #else
       
    45 #define DUMPCOMSTAT(x)
       
    46 #define DUMPCOMSTATP(x)
       
    47 #endif
       
    48 
       
    49 CRealSerialComm::CRealSerialComm()
       
    50 {
       
    51 #ifdef _DEBUG
       
    52 	if (gDoLogging)
       
    53 	{
       
    54 		FILE* f = fopen("c:\\tcf\\rscommlog.txt", "at");
       
    55 		fprintf(f, "CRealSerialComm::CRealSerialComm() (default constructor)\n");
       
    56 		fclose(f);
       
    57 	}
       
    58 #endif
       
    59 	m_hSerial = INVALID_HANDLE_VALUE;
       
    60 	m_serialPortName[0] = 0;
       
    61 	m_pBuffer = NULL;
       
    62 	m_ProcDebugLog = NULL;
       
    63 
       
    64 }
       
    65 CRealSerialComm::CRealSerialComm(ConnectData* connectSettings, DWORD connectionId, CBaseProtocol* protocol)
       
    66 {
       
    67 #ifdef _DEBUG
       
    68 	if (gDoLogging)
       
    69 	{
       
    70 		FILE* f = fopen("c:\\tcf\\rscommlog.txt", "at");
       
    71 		fprintf(f, "connectSettings=%x connectionId=%d, protocol=%x\n", connectSettings, connectionId, protocol);
       
    72 		fclose(f);
       
    73 	}
       
    74 #endif
       
    75 	m_hSerial = INVALID_HANDLE_VALUE;
       
    76 	m_serialPortName[0] = 0;
       
    77 	m_pBuffer = NULL;
       
    78 
       
    79 	m_connId = connectionId;
       
    80 	m_Protocol = protocol;
       
    81 
       
    82 	m_ConnectSettings = new ConnectData();
       
    83 	memcpy(m_ConnectSettings, connectSettings, sizeof(ConnectData));
       
    84 
       
    85 #if (defined(LOG_COMM) || defined(LOG_PROCCOMM)) && defined(_DEBUG)
       
    86 	if (gDoLogging)
       
    87 	{
       
    88 		m_CommDebugLog = new TCDebugLog("TCF_Comm", connectionId, 2000L);
       
    89 		m_ProcDebugLog = new TCDebugLog("TCF_CommP", connectionId, 2000L);
       
    90 	}
       
    91 #endif
       
    92 }
       
    93 CRealSerialComm::~CRealSerialComm()
       
    94 {
       
    95 #ifdef _DEBUG
       
    96 	if (gDoLogging)
       
    97 	{
       
    98 		FILE* f = fopen("c:\\tcf\\rscommlog.txt", "at");
       
    99 		fprintf(f, "CRealSerialComm::~CRealSerialComm()\n");
       
   100 		fclose(f);
       
   101 	}
       
   102 #endif
       
   103 	if (m_hSerial != INVALID_HANDLE_VALUE)
       
   104 		::CloseHandle(m_hSerial);
       
   105 
       
   106 	if (m_pBuffer)
       
   107 		delete[] m_pBuffer;
       
   108 
       
   109 }
       
   110 
       
   111 long CRealSerialComm::OpenPort()
       
   112 {
       
   113 	COMMLOGOPEN();
       
   114 	COMMLOGS("CRealSerialComm::OpenPort\n");
       
   115 
       
   116 	long err = TCAPI_ERR_NONE;
       
   117 
       
   118 	char* comPort = m_ConnectSettings->realSerialSettings.comPort;
       
   119 	DWORD baudRate = m_ConnectSettings->realSerialSettings.baudRate;
       
   120 	DWORD dataBits = m_ConnectSettings->realSerialSettings.dataBits;
       
   121 	eParity parity = m_ConnectSettings->realSerialSettings.parity;
       
   122 	eStopBits stopBits = m_ConnectSettings->realSerialSettings.stopBits;
       
   123 	eFlowControl flow = m_ConnectSettings->realSerialSettings.flowControl;
       
   124 
       
   125 	COMMLOGA2("CRealSerialComm::OpenPort comPort=%s baudRate=%d\n", comPort, baudRate);
       
   126 	COMMLOGA2("CRealSerialComm::OpenPort dataBits=%d parity=%d\n", dataBits, parity);
       
   127 	COMMLOGA2("CRealSerialComm::OpenPort stopBits=%d flow=%d\n", stopBits, flow);
       
   128 
       
   129 	// fill in DCB
       
   130 	m_dcb.DCBlength = sizeof(DCB);
       
   131 	m_dcb.BaudRate = baudRate;
       
   132 	m_dcb.ByteSize = dataBits;
       
   133 
       
   134 	// parity
       
   135 	switch(parity)
       
   136 	{
       
   137 	default:
       
   138 	case eParityNone:
       
   139 		m_dcb.fParity = FALSE;
       
   140 		m_dcb.Parity = NOPARITY;
       
   141 		break;
       
   142 	case eParityEven:
       
   143 		m_dcb.fParity = TRUE;
       
   144 		m_dcb.Parity = EVENPARITY;
       
   145 		break;
       
   146 	case eParityOdd:
       
   147 		m_dcb.fParity = TRUE;
       
   148 		m_dcb.Parity = ODDPARITY;
       
   149 		break;
       
   150 	}
       
   151 
       
   152 	// stop bits
       
   153 	switch(stopBits)
       
   154 	{
       
   155 	default:
       
   156 	case eStopBits1:
       
   157 		m_dcb.StopBits = ONESTOPBIT;
       
   158 		break;
       
   159 	case eStopBits15:
       
   160 		m_dcb.StopBits = ONE5STOPBITS;
       
   161 		break;
       
   162 	case eStopBits2:
       
   163 		m_dcb.StopBits = TWOSTOPBITS;
       
   164 		break;
       
   165 	}
       
   166 
       
   167 	// flow control
       
   168 	switch(flow)
       
   169 	{
       
   170 	default:
       
   171 	case eFlowControlNone:
       
   172 		m_dcb.fRtsControl = RTS_CONTROL_DISABLE;
       
   173 		m_dcb.fOutxCtsFlow = FALSE;
       
   174 		m_dcb.fInX = m_dcb.fOutX = FALSE;
       
   175 		break;
       
   176 	case eFlowControlHW:
       
   177 		m_dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
       
   178 		m_dcb.fOutxCtsFlow = TRUE;
       
   179 		m_dcb.fInX = m_dcb.fOutX = FALSE;
       
   180 		break;
       
   181 	case eFlowControlSW:
       
   182 		m_dcb.fRtsControl = RTS_CONTROL_DISABLE;
       
   183 		m_dcb.fOutxCtsFlow = FALSE;
       
   184 		m_dcb.fInX = m_dcb.fOutX = TRUE;
       
   185 		m_dcb.XonChar = '\021';	// Ctrl-Q;
       
   186 		m_dcb.XoffChar = '\023';	// Ctrl-S;
       
   187 		m_dcb.XonLim = 100;
       
   188 		m_dcb.XoffLim = 100;
       
   189 		break;
       
   190 	}
       
   191 
       
   192 	// other things in DCB
       
   193 	m_dcb.fDtrControl = DTR_CONTROL_ENABLE;	
       
   194 	m_dcb.fDsrSensitivity = FALSE;
       
   195 	m_dcb.fBinary = TRUE;
       
   196 	m_dcb.fNull = FALSE;
       
   197 	m_dcb.fAbortOnError = TRUE;		// reads & writes will terminate with errors if one occurs
       
   198 
       
   199 	// translate serial port
       
   200 	char p[20]; char* pp = p;
       
   201 	strncpy(p, comPort, 20);
       
   202 	int len = (int)strlen(p);
       
   203 	for (int i = 0; i < len; i++)
       
   204 	{
       
   205 		p[i] = toupper(p[i]);
       
   206 	}
       
   207 	if (strncmp(p, "COM", 3) == 0)
       
   208 	{
       
   209 		pp+=3;
       
   210 	}
       
   211 	int val = atoi((const char*)pp);
       
   212 	if (val == INT_MIN || val == INT_MAX)
       
   213 	{
       
   214 		err = TCAPI_ERR_INVALID_MEDIA_DATA;
       
   215 	}
       
   216 	else
       
   217 	{
       
   218 		// must translate for CreatFile
       
   219 		_snprintf(m_serialPortName, MAX_COMPORT_SIZE, "\\\\.\\COM%d", val);
       
   220 	}
       
   221 
       
   222 
       
   223 	if (err == TCAPI_ERR_NONE)
       
   224 	{
       
   225 		m_hSerial = CreateFile(m_serialPortName,
       
   226 			GENERIC_READ|GENERIC_WRITE,	// dwDesiredAccess = read & write
       
   227 			0,							// dwSharedMode = 0 ==> device not shared
       
   228 			NULL,						// lpSecurityAttributes = NULL ==> not inheritable
       
   229 			OPEN_EXISTING,				// dwCreationDisposition ==> required for devices
       
   230 			0,							// dwFlagsAndAttributes ==> no special flags or attributes (not overlapped)
       
   231 			NULL );						// hTemplateFile = NULL ==> required for devices
       
   232 
       
   233 		if (m_hSerial != INVALID_HANDLE_VALUE)
       
   234 		{
       
   235 			// TODO: this is really not needed as we're not doing overlapped IO
       
   236 			//   and we're not creating an event nor waiting on that event
       
   237 			if (!SetCommMask(m_hSerial, EV_RXCHAR))
       
   238 			{
       
   239 				::CloseHandle(m_hSerial);
       
   240 				m_hSerial = INVALID_HANDLE_VALUE;
       
   241 				m_lastCommError = GetLastError();
       
   242 				err = TCAPI_ERR_WHILE_CONFIGURING_MEDIA;
       
   243 			}
       
   244 			else
       
   245 			{
       
   246 				// no error from SetCommMask
       
   247 				if (!SetupComm(m_hSerial,MAX_MESSAGE_LENGTH,MAX_SERIAL_MESSAGE_BUFFER_LENGTH))
       
   248 				{
       
   249 					CloseHandle(m_hSerial);
       
   250 					m_hSerial = INVALID_HANDLE_VALUE;
       
   251 					m_lastCommError = GetLastError();
       
   252 					err = TCAPI_ERR_WHILE_CONFIGURING_MEDIA;
       
   253 				}
       
   254 				else
       
   255 				{
       
   256 					// no error from SetupComm
       
   257 					// Get rid of any junk that might be sitting there.
       
   258 					PurgeComm( m_hSerial, PURGE_TXABORT | PURGE_RXABORT |
       
   259 										  PURGE_TXCLEAR | PURGE_RXCLEAR );
       
   260 
       
   261 					// Using these settings, the ReadFile command will return immediately
       
   262 					// rather than waiting for a timeout.
       
   263 					COMMTIMEOUTS lclCommTimeOuts;
       
   264 
       
   265 					lclCommTimeOuts.ReadIntervalTimeout			= MAXDWORD;	// we don't care about time between chars
       
   266 					lclCommTimeOuts.ReadTotalTimeoutMultiplier	= 100;
       
   267 					lclCommTimeOuts.ReadTotalTimeoutConstant	= 0;
       
   268 					lclCommTimeOuts.WriteTotalTimeoutMultiplier	= 100;
       
   269 					lclCommTimeOuts.WriteTotalTimeoutConstant	= 0;
       
   270 					
       
   271 					if (!SetCommTimeouts( m_hSerial, &lclCommTimeOuts ))
       
   272 					{
       
   273 						CloseHandle(m_hSerial); 
       
   274 						m_hSerial = INVALID_HANDLE_VALUE;
       
   275 						m_lastCommError = GetLastError();
       
   276 						err = TCAPI_ERR_WHILE_CONFIGURING_MEDIA;
       
   277 					}
       
   278 					else
       
   279 					{
       
   280 						// no error from SetCommTimeouts
       
   281 						err = SetDCB();
       
   282 						if (err != TCAPI_ERR_NONE)
       
   283 						{
       
   284 							CloseHandle(m_hSerial); 
       
   285 							m_hSerial = INVALID_HANDLE_VALUE;
       
   286 						}
       
   287 						else
       
   288 						{
       
   289 							// no error from SetDCB 
       
   290 							err = TCAPI_ERR_NONE;
       
   291 							m_numberBytes = 0;
       
   292 							m_lastCommError = 0;
       
   293 							m_isConnected = true;
       
   294 							m_pBuffer = new BYTE[MAX_SERIAL_MESSAGE_BUFFER_LENGTH];
       
   295 						}
       
   296 					}
       
   297 				}
       
   298 			}
       
   299 		}
       
   300 		else
       
   301 		{
       
   302 			// error from CreateFile
       
   303 			// couldn't open serial port
       
   304 			m_lastCommError = GetLastError();
       
   305 			err = TCAPI_ERR_WHILE_CONFIGURING_MEDIA;
       
   306 		}
       
   307 	}
       
   308 
       
   309 	COMMLOGA2("CRealSerialComm::OpenPort err=%d osError=%d\n", err, m_lastCommError);
       
   310 	LogErrorText(m_lastCommError);
       
   311 //	if (m_lastCommError > 0)
       
   312 //		LogErrorText(m_lastCommError);
       
   313 	COMMLOGCLOSE();
       
   314 	return err;
       
   315 }
       
   316 
       
   317 long CRealSerialComm::SetDCB()
       
   318 {
       
   319 	// assumes serial port is open
       
   320 	long err = TCAPI_ERR_NONE;
       
   321 	if (m_hSerial == INVALID_HANDLE_VALUE)
       
   322 		return err;
       
   323 
       
   324 	// setup DCB
       
   325 	DCB lcldcb;
       
   326 	lcldcb.DCBlength = sizeof(DCB);
       
   327 
       
   328 	if (!GetCommState( m_hSerial, &lcldcb ))
       
   329 	{
       
   330 		m_lastCommError = GetLastError();
       
   331 		err = TCAPI_ERR_WHILE_CONFIGURING_MEDIA;
       
   332 	}
       
   333 
       
   334 //	LogDCB(pInfo);
       
   335 	// copy only the ones that Connect() set initially
       
   336 	lcldcb.BaudRate = m_dcb.BaudRate;
       
   337 	lcldcb.ByteSize = m_dcb.ByteSize;
       
   338 	lcldcb.Parity = m_dcb.Parity;
       
   339 	lcldcb.StopBits = m_dcb.StopBits;
       
   340 	lcldcb.fRtsControl = m_dcb.fRtsControl;
       
   341 	lcldcb.fOutxCtsFlow = m_dcb.fOutxCtsFlow;
       
   342 	lcldcb.fDtrControl = m_dcb.fDtrControl;
       
   343 	lcldcb.fDsrSensitivity = m_dcb.fDsrSensitivity;
       
   344 	lcldcb.fInX = m_dcb.fInX;
       
   345 	lcldcb.fOutX = m_dcb.fOutX;
       
   346 	lcldcb.XonChar = m_dcb.XonChar;
       
   347 	lcldcb.XoffChar = m_dcb.XoffChar;
       
   348 	lcldcb.XonLim = m_dcb.XonLim;
       
   349 	lcldcb.XoffLim = m_dcb.XoffLim;
       
   350 	lcldcb.fBinary = m_dcb.fBinary;
       
   351 	lcldcb.fParity = m_dcb.fParity;
       
   352 	lcldcb.fNull = m_dcb.fNull;
       
   353 	lcldcb.fAbortOnError = m_dcb.fAbortOnError;
       
   354 
       
   355 	// DCB has been changed
       
   356 	// If setting the port went well then we are connected properly!
       
   357 	if (!SetCommState( m_hSerial, &lcldcb))
       
   358 	{
       
   359 		m_lastCommError = GetLastError();
       
   360 		err = TCAPI_ERR_WHILE_CONFIGURING_MEDIA;
       
   361 	}
       
   362 
       
   363 	return err;
       
   364 }
       
   365 
       
   366 long CRealSerialComm::ClosePort()
       
   367 {
       
   368 	COMMLOGOPEN();
       
   369 	COMMLOGS("CRealSerialComm::ClosePort\n");
       
   370 
       
   371 	long err = TCAPI_ERR_NONE;
       
   372 
       
   373 	if (!IsConnected()) 
       
   374 	{
       
   375 
       
   376 		err = TCAPI_ERR_MEDIA_NOT_OPEN;
       
   377 	}
       
   378 	else if (m_hSerial != INVALID_HANDLE_VALUE)
       
   379 	{
       
   380 		// disable event notification 
       
   381 		SetCommMask( m_hSerial, 0 );
       
   382 
       
   383 		// drop DTR
       
   384 		EscapeCommFunction( m_hSerial, CLRDTR );
       
   385 
       
   386 		// purge any outstanding reads/writes and close device handle
       
   387 		PurgeComm(	m_hSerial, 
       
   388 					PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
       
   389 		
       
   390 		CloseHandle( m_hSerial );
       
   391 		m_hSerial = INVALID_HANDLE_VALUE;
       
   392 
       
   393 		if (m_pBuffer)
       
   394 		{
       
   395 			delete[] m_pBuffer;
       
   396 			m_pBuffer = NULL;
       
   397 		}
       
   398 		m_isConnected = false;
       
   399 	}
       
   400 
       
   401 	COMMLOGCLOSE();
       
   402 	return err;
       
   403 }
       
   404 
       
   405 void CRealSerialComm::DeleteMsg(DWORD inMsgLength)
       
   406 {
       
   407 	if (!IsConnected())
       
   408 		return;
       
   409 	// inMsgLength includes header
       
   410 	// delete from beginning of buffer
       
   411 	if (inMsgLength == 0)
       
   412 		return;
       
   413 	if (m_numberBytes > 0 && m_numberBytes >= inMsgLength)
       
   414 	{
       
   415 		size_t moveLen = m_numberBytes - inMsgLength;
       
   416 		if (moveLen > 0)
       
   417 			memcpy(&m_pBuffer[0], &m_pBuffer[inMsgLength], moveLen);
       
   418 		m_numberBytes -= inMsgLength;
       
   419 	}
       
   420 }
       
   421 
       
   422 long CRealSerialComm::SendDataToPort(DWORD inSize, const void *inData)
       
   423 {
       
   424 
       
   425 	long err = TCAPI_ERR_NONE;
       
   426 	DWORD lclNumBytes=0;
       
   427 	COMMLOGOPEN();
       
   428 	COMMLOGS("CRealSerialComm::SendDataToPort\n");
       
   429 	COMMLOGCLOSE();
       
   430 	if (!IsConnected())
       
   431 	{
       
   432 
       
   433 		COMMLOGOPEN();
       
   434 		COMMLOGS("CRealSerialComm::SendDataToPort notConnected\n");
       
   435 		COMMLOGCLOSE();
       
   436 		return TCAPI_ERR_MEDIA_NOT_OPEN;
       
   437 	}
       
   438 
       
   439 	if (WriteFile(m_hSerial, inData, inSize, &lclNumBytes, NULL))
       
   440 	{
       
   441 		// we were successful, but did we send all data? (i.e., a timeout occurred)
       
   442 		// we are not doing overlapped I/O so if not all data went, then we timed out
       
   443 		//   and there was some kind of error
       
   444 		if (lclNumBytes != inSize)
       
   445 		{
       
   446 			COMMLOGOPEN();
       
   447 			COMMLOGA3("CRealSerialComm::SendDataToPort WriteFile not all bytes sent: lclNumBytes=%d inSize=%d err=%d\n", lclNumBytes, inSize, GetLastError());
       
   448 			COMMLOGCLOSE();
       
   449 
       
   450 			COMSTAT lclComStat;
       
   451 			DWORD lclErrorFlags = 0;
       
   452 			if (!ClearCommError(m_hSerial, &lclErrorFlags, &lclComStat))
       
   453 			{
       
   454 				// clear comm error returned error (this doesn't normally happen if the handle is valid and port is still open)
       
   455 				m_lastCommError = GetLastError();
       
   456 				err = TCAPI_ERR_COMM_ERROR;
       
   457 				COMMLOGOPEN();
       
   458 				COMMLOGA1("CRealSerialComm::SendDataToPort ClearCommError failed=%d\n", m_lastCommError);
       
   459 				COMMLOGCLOSE();
       
   460 			}
       
   461 			else
       
   462 			{
       
   463 				// clear comm error returned OK
       
   464 				// check error flags
       
   465 				if (lclErrorFlags)
       
   466 				{
       
   467 					// there really was an error
       
   468 					m_lastCommError = lclErrorFlags;
       
   469 					err = TCAPI_ERR_COMM_ERROR;
       
   470 					COMMLOGOPEN();
       
   471 					COMMLOGA1("CRealSerialComm::SendDataToPort ClearCommError succeeded lclErrorFlags=%d\n", m_lastCommError);
       
   472 					COMMLOGCLOSE();
       
   473 				}
       
   474 				else
       
   475 				{
       
   476 					// No OS error returned, but WriteFile failed to write out all bytes
       
   477 					//  therefore, since we are not doing overlapped I/O, this is an error.
       
   478 					err = TCAPI_ERR_COMM_ERROR;
       
   479 					COMMLOGOPEN();
       
   480 					COMMLOGS("CRealSerialComm::SendDataToPort ClearCommError succeeded lclErrorFlags=0\n");
       
   481 					COMMLOGCLOSE();
       
   482 //					DUMPCOMSTAT(&lclComStat);
       
   483 				}
       
   484 			}
       
   485 		}
       
   486 		else
       
   487 		{
       
   488 			// we sent all the data we requested
       
   489 			err = TCAPI_ERR_NONE;
       
   490 #ifdef _DEBUG
       
   491 			COMMLOGOPEN();
       
   492 			COMMLOGS("CRealSerialComm::SendDataToPort WriteFile successful\n");
       
   493 			BYTE* ptr = (BYTE*)inData;
       
   494 			long numBytes = (inSize > 20) ? 20 : inSize;
       
   495 			char msg[200];
       
   496 			sprintf(msg, "CRealSerialComm::SendDataToPort = ");
       
   497 			for (int i = 0; i < numBytes; i++)
       
   498 			{
       
   499 				sprintf(msg, "%s %02.2x", msg, ptr[i]);
       
   500 			}
       
   501 			sprintf(msg, "%s\n", msg);
       
   502 			COMMLOGS(msg);
       
   503 			COMMLOGCLOSE();
       
   504 #endif
       
   505 		}
       
   506 	}
       
   507 	else
       
   508 	{
       
   509 		// write failed
       
   510 		m_lastCommError = GetLastError();
       
   511 		err = TCAPI_ERR_COMM_ERROR;
       
   512 		COMMLOGOPEN();
       
   513 		COMMLOGA1("CRealSerialComm::SendDataToPort WriteFile failed = %d\n", m_lastCommError);
       
   514 		COMMLOGCLOSE();
       
   515 	}
       
   516 	
       
   517 	return err;
       
   518 }
       
   519 long CRealSerialComm::PollPort(DWORD &outSize)
       
   520 {
       
   521 	long err = TCAPI_ERR_NONE;
       
   522 	outSize = 0;
       
   523 
       
   524 	COMSTAT lclComStat;
       
   525 	DWORD lclErrorFlags=0;
       
   526 
       
   527 	if (!IsConnected())
       
   528 		return TCAPI_ERR_MEDIA_NOT_OPEN;
       
   529 
       
   530 //	Sleep(1);
       
   531 	if (!ClearCommError( m_hSerial, &lclErrorFlags, &lclComStat ))
       
   532 	{
       
   533 		m_lastCommError = GetLastError();
       
   534 		err = TCAPI_ERR_COMM_ERROR;
       
   535 
       
   536 		PROCLOGOPEN();
       
   537 		PROCLOGA1("CRealSerialComm::PollPort ClearCommError failed=%d\n", m_lastCommError);
       
   538 //		if (m_lastCommError > 0)
       
   539 		LogErrorText2(m_lastCommError);
       
   540 		PROCLOGCLOSE();
       
   541 	}
       
   542 	else
       
   543 	{
       
   544 		// ClearCommError succeeded
       
   545 		if (lclErrorFlags)
       
   546 		{
       
   547 			m_lastCommError = lclErrorFlags;
       
   548 			err = TCAPI_ERR_COMM_ERROR;
       
   549 			PROCLOGOPEN();
       
   550 			PROCLOGA1("CRealSerialComm::PollPort ClearCommError succeeded but lclErrorFlags=%d\n", m_lastCommError);
       
   551 			PROCLOGCLOSE();
       
   552 		}
       
   553 		else
       
   554 		{
       
   555 //			DUMPCOMSTATP(&lclComStat);
       
   556 //			PROCLOGOPEN();
       
   557 //			PROCLOGA1("CRealSerialComm::PollPort ClearCommError succeeded cbInQue=%d\n", lclComStat.cbInQue);
       
   558 //			PROCLOGCLOSE();
       
   559 			m_lastCommError = 0;
       
   560 		}
       
   561 		outSize = lclComStat.cbInQue;
       
   562 	}
       
   563 
       
   564 	return err;
       
   565 }
       
   566 #ifdef _DEBUG
       
   567 void CRealSerialComm::DumpComStat(COMSTAT* stat)
       
   568 {
       
   569 	COMMLOGOPEN();
       
   570 	COMMLOGA3(" comstat fCtsHold =%d fDsrHold =%d fRlsdHold=%d\n", stat->fCtsHold, stat->fDsrHold, stat->fRlsdHold);
       
   571 	COMMLOGA3(" comstat fXoffHold=%d fXoffSent=%d fEof     =%d\n", stat->fXoffHold, stat->fXoffSent, stat->fEof);
       
   572 	COMMLOGA3(" comstat fTxim    =%d cbInQue  =%d cbOutQue =%d\n", stat->fTxim, stat->cbInQue, stat->cbOutQue);
       
   573 	COMMLOGCLOSE();
       
   574 }
       
   575 void CRealSerialComm::DumpComStatP(COMSTAT* stat)
       
   576 {
       
   577 	PROCLOGOPEN();
       
   578 	PROCLOGA3(" comstat fCtsHold =%d fDsrHold =%d fRlsdHold=%d\n", stat->fCtsHold, stat->fDsrHold, stat->fRlsdHold);
       
   579 	PROCLOGA3(" comstat fXoffHold=%d fXoffSent=%d fEof     =%d\n", stat->fXoffHold, stat->fXoffSent, stat->fEof);
       
   580 	PROCLOGA3(" comstat fTxim    =%d cbInQue  =%d cbOutQue =%d\n", stat->fTxim, stat->cbInQue, stat->cbOutQue);
       
   581 	PROCLOGCLOSE();
       
   582 }
       
   583 #endif
       
   584 long CRealSerialComm::ReadPort(DWORD inSize, void *outData, DWORD &outSize)
       
   585 {
       
   586 	long err = TCAPI_ERR_NONE;
       
   587 	outSize = 0;
       
   588 
       
   589 	COMSTAT lclComStat;
       
   590 	DWORD lclErrorFlags=0;
       
   591 	DWORD lclLength;
       
   592 	if (!IsConnected())
       
   593 		return TCAPI_ERR_MEDIA_NOT_OPEN;
       
   594 
       
   595 	// clear out any errors in the channel and get the length of the buffer
       
   596 	if (!ClearCommError( m_hSerial, &lclErrorFlags, &lclComStat ))
       
   597 	{
       
   598 		// ClearCommError failed
       
   599 		m_lastCommError = GetLastError();
       
   600 		err = TCAPI_ERR_COMM_ERROR;
       
   601 		PROCLOGOPEN();
       
   602 		PROCLOGA1("CRealSerialComm::ReadPort ClearCommError failed=%d\n", m_lastCommError);
       
   603 		PROCLOGCLOSE();
       
   604 	}
       
   605 	else
       
   606 	{
       
   607 		if (lclErrorFlags)
       
   608 		{
       
   609 			m_lastCommError = lclErrorFlags;
       
   610 			err = TCAPI_ERR_COMM_ERROR;
       
   611 			PROCLOGOPEN();
       
   612 			PROCLOGA1("CRealSerialComm::ReadPort ClearCommError succeeded but lclErrorFlags=%d\n", m_lastCommError);
       
   613 			PROCLOGCLOSE();
       
   614 		}
       
   615 		else
       
   616 		{
       
   617 			m_lastCommError = 0;
       
   618 
       
   619 			lclLength = min( inSize, lclComStat.cbInQue );
       
   620 
       
   621 			if (lclLength > 0)
       
   622 			{
       
   623 				// Read lclLength number of bytes into outData.
       
   624 				if (!ReadFile(m_hSerial,outData,lclLength,&outSize,NULL))
       
   625 				{
       
   626 					m_lastCommError = GetLastError();
       
   627 					err = TCAPI_ERR_COMM_ERROR;
       
   628 					PROCLOGOPEN();
       
   629 					PROCLOGA1("CRealSerialComm::ReadPort ReadFile failed = %d\n", m_lastCommError);
       
   630 					PROCLOGCLOSE();
       
   631 				}
       
   632 				else
       
   633 				{
       
   634 					// ReadFile returned successful, check to see all our bytes came in
       
   635 					//  If a timeout happened - we may not get all the data
       
   636 					if (lclLength != outSize)
       
   637 					{
       
   638 						lclErrorFlags = 0;
       
   639 						if (!ClearCommError( m_hSerial, &lclErrorFlags, &lclComStat ))
       
   640 						{
       
   641 							// ClearCommError failed
       
   642 							m_lastCommError = GetLastError();
       
   643 							err = TCAPI_ERR_COMM_ERROR;
       
   644 							PROCLOGOPEN();
       
   645 							PROCLOGA1("CRealSerialComm::ReadPort ClearCommError failed=%d\n", m_lastCommError);
       
   646 							PROCLOGCLOSE();
       
   647 						}
       
   648 						else
       
   649 						{
       
   650 							// ClearCommError succeeded
       
   651 							if (lclErrorFlags)
       
   652 							{
       
   653 								// there really was an error
       
   654 								m_lastCommError = lclErrorFlags;
       
   655 								err = TCAPI_ERR_COMM_ERROR;
       
   656 								PROCLOGOPEN();
       
   657 								PROCLOGA1("CRealSerialComm::ReadPort ReadFile succeeded-not all data read lclErrorFlags=%d\n", m_lastCommError);
       
   658 								PROCLOGCLOSE();
       
   659 							}
       
   660 							else
       
   661 							{
       
   662 								// Since we are not doing overlapped I/O 
       
   663 								//  and our timeout values say to timeout, we should read all the bytes
       
   664 								//  that the last Poll told us, if not this is an error
       
   665 								err = TCAPI_ERR_COMM_ERROR;
       
   666 								PROCLOGOPEN();
       
   667 								PROCLOGS("CRealSerialComm::ReadPort ReadFile succeeded-not all data read lclErrorFlags=0\n");
       
   668 								PROCLOGCLOSE();
       
   669 							}
       
   670 						}
       
   671 					}
       
   672 					else
       
   673 					{
       
   674 						// all data read
       
   675 						m_lastCommError = 0;
       
   676 						PROCLOGOPEN();
       
   677 						PROCLOGS("CRealSerialComm::ReadPort ReadFile successful\n");
       
   678 						PROCLOGCLOSE();
       
   679 					}
       
   680 				}
       
   681 			}
       
   682 		}
       
   683 	}
       
   684 
       
   685 	return err;
       
   686 }
       
   687 
       
   688 long CRealSerialComm::ProcessBuffer(CConnection* pConn, CRegistry* pRegistry, long& numberProcessed)
       
   689 {
       
   690 	PROCLOGOPEN();
       
   691 	PROCLOGS("CRealSerialComm::ProcessBuffer\n");
       
   692 	PROCLOGCLOSE();
       
   693 
       
   694 	long err = TCAPI_ERR_NONE;
       
   695 	long routingErr = TCAPI_ERR_NONE;
       
   696 
       
   697 	if (!IsConnected())
       
   698 		return TCAPI_ERR_MEDIA_NOT_OPEN;
       
   699 
       
   700 	if (!m_Protocol)
       
   701 		return TCAPI_ERR_UNKNOWN_MEDIA_TYPE;
       
   702 
       
   703 	DWORD protocolHeaderLength = m_Protocol->GetHeaderLength();
       
   704 
       
   705 	// fill buffer
       
   706 	if (m_numberBytes < MAX_SERIAL_MESSAGE_BUFFER_LENGTH)
       
   707 	{
       
   708 		DWORD outLen = 0;
       
   709 		err = PollPort(outLen);
       
   710 		if (err == TCAPI_ERR_NONE && outLen > 0)
       
   711 		{
       
   712 			if (outLen > (MAX_SERIAL_MESSAGE_BUFFER_LENGTH - m_numberBytes))
       
   713 				outLen = MAX_SERIAL_MESSAGE_BUFFER_LENGTH - m_numberBytes;
       
   714 			BYTE *ptr = &m_pBuffer[m_numberBytes];
       
   715 			err = ReadPort(outLen, ptr, outLen);
       
   716 			if (err == TCAPI_ERR_NONE && outLen > 0)
       
   717 			{
       
   718 				m_numberBytes += outLen;
       
   719 			}
       
   720 		}
       
   721 	}
       
   722 	// now process buffer but only for complete messages
       
   723 	if (err == TCAPI_ERR_NONE)
       
   724 	{
       
   725 		if (m_numberBytes >= protocolHeaderLength)
       
   726 		{
       
   727 			BYTE* ptr = m_pBuffer;
       
   728 			long bytesRemaining = m_numberBytes;
       
   729 			long usedLen = 0;
       
   730 			bool done = false;
       
   731 
       
   732 			while (!done)
       
   733 			{
       
   734 				DWORD fullMessageLength = bytesRemaining;
       
   735 				DWORD rawLength = 0;
       
   736 				BYTE* fullMessage = ptr;
       
   737 				BYTE* rawMessage = ptr;
       
   738 				BYTE msgId = 0;
       
   739 				if (m_Protocol->DecodeMessage(fullMessage, fullMessageLength, msgId, rawMessage, rawLength))
       
   740 				{
       
   741 					err = PreProcessMessage(msgId, fullMessageLength, fullMessage);
       
   742 					if (err != TCAPI_ERR_NONE)
       
   743 					{
       
   744 						// notify all clients right now 
       
   745 						pConn->NotifyClientsCommError(err, false, 0);
       
   746 						err = TCAPI_ERR_NONE;
       
   747 					}
       
   748 #ifdef _DEBUG
       
   749 					int reallen = fullMessageLength;
       
   750 					if (reallen > 50) reallen = 50;
       
   751 					char msg[6];
       
   752 					msg[0] = '\0';
       
   753 
       
   754 					sLogMsg[0] = '\0';
       
   755 					if (reallen > 0)
       
   756 					{
       
   757 						sLogMsg[0] = '\0';
       
   758 						for (int i = 0; i < reallen; i++)
       
   759 						{
       
   760 							sprintf(msg, "%02.2x ", ptr[i]);
       
   761 							strcat(sLogMsg, msg);
       
   762 						}
       
   763 					}
       
   764 #endif
       
   765 					PROCLOGOPEN();
       
   766 					PROCLOGA5("CRealSerialComm::ProcessBuffer - RouteMesssage pRegistry = %x id=%x len=%d len=%d\n  msg=%s\n", pRegistry, msgId, fullMessageLength, rawLength, sLogMsg);
       
   767 					PROCLOGCLOSE();
       
   768 
       
   769 					err = pRegistry->RouteMessage(msgId, fullMessage, fullMessageLength, rawMessage, rawLength);
       
   770 					if (err != TCAPI_ERR_NONE) routingErr = err; // saved for future
       
   771 
       
   772 					numberProcessed++;
       
   773 					usedLen += fullMessageLength;
       
   774 					bytesRemaining -= fullMessageLength;
       
   775 					ptr += fullMessageLength;
       
   776 					if (bytesRemaining < protocolHeaderLength)
       
   777 						done = true;
       
   778 				}
       
   779 				else
       
   780 				{
       
   781 					done = true;
       
   782 				}
       
   783 			}
       
   784 			DeleteMsg(usedLen);
       
   785 		}
       
   786 	}
       
   787 //	PROCLOGOPEN();
       
   788 //	PROCLOGA1("CRealSerialComm::ProcessBuffer err = %d\n", err);
       
   789 //	PROCLOGCLOSE();
       
   790 	if (routingErr == TCAPI_ERR_NONE)
       
   791 		return err;
       
   792 	else
       
   793 		return routingErr;
       
   794 }
       
   795 bool CRealSerialComm::IsConnectionEqual(ConnectData* pConn)
       
   796 {
       
   797 	bool equal = false;
       
   798 
       
   799 	// forms accepted:
       
   800 	//   "comNN", "NN"
       
   801 	char* ptr1 = m_ConnectSettings->realSerialSettings.comPort;
       
   802 	char* ptr2 = pConn->realSerialSettings.comPort;
       
   803 	bool digit1found = false;
       
   804 	while(!digit1found && *ptr1 != NULL) 
       
   805 	{
       
   806 		if (*ptr1 >= '0' && *ptr1 <= '9')
       
   807 		{
       
   808 			digit1found = true;
       
   809 			break;
       
   810 		}
       
   811 		ptr1++;
       
   812 	}
       
   813 	bool digit2found = false;
       
   814 	while(!digit2found && *ptr2 != NULL) 
       
   815 	{
       
   816 		if (*ptr2 >= '0' && *ptr2 <= '9')
       
   817 		{
       
   818 			digit2found = true;
       
   819 			break;
       
   820 		}
       
   821 		ptr2++;
       
   822 	}
       
   823 	if (digit1found && digit2found)
       
   824 	{
       
   825 		if (strcmp(ptr1, ptr2) == 0)
       
   826 			equal = true;
       
   827 	}
       
   828 	return equal;
       
   829 }
       
   830 
       
   831 #ifdef _DEBUG
       
   832 DWORD CRealSerialComm::GetErrorText(DWORD inError)
       
   833 {
       
   834 	LPVOID lpMsgBuf;
       
   835 	
       
   836 	if (inError == 0) return inError;
       
   837 
       
   838 	FormatMessage( 
       
   839 		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
       
   840 		NULL,
       
   841 		inError,
       
   842 		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 	// Default language
       
   843 		(LPTSTR) &lpMsgBuf,
       
   844 		0,
       
   845 		NULL );
       
   846 
       
   847 	COMMLOGA1(" -- GetErrorText=%s", lpMsgBuf);
       
   848 	// Free the buffer.
       
   849 	LocalFree( lpMsgBuf );
       
   850 	
       
   851 	return inError;
       
   852 }
       
   853 DWORD CRealSerialComm::GetErrorText2(DWORD inError)
       
   854 {
       
   855 	LPVOID lpMsgBuf;
       
   856 	
       
   857 	if (inError == 0) return inError;
       
   858 
       
   859 	FormatMessage( 
       
   860 		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
       
   861 		NULL,
       
   862 		inError,
       
   863 		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 	// Default language
       
   864 		(LPTSTR) &lpMsgBuf,
       
   865 		0,
       
   866 		NULL );
       
   867 
       
   868 	PROCLOGA1(" -- GetErrorText=%s", lpMsgBuf);
       
   869 	// Free the buffer.
       
   870 	LocalFree( lpMsgBuf );
       
   871 	
       
   872 	return inError;
       
   873 }
       
   874 
       
   875 void CRealSerialComm::DumpBuffer(BYTE* ptr, long length)
       
   876 {
       
   877 	char msg[256] = {0};
       
   878 	if (length > 50) length = 50;
       
   879 	for (int i = 0; i < length; i++)
       
   880 	{
       
   881 		sprintf(msg, "%s%02.2X ", msg, ptr[i]);
       
   882 	}
       
   883 	sprintf(msg, "%s\n", msg);
       
   884 	PROCLOGS(msg);
       
   885 }
       
   886 #endif