testtoolsconn/stat/desktop/source/trgtest/src/trgtest.cpp
changeset 0 3da2a79470a7
equal deleted inserted replaced
-1:000000000000 0:3da2a79470a7
       
     1 /*
       
     2 * Copyright (c) 1994-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 * e32utils\trgtest\trgtesth.cpp
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 #include <e32err.h>
       
    21 #include <windows.h>
       
    22 #include <shlwapi.h>
       
    23 #include <stdio.h>
       
    24 #include <time.h>
       
    25 
       
    26 #pragma comment(lib, "shlwapi.lib")
       
    27 
       
    28 const TUint8 SOH=0x01;
       
    29 const TUint8 STX=0x02;
       
    30 const TUint8 EOT=0x04;
       
    31 const TUint8 ACK=0x06;
       
    32 const TUint8 NAK=0x15;
       
    33 const TUint8 CAN=0x18;
       
    34 const TUint8 SUB=0x1A;
       
    35 const TUint8 BIGC=0x43;
       
    36 const TUint8 BIGG=0x47;
       
    37 
       
    38 // Try 115200bps first since it is the most commonly supported baud rate.  Newer platforms like the
       
    39 // NaviEngine support 230400bps and above.
       
    40 const TUint KDefaultBaudRate = 115200;
       
    41 const TUint KBaudRateSearchList[] = {KDefaultBaudRate, 230400, 460800};
       
    42 
       
    43 #define READ_BUF_SIZE	32768
       
    44 #define WRITE_BUF_SIZE	32768
       
    45 #define MAX_LINE		32768
       
    46 #define PACKET_SIZE		1024
       
    47 
       
    48 #define MIN(a,b)		((a)<(b)?(a):(b))
       
    49 #define OFFSET(p,off)	((void*)((char*)p+off))
       
    50 
       
    51 #define RESET_COMM()	PurgeComm(Comm, PURGE_RXCLEAR|PURGE_TXCLEAR)
       
    52 
       
    53 const TInt	KExitCodeOK							= 0;		// no failure
       
    54 const TInt	KExitCodeUsage						= 1;		// command like usage
       
    55 const TInt	KExitCodeLog						= 2;		// can't open log file
       
    56 const TInt	KExitCodeImage						= 3;		// can't open image file
       
    57 const TInt	KExitCodeSerial						= 4;		// can't open serial port
       
    58 const TInt	KExitCodeDownload					= 5;		// download started, but failed
       
    59 const TInt	KExitCodeFaulted					= 6;		// entered debug monitor abnormally
       
    60 const TInt	KExitCodeHung						= 7;		// target hung
       
    61 const TInt	KExitCodeDOA						= 8;		// board was in debug monitor at start
       
    62 const TInt	KExitCodeUnsupportedBaudRate		= 9;		// the baud rate set by the -b parameter is not supported by the PC's COM port
       
    63 const TInt	KExitCodeAssert						= 99;		// trgtest assertion failed
       
    64 
       
    65 FILE* LogFile = NULL;
       
    66 HANDLE Comm = INVALID_HANDLE_VALUE;
       
    67 
       
    68 char ImgFileName[MAX_PATH] = "";
       
    69 TInt ImgFileSize = 0;
       
    70 char LineBuf[MAX_LINE+1];
       
    71 void* ImgFileChunkBase = NULL;
       
    72 TBool use_stdout = false;
       
    73 
       
    74 enum EDebugMonitorOptions
       
    75 {
       
    76 	kDebugDumpCodeSegs = 1
       
    77 };
       
    78 
       
    79 TUint DebugMonitorOptions = kDebugDumpCodeSegs;
       
    80 
       
    81 #define TT_ASSERT(x)	__ASSERT_ALWAYS(x, __Panic(__LINE__))
       
    82 
       
    83 const char* GetWinErrMsg(DWORD errorCode)
       
    84 	{
       
    85 	static char lastErrorBuffer[512]; // not thread safe or reentrant (but shouldn't need to be)
       
    86 	strcpy(lastErrorBuffer, "Unknown error");
       
    87 	
       
    88 	if(errorCode != ERROR_SUCCESS)
       
    89 		{
       
    90 		if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorCode, 0, lastErrorBuffer, 512, NULL) != 0)
       
    91 			{
       
    92 			size_t size = strlen(lastErrorBuffer);
       
    93 			
       
    94 			// Strip any trailing carriage return.
       
    95 			if(StrCmpNI(lastErrorBuffer + size - 2, "\r\n", 2) == 0)
       
    96 				{
       
    97 				lastErrorBuffer[size - 2] = '\0';
       
    98 				size -= 2;
       
    99 				}
       
   100 
       
   101 			// Strip any trailing period.
       
   102 			if(lastErrorBuffer[size - 1] == '.')
       
   103 				{
       
   104 				lastErrorBuffer[size - 1] = '\0';
       
   105 				}
       
   106 			}
       
   107 		}
       
   108 	
       
   109 	return lastErrorBuffer;
       
   110 	}
       
   111 
       
   112 const char* GetSymOrWinErrMsg(TInt errorCode)
       
   113 	{
       
   114 	static char lastErrorBuffer[512]; // not thread safe or reentrant (but shouldn't need to be)
       
   115 	strcpy(lastErrorBuffer, "Unknown error");
       
   116 	
       
   117 	switch(errorCode)
       
   118 		{
       
   119 		case KErrNone:
       
   120 			{
       
   121 			// Unknown error
       
   122 			}
       
   123 		break;
       
   124 		case KErrEof:
       
   125 			{
       
   126 			strcpy(lastErrorBuffer, "Unexpected end of file");
       
   127 			}
       
   128 		break;
       
   129 		case KErrTimedOut:
       
   130 			{
       
   131 			strcpy(lastErrorBuffer, "Timed-out");
       
   132 			}
       
   133 		break;
       
   134 		default:
       
   135 			{
       
   136 			if(errorCode > 0)
       
   137 				{
       
   138 				strcpy(lastErrorBuffer, GetWinErrMsg(errorCode));
       
   139 				}
       
   140 			}
       
   141 		break;
       
   142 		}
       
   143 	
       
   144 	return lastErrorBuffer;
       
   145 	}
       
   146 
       
   147 void __Panic(TInt aLine)
       
   148 	{
       
   149 	fprintf(stderr, "Assertion failed at line %d\n", aLine);
       
   150 	exit(KExitCodeAssert);
       
   151 	}
       
   152 
       
   153 void WriteLog(const void* aBuf, TInt aLength)
       
   154 	{
       
   155 	if (LogFile)
       
   156 		fwrite(aBuf, 1, aLength, LogFile);
       
   157 	}
       
   158 
       
   159 void WriteLogS(const char* aString)
       
   160 	{
       
   161 	WriteLog( aString, strlen(aString) );
       
   162 	}
       
   163 
       
   164 void TraceLog(const char* aFmt, ...)
       
   165 	{
       
   166 	char buf[512];
       
   167 	va_list list;
       
   168 	va_start(list, aFmt);
       
   169 	if (!LogFile)
       
   170 		return;
       
   171 	sprintf(buf, "TRGTEST: ");
       
   172 	vsprintf(buf, aFmt, list);
       
   173 	strcat(buf, "\r\n");
       
   174 	WriteLogS(buf);
       
   175 	}
       
   176 
       
   177 /*
       
   178 YModem packet structure:
       
   179 Byte 0 = STX
       
   180 Byte 1 = sequence number (first user data packet is 1)
       
   181 Byte 2 = complement of sequence number
       
   182 Bytes 3-1026 = data (1K per packet)
       
   183 Bytes 1027, 1028 = 16-bit CRC (big-endian)
       
   184 
       
   185 A herald packet is sent first, with sequence number 0
       
   186 The data field consists of the null-terminated file name
       
   187 followed by the null-terminated file size in ASCII decimal
       
   188 digits.
       
   189 */
       
   190 struct SPacket
       
   191 	{
       
   192 	TUint8 iPTI;
       
   193 	TUint8 iSeq;
       
   194 	TUint8 iSeqBar;
       
   195 	TUint8 iData[PACKET_SIZE];
       
   196 	TUint8 iCRC1;
       
   197 	TUint8 iCRC0;
       
   198 	};
       
   199 
       
   200 static const TUint16 crcTab[256] =
       
   201     {
       
   202 	0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,0x8108,0x9129,0xa14a,
       
   203 	0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,
       
   204 	0x72f7,0x62d6,0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,0x2462,
       
   205 	0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,0xa56a,0xb54b,0x8528,0x9509,
       
   206 	0xe5ee,0xf5cf,0xc5ac,0xd58d,0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,
       
   207 	0x46b4,0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,0x48c4,0x58e5,
       
   208 	0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,
       
   209 	0x9969,0xa90a,0xb92b,0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,
       
   210 	0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,0x6ca6,0x7c87,0x4ce4,
       
   211 	0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,
       
   212 	0x8d68,0x9d49,0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,0xff9f,
       
   213 	0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,0x9188,0x81a9,0xb1ca,0xa1eb,
       
   214 	0xd10c,0xc12d,0xf14e,0xe16f,0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,
       
   215 	0x6067,0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,0x02b1,0x1290,
       
   216 	0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,
       
   217 	0xe54f,0xd52c,0xc50d,0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,
       
   218 	0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,0x26d3,0x36f2,0x0691,
       
   219 	0x16b0,0x6657,0x7676,0x4615,0x5634,0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,
       
   220 	0xb98a,0xa9ab,0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,0xcb7d,
       
   221 	0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,0x4a75,0x5a54,0x6a37,0x7a16,
       
   222 	0x0af1,0x1ad0,0x2ab3,0x3a92,0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,
       
   223 	0x8dc9,0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,0xef1f,0xff3e,
       
   224 	0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,
       
   225 	0x3eb2,0x0ed1,0x1ef0
       
   226     };
       
   227 
       
   228 void UpdateCrc(const void* aPtr, TInt aLength, TUint16& aCrc)
       
   229 //
       
   230 // Perform a CCITT CRC checksum.
       
   231 //
       
   232 	{
       
   233 
       
   234 	register const TUint8* pB = (const TUint8*)aPtr;
       
   235 	register TUint16 crc=aCrc;
       
   236     while (aLength--)
       
   237 		crc=TUint16((crc<<8)^crcTab[(crc>>8)^*pB++]);
       
   238 	aCrc=crc;
       
   239 	}
       
   240 
       
   241 void ClearCommError()
       
   242 	{
       
   243 	DWORD err;
       
   244 	COMSTAT s;
       
   245 	TT_ASSERT(ClearCommError(Comm,&err,&s));
       
   246 	}
       
   247 	
       
   248 void OpenCommPort(TInt aPort)
       
   249 	{
       
   250 	char buf[20];
       
   251 
       
   252 	sprintf(buf, "\\\\.\\COM%d", aPort); // COM ports with indexes higher than 9 can only be referenced by prefixing the device name with "\\.\\"
       
   253 	Comm = CreateFile(buf, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
       
   254 	if (Comm == INVALID_HANDLE_VALUE)
       
   255 		{
       
   256 		if(GetLastError() == ERROR_ACCESS_DENIED)
       
   257 			{
       
   258 			fprintf(stderr, "Can't open COM%d: Error %d (Access denied) - a terminal application has probably been left running with the port still open\n", aPort, ERROR_ACCESS_DENIED);
       
   259 			}
       
   260 		else
       
   261 			{
       
   262 			fprintf(stderr, "Can't open COM%d: Error %d (%s)\n", aPort, GetLastError(), GetWinErrMsg(GetLastError()));
       
   263 			}
       
   264 		exit(KExitCodeSerial);
       
   265 		}
       
   266 
       
   267 	// Raise our thread priority to avoid being starved if builds are continuing in parallel while we are communicating with the target
       
   268 	// at high speeds.  TrgTest does not use serial flow control so if the buffers fill up, data will be lost.  We do not try to use the
       
   269 	// real-time process priority class because it requires administrator privileges.
       
   270 	SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
       
   271 	}
       
   272 	
       
   273 TInt SetupCommPort(TInt aPort, TUint aBaudRate, TBool aIgnoreInvalidBaudRateError = false)
       
   274 	{
       
   275 	TInt r = KErrNone;
       
   276 	const char* errFuncName = NULL;
       
   277 
       
   278 	DCB dcb;
       
   279 
       
   280 	dcb.DCBlength = sizeof(dcb);
       
   281 	if(!GetCommState(Comm, &dcb))
       
   282 		{
       
   283 		r = GetLastError();
       
   284 		errFuncName = "GetCommState";
       
   285 		}
       
   286 	else if(!SetCommMask(Comm, EV_ERR|EV_RXCHAR))
       
   287 		{
       
   288 		r = GetLastError();
       
   289 		errFuncName = "SetCommMask";
       
   290 		}
       
   291 	else if(!SetupComm(Comm, READ_BUF_SIZE, WRITE_BUF_SIZE))
       
   292 		{
       
   293 		r = GetLastError();
       
   294 		errFuncName = "SetupComm";
       
   295 		}
       
   296 	if(r != KErrNone)
       
   297 		{
       
   298 		TT_ASSERT(errFuncName);
       
   299 		
       
   300 		fprintf(stderr, "Error in SetupComm: Error %d (%s) calling %s\n", r, GetWinErrMsg(r), errFuncName);
       
   301 		TraceLog("Error in SetupComm: Error %d (%s) calling %s", r, GetWinErrMsg(r), errFuncName);
       
   302 		fprintf(stderr, "Trying to proceed anyway, be suspicious of any problems!\n");
       
   303 		TraceLog("Trying to proceed anyway, be suspicious of any problems!");
       
   304 		}
       
   305 	ClearCommError();
       
   306 	r = KErrNone;
       
   307 
       
   308 	dcb.fAbortOnError = TRUE;
       
   309 	dcb.BaudRate=aBaudRate;
       
   310 	dcb.Parity=NOPARITY;
       
   311 	dcb.fParity = FALSE;
       
   312 	dcb.fErrorChar = FALSE;
       
   313 	dcb.ByteSize = 8;
       
   314 	dcb.StopBits=ONESTOPBIT;
       
   315 	dcb.fInX  = FALSE;
       
   316 	dcb.fOutX = FALSE;
       
   317 	dcb.XonChar = 0;
       
   318 	dcb.XoffChar = 0;
       
   319 	dcb.ErrorChar = 0;
       
   320 	dcb.fOutxDsrFlow = FALSE;
       
   321 	dcb.fOutxCtsFlow = FALSE;
       
   322 	dcb.fDsrSensitivity =  FALSE;
       
   323 	dcb.fRtsControl = RTS_CONTROL_DISABLE;
       
   324 	dcb.fDtrControl = DTR_CONTROL_DISABLE;
       
   325 	if(!SetCommState(Comm, &dcb))
       
   326 		{
       
   327 		if(GetLastError() == ERROR_INVALID_PARAMETER)
       
   328 			{
       
   329 			r = KExitCodeUnsupportedBaudRate;
       
   330 
       
   331 			if(aIgnoreInvalidBaudRateError)
       
   332 				{
       
   333 				return r;
       
   334 				}
       
   335 			else
       
   336 				{
       
   337 				fprintf(stderr, "Error in SetCommState : Error %d (%s) - a baud rate of %dbps is not supported by COM%d - try a different port\n", GetLastError(), GetWinErrMsg(GetLastError()), aBaudRate, aPort);
       
   338 				TraceLog("Error in SetCommState : Error %d (%s) - a baud rate of %dbps is not supported by COM%d - try a different port", GetLastError(), GetWinErrMsg(GetLastError()), aBaudRate, aPort);
       
   339 				}
       
   340 			}
       
   341 		else
       
   342 			{
       
   343 			fprintf(stderr, "Error in SetCommState : Error %d calling (%s) SetCommState\n", GetLastError(), GetWinErrMsg(GetLastError()), aBaudRate);
       
   344 			TraceLog("Error in SetCommState : Error %d (%s) SetCommState", GetLastError(), GetWinErrMsg(GetLastError()), aBaudRate);
       
   345 			r = KExitCodeSerial;
       
   346 			}
       
   347 
       
   348 		exit(r);
       
   349 		}
       
   350 	EscapeCommFunction(Comm, SETDTR);
       
   351 	EscapeCommFunction(Comm, SETRTS);
       
   352 	
       
   353 	return KErrNone;
       
   354 	}
       
   355 
       
   356 void SetupTimeout(TInt aInt, TInt aTot)
       
   357 	{
       
   358 	COMMTIMEOUTS ct;
       
   359 	GetCommTimeouts(Comm, &ct);
       
   360 	ct.ReadIntervalTimeout = aInt;		// ms
       
   361 	ct.ReadTotalTimeoutMultiplier = 0;
       
   362 	ct.ReadTotalTimeoutConstant = aTot;	// ms
       
   363 	ct.WriteTotalTimeoutConstant = 0;
       
   364 	ct.WriteTotalTimeoutMultiplier = 0;
       
   365 	SetCommTimeouts(Comm, &ct);
       
   366 	}
       
   367 
       
   368 TInt CommRead1(TInt aTimeout)
       
   369 	{
       
   370 	unsigned char c;
       
   371 	DWORD n=0;
       
   372 	BOOL ok;
       
   373 
       
   374 	SetupTimeout(0, aTimeout);
       
   375 	ok = ReadFile(Comm, &c, 1, &n, NULL);
       
   376 	if (!ok)
       
   377 		ClearCommError();
       
   378 	if (ok && n)
       
   379 		return c;
       
   380 	return KErrTimedOut;
       
   381 	}
       
   382 
       
   383 TInt CommRead(void* aBuf, TInt aMax, TInt aTimeout)
       
   384 	{
       
   385 	DWORD n=0;
       
   386 	BOOL ok;
       
   387 
       
   388 	SetupTimeout(100, aTimeout);
       
   389 	ok = ReadFile(Comm, aBuf, aMax, &n, NULL);
       
   390 	if (!ok)
       
   391 		ClearCommError();
       
   392 	if (n==0)
       
   393 		return KErrTimedOut;
       
   394 	return n;
       
   395 	}
       
   396 
       
   397 void CommWrite(const void* aBuf, TInt aLen)
       
   398 	{
       
   399 	DWORD n = 0;
       
   400 	BOOL ok = WriteFile(Comm, aBuf, aLen, &n, NULL);
       
   401 	if (!ok)
       
   402 		ClearCommError();
       
   403 	}
       
   404 
       
   405 void CommWriteC(TUint aChar)
       
   406 	{
       
   407 	unsigned char c = (unsigned char)aChar;
       
   408 	CommWrite(&c, 1);
       
   409 	}
       
   410 
       
   411 void CommWriteS(const char* aString)
       
   412 	{
       
   413 	CommWrite( aString, strlen(aString) );
       
   414 	}
       
   415 
       
   416 TInt PreparePacket(SPacket& pkt, TInt aSeq, TInt& aOutBytesUploaded)
       
   417 	{
       
   418 	TInt r = KErrNone;
       
   419 	TUint16 crc = 0;
       
   420 
       
   421 	pkt.iPTI = STX;
       
   422 	pkt.iSeq = (TUint8)(aSeq>=0 ? aSeq : 0);
       
   423 	pkt.iSeqBar = (TUint8)~pkt.iSeq;
       
   424 	if (aSeq>0)
       
   425 		{
       
   426 		TInt l;
       
   427 		aOutBytesUploaded = (aSeq-1)*PACKET_SIZE;	// file position of packet
       
   428 		if ( aOutBytesUploaded >= ImgFileSize )
       
   429 			return KErrEof;
       
   430 		l = MIN(PACKET_SIZE, ImgFileSize-aOutBytesUploaded);
       
   431 		memcpy(pkt.iData, OFFSET(ImgFileChunkBase,aOutBytesUploaded), l);
       
   432 		if (l<PACKET_SIZE)
       
   433 			memset(pkt.iData+l, 0, PACKET_SIZE-l);
       
   434 		aOutBytesUploaded = max( aOutBytesUploaded, 0L );
       
   435 		}
       
   436 	else
       
   437 		{
       
   438 		aOutBytesUploaded = 0;
       
   439 		memset(pkt.iData, 0, PACKET_SIZE);
       
   440 		if (aSeq==0)
       
   441 			{
       
   442 			const char* p = ImgFileName;
       
   443 			const char* q = p + strlen(p);
       
   444 			while (--q>=p && *q!='\\') {}
       
   445 			sprintf( (char*)pkt.iData, "%s%c%d", q+1, 0, ImgFileSize);
       
   446 			}
       
   447 		}
       
   448 	UpdateCrc(pkt.iData, PACKET_SIZE, crc);
       
   449 	pkt.iCRC1 = (TUint8)(crc>>8);
       
   450 	pkt.iCRC0 = (TUint8)crc;
       
   451 	return r;
       
   452 	}
       
   453 
       
   454 TInt SendPacket(TInt& aSeq, TBool aStream, clock_t startTime)
       
   455 	{
       
   456 	TBool ackPacket = aSeq == -1;
       
   457 	TInt c;
       
   458 	SPacket pkt;
       
   459 	TInt retries = 10;
       
   460 	TInt tmout = (aSeq>=0) ? 2000 : 500;
       
   461 	TInt bytesUploaded;
       
   462 	
       
   463 	// Prepare the next packet.
       
   464 	TInt r = PreparePacket(pkt, aSeq, bytesUploaded);
       
   465 		
       
   466 	if (r==KErrNone)
       
   467 		{
       
   468 		// Keep trying to send the packet until it is acknowledged.
       
   469 		for(;;)
       
   470 			{
       
   471 			RESET_COMM();
       
   472 			CommWrite(&pkt, sizeof(pkt));
       
   473 			if (aStream)
       
   474 				break;
       
   475 			c = CommRead1(tmout);
       
   476 			if (c==KErrTimedOut && aSeq<0)
       
   477 				{
       
   478 				return KErrNone;
       
   479 				}
       
   480 			if (c>=0)
       
   481 				{
       
   482 				if (c==ACK)
       
   483 					break;
       
   484 				}
       
   485 			if (--retries==0)
       
   486 				{
       
   487 				r = KErrTimedOut;
       
   488 				break;
       
   489 				}
       
   490 			}
       
   491 	
       
   492 		// Check to see if the send operation was successful.	
       
   493 		if (r == KErrNone || (r == KErrEof))
       
   494 			{
       
   495 			// Verify the stream type for the first packet.
       
   496 			if(aSeq==0)
       
   497 				{
       
   498 				c = CommRead1(100);
       
   499 				if (c==KErrTimedOut)
       
   500 					{
       
   501 					r = KErrNone;
       
   502 					}
       
   503 				else if (aStream && c!=BIGG)
       
   504 					r = KErrTimedOut;
       
   505 				else if (!aStream && c!=BIGC)
       
   506 					r = KErrTimedOut;
       
   507 				}
       
   508 			
       
   509 			if(r == KErrNone)
       
   510 				{
       
   511 				++aSeq;
       
   512 				}
       
   513 			}
       
   514 		}
       
   515 		
       
   516 	// Print the progress info.
       
   517 	if (((r == KErrNone) && ((aSeq & 7) == 0)) || (r != KErrNone) || ackPacket)
       
   518 		{
       
   519 		// Calculate total packet count.
       
   520 		TInt totalPacketCount = (ImgFileSize / PACKET_SIZE) + 2; // one extra packet for handshake and one extra packet for acknowledgement
       
   521 		TInt roundedImageFileSize = ImgFileSize;
       
   522 		TInt remainderSize = ImgFileSize % PACKET_SIZE;
       
   523 		if(remainderSize != 0)
       
   524 			{
       
   525 			totalPacketCount ++;
       
   526 			roundedImageFileSize += (PACKET_SIZE - remainderSize);
       
   527 			}
       
   528 		
       
   529 		// Calculate the percentage complete.
       
   530 		TInt percentComplete = (bytesUploaded * 100) / roundedImageFileSize;
       
   531 		
       
   532 		// Calculate the ETA.
       
   533 		clock_t elapsedTime = clock() - startTime;
       
   534 		clock_t etaM = -1L;
       
   535 		clock_t etaS = -1L;
       
   536 		if(aSeq > 0)
       
   537 			{
       
   538 			double bytesPerSec = double(bytesUploaded) / (double(elapsedTime) / double(CLOCKS_PER_SEC));
       
   539 			clock_t etaTotalS = clock_t((double(roundedImageFileSize) - double(bytesUploaded)) / bytesPerSec);
       
   540 			etaM = max(etaTotalS / 60, 0L);
       
   541 			etaS = max(etaTotalS % 60, 0L);
       
   542 			}
       
   543 
       
   544 		// Ensure upload always halts at 100%.
       
   545 		if(ackPacket)
       
   546 			{
       
   547 			aSeq = totalPacketCount;
       
   548 			bytesUploaded = roundedImageFileSize;
       
   549 			percentComplete = 100;
       
   550 			etaM = 0L;
       
   551 			etaS = 0L;
       
   552 			}
       
   553 
       
   554 		// Format uploaded bytes and ROM size.
       
   555 		char sizeBuffer[256];
       
   556 		StrFormatByteSize(bytesUploaded, sizeBuffer, sizeof(sizeBuffer));
       
   557 		char imageSizeBuffer[256];
       
   558 		StrFormatByteSize(roundedImageFileSize, imageSizeBuffer, sizeof(imageSizeBuffer));
       
   559 
       
   560 		// Update the currently uploaded bytes, percentage complete and ETA in-place.
       
   561 		// We add additional spacing to overwrite the previous line if the new line
       
   562 		// contracts because the byte sizes have switched to larger units.
       
   563 		if(ackPacket)
       
   564 			{
       
   565 			elapsedTime /= CLOCKS_PER_SEC;
       
   566 			clock_t elapsedM = max(elapsedTime / 60, 0L);
       
   567 			clock_t elapsedS = max(elapsedTime % 60, 0L);
       
   568 			printf("\r%05d Packets Sent: %s / %s (%02d %%), Time Taken: %02d:%02d      ", aSeq, sizeBuffer, imageSizeBuffer, percentComplete, elapsedM, elapsedS);
       
   569 			}
       
   570 		else if((r == KErrNone) || (r == KErrEof))
       
   571 			{
       
   572 			if(etaM >= 0L)
       
   573 				{
       
   574 				printf("\r%05d Packets Sent: %s / %s (%02d %%), ETA: %02d:%02d      ", aSeq, sizeBuffer, imageSizeBuffer, percentComplete, etaM, etaS);
       
   575 				}
       
   576 			else
       
   577 				{
       
   578 				printf("\r%05d Packets Sent: %s / %s (%02d %%), ETA: ??:??      ", aSeq, sizeBuffer, imageSizeBuffer, percentComplete);
       
   579 				}
       
   580 			}
       
   581 		else
       
   582 			{
       
   583 			fprintf(stderr, "\rFailed to send packet %d: %s / %s (%02d %%), Error: %d (%s)      ", ackPacket ? (totalPacketCount - 1) : aSeq, sizeBuffer, imageSizeBuffer, percentComplete, r, GetSymOrWinErrMsg(r));
       
   584 			}
       
   585 		}
       
   586 		
       
   587 	return r;
       
   588 	}
       
   589 
       
   590 TInt GetMonitorInfo();
       
   591 
       
   592 TInt Handshake(TBool& aOutStream, TBool aIgnoreHandshakeFailure = false)
       
   593 	{
       
   594 	TInt r = 0;
       
   595 	TInt r2 = 0;
       
   596 	TUint8 b2[256];
       
   597 
       
   598 	Sleep(2000); // wait 2 seconds
       
   599 	RESET_COMM();
       
   600 	Sleep(2000); // wait 2 seconds
       
   601 flush:
       
   602 	r = CommRead(b2, sizeof(b2), 60000);	// 60 second timeout
       
   603 	if(r==sizeof(b2))
       
   604 		{
       
   605 		printf("Flushing data from port\n");
       
   606 		TraceLog("Flushing data from port");
       
   607 		goto flush;
       
   608 		}
       
   609 
       
   610 	if (r<0)
       
   611 		{
       
   612 		TraceLog("ERROR Handshake 1: r=%d (%s)", r, GetSymOrWinErrMsg(r));
       
   613 		// Send CR to see if it elicits monitor prompt
       
   614 		CommWriteC(0x0d);
       
   615 		r2 = CommRead(LineBuf, 12, 1000);		// 1 second timeout
       
   616 		if (r2==12 && memcmp(LineBuf, "\xd\xaPassword: ", 12)==0)
       
   617 			{
       
   618 			printf("ERROR: target is in debug monitor\n");
       
   619 			TraceLog("ERROR: target is in debug monitor");
       
   620 			if (LogFile)
       
   621 				{
       
   622 				printf("Gathering information...\n");
       
   623 				TraceLog("Gathering information...");
       
   624 				r2 = GetMonitorInfo();
       
   625 				printf("Rebooting...\n");
       
   626 				TraceLog("Rebooting...");
       
   627 				CommWriteS("X\xd");
       
   628 				}
       
   629 			else
       
   630 				{
       
   631 				printf("No logfile - preserving state (not rebooting)\n");
       
   632 				TraceLog("No logfile - preserving state (not rebooting)");
       
   633 				}
       
   634 			return KExitCodeDOA;
       
   635 			}
       
   636 		return r;
       
   637 		}
       
   638 	if (b2[r-1]!=BIGG && b2[r-1]!=BIGC)
       
   639 		{
       
   640 		if(!aIgnoreHandshakeFailure)
       
   641 			{
       
   642 			TraceLog("ERROR Handshake 2: r=%d (%s)", KErrTimedOut, GetSymOrWinErrMsg(KErrTimedOut));
       
   643 			}
       
   644 		return KErrTimedOut;
       
   645 		}
       
   646 		
       
   647 	aOutStream = (b2[r-1]==BIGG);
       
   648 	
       
   649 	return KErrNone;
       
   650 	}
       
   651 	
       
   652 TInt SendImageFile(TUint aPort, TUint aBaudRate, TBool aStream)
       
   653 	{
       
   654 	printf("Sending ROM image %s on COM%d at %dbps\n",ImgFileName,aPort,aBaudRate);
       
   655 	TraceLog("Sending ROM image %s on COM%d at %dbps",ImgFileName,aPort,aBaudRate);
       
   656 
       
   657 	TInt r = KErrNone;
       
   658 
       
   659 	// Keep sending packets until we reach the end of the file or an error occurs.
       
   660 	TInt seq = 0;
       
   661 	clock_t startTime = clock();
       
   662 	while(r==KErrNone)
       
   663 		{
       
   664 		r = SendPacket(seq, aStream, startTime);
       
   665 		}
       
   666 	
       
   667 	// If we reached the end of the file, acknowledge that the transfer is complete.
       
   668 	if(r==KErrEof)
       
   669 		{
       
   670 		RESET_COMM();
       
   671 		CommWriteC(EOT);
       
   672 		TInt b1 = CommRead1(500);
       
   673 		if (b1==KErrTimedOut)
       
   674 			{
       
   675 			r = KErrNone;
       
   676 			}
       
   677 		else if (b1!=ACK)
       
   678 			{
       
   679 			r = KErrNone;
       
   680 			}
       
   681 		
       
   682 		if(r == KErrNone)
       
   683 			{
       
   684 			printf("\n");
       
   685 			}
       
   686 		else
       
   687 			{
       
   688 			// Wait for acknowledgement from the target.
       
   689 			TBool noAck = false;
       
   690 			b1 = CommRead1(1000);
       
   691 			if (b1==KErrTimedOut)
       
   692 				{
       
   693 				r = KErrNone;
       
   694 				noAck = true;
       
   695 				}
       
   696 			else if (aStream && b1!=BIGG)
       
   697 				{
       
   698 				r = KErrNone;
       
   699 				noAck = true;
       
   700 				}
       
   701 			else if (!aStream && b1!=BIGC)
       
   702 				{
       
   703 				r = KErrNone;
       
   704 				noAck = true;
       
   705 				}
       
   706 			
       
   707 			// If there was no acknowledgement from the target, ignore the problem at this point and print the newline.
       
   708 			if(noAck)
       
   709 				{
       
   710 				printf("\n");
       
   711 				}
       
   712 
       
   713 			// Else, send our acknowledgement packet to complete the transfer.
       
   714 			else
       
   715 				{
       
   716 				seq = -1;
       
   717 				TInt bytesUploaded = 0;
       
   718 				r = SendPacket(seq, aStream, bytesUploaded);
       
   719 				printf("\n");
       
   720 				if(r)
       
   721 					{
       
   722 					TraceLog("ERROR: SendImageFile r=%d (%s)", r, GetSymOrWinErrMsg(r));
       
   723 					}
       
   724 				}
       
   725 			}
       
   726 		}
       
   727 		
       
   728 	// Else, print any error.
       
   729 	else
       
   730 		{
       
   731 		printf("\n<SendPacket %d -> %d (%s)\n", seq, r, GetSymOrWinErrMsg(r));
       
   732 		TraceLog("ERROR: <SendPacket seq=%d r=%d (%s)", seq, r, GetSymOrWinErrMsg(r));
       
   733 		}
       
   734 
       
   735 	return r;
       
   736 	}
       
   737 
       
   738 void GetResponse()
       
   739 	{
       
   740 	TInt r;
       
   741 	do	{
       
   742 		r = CommRead(LineBuf, MAX_LINE, 1000);
       
   743 		if (r>=0)
       
   744 			if(use_stdout)
       
   745 				{
       
   746 				LineBuf[r]=0;
       
   747 				printf(LineBuf);
       
   748 				}
       
   749 			else
       
   750 				{
       
   751 				WriteLog(LineBuf, r);
       
   752 				}
       
   753 		} while (r>=0);
       
   754 	}
       
   755 
       
   756 void IssueCommandAndGetResponse(const char* aCmd)
       
   757 	{
       
   758 	CommWriteS(aCmd);
       
   759 	GetResponse();
       
   760 	}
       
   761 
       
   762 int token_length(const char* s)
       
   763 	{
       
   764 	const char* p = s;
       
   765 	for (; *p && !isspace(*p); ++p) {}
       
   766 	return p - s;
       
   767 	}
       
   768 
       
   769 const char* skip_space(const char* s)
       
   770 	{
       
   771 	for (; *s && isspace(*s); ++s) {}
       
   772 	return s;
       
   773 	}
       
   774 
       
   775 TInt GetMonitorInfo()
       
   776 /*
       
   777  return 0 on success, -1 on failure
       
   778  */
       
   779 	{
       
   780 	BOOL ok = FALSE;
       
   781 	int l;
       
   782 	int type;
       
   783 	RESET_COMM();
       
   784 	IssueCommandAndGetResponse("replacement\xd");
       
   785 	IssueCommandAndGetResponse("f\xd");
       
   786 	const char* p = LineBuf;
       
   787 	const char* q = LineBuf + strlen(LineBuf);
       
   788 	while (p<q)
       
   789 		{
       
   790 		p = skip_space(p);
       
   791 		if (p+16>q || memcmp(p, "Fault Category: ", 16))
       
   792 			{
       
   793 			p += token_length(p);
       
   794 			continue;
       
   795 			}
       
   796 		p = skip_space(p+16);
       
   797 		l = token_length(p);
       
   798 		if (l!=4 || memcmp(p, "KERN", 4))
       
   799 			{
       
   800 			p += l;
       
   801 			continue;
       
   802 			}
       
   803 		p = skip_space(p+4);
       
   804 		if (p+14>q || memcmp(p, "Fault Reason: ", 14))
       
   805 			{
       
   806 			p += token_length(p);
       
   807 			continue;
       
   808 			}
       
   809 		p = skip_space(p+14);
       
   810 		if (p+8<=q && memcmp(p, "00000050", 8)==0)
       
   811 			{
       
   812 			ok = true;
       
   813 			break;
       
   814 			}
       
   815 		p+=8;
       
   816 		continue;
       
   817 		}
       
   818 	if (ok)
       
   819 		{
       
   820 		// Add a line after the "." debug monitor prompt so the next log line won't appear next to it.
       
   821 		TraceLog("");
       
   822 		
       
   823 		return 0;
       
   824 		}
       
   825 
       
   826 	IssueCommandAndGetResponse("i\xd");
       
   827 	for (type=0; type<14; ++type)
       
   828 		{
       
   829 		char b[8];
       
   830 		sprintf(b, "c%x\xd", type);
       
   831 		IssueCommandAndGetResponse(b);
       
   832 		}
       
   833 
       
   834 	IssueCommandAndGetResponse("S\xd");
       
   835 	
       
   836 	// Optionally, dump the code segs to make it clear where non-XIP code is loaded
       
   837 	// and make debugging easier.
       
   838 	if(DebugMonitorOptions & kDebugDumpCodeSegs)
       
   839 		{
       
   840 		IssueCommandAndGetResponse("p all\xd");
       
   841 		}
       
   842 		
       
   843 	// Add a line after the "." debug monitor prompt so the next log line won't appear next to it.
       
   844 	TraceLog("");
       
   845 
       
   846 	return -1;
       
   847 	}
       
   848 	
       
   849 TInt ReceiveTestLog(TInt aOverallTimeOutS)
       
   850 	{
       
   851 	TInt r=0;
       
   852 	TInt r2;
       
   853 	clock_t iterationStartTime = clock();
       
   854 	
       
   855 	for(;;)
       
   856 		{
       
   857 		TBool checkDebugMonitor = false;
       
   858 		
       
   859 		r = CommRead(LineBuf, MAX_LINE, aOverallTimeOutS * 1000);
       
   860 		
       
   861 		// If a time-out occured, print an error message.
       
   862 		if (r==KErrTimedOut)
       
   863 			{
       
   864 			clock_t elapsedTimeC = clock() - iterationStartTime;
       
   865 			double elapsedTimeS = double(elapsedTimeC) / double(CLOCKS_PER_SEC);
       
   866 
       
   867 			if(elapsedTimeS < 10.0)
       
   868 				{
       
   869 				if(!use_stdout)
       
   870 					{
       
   871 					fprintf(stderr, "Nothing received for past %.02f seconds\n", elapsedTimeS);
       
   872 					}
       
   873 				TraceLog("Nothing received for past %.02f seconds", elapsedTimeS);
       
   874 				}
       
   875 			else
       
   876 				{
       
   877 				elapsedTimeC /= CLOCKS_PER_SEC;
       
   878 				clock_t elapsedM = max(elapsedTimeC / 60, 0L);
       
   879 				clock_t elapsedS = max(elapsedTimeC % 60, 0L);
       
   880 
       
   881 				if(!use_stdout)
       
   882 					{
       
   883 					fprintf(stderr, "Nothing received for past %02d:%02d minutes\n", elapsedM, elapsedS);
       
   884 					}
       
   885 				TraceLog("Nothing received for past %02d:%02d minutes", elapsedM, elapsedS);
       
   886 				}
       
   887 
       
   888 			checkDebugMonitor = true;
       
   889 			}
       
   890 			
       
   891 		// If the string "Password: " was read, this probably indicates the kernel
       
   892 		// has jumped into the debug monitor.
       
   893 		if (r>=10 && memcmp(LineBuf+r-10, "Password: ", 10)==0)
       
   894 			{
       
   895 			checkDebugMonitor = true;
       
   896 			}
       
   897 			
       
   898 		// If real data was received, print it to the selected output.
       
   899 		if (r>0)
       
   900 			{
       
   901 			if (use_stdout)
       
   902 				{
       
   903 				LineBuf[r]=0;		// terminate string
       
   904 				printf(LineBuf);
       
   905 				}
       
   906 			else
       
   907 				{
       
   908 				WriteLog(LineBuf, r);
       
   909 				}
       
   910 
       
   911 			iterationStartTime = clock();
       
   912 			}
       
   913 		
       
   914 		// If an error occured, check to see if the debug monitor is running.  If it is,
       
   915 		// we can extract information about the fault and use it to reboot the board.
       
   916 		if (checkDebugMonitor || (r==KErrTimedOut))
       
   917 			{
       
   918 			// Send CR to see if it elicits monitor prompt.
       
   919 			CommWriteC(0x0d);
       
   920 			r2 = CommRead(LineBuf, 12, 1000);
       
   921 			if (r2>0)
       
   922 				{
       
   923 				if(use_stdout)
       
   924 					{
       
   925 					LineBuf[r2]=0;
       
   926 					printf(LineBuf);
       
   927 					}
       
   928 				else
       
   929 					{
       
   930 					WriteLog(LineBuf, r2);
       
   931 					}
       
   932 				}
       
   933 			if (r2==12 && memcmp(LineBuf, "\xd\xaPassword: ", 12)==0)
       
   934 				{
       
   935 				break;
       
   936 				}
       
   937 			}
       
   938 			
       
   939 		// If an error occured and the debug monitor is not running, stop trying to receive the session log.
       
   940 		if (r<0)
       
   941 			{
       
   942 			break;
       
   943 			}
       
   944 		}
       
   945 
       
   946 	// Check to see if the debug monitor was successfully prompted.
       
   947 	TT_ASSERT((r>0) || (r==KErrTimedOut));
       
   948 	if (r>0)
       
   949 		{
       
   950 		// The debug monitor is accessible so extract debugging information.
       
   951 		r = GetMonitorInfo();
       
   952 		
       
   953 		// Issue the command to try to reboot the board.
       
   954 		CommWriteS("X\xd");
       
   955 		if (r)
       
   956 			{
       
   957 			r = KExitCodeFaulted;
       
   958 			}
       
   959 		else
       
   960 			{
       
   961 			r = KErrNone;
       
   962 			}
       
   963 		}
       
   964 	else if(r<0)
       
   965 		{
       
   966 		// The board debug monitor is not accessible or the board has locked up.
       
   967 		printf("Target hung\n");
       
   968 		TraceLog("Target hung");
       
   969 		r = KExitCodeHung;
       
   970 		}
       
   971 		
       
   972 	return r;	
       
   973 	}
       
   974 
       
   975 TInt DetermineBaudRate(TInt aPort, TUint& outBaudRate, TBool& aOutStream)
       
   976 	{
       
   977 	TInt r = KErrNone;
       
   978 	
       
   979 	for( TUint i = 0; i < sizeof(KBaudRateSearchList) / sizeof(TUint); i ++ )
       
   980 		{
       
   981 		// Set the COM port to use the next baud rate to try.
       
   982 		if(i != 0)	// hide the first test so that the UI for boards supporting 115200bps-only remains the same as it
       
   983 			{		// was before.
       
   984 			printf("Testing COM%d at %dbps...", aPort, KBaudRateSearchList[i]);
       
   985 			}
       
   986 		TraceLog("Testing COM%d at %dbps", aPort, KBaudRateSearchList[i]);
       
   987 		r = SetupCommPort(aPort, KBaudRateSearchList[i], true);
       
   988 
       
   989 		if(r == KErrNone)
       
   990 			{
       
   991 			// Try to Y-modem handshake with the board.  If we succeed then we have found the correct speed.
       
   992 			r = Handshake(aOutStream, true);
       
   993 			if(r == KErrNone)
       
   994 				{
       
   995 				if(i != 0)
       
   996 					{
       
   997 					// If we finished the first test (115200bps) successfully, we do not reveal the fact that we are
       
   998 					// prepared to test multiple baud rates so that the UI for boards supporting 115200bps only remains
       
   999 					// the same as it was before.
       
  1000 					printf(" Succeeded\n", aPort, KBaudRateSearchList[i]);
       
  1001 					}
       
  1002 				TraceLog("Testing of COM%d at %dbps Succeeded", aPort, KBaudRateSearchList[i]);
       
  1003 				outBaudRate = KBaudRateSearchList[i];
       
  1004 				
       
  1005 				break;
       
  1006 				}
       
  1007 			else if(r == KExitCodeDOA)
       
  1008 				{
       
  1009 				// The board is stuck in the crash debugger and is unusable.
       
  1010 				break;
       
  1011 				}
       
  1012 			else
       
  1013 				{
       
  1014 				if(i == 0)
       
  1015 					{
       
  1016 					// If we finished the first test (115200bps) unsuccessfully, at this point we reveal that we are
       
  1017 					// testing multiple baud rates and report the results of the failure.
       
  1018 					printf("Testing COM%d at %dbps...", aPort, KBaudRateSearchList[i]);
       
  1019 					}
       
  1020 				printf(" Failed (%d) %s\n", r, GetSymOrWinErrMsg(r));
       
  1021 				TraceLog("Testing of COM%d at %dbps Failed (%d) %s", aPort, KBaudRateSearchList[i], r, GetSymOrWinErrMsg(r));
       
  1022 				}
       
  1023 			}
       
  1024 		else if(r == KExitCodeUnsupportedBaudRate)
       
  1025 			{
       
  1026 			if(i == 0)
       
  1027 				{
       
  1028 				// If we finished the first test (115200bps) and the baud rate setting is unsupported, at this point
       
  1029 				// we reveal that we are testing multiple baud rates and report the results of the failure.
       
  1030 				printf("Testing COM%d at %dbps...", aPort, KBaudRateSearchList[i]);
       
  1031 				}
       
  1032 			printf(" COM%d port doesn't support this baud rate setting\n", aPort);
       
  1033 			TraceLog("COM%d port doesn't support %dbps setting", aPort, KBaudRateSearchList[i]);
       
  1034 			}
       
  1035 		}
       
  1036 		
       
  1037 	return r;
       
  1038 	}
       
  1039 
       
  1040 void UploadROM(TInt aPort, TUint& aInOutBaudRate)
       
  1041 	{
       
  1042 	// Open the ROM image file and copy it into memory.
       
  1043 	FILE* img = fopen(ImgFileName, "rb");
       
  1044 	if (!img)
       
  1045 		{
       
  1046 		fprintf(stderr, "Can't open %s for read (%d) %s\n", ImgFileName, errno, strerror(errno));
       
  1047 		exit(KExitCodeImage);
       
  1048 		}
       
  1049 	fseek(img,0,SEEK_END);
       
  1050 	ImgFileSize=ftell(img);
       
  1051 	fseek(img,0,SEEK_SET);
       
  1052 	TraceLog("ROM Image File Size   = %d bytes\n", ImgFileSize);
       
  1053 	ImgFileChunkBase = malloc(ImgFileSize);
       
  1054 	TT_ASSERT(ImgFileChunkBase != NULL);
       
  1055 	int n = fread(ImgFileChunkBase, 1, ImgFileSize, img);
       
  1056 	TT_ASSERT(n == ImgFileSize);
       
  1057 	fclose(img);
       
  1058 
       
  1059 	// Check to see if we should flash the ROM image or the boot loader based
       
  1060 	// on the filename of the tool.
       
  1061 	if (strcmpi("flashimg", __argv[0])==0)
       
  1062 		{
       
  1063 		printf("Uploading image %s to flash ", ImgFileName);
       
  1064 		if (strstr(ImgFileName, ".zip") || strstr(ImgFileName, ".zip"))
       
  1065 			strcpy(ImgFileName, "flashimg.zip");
       
  1066 		else
       
  1067 			strcpy(ImgFileName, "flashimg.bin");
       
  1068 		printf("[%s]\n", ImgFileName);
       
  1069 		}
       
  1070 	else if (strcmpi("flashldr", __argv[0])==0)
       
  1071 		{
       
  1072 		printf("Uploading image %s to flash as bootloader ", ImgFileName);
       
  1073 		if (strstr(ImgFileName, ".zip") || strstr(ImgFileName, ".zip"))
       
  1074 			strcpy(ImgFileName, "flashldr.zip");
       
  1075 		else
       
  1076 			strcpy(ImgFileName, "flashldr.bin");
       
  1077 		printf("[%s]\n", ImgFileName);
       
  1078 		}
       
  1079 
       
  1080 	// Open the COM port.
       
  1081 	OpenCommPort(aPort);
       
  1082 	
       
  1083 	// Check to see if we should try to automatically determine the baud rate.
       
  1084 	TInt r;
       
  1085 	TBool stream = true;
       
  1086 	if(aInOutBaudRate == 0)
       
  1087 		{
       
  1088 		r = DetermineBaudRate(aPort, aInOutBaudRate, stream);
       
  1089 		if(r != KErrNone)
       
  1090 			{
       
  1091 			if(r != KExitCodeDOA) // DetermineBaudRate prints its own error message for KExitCodeDOA
       
  1092 				{
       
  1093 				fprintf(stderr, "Unable to determine baud rate or the target is hung/unplugged\n");
       
  1094 				TraceLog("Unable to determine baud rate or the target is hung/unplugged");
       
  1095 				}
       
  1096 			exit(r);
       
  1097 			}
       
  1098 		}
       
  1099 	else
       
  1100 		{
       
  1101 		r = SetupCommPort(aPort, aInOutBaudRate);
       
  1102 		if(r == KErrNone)
       
  1103 			{
       
  1104 			r = Handshake(stream);
       
  1105 			}
       
  1106 		if(r != KErrNone)
       
  1107 			{
       
  1108 			fprintf(stderr, "Unable to connect to target on COM%d at %dbps (%d) %s\n", aPort, aInOutBaudRate, r, GetSymOrWinErrMsg(r));
       
  1109 			TraceLog("Unable to connect to target on COM%d at %dbps (%d) %s", aPort, aInOutBaudRate, r, GetSymOrWinErrMsg(r));
       
  1110 			exit(r);
       
  1111 			}
       
  1112 		}
       
  1113 
       
  1114 	// Send the image.
       
  1115 	r = SendImageFile(aPort, aInOutBaudRate, stream);
       
  1116 	
       
  1117 	free(ImgFileChunkBase);
       
  1118 	}
       
  1119 	
       
  1120 TInt LogTargetOutput(const char* aLogFileName, TBool aUseStdOut, TInt aPort, TUint& aInOutBaudRate, TUint& aInOutLogBaudRate, TInt aOverallTimeOutS)
       
  1121 	{
       
  1122 	TInt r;
       
  1123 	
       
  1124 	// Switch to the session log baud rate (default 115200bps) - higher speeds are usually only used for serial
       
  1125 	// upload and not for the log download.  It is possible to utilise higher log baud rates by manually modifying
       
  1126 	// the debugport code in the board support package.
       
  1127 	if(aInOutBaudRate != aInOutLogBaudRate)
       
  1128 		{
       
  1129 		r = SetupCommPort(aPort, aInOutLogBaudRate);
       
  1130 
       
  1131 		if(r != KErrNone)
       
  1132 			{
       
  1133 			fprintf(stderr, "Unable to switch to session log baud rate (%dbps) or the target is hung/unplugged\n", aInOutLogBaudRate);
       
  1134 			TraceLog("Unable to switch to session log baud rate (%dbps) or the target is hung/unplugged", aInOutLogBaudRate);
       
  1135 			exit(r);
       
  1136 			}
       
  1137 		
       
  1138 		aInOutBaudRate = aInOutLogBaudRate;
       
  1139 		}
       
  1140 
       
  1141 	// Check to see if we are logging to STDOUT or to a file.
       
  1142 	if(!aUseStdOut)
       
  1143 		{
       
  1144 		printf("Logging target output from COM%d at %dbps to %s...\n", aPort, aInOutLogBaudRate, aLogFileName);
       
  1145 		TraceLog("BEGIN TARGET LOG", aLogFileName);
       
  1146 		}
       
  1147 	
       
  1148 	// Receive the session log.
       
  1149 	clock_t startTime = clock();
       
  1150 	r = ReceiveTestLog(aOverallTimeOutS);
       
  1151 	
       
  1152 	// Print the duration of the session.
       
  1153 	clock_t elapsedTimeC = clock() - startTime;
       
  1154 	double elapsedTimeS = double(elapsedTimeC) / double(CLOCKS_PER_SEC);
       
  1155 	if(elapsedTimeS < 10.0)
       
  1156 		{
       
  1157 		if(!use_stdout)
       
  1158 			{
       
  1159 			printf("Target output log ended after %.02f seconds\n", elapsedTimeS);
       
  1160 			}
       
  1161 		TraceLog("END TARGET LOG after %.02f seconds", elapsedTimeS);
       
  1162 		}
       
  1163 	else
       
  1164 		{
       
  1165 		elapsedTimeC /= CLOCKS_PER_SEC;
       
  1166 		clock_t elapsedM = max(elapsedTimeC / 60, 0L);
       
  1167 		clock_t elapsedS = max(elapsedTimeC % 60, 0L);
       
  1168 
       
  1169 		if(!use_stdout)
       
  1170 			{
       
  1171 			printf("Target output log ended after %02d:%02d minutes\n", elapsedM, elapsedS);
       
  1172 			}
       
  1173 		TraceLog("END TARGET LOG after %02d:%02d minutes", elapsedM, elapsedS);
       
  1174 		}
       
  1175 	
       
  1176 	return r;
       
  1177 	}
       
  1178 	
       
  1179 void CloseSession()
       
  1180 	{
       
  1181 	// Perform cleanup...
       
  1182 	
       
  1183 	WriteLogS("\n\n");
       
  1184 	TraceLog("DONE");
       
  1185 
       
  1186 	EscapeCommFunction(Comm, CLRRTS);
       
  1187 	EscapeCommFunction(Comm, CLRDTR);
       
  1188 
       
  1189 	if(Comm != INVALID_HANDLE_VALUE)
       
  1190 		{
       
  1191 		CloseHandle(Comm);
       
  1192 		Comm = INVALID_HANDLE_VALUE;
       
  1193 		}
       
  1194 
       
  1195 	if (LogFile)
       
  1196 		{
       
  1197 		fclose(LogFile);
       
  1198 		LogFile = NULL;
       
  1199 		}
       
  1200 	}
       
  1201 
       
  1202 void PrintHelp()
       
  1203 	{
       
  1204 	fprintf(stderr, "\n");
       
  1205 	fprintf(stderr, "TrgTest Serial Y-Modem Upload Test Utility\n");
       
  1206 	fprintf(stderr, "==========================================\n\n");
       
  1207 	fprintf(stderr, "trgtest port# [-b<baudrate> default: 0 (auto)] [-lb<baudrate> default: 115200]");
       
  1208 	fprintf(stderr, "        imagefilename [logfilename] [timeout]\n\n");
       
  1209 	fprintf(stderr, "  port#              = COM port e.g., \"1\"\n");
       
  1210 	fprintf(stderr, "  -b (optional)      = ROM image serial upload baud rate e.g., \"-b115200\"\n");
       
  1211 	fprintf(stderr, "  -lb (opt.)         = session log download baud rate e.g., \"-lb115200\"\n");
       
  1212 	fprintf(stderr, "  imagefilename      = path to ROM image e.g., \"rom.img\" or \"nul\" for no image\n");
       
  1213 	fprintf(stderr, "  logfilename (opt.) = path to session log e.g., \"test.log\" or \"-\" for STDOUT\n");
       
  1214 	fprintf(stderr, "  timeout (opt.)     = timeout after inactivity in seconds e.g., \"1800\"\n\n");
       
  1215 	fprintf(stderr, "Example Usage:\n\n");
       
  1216 	fprintf(stderr, "  trgtest 1 rom.img log.txt\n");
       
  1217 	}
       
  1218 
       
  1219 
       
  1220 int main(int argc, char** argv)
       
  1221 	{
       
  1222 	TInt r = KErrNone;
       
  1223 	TInt port = 0;
       
  1224 	TUint baudRate = 0;
       
  1225 	TUint logBaudRate = 0;
       
  1226 	TInt overallTimeOutS = 1800;  // default time to wait for output (in seconds)
       
  1227 	const char* logfilename = NULL;
       
  1228 	int paramIndex = 1;
       
  1229 	
       
  1230 	// Disable stream buffering.
       
  1231 	setvbuf(stdout,NULL,_IONBF,0);
       
  1232 	
       
  1233 	// Print help if the parameter count is incorrect.
       
  1234 	if (argc<3 || argc>7)
       
  1235 		{
       
  1236 		PrintHelp();
       
  1237 		exit(KExitCodeUsage);
       
  1238 		}
       
  1239 		
       
  1240 	// Get the COM port.
       
  1241 	if(isdigit(argv[paramIndex][0]))
       
  1242 		{
       
  1243 		port = atoi(argv[paramIndex]);
       
  1244 		if(port == 0)
       
  1245 			{
       
  1246 			fprintf(stderr, "\"0\" is not valid - specify a serial COM port index number >= 1");
       
  1247 			exit(KExitCodeUsage);
       
  1248 			}
       
  1249 		paramIndex ++;
       
  1250 		}
       
  1251 	else
       
  1252 		{
       
  1253 		fprintf(stderr, "\"%s\" is not valid - specify a serial COM port index number >= 1", argv[paramIndex]);
       
  1254 		exit(KExitCodeUsage);
       
  1255 		}
       
  1256 	
       
  1257 	// Parse the optional parameters - order is not important.	
       
  1258 	while(paramIndex < argc)
       
  1259 		{
       
  1260 		// Get the serial upload baud rate.
       
  1261 		if(StrCmpNI(argv[paramIndex], "-b", 2) == 0)
       
  1262 			{
       
  1263 			baudRate = atoi(argv[paramIndex] + 2);
       
  1264 			paramIndex ++;
       
  1265 			}
       
  1266 			
       
  1267 		// Get the session log baud rate.
       
  1268 		else if(StrCmpNI(argv[paramIndex], "-lb", 3) == 0)
       
  1269 			{
       
  1270 			logBaudRate = atoi(argv[paramIndex] + 3);
       
  1271 			paramIndex ++;
       
  1272 			}
       
  1273 		
       
  1274 		// Stop if we parse an unknown option - it is probably the ROM image file path.	
       
  1275 		else
       
  1276 			{
       
  1277 			break;
       
  1278 			}
       
  1279 		}
       
  1280 		
       
  1281 	// If no session log baud rate was specified, set the default rate of 115200bps.
       
  1282 	if(logBaudRate == 0)
       
  1283 		{
       
  1284 		logBaudRate = KDefaultBaudRate;
       
  1285 		}
       
  1286 		
       
  1287 	// Get the ROM image file path.
       
  1288 	if(paramIndex >= argc)
       
  1289 		{
       
  1290 		fprintf(stderr, "No ROM image file specified\n");
       
  1291 		exit(KExitCodeUsage);
       
  1292 		}
       
  1293 	strcpy(ImgFileName, argv[paramIndex]);
       
  1294 	paramIndex ++;
       
  1295 
       
  1296 	// Get the session log options.
       
  1297 	if (paramIndex < argc)
       
  1298 		{
       
  1299 		// Check to see if TrgTest should log the target output and to what.
       
  1300 		logfilename = argv[paramIndex];
       
  1301 		if (!strcmp(logfilename, "-"))
       
  1302 			{
       
  1303 			printf("After the upload has completed, TrgTest will read from the serial port and write to STDOUT.\n");
       
  1304 			use_stdout = true;
       
  1305 			}
       
  1306 		else
       
  1307 			{
       
  1308 			LogFile = fopen(logfilename, "wb");
       
  1309 			
       
  1310 			if (!LogFile)
       
  1311 				{
       
  1312 				fprintf(stderr, "Can't open %s for write (%d) %s\n", logfilename, errno, strerror(errno));
       
  1313 				exit(KExitCodeLog);
       
  1314 				}
       
  1315 			
       
  1316 			// Disable stream buffering.
       
  1317 			setvbuf(LogFile,NULL,_IONBF,0);
       
  1318 			}
       
  1319 		paramIndex ++;
       
  1320 
       
  1321 		// Check to see if a non-default inactivity timeout has been specified.
       
  1322 		if (paramIndex < argc)
       
  1323 			{
       
  1324 			overallTimeOutS = atoi(argv[paramIndex]);
       
  1325 			}
       
  1326 		}
       
  1327 
       
  1328 	TBool sendImage = strcmpi(ImgFileName, "nul") != 0;
       
  1329 
       
  1330 	// Log the trgtest parameters.
       
  1331 	TraceLog("Port                  = COM%d", port);
       
  1332 	if(sendImage)
       
  1333 		{
       
  1334 		if(baudRate == 0)
       
  1335 			{
       
  1336 			TraceLog("Baud Rate             = Auto");
       
  1337 			}
       
  1338 		else
       
  1339 			{
       
  1340 			TraceLog("Baud Rate             = %dbps", baudRate);
       
  1341 			}
       
  1342 		TraceLog("ROM Image             = %s", ImgFileName);
       
  1343 		}
       
  1344 	else
       
  1345 		{
       
  1346 		TraceLog("ROM Image             = None");
       
  1347 		}
       
  1348 	TraceLog("Log Baud Rate         = %dbps", logBaudRate);
       
  1349 	if(use_stdout)
       
  1350 		{
       
  1351 		TraceLog("Log                   = STDOUT");
       
  1352 		}
       
  1353 	else if(logfilename)
       
  1354 		{
       
  1355 		TraceLog("Log                   = %s", logfilename);
       
  1356 		}
       
  1357 	else
       
  1358 		{
       
  1359 		TraceLog("Log                   = None", logfilename);
       
  1360 		}
       
  1361 	TraceLog("Inactivity Timeout    = %d secs.", overallTimeOutS);
       
  1362 	if(DebugMonitorOptions & kDebugDumpCodeSegs)
       
  1363 		{
       
  1364 		TraceLog("Debug Monitor Options = Dump Code Segs");
       
  1365 		}
       
  1366 	else
       
  1367 		{
       
  1368 		TraceLog("Debug Monitor Options = None");
       
  1369 		}
       
  1370 
       
  1371 	// Initiate serial upload if a ROM image was specified.
       
  1372 	if(sendImage)
       
  1373 		{
       
  1374 		UploadROM(port, baudRate);
       
  1375 		}
       
  1376 
       
  1377 	if(r==KErrNone)
       
  1378 		{
       
  1379 		// Check to see if the ROM upload (if any) succeeded.
       
  1380 		if(sendImage)
       
  1381 			{
       
  1382 			printf("Sent image file OK\n");
       
  1383 			TraceLog("Sent image file OK");
       
  1384 			}
       
  1385 		
       
  1386 		// Check to see if we should log the target output.
       
  1387 		if (LogFile || use_stdout)
       
  1388 			{
       
  1389 			// If no serial upload was performed the COM port is not yet open.
       
  1390 			if(!sendImage)
       
  1391 				{
       
  1392 				// Open the COM port.
       
  1393 				OpenCommPort(port);
       
  1394 				}
       
  1395 
       
  1396 			// Log the target output if a log file was specified.
       
  1397 			r = LogTargetOutput(logfilename, use_stdout, port, baudRate, logBaudRate, overallTimeOutS);
       
  1398 			}
       
  1399 		}
       
  1400 	else
       
  1401 		{
       
  1402 		printf("SendImageFile upload failed -> (%d) %s\n", r, GetSymOrWinErrMsg(r));
       
  1403 		TraceLog("SendImageFile upload failed -> (%d) %s", r, GetSymOrWinErrMsg(r));
       
  1404 		r = KExitCodeDownload;
       
  1405 		}
       
  1406 
       
  1407 	// Close the session
       
  1408 	CloseSession();
       
  1409 
       
  1410 	// Print any exit error. 
       
  1411 	if (r!=KErrNone)
       
  1412 		{
       
  1413 		fprintf(stderr, "Exiting with error %d\n", r);
       
  1414 		}
       
  1415 
       
  1416 	return r;
       
  1417 	}