testtoolsconn/stat/desktop/source/lib/src/statserial.cpp
changeset 0 3da2a79470a7
equal deleted inserted replaced
-1:000000000000 0:3da2a79470a7
       
     1 /*
       
     2 * Copyright (c) 2005-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 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 ////////////////////////////////////////////////////////////////////////////////////////
       
    22 // STATSerial.cpp
       
    23 // Implementation of the serial comms transport
       
    24 ////////////////////////////////////////////////////////////////////////////////////////
       
    25 #include "stdafx.h"
       
    26 #include "statserial.h"
       
    27 #include "assert.h"
       
    28 #include "../../../../Common/inc/SerialPacketSize.h"
       
    29 
       
    30 #define SP_COMMANDSIZE	4
       
    31 #define SP_LENGTHSIZE	4
       
    32 
       
    33 ////////////////////////////////////////////////////////////////////////////////////////
       
    34 // Constructor
       
    35 CSTATSerial::CSTATSerial(STATCONNECTTYPE eConnect)
       
    36 : hComPort((HANDLE)0), 	pBuffer(NULL), iBufferLength(0), iMaxPacketSize(0)
       
    37 {
       
    38 	switch(eConnect)
       
    39 	{
       
    40 		case SymbianSerial:
       
    41 		case SymbianInfrared:
       
    42 			iMaxPacketSize = KMaxPacketSize;
       
    43 			break;
       
    44 		case SymbianBluetooth:
       
    45 			iMaxPacketSize = KMaxBluetoothPacketSize;
       
    46 			break;
       
    47 		default:
       
    48 			assert(0);
       
    49 			break;
       
    50 	};
       
    51 
       
    52 	assert(0 != iMaxPacketSize);
       
    53 }
       
    54 
       
    55 
       
    56 ////////////////////////////////////////////////////////////////////////////////////////
       
    57 // Destructor
       
    58 CSTATSerial::~CSTATSerial()
       
    59 {
       
    60 	Disconnect();
       
    61 	Release();
       
    62 }
       
    63 
       
    64 
       
    65 ////////////////////////////////////////////////////////////////////////////////////////
       
    66 // Initialisation stuff
       
    67 int CSTATSerial::Initialise(void)
       
    68 {
       
    69 	return ITS_OK;
       
    70 }
       
    71 
       
    72 
       
    73 ////////////////////////////////////////////////////////////////////////////////////////
       
    74 // Open a connection
       
    75 int CSTATSerial::Connect(const char *pAddress)
       
    76 {
       
    77 	// already connected
       
    78 	if (hComPort)
       
    79 		return ITS_OK;
       
    80 
       
    81 	if (OpenComPort(pAddress))
       
    82 	{
       
    83 		SetError("Connected to port %s Speed %d Bytes %d Parity %d Stop %d",
       
    84 			pAddress, STAT_BAUDRATE, STAT_BYTESIZE, STAT_PARITY, STAT_STOPBITS);
       
    85 		return ITS_OK;
       
    86 	}
       
    87 
       
    88 	return E_CONNECTIONFAILED;
       
    89 }
       
    90 
       
    91 
       
    92 ////////////////////////////////////////////////////////////////////////////////////////
       
    93 // Send a command and associated data
       
    94 ////////////////////////////////////////////////////////////////////////////////////////
       
    95 int CSTATSerial::Send(const char cIdentifier, const char *pCommand, const unsigned long ulLength)
       
    96 {
       
    97 	DWORD dwBytes = 0;
       
    98 	int ret = E_WRITEFAILED;
       
    99 
       
   100 	// prepare command
       
   101 	STATCOMMAND STATSendCommand;
       
   102 	memset(&STATSendCommand, 0, sizeof(STATCOMMAND));
       
   103 	STATSendCommand.cIdentifier = cIdentifier;
       
   104 	STATSendCommand.ulLength = ulLength;
       
   105 
       
   106 	int result = 0;
       
   107 	if (result = WriteFile(hComPort, (LPVOID)&STATSendCommand, sizeof(STATCOMMAND), &dwBytes, NULL))
       
   108 	{
       
   109 		if (dwBytes == sizeof(STATCOMMAND))
       
   110 		{
       
   111 			// only send data if it will fit into our buffer
       
   112 			if (pCommand && STATSendCommand.ulLength && STATSendCommand.ulLength <= iMaxPacketSize)
       
   113 			{
       
   114 				if (WriteFile(hComPort, (LPVOID)pCommand, STATSendCommand.ulLength, &dwBytes, NULL))
       
   115 				{
       
   116 					if (dwBytes == STATSendCommand.ulLength)
       
   117 					{
       
   118 						SetError("Sent successfully %ld bytes", STATSendCommand.ulLength);
       
   119 						ret = ITS_OK;
       
   120 					}
       
   121 					else
       
   122 					{
       
   123 						SetError("Incorrect number of bytes written - expected %ld sent %ld", STATSendCommand.ulLength, dwBytes);
       
   124 						ret = E_BADNUMBERBYTES;
       
   125 					}
       
   126 				}
       
   127 				else
       
   128 					SetError("Write data to port failed");
       
   129 			}
       
   130 			else
       
   131 			{
       
   132 				SetError("Sent successfully");
       
   133 				ret = ITS_OK;
       
   134 			}
       
   135 		}
       
   136 		else
       
   137 		{
       
   138 			int err = ::GetLastError();
       
   139 			SetError("Incorrect number of bytes written - expected %ld sent %ld", sizeof(STATCOMMAND), dwBytes);
       
   140 			ret = E_BADNUMBERBYTES;
       
   141 		}
       
   142 	}
       
   143 	else
       
   144 		SetError("Write command to port failed");
       
   145 
       
   146 	return ret;
       
   147 }
       
   148 
       
   149 
       
   150 ////////////////////////////////////////////////////////////////////////////////////////
       
   151 // Receive a command and associated data
       
   152 //
       
   153 // Tries to read a STATCOMMAND structure from the port.  If successful, the length
       
   154 // of any data following will be specified in the structure.  If extra data, try to
       
   155 // read this.  If all successful, set the pointers to point to it
       
   156 //
       
   157 ////////////////////////////////////////////////////////////////////////////////////////
       
   158 int CSTATSerial::ReceiveBytes( char *buff, unsigned long size )
       
   159 {
       
   160 	int ret;
       
   161 	int err;
       
   162 	unsigned long bytes_read = 0;
       
   163 	unsigned long bytes_read_this_iteration = 0;
       
   164 
       
   165 	// make sure size > 0 otherwise the following semantics fail
       
   166 	assert( size > 0 );
       
   167 
       
   168 	// loop until either all bytes have been received or an error occurs
       
   169 	for( bytes_read = 0; bytes_read < size; bytes_read += bytes_read_this_iteration ) { 
       
   170 		ret = ReadFile( hComPort, &(buff[bytes_read]), (size - bytes_read), &bytes_read_this_iteration, NULL );
       
   171 		if( bytes_read_this_iteration == 0 ) {
       
   172 			return NO_DATA_AT_PORT;
       
   173 		}
       
   174 		if( ret == 0 ) {
       
   175 			err = ::GetLastError();
       
   176 			SetError( "Error while receiving command - %ld", err );
       
   177 			return err;
       
   178 		}
       
   179 	}
       
   180 
       
   181 	// everything is OK
       
   182 	return 0;
       
   183 }
       
   184 
       
   185 int CSTATSerial::Receive( char *cIdentifier, char **ppData, unsigned long *pLength )
       
   186 {
       
   187 	int ret;
       
   188 	unsigned long command;
       
   189 	unsigned long data_length;
       
   190 
       
   191 	// initialise parameters
       
   192 	*cIdentifier = 0;
       
   193 	*ppData = NULL;
       
   194 	*pLength = 0;
       
   195 
       
   196 	// get command
       
   197 	ret = ReceiveBytes( (char*)&command, SP_COMMANDSIZE );
       
   198 	if( ret != 0 ) {
       
   199 		return ret;
       
   200 	}
       
   201 
       
   202 	static const int MAX_COMMAND = 127;
       
   203 	if( command > MAX_COMMAND ){
       
   204 		return INVALID_COMMAND_FORMAT;
       
   205 	}
       
   206 
       
   207 	// get length
       
   208 	ret = ReceiveBytes( (char*)&data_length, SP_LENGTHSIZE );
       
   209 	if( ret != 0 ) {
       
   210 		return ret;
       
   211 	}
       
   212 
       
   213 	// put these values into the return slots
       
   214 	*cIdentifier = (char)command;
       
   215 	*pLength = data_length;
       
   216 
       
   217 	// if the length is zero then there is no more to do
       
   218 	if( data_length == 0 ) {
       
   219 		return ITS_OK;
       
   220 	}
       
   221 
       
   222 	// if the length is greater than the buffer size then this is a header packet and we are not
       
   223 	// supposed to actually read any data from it.
       
   224 	// if( data_length > SP_BUFFERSIZE ) {
       
   225 	if( data_length > iMaxPacketSize ) {
       
   226 		SetError( "Received command ID: %c successfully length %d", (*cIdentifier), (*pLength) );
       
   227 		return ITS_OK;
       
   228 	}
       
   229 
       
   230 	// Otherwise we are about to read some data. We first have to setup the memory management
       
   231 	// which is done in a pretty ugly way IMAO.
       
   232 	if( data_length > iBufferLength )
       
   233 	{
       
   234 		if( pBuffer ) {
       
   235 			delete [] pBuffer;
       
   236 			pBuffer = NULL;
       
   237 			iBufferLength = 0;
       
   238 		}
       
   239 		pBuffer = new char [data_length];
       
   240 		if( pBuffer == NULL ) {
       
   241 			SetError( "Unable to allocate %ld bytes of memory to hold data", data_length );
       
   242 			return E_OUTOFMEM;
       
   243 		}
       
   244 		iBufferLength = data_length;
       
   245 	}
       
   246 
       
   247 	// now read the data
       
   248 	ret = ReceiveBytes( pBuffer, data_length );
       
   249 	if( ret != 0 ) {
       
   250 		return ret;
       
   251 	}
       
   252 	*ppData = pBuffer;
       
   253 
       
   254 	return ITS_OK;
       
   255 }
       
   256 
       
   257 
       
   258 ////////////////////////////////////////////////////////////////////////////////////////
       
   259 // Disconnect from the port
       
   260 int CSTATSerial::Disconnect(void)
       
   261 {
       
   262 	// release previous resources
       
   263 	if (pBuffer)
       
   264 	{
       
   265 		delete [] pBuffer;
       
   266 		pBuffer = NULL;
       
   267 		iBufferLength = 0;
       
   268 	}
       
   269 
       
   270 	// disconnect
       
   271 	if (hComPort)
       
   272 	{
       
   273 		CloseHandle(hComPort);
       
   274 		hComPort = (HANDLE)0;
       
   275 	}
       
   276 
       
   277 	SetError("Disconnected successfully");
       
   278 	return ITS_OK;
       
   279 }
       
   280 
       
   281 
       
   282 ////////////////////////////////////////////////////////////////////////////////////////
       
   283 // Release resources
       
   284 int CSTATSerial::Release(void)
       
   285 {
       
   286 	Disconnect();
       
   287 	return ITS_OK;
       
   288 }
       
   289 
       
   290 
       
   291 ////////////////////////////////////////////////////////////////////////////////////////
       
   292 //	PRIVATE FUNCTIONS
       
   293 ////////////////////////////////////////////////////////////////////////////////////////
       
   294 
       
   295 ////////////////////////////////////////////////////////////////////////////////////////
       
   296 // 
       
   297 bool CSTATSerial::OpenComPort(const char *pAddress)
       
   298 {
       
   299 	TCHAR szAddress[256] = {0};
       
   300 
       
   301 #ifdef UNICODE
       
   302 	szAddress[0] = (TCHAR)0;
       
   303 
       
   304     // Convert to UNICODE.
       
   305     MultiByteToWideChar(CP_ACP,					// conversion type
       
   306 						 0,							// flags
       
   307 						 pAddress,					// source
       
   308 						 -1,						// length
       
   309 						 szAddress,					// dest
       
   310 						 256);						// length
       
   311 #else
       
   312 	strcpy(szAddress, pAddress);
       
   313 #endif
       
   314 
       
   315 	// Use device naming for COM port.
       
   316 	CString port;
       
   317 	CString address(pAddress);	// Local variable to cope with 
       
   318 								// wide UNICODE characters.
       
   319 	port.Format(_T("\\\\.\\%s"), address.operator LPCTSTR());
       
   320 
       
   321 	if (INVALID_HANDLE_VALUE == (hComPort = CreateFile(port,
       
   322 					 GENERIC_READ | GENERIC_WRITE,
       
   323 					 0,
       
   324 					 NULL,
       
   325 					 OPEN_EXISTING,
       
   326 					 FILE_FLAG_WRITE_THROUGH,
       
   327 					 NULL)))
       
   328 	{
       
   329 		SetError("Port [%s] could not be opened", pAddress);
       
   330 		int err = ::GetLastError();
       
   331 		hComPort = (HANDLE)0;
       
   332 		return false;
       
   333 	}
       
   334 
       
   335 	COMMTIMEOUTS CommTimeOuts;
       
   336 	CommTimeOuts.WriteTotalTimeoutMultiplier	= STAT_WRITETOTALTIMEOUTMULTIPLIER; 
       
   337 	CommTimeOuts.WriteTotalTimeoutConstant		= STAT_WRITETOTALTIMEOUTCONSTANT;
       
   338 	CommTimeOuts.ReadIntervalTimeout			= STAT_READINTERVALTIMEOUT;
       
   339 	CommTimeOuts.ReadTotalTimeoutMultiplier		= STAT_READTOTALTIMEOUTMULTIPLIER;
       
   340 	CommTimeOuts.ReadTotalTimeoutConstant		= STAT_READTOTALTIMEOUTCONSTANT;
       
   341 
       
   342 	if (!SetCommTimeouts(hComPort, &CommTimeOuts))
       
   343 	{
       
   344 		SetError("Comm port timeouts could not be set");
       
   345 		CloseHandle(hComPort);
       
   346 		hComPort = (HANDLE)0;
       
   347 		return false;
       
   348 	} 
       
   349 
       
   350 	// Configure the COM port 
       
   351 	DCB dcb;
       
   352 	GetCommState(hComPort, &dcb);
       
   353 	dcb.DCBlength			= sizeof(dcb); 
       
   354 	dcb.BaudRate			= STAT_BAUDRATE;
       
   355 	dcb.fBinary				= TRUE;
       
   356 	dcb.fParity				= STAT_PARITY;
       
   357 	dcb.fOutxCtsFlow		= TRUE;
       
   358 	dcb.fOutxDsrFlow		= FALSE;
       
   359 	dcb.fDtrControl			= DTR_CONTROL_ENABLE;	
       
   360 	dcb.fDsrSensitivity		= FALSE;
       
   361 	dcb.fTXContinueOnXoff	= TRUE;
       
   362 	dcb.fOutX				= FALSE;
       
   363 	dcb.fInX				= FALSE;
       
   364 	dcb.fErrorChar			= FALSE;
       
   365 	dcb.fNull				= FALSE;
       
   366 	dcb.fRtsControl			= RTS_CONTROL_HANDSHAKE;
       
   367 	dcb.fAbortOnError		= TRUE;
       
   368 	dcb.XonLim				= 4096;
       
   369 	dcb.XoffLim				= 1024;
       
   370 	dcb.ByteSize			= STAT_BYTESIZE;
       
   371 	dcb.Parity				= STAT_PARITY;
       
   372 	dcb.StopBits			= STAT_STOPBITS;
       
   373 	dcb.XonChar				= 17;
       
   374 	dcb.XoffChar			= 19;
       
   375 
       
   376 //	dcb.fRtsControl		= RTS_CONTROL_ENABLE;
       
   377 //	dcb.BaudRate		= STAT_BAUDRATE;
       
   378 //	dcb.fOutxCtsFlow	= FALSE;
       
   379 //	dcb.XonLim			= STAT_XONLIMIT;
       
   380 //	dcb.XoffLim			= STAT_XOFFLIMIT;
       
   381 	
       
   382 	if (!SetCommState(hComPort, &dcb))
       
   383 	{
       
   384 		SetError("Comm port state could not be set");
       
   385 		CloseHandle(hComPort);
       
   386 		hComPort = (HANDLE)0;
       
   387 		return false;
       
   388 	} 
       
   389 
       
   390 	return true;
       
   391 }