hti/PC_Tools/HTIGateway/HtiGateway/src/SerialComm.cpp
branchRCL_3
changeset 59 8ad140f3dd41
parent 0 a03f92240627
equal deleted inserted replaced
49:7fdc9a71d314 59:8ad140f3dd41
       
     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 "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 *   This file contains implementation of SerialComm communication channel plugin objects. These classes are SerialComm, SerialCommPlugin and
       
    16 *	SerialCommIoThread classes.
       
    17 */
       
    18 
       
    19 // INCLUDES
       
    20 #include "SerialCommPlugin.h"
       
    21 #include "util.h"
       
    22 
       
    23 #define HIGH_COM_PORT "\\\\.\\"
       
    24 const static int g_SerialMaxResendNumber = 2;
       
    25 
       
    26 //**********************************************************************************
       
    27 // Class SerialCommPlugin
       
    28 //
       
    29 // This class implements a CommChannelPlugin used in serial communication with device
       
    30 //**********************************************************************************
       
    31 
       
    32 SerialCommPlugin::SerialCommPlugin(const CommChannelPluginObserver* observer)
       
    33     : CommChannelPlugin(observer),
       
    34       m_TxQueue(),
       
    35       m_RxQueue(),
       
    36       m_PropertySerialCommTimeout(g_SerialCommDefaultTimeout),
       
    37 	  m_PropertySerialMaxSendSize(0),
       
    38 	  m_ProperySerialSendPause(0),
       
    39 	  m_PropertySerialHwFlowControl(false)
       
    40 {
       
    41     m_IoThread = NULL;
       
    42 }
       
    43 
       
    44 SerialCommPlugin::~SerialCommPlugin()
       
    45 {
       
    46     Util::Debug("SerialCommPlugin::~SerialCommPlugin()");
       
    47     if ( m_Open )
       
    48     {
       
    49         Close();
       
    50     }
       
    51     if ( m_IoThread != NULL )
       
    52     {
       
    53         delete m_IoThread;
       
    54         m_IoThread = NULL;
       
    55     }
       
    56 }
       
    57 
       
    58 /*
       
    59  * This method initializes SerialCommPlugin and starts SerialCommPluginIoThread
       
    60  */
       
    61 DWORD SerialCommPlugin::Init()
       
    62 {
       
    63     Util::Debug("SerialCommPlugin::Init()");
       
    64 
       
    65     std::string filename = SERIAL_INI_FILE_NAME;
       
    66 	//read properties from serialplugin.ini file
       
    67 	Util::ReadProperties(filename.c_str(), m_SerialCommPluginProperties);
       
    68     
       
    69 	CheckProperties(m_SerialCommPluginProperties);
       
    70 
       
    71     CommChannelPlugin::Init();
       
    72 
       
    73     m_IoThread = new SerialCommIoThread(
       
    74 						&m_RxQueue,
       
    75 						&m_TxQueue,
       
    76                         m_PropertySerialCommInitString,
       
    77 						m_PropertySerialCommPort,
       
    78 						m_PropertySerialCommTimeout,
       
    79 						m_PropertySerialHwFlowControl,
       
    80 						m_ProperySerialSendPause,
       
    81 						m_PropertySerialMaxSendSize
       
    82 						);
       
    83 
       
    84 	m_IoThread->Start();
       
    85 
       
    86 	Event e = m_IoThread->GetOpenedEvent();
       
    87     if ( e.Wait(m_PropertySerialCommTimeout) == WAIT_TIMEOUT )
       
    88     {
       
    89         Util::Debug("SerialCommPlugin::Init()   SerialComm opening timed out");
       
    90         m_Open = false;
       
    91         return ERR_DG_COMM_OPEN_TIMEOUT;
       
    92     }
       
    93     Util::Debug("SerialCommPlugin::Init() SerialComm opened");
       
    94     m_Open = true;
       
    95     Util::Debug("SerialCommPlugin::Init() OK");
       
    96     return NO_ERRORS;
       
    97 }
       
    98 
       
    99 /*
       
   100  * This method initializes class member variables from values in map
       
   101  */
       
   102 void SerialCommPlugin::CheckProperties(map<string, string>& props)
       
   103 {
       
   104     char tmp[256];
       
   105 
       
   106     // Init values for connection
       
   107     m_PropertySerialCommInitString = props[SERIAL_INI_INIT_PARAM];
       
   108 	Util::CheckCommandlineParam( PARAM_SWITCH_INIT_PARAM, m_PropertySerialCommInitString );
       
   109     if ( m_PropertySerialCommInitString.empty() )
       
   110     {
       
   111         m_PropertySerialCommInitString = SERIAL_DEFAULT_INIT_STRING;
       
   112     }
       
   113     sprintf_s(tmp, 256, "Connection Init : '%s'", m_PropertySerialCommInitString.c_str());
       
   114     string s(tmp);
       
   115     Util::Debug(s);
       
   116 
       
   117     // comm port
       
   118     m_PropertySerialCommPort = props[SERIAL_INI_COMPORT_PARAM];
       
   119 	Util::CheckCommandlineParam( PARAM_SWITCH_COMPORT_PARAM, m_PropertySerialCommPort );
       
   120     if ( m_PropertySerialCommPort.empty() )
       
   121     {
       
   122         m_PropertySerialCommPort = SERIAL_DEFAULT_COMPORT;
       
   123     }
       
   124     sprintf_s(tmp, 256, "Connection port : '%s'", m_PropertySerialCommPort.c_str());
       
   125     s = tmp;
       
   126     Util::Debug(s);
       
   127 
       
   128     // Serial operations timeout
       
   129     string val = props[SERIAL_INI_COMPORT_TIMEOUT];
       
   130 	Util::CheckCommandlineParam( PARAM_SWITCH_COMPORT_TIMEOUT, val );
       
   131 	m_PropertySerialCommTimeout = 0;
       
   132     if ( !val.empty() )
       
   133     {
       
   134         m_PropertySerialCommTimeout = atol(val.c_str());
       
   135     }
       
   136 
       
   137     if ( m_PropertySerialCommTimeout <= 0 )
       
   138     {
       
   139         m_PropertySerialCommTimeout = g_SerialCommDefaultTimeout;
       
   140     }
       
   141 	sprintf_s(tmp, 256, "Timeout: '%d'", m_PropertySerialCommTimeout);
       
   142     s = tmp;
       
   143     Util::Debug(s);
       
   144 
       
   145 	// flow control
       
   146 	m_PropertySerialHwFlowControl = false;
       
   147 	val = props[SERIAL_INI_USE_HW_FLOW_CONTROL];
       
   148 	Util::CheckCommandlineParam( PARAM_SWITCH_USE_HW_FLOW_CONTROL, val );
       
   149 	if ( !val.empty() && val == "1" )
       
   150 	{
       
   151 		m_PropertySerialHwFlowControl = true;
       
   152 		Util::Debug("Use serial HW flow control");
       
   153 	}
       
   154 	else
       
   155 	{
       
   156 		Util::Debug("Do not use serial HW flow control");
       
   157 	}
       
   158 
       
   159 	// send pause
       
   160 	val = props[SERIAL_INI_SEND_SLEEP_PAUSE];
       
   161 	Util::CheckCommandlineParam( PARAM_SWITCH_SEND_SLEEP_PAUSE, val );
       
   162     if ( !val.empty() )
       
   163     {
       
   164         m_ProperySerialSendPause = atol(val.c_str());
       
   165     }
       
   166     if ( m_ProperySerialSendPause <= 0 )
       
   167     {
       
   168         m_ProperySerialSendPause = g_SerialCommDefaultSendPause;
       
   169     }
       
   170 	sprintf_s(tmp, 256, "Send pause: '%d'", m_ProperySerialSendPause);
       
   171     s = tmp;
       
   172     Util::Debug(s);
       
   173 
       
   174 	// send size
       
   175 	val = props[SERIAL_INI_SEND_SIZE];
       
   176 	Util::CheckCommandlineParam( PARAM_SWITCH_SEND_SIZE, val );
       
   177     if ( !val.empty() )
       
   178     {
       
   179         m_PropertySerialMaxSendSize = atol(val.c_str());
       
   180     }
       
   181     if ( m_PropertySerialMaxSendSize <= 0 )
       
   182     {
       
   183         m_PropertySerialMaxSendSize = 0;
       
   184     }
       
   185 	sprintf_s(tmp, 256, "Send max size: '%d'", m_PropertySerialMaxSendSize);
       
   186     s = tmp;
       
   187     Util::Debug(s);
       
   188 }
       
   189 
       
   190 /*
       
   191  * This method checks if data is available on incoming queue
       
   192  */
       
   193 bool SerialCommPlugin::IsDataAvailable()
       
   194 {
       
   195     return ( !m_RxQueue.empty() );
       
   196 }
       
   197 
       
   198 /*
       
   199  * This method is used to:
       
   200  * -push given data to outgoing queue
       
   201  * -wait for data to become available in incoming queue
       
   202  * -pop the first Data object from queue and store it to the Data object given as parameter
       
   203  */
       
   204 DWORD SerialCommPlugin::SendReceive(Data* data_in, Data** data_out, long timeout)
       
   205 {
       
   206     DWORD res;
       
   207     if ( ( res = Send(data_in, timeout)) == NO_ERRORS &&
       
   208          ( res = ReceiveWait(data_out, timeout)) == NO_ERRORS )
       
   209     {
       
   210         return NO_ERRORS;
       
   211     }
       
   212     cout << "SerialCommPlugin::SendReceive: error" << endl;
       
   213     return res;
       
   214 }
       
   215 
       
   216 /*
       
   217  * This method pushes the given Data object(of type Data::EData) to outgoing queue
       
   218  */
       
   219 DWORD SerialCommPlugin::Send(Data* data_in, long timeout)
       
   220 {
       
   221     Data::DataType type = data_in->GetType();
       
   222     if ( type == Data::EData )
       
   223     {
       
   224         DWORD length = data_in->GetLength();
       
   225         m_TxQueue.push(data_in);
       
   226         return NO_ERRORS;
       
   227     }
       
   228     else if ( type == Data::EControl )
       
   229     {
       
   230         Util::Debug("SerialCommPlugin::Send: Control Message Received");
       
   231         return NO_ERRORS;
       
   232     }
       
   233     return ERR_DG_COMM_DATA_SEND;
       
   234 }
       
   235 
       
   236 /*
       
   237  * This method is used to wait for data to become available in incoming queue 
       
   238  * and then pop the first Data object from the queue and and store it to Data object given as parameter.
       
   239  */
       
   240 DWORD SerialCommPlugin::ReceiveWait(Data** data_out, long timeout)
       
   241 {
       
   242     long elapsed = 0;
       
   243     while (elapsed < timeout && !IsDataAvailable())
       
   244     {
       
   245         elapsed += 25;
       
   246         Sleep(25);
       
   247     }
       
   248     if ( elapsed >= timeout )
       
   249     {
       
   250         return ERR_DG_COMM_DATA_RECV_TIMEOUT;
       
   251     }
       
   252     return Receive(data_out, timeout);
       
   253 }
       
   254 
       
   255 /*
       
   256  * This method is used to pop the first data object from incoming queue and store it to data object given as parameter
       
   257  */
       
   258 DWORD SerialCommPlugin::Receive(Data** data_out, long timeout)
       
   259 {
       
   260     if ( !m_RxQueue.empty() )
       
   261     {
       
   262         *data_out = m_RxQueue.front();
       
   263         m_RxQueue.pop();
       
   264         return NO_ERRORS;
       
   265     }
       
   266     return ERR_DG_COMM_DATA_RECV;
       
   267 }
       
   268 
       
   269 
       
   270 DWORD SerialCommPlugin::Open()
       
   271 {
       
   272     return ( m_Open ? NO_ERRORS : ERR_DG_COMM_OPEN );
       
   273 }
       
   274 
       
   275 /*
       
   276  * This method stops SerialCommIoThread and waits for it to be in signaled state
       
   277  */
       
   278 DWORD SerialCommPlugin::Close()
       
   279 {
       
   280     m_IoThread->Stop();
       
   281     WaitForSingleObject( m_IoThread->ThreadHandle(), g_MaximumShutdownWaitTime );
       
   282     return NO_ERRORS;
       
   283 }
       
   284 
       
   285 //**********************************************************************************
       
   286 // Class SerialComm
       
   287 //
       
   288 // This class implements the actual serial communication using Windows API
       
   289 //**********************************************************************************
       
   290 
       
   291 SerialComm::SerialComm()
       
   292     : m_Open(false),
       
   293 	m_SendPause(0),
       
   294 	m_SendMaxSize(0)
       
   295 {
       
   296 
       
   297 }
       
   298 
       
   299 SerialComm::~SerialComm()
       
   300 {
       
   301     Util::Debug("SerialComm::~SerialComm()");
       
   302     if ( m_Open )
       
   303     {
       
   304         Close();
       
   305     }
       
   306 }
       
   307 /*
       
   308  * This method opens a communication device that uses serial communication and
       
   309  * configures it according initialization parameters
       
   310  */
       
   311 WORD SerialComm::Open( const string& commPort, const string& initParameters,
       
   312 					   long timeout,
       
   313 					   bool hwFlowControl, long sendPause, long sendMaxSize)
       
   314 {
       
   315     Util::Debug("SerialComm::Open()");
       
   316 
       
   317 	m_SendPause = sendPause;
       
   318 
       
   319 	if ( sendMaxSize>0 )
       
   320 	{
       
   321 		m_SendMaxSize = sendMaxSize;
       
   322 	}
       
   323 
       
   324 	DWORD err;
       
   325 	//check commPort and add "\\.\" prefix if port is larger than 9
       
   326 	string localCommPort(commPort);
       
   327 	static const basic_string <char>::size_type npos = -1;
       
   328 	if ( localCommPort.find(HIGH_COM_PORT) == npos &&
       
   329 		 localCommPort.find("COM") == 0 &&
       
   330 		 localCommPort.length() > 4 //two digit port number
       
   331 	   )
       
   332 	{
       
   333 		localCommPort.insert(0, HIGH_COM_PORT);
       
   334 	}
       
   335 	Util::Debug(localCommPort.c_str());
       
   336 
       
   337     // If COM-port opening fails, it's retried until HtiGateway is killed.
       
   338     m_Com = INVALID_HANDLE_VALUE;
       
   339     while ( m_Com == INVALID_HANDLE_VALUE )
       
   340     {
       
   341 	    // Open file (COM port)
       
   342 	    m_Com = CreateFile( localCommPort.c_str(),
       
   343 					    GENERIC_READ | GENERIC_WRITE,
       
   344 					    0, //excusive access
       
   345 					    NULL, //no security
       
   346 					    OPEN_EXISTING, //must use
       
   347 					    0, //not overlapped i/o
       
   348 					    NULL // must be NULL for comm
       
   349 					    );
       
   350 
       
   351 	    if ( m_Com == INVALID_HANDLE_VALUE )
       
   352 	    {
       
   353 		    err = GetLastError();
       
   354             Util::Error("[SerialComm] Failed to open COM port", err);
       
   355             Util::Info("[SerialComm] Retrying...");
       
   356             Sleep(5000);
       
   357         }
       
   358     }
       
   359 
       
   360     // Serial port cfg
       
   361 	Util::Debug(initParameters.c_str());
       
   362 	DCB dcb;
       
   363 
       
   364 	FillMemory(&dcb, sizeof(dcb), 0);
       
   365 	dcb.DCBlength = sizeof(dcb);
       
   366 	if ( !BuildCommDCB(initParameters.c_str(), &dcb) )
       
   367 	{
       
   368 		err = GetLastError();
       
   369 		Util::Error("[SerialComm] Failed to build port settings ", err);
       
   370 		return ERR_DG_COM_INIT;
       
   371 	}
       
   372 
       
   373 	dcb.fBinary = TRUE ; 
       
   374 
       
   375 	//set hw handshaking
       
   376 	dcb.fOutX  = FALSE;
       
   377     dcb.fInX   = FALSE;
       
   378     dcb.fNull   = FALSE;
       
   379     dcb.fAbortOnError = TRUE;
       
   380 	
       
   381 	dcb.fOutxDsrFlow = FALSE;
       
   382 	dcb.fDtrControl = DTR_CONTROL_DISABLE;
       
   383 	dcb.fDsrSensitivity= FALSE;
       
   384 	dcb.fDtrControl = DTR_CONTROL_DISABLE;
       
   385 
       
   386 	if ( hwFlowControl )
       
   387 	{
       
   388 		dcb.fOutxCtsFlow = TRUE;
       
   389 		dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
       
   390 	}
       
   391 	else
       
   392 	{
       
   393 		dcb.fOutxCtsFlow = FALSE;
       
   394 		dcb.fRtsControl = RTS_CONTROL_ENABLE;
       
   395 	}
       
   396 
       
   397 	if ( !SetCommState(m_Com, &dcb) )
       
   398 	{
       
   399 		err = GetLastError();
       
   400 		Util::Error("[SerialComm] Failed to set port settings ", err);
       
   401 		return ERR_DG_COM_INIT;
       
   402 	}
       
   403 
       
   404 	COMMTIMEOUTS timeouts;
       
   405 
       
   406 	timeouts.ReadIntervalTimeout = MAXDWORD; 
       
   407 
       
   408 	timeouts.ReadTotalTimeoutMultiplier = timeout;
       
   409 	timeouts.ReadTotalTimeoutConstant = 1;
       
   410 	timeouts.WriteTotalTimeoutMultiplier = 1;
       
   411 	timeouts.WriteTotalTimeoutConstant = timeout;
       
   412 
       
   413 	if ( !SetCommTimeouts(m_Com, &timeouts) )
       
   414 	{
       
   415 		// Error setting time-outs.
       
   416 		err = GetLastError();
       
   417 		Util::Error("[SerialComm] Failed to set port timeouts ", err);
       
   418 		return ERR_DG_COM_INIT;
       
   419 	}
       
   420 
       
   421 
       
   422 	m_Open = true;
       
   423     Util::Debug("SerialComm::Open() OK");
       
   424     Util::Info("[SerialComm] COM port open");
       
   425     return NO_ERRORS;
       
   426 }
       
   427 
       
   428 /*
       
   429  * This method is used to send Data object using serial communication
       
   430  */
       
   431 DWORD SerialComm::Send(const Data& data_in)
       
   432 {
       
   433     Util::Debug("SerialComm::Send()");
       
   434 	if ( data_in.GetLength() > 0 )
       
   435 	{
       
   436 		DWORD sentBytes = 0;
       
   437 		void* data = data_in.GetData();
       
   438 		int numOfTries = 0;
       
   439 		//loop until whole Data object is sent
       
   440 		while ( sentBytes < data_in.GetLength() )
       
   441 		{
       
   442 			//Util::Debug("while");
       
   443 			DWORD sent;
       
   444 			BOOL r;
       
   445 			if ( m_SendMaxSize>0 )
       
   446 			{
       
   447 				//Write data to the communication device				
       
   448 				r = WriteFile(m_Com,
       
   449 						((char*)data) + sentBytes,
       
   450 						//data_in.GetLength() - sentBytes,
       
   451 						min(data_in.GetLength() - sentBytes, m_SendMaxSize),
       
   452 						&sent,
       
   453 						NULL);
       
   454 			}
       
   455 			else
       
   456 			{
       
   457 				r = WriteFile(m_Com,
       
   458 						((char*)data) + sentBytes,
       
   459 						data_in.GetLength() - sentBytes,
       
   460 						&sent,
       
   461 						NULL);
       
   462 			}
       
   463 
       
   464 			if ( r && sent > 0 )
       
   465 			{
       
   466 				if (Util::GetVerboseLevel() == Util::debug)
       
   467 				{
       
   468 					Util::Hex(((char*)data) + sentBytes, min(sent,16));
       
   469 				}
       
   470 				sentBytes+=sent;
       
   471 			}
       
   472 			else
       
   473 			{
       
   474 				if ( !r )
       
   475 				{
       
   476 					DWORD err = GetLastError();
       
   477 					Util::Error("[SerialComm] Send error", err);
       
   478 				}
       
   479 				else
       
   480 				{
       
   481 					Util::Error("[SerialComm] Send failed");
       
   482 				}
       
   483 				if ( numOfTries++==g_SerialMaxResendNumber )
       
   484 				{
       
   485 					return ERR_DG_COMM_DATA_RECV;
       
   486 				}
       
   487 			}
       
   488 			//used to "solve" overflow problem
       
   489 			if ( m_SendPause > 0 )
       
   490 			{
       
   491 				Sleep(m_SendPause);
       
   492 			}
       
   493 		}
       
   494 	}
       
   495 
       
   496     Util::Debug("SerialComm::Send() OK");
       
   497     return NO_ERRORS;
       
   498 }
       
   499 
       
   500 /*
       
   501  * This method reads all available data from communication media 
       
   502  * and returns it in the Data object given as parameter
       
   503  */
       
   504 DWORD SerialComm::Receive(Data* data_out)
       
   505 {
       
   506     Util::Debug("SerialComm::Receive()");
       
   507 
       
   508 	//get available bytes in incoming communication channel	
       
   509 	LONG rxBytes = GetRxBytesAvailable();
       
   510 
       
   511 	if ( rxBytes > 0 )
       
   512 	{
       
   513 		char* data = new char[rxBytes];
       
   514 		DWORD readBytes = 0;
       
   515 		//read data until all available bytes have been red		
       
   516 		do
       
   517 		{
       
   518 			DWORD reallyRead;
       
   519 			if ( ReadFile(m_Com,
       
   520 					 data + readBytes,
       
   521 					 rxBytes - readBytes,
       
   522 					 &reallyRead,
       
   523 					 NULL) )
       
   524 			{
       
   525 				if (Util::GetVerboseLevel() == Util::debug)
       
   526 				{
       
   527 					char temp[64];
       
   528 					sprintf_s(temp, 64, "Received %d bytes", reallyRead);
       
   529 					Util::Debug( temp );
       
   530 					Util::Hex(data + readBytes, min(16,reallyRead));
       
   531 				}
       
   532 				readBytes += reallyRead;
       
   533 			}
       
   534 			else
       
   535 			{
       
   536 				delete[] data;
       
   537 				DWORD err = GetLastError();
       
   538 				Util::Error("[SerialComm] Error %d", err);
       
   539 				return ERR_DG_COMM_DATA_RECV;
       
   540 			}
       
   541 			if ( readBytes > rxBytes )
       
   542 			{
       
   543 				Util::Error("[SerialComm] !!! readBytes > rxBytes !!!");
       
   544 			}
       
   545 		}
       
   546 		while( readBytes < rxBytes );
       
   547 
       
   548 		data_out->SetData( data, rxBytes, Data::EData);
       
   549 		delete[] data;
       
   550 	}
       
   551 	else if ( rxBytes < 0 ) //err
       
   552 	{
       
   553         return ERR_DG_COMM_DATA_RECV;
       
   554 	}
       
   555 	return NO_ERRORS;
       
   556 }
       
   557 
       
   558 /*
       
   559  * This method returns number of bytes available in incoming queue or
       
   560  * -1 if communication error has occurred
       
   561  */
       
   562 LONG SerialComm::GetRxBytesAvailable()
       
   563 {
       
   564     COMSTAT res;
       
   565 	DWORD err;
       
   566 
       
   567 	if ( ClearCommError(m_Com, &err, &res ) )
       
   568 	{
       
   569 		return res.cbInQue;
       
   570 	}
       
   571 	else
       
   572     {
       
   573 		DWORD err = GetLastError();
       
   574         Util::Error("[SerialComm] Error getting Rx bytes %d", err);
       
   575         return -1;
       
   576     }
       
   577 }
       
   578 
       
   579 DWORD SerialComm::Close()
       
   580 {
       
   581     Util::Debug("SerialComm::Close()");
       
   582     m_Open = false;
       
   583 
       
   584 	if ( m_Com != INVALID_HANDLE_VALUE )
       
   585 	{
       
   586 		CloseHandle(m_Com);
       
   587 		m_Com = INVALID_HANDLE_VALUE;
       
   588 	}
       
   589 
       
   590     Util::Debug("SerialComm::Close() OK");
       
   591     return NO_ERRORS;
       
   592 }
       
   593 
       
   594 //**********************************************************************************
       
   595 // Class SerialCommIoThread
       
   596 //
       
   597 // This thread is used to send data from outgoing queue to serial port
       
   598 // and read bytes from serial port and push it to incoming queue 
       
   599 //**********************************************************************************
       
   600 
       
   601 SerialCommIoThread::SerialCommIoThread(SafeQueue<Data*>* in,
       
   602                            SafeQueue<Data*>* out,
       
   603                            const string& init,  const string& commPort, long timeout,
       
   604 						   bool hwFlowControl, long sendPause, long sendMaxSize)
       
   605     : m_InitString(init),
       
   606 	  m_CommPort( commPort ),
       
   607 	  m_PropertySerialCommTimeout( timeout ),
       
   608 	  m_PropertySerialHwFlowControl( hwFlowControl ),
       
   609 	  m_ProperySerialSendPause(sendPause),
       
   610 	  m_PropertySerialMaxSendSize(sendMaxSize)
       
   611 {
       
   612     m_InQueue = in;
       
   613     m_OutQueue = out;
       
   614     m_Running = true;
       
   615     m_OpenedEvent.Reset();
       
   616 }
       
   617 
       
   618 /*
       
   619  * Main execution loop which is used to send Data from outgoing queue to serial port
       
   620  * and read bytes from serial port, encapsulate it to Data objects and push them to incoming queue 
       
   621  */
       
   622 void SerialCommIoThread::Run()
       
   623 {
       
   624     while ( m_Running )
       
   625     {
       
   626 	    Util::Debug("SerialCommIoThread::Run()");
       
   627         SerialComm m_SerialComm;
       
   628 
       
   629         if ( m_SerialComm.Open(m_CommPort, m_InitString, m_PropertySerialCommTimeout,
       
   630 							    m_PropertySerialHwFlowControl, m_ProperySerialSendPause,
       
   631 							    m_PropertySerialMaxSendSize) != NO_ERRORS )
       
   632         {
       
   633             m_Running = false;
       
   634             return;
       
   635         }
       
   636         m_OpenedEvent.Set();
       
   637 
       
   638 	    Util::Debug("SerialCommIoThread::Run() start loop");
       
   639         while ( m_Running )
       
   640         {
       
   641             // Sending data
       
   642             try
       
   643             {
       
   644                 Data* out = m_OutQueue->front(30);
       
   645                 if ( m_SerialComm.Send(*out) != NO_ERRORS )
       
   646                 {
       
   647                 //Data* d = new Data("Error sending data", 19, Data::EControl);
       
   648 				Data* d = CREATE_CONTROL_MESSAGE("[HtiGateway]: Error sending data");
       
   649                     m_InQueue->push(d);
       
   650                     d = NULL;
       
   651                 }
       
   652                 m_OutQueue->pop();
       
   653                 delete out;
       
   654                 out = NULL;
       
   655             } catch (TimeoutException te) {}
       
   656 
       
   657 
       
   658 		    // Receiving data
       
   659 		    LONG rxBytes = 0;
       
   660             while ( ( rxBytes = m_SerialComm.GetRxBytesAvailable() ) > 0 )
       
   661             {
       
   662                 Data* in = new Data;
       
   663                 if ( m_SerialComm.Receive(in) == NO_ERRORS )
       
   664                 {
       
   665 				    m_InQueue->push(in);
       
   666 				    in = NULL;
       
   667                 }
       
   668                 else
       
   669                 {
       
   670                     delete in;
       
   671                     in = NULL;
       
   672                 }
       
   673             }
       
   674             if ( rxBytes < 0 )
       
   675             {
       
   676                 Util::Info("[SerialCommIoThread] COM-port lost. Trying to close & reopen");
       
   677                 break; // break out but keep the outermost while loop running
       
   678             }
       
   679         }
       
   680         m_OpenedEvent.Reset();
       
   681         m_SerialComm.Close();
       
   682     }
       
   683     Util::Debug("SerialCommIoThread::Run() exiting");
       
   684 }
       
   685 
       
   686 void SerialCommIoThread::Stop()
       
   687 {
       
   688     Util::Debug("SerialCommIoThread::Stop()");
       
   689     m_Running = false;
       
   690 }
       
   691 
       
   692 Event SerialCommIoThread::GetOpenedEvent()
       
   693 {
       
   694     return m_OpenedEvent;
       
   695 }
       
   696 
       
   697 void SerialCommIoThread::SetTimeout(long timeout)
       
   698 {
       
   699     if ( timeout > 0 )
       
   700     {
       
   701         m_PropertySerialCommTimeout = timeout;
       
   702     }
       
   703     else
       
   704     {
       
   705         m_PropertySerialCommTimeout = g_SerialCommDefaultTimeout;
       
   706     }
       
   707 }
       
   708 
       
   709 long SerialCommIoThread::GetTimeout() const
       
   710 {
       
   711     return m_PropertySerialCommTimeout;
       
   712 }
       
   713 
       
   714 // End of the file